1
0
mirror of https://github.com/PaperMC/Paper.git synced 2025-04-10 05:55:45 +02:00
Paper/src/main/java/net/minecraft/server/EntityWither.java
Travis Watkins e080bafa58 Rework mob item dropping on death. Fixes BUKKIT-5625
After the changes in d611cff2 we started including a mob's equipment when
calling EntityDeathEvent so plugins can access this data. However, the
changes to enable this triggered a bug that makes skeletons and pig zombies
no longer drop equipment because they handle this differently than the rest.
On top of this we don't handle dropping equipment for mobs that cannot
pick up items in vanilla even though vanilla does drop equipment for them
if you summon them with it. We also do not include a horse's inventory
in the event so they drop their saddle, armor, chest, and chest contents
with no way for a plugin to control this.

To solve this issues we revert mob item dropping back to vanilla logic
and instead just capture all their drops in the method they all call to
spawn them into the world. We also move horse inventory dropping so it
happens at a time when we're capturing these drops. With these changes
all items mobs drop on death should now be included in the event and
we have less diff to worry about for future updates.
2014-05-26 18:42:47 -05:00

462 lines
16 KiB
Java

package net.minecraft.server;
import java.util.Iterator;
import java.util.List;
// CraftBukkit start
import org.bukkit.craftbukkit.event.CraftEventFactory;
import org.bukkit.event.entity.EntityRegainHealthEvent;
import org.bukkit.event.entity.ExplosionPrimeEvent;
// CraftBukkit end
public class EntityWither extends EntityMonster implements IRangedEntity {
private float[] bp = new float[2];
private float[] bq = new float[2];
private float[] br = new float[2];
private float[] bs = new float[2];
private int[] bt = new int[2];
private int[] bu = new int[2];
private int bv;
private static final IEntitySelector bw = new EntitySelectorNotUndead();
public EntityWither(World world) {
super(world);
this.setHealth(this.getMaxHealth());
this.a(0.9F, 4.0F);
this.fireProof = true;
this.getNavigation().e(true);
this.goalSelector.a(0, new PathfinderGoalFloat(this));
this.goalSelector.a(2, new PathfinderGoalArrowAttack(this, 1.0D, 40, 20.0F));
this.goalSelector.a(5, new PathfinderGoalRandomStroll(this, 1.0D));
this.goalSelector.a(6, new PathfinderGoalLookAtPlayer(this, EntityHuman.class, 8.0F));
this.goalSelector.a(7, new PathfinderGoalRandomLookaround(this));
this.targetSelector.a(1, new PathfinderGoalHurtByTarget(this, false));
this.targetSelector.a(2, new PathfinderGoalNearestAttackableTarget(this, EntityInsentient.class, 0, false, false, bw));
this.b = 50;
}
protected void c() {
super.c();
this.datawatcher.a(17, new Integer(0));
this.datawatcher.a(18, new Integer(0));
this.datawatcher.a(19, new Integer(0));
this.datawatcher.a(20, new Integer(0));
}
public void b(NBTTagCompound nbttagcompound) {
super.b(nbttagcompound);
nbttagcompound.setInt("Invul", this.ca());
}
public void a(NBTTagCompound nbttagcompound) {
super.a(nbttagcompound);
this.s(nbttagcompound.getInt("Invul"));
}
protected String t() {
return "mob.wither.idle";
}
protected String aS() {
return "mob.wither.hurt";
}
protected String aT() {
return "mob.wither.death";
}
public void e() {
this.motY *= 0.6000000238418579D;
double d0;
double d1;
double d2;
if (!this.world.isStatic && this.t(0) > 0) {
Entity entity = this.world.getEntity(this.t(0));
if (entity != null) {
if (this.locY < entity.locY || !this.cb() && this.locY < entity.locY + 5.0D) {
if (this.motY < 0.0D) {
this.motY = 0.0D;
}
this.motY += (0.5D - this.motY) * 0.6000000238418579D;
}
double d3 = entity.locX - this.locX;
d0 = entity.locZ - this.locZ;
d1 = d3 * d3 + d0 * d0;
if (d1 > 9.0D) {
d2 = (double) MathHelper.sqrt(d1);
this.motX += (d3 / d2 * 0.5D - this.motX) * 0.6000000238418579D;
this.motZ += (d0 / d2 * 0.5D - this.motZ) * 0.6000000238418579D;
}
}
}
if (this.motX * this.motX + this.motZ * this.motZ > 0.05000000074505806D) {
this.yaw = (float) Math.atan2(this.motZ, this.motX) * 57.295776F - 90.0F;
}
super.e();
int i;
for (i = 0; i < 2; ++i) {
this.bs[i] = this.bq[i];
this.br[i] = this.bp[i];
}
int j;
for (i = 0; i < 2; ++i) {
j = this.t(i + 1);
Entity entity1 = null;
if (j > 0) {
entity1 = this.world.getEntity(j);
}
if (entity1 != null) {
d0 = this.u(i + 1);
d1 = this.v(i + 1);
d2 = this.w(i + 1);
double d4 = entity1.locX - d0;
double d5 = entity1.locY + (double) entity1.getHeadHeight() - d1;
double d6 = entity1.locZ - d2;
double d7 = (double) MathHelper.sqrt(d4 * d4 + d6 * d6);
float f = (float) (Math.atan2(d6, d4) * 180.0D / 3.1415927410125732D) - 90.0F;
float f1 = (float) (-(Math.atan2(d5, d7) * 180.0D / 3.1415927410125732D));
this.bp[i] = this.b(this.bp[i], f1, 40.0F);
this.bq[i] = this.b(this.bq[i], f, 10.0F);
} else {
this.bq[i] = this.b(this.bq[i], this.aM, 10.0F);
}
}
boolean flag = this.cb();
for (j = 0; j < 3; ++j) {
double d8 = this.u(j);
double d9 = this.v(j);
double d10 = this.w(j);
this.world.addParticle("smoke", d8 + this.random.nextGaussian() * 0.30000001192092896D, d9 + this.random.nextGaussian() * 0.30000001192092896D, d10 + this.random.nextGaussian() * 0.30000001192092896D, 0.0D, 0.0D, 0.0D);
if (flag && this.world.random.nextInt(4) == 0) {
this.world.addParticle("mobSpell", d8 + this.random.nextGaussian() * 0.30000001192092896D, d9 + this.random.nextGaussian() * 0.30000001192092896D, d10 + this.random.nextGaussian() * 0.30000001192092896D, 0.699999988079071D, 0.699999988079071D, 0.5D);
}
}
if (this.ca() > 0) {
for (j = 0; j < 3; ++j) {
this.world.addParticle("mobSpell", this.locX + this.random.nextGaussian() * 1.0D, this.locY + (double) (this.random.nextFloat() * 3.3F), this.locZ + this.random.nextGaussian() * 1.0D, 0.699999988079071D, 0.699999988079071D, 0.8999999761581421D);
}
}
}
protected void bm() {
int i;
if (this.ca() > 0) {
i = this.ca() - 1;
if (i <= 0) {
// CraftBukkit start
ExplosionPrimeEvent event = new ExplosionPrimeEvent(this.getBukkitEntity(), 7.0F, false);
this.world.getServer().getPluginManager().callEvent(event);
if (!event.isCancelled()) {
this.world.createExplosion(this, this.locX, this.locY + (double) this.getHeadHeight(), this.locZ, event.getRadius(), event.getFire(), this.world.getGameRules().getBoolean("mobGriefing"));
}
// CraftBukkit end
this.world.createExplosion(this, this.locX, this.locY + (double) this.getHeadHeight(), this.locZ, 7.0F, false, this.world.getGameRules().getBoolean("mobGriefing"));
this.world.b(1013, (int) this.locX, (int) this.locY, (int) this.locZ, 0);
}
this.s(i);
if (this.ticksLived % 10 == 0) {
this.heal(10.0F, EntityRegainHealthEvent.RegainReason.WITHER_SPAWN); // CraftBukkit
}
} else {
super.bm();
int j;
for (i = 1; i < 3; ++i) {
if (this.ticksLived >= this.bt[i - 1]) {
this.bt[i - 1] = this.ticksLived + 10 + this.random.nextInt(10);
if (this.world.difficulty == EnumDifficulty.NORMAL || this.world.difficulty == EnumDifficulty.HARD) {
int i1001 = i - 1;
int i1003 = this.bu[i - 1];
this.bu[i1001] = this.bu[i - 1] + 1;
if (i1003 > 15) {
float f = 10.0F;
float f1 = 5.0F;
double d0 = MathHelper.a(this.random, this.locX - (double) f, this.locX + (double) f);
double d1 = MathHelper.a(this.random, this.locY - (double) f1, this.locY + (double) f1);
double d2 = MathHelper.a(this.random, this.locZ - (double) f, this.locZ + (double) f);
this.a(i + 1, d0, d1, d2, true);
this.bu[i - 1] = 0;
}
}
j = this.t(i);
if (j > 0) {
Entity entity = this.world.getEntity(j);
if (entity != null && entity.isAlive() && this.f(entity) <= 900.0D && this.p(entity)) {
this.a(i + 1, (EntityLiving) entity);
this.bt[i - 1] = this.ticksLived + 40 + this.random.nextInt(20);
this.bu[i - 1] = 0;
} else {
this.b(i, 0);
}
} else {
List list = this.world.a(EntityLiving.class, this.boundingBox.grow(20.0D, 8.0D, 20.0D), bw);
for (int i1 = 0; i1 < 10 && !list.isEmpty(); ++i1) {
EntityLiving entityliving = (EntityLiving) list.get(this.random.nextInt(list.size()));
if (entityliving != this && entityliving.isAlive() && this.p(entityliving)) {
if (entityliving instanceof EntityHuman) {
if (!((EntityHuman) entityliving).abilities.isInvulnerable) {
this.b(i, entityliving.getId());
}
} else {
this.b(i, entityliving.getId());
}
break;
}
list.remove(entityliving);
}
}
}
}
if (this.getGoalTarget() != null) {
this.b(0, this.getGoalTarget().getId());
} else {
this.b(0, 0);
}
if (this.bv > 0) {
--this.bv;
if (this.bv == 0 && this.world.getGameRules().getBoolean("mobGriefing")) {
i = MathHelper.floor(this.locY);
j = MathHelper.floor(this.locX);
int j1 = MathHelper.floor(this.locZ);
boolean flag = false;
for (int k1 = -1; k1 <= 1; ++k1) {
for (int l1 = -1; l1 <= 1; ++l1) {
for (int i2 = 0; i2 <= 3; ++i2) {
int j2 = j + k1;
int k2 = i + i2;
int l2 = j1 + l1;
Block block = this.world.getType(j2, k2, l2);
if (block.getMaterial() != Material.AIR && block != Blocks.BEDROCK && block != Blocks.ENDER_PORTAL && block != Blocks.ENDER_PORTAL_FRAME && block != Blocks.COMMAND) {
// CraftBukkit start
if (CraftEventFactory.callEntityChangeBlockEvent(this, j2, k2, l2, Blocks.AIR, 0).isCancelled()) {
continue;
}
// CraftBukkit end
flag = this.world.setAir(j2, k2, l2, true) || flag;
}
}
}
}
if (flag) {
this.world.a((EntityHuman) null, 1012, (int) this.locX, (int) this.locY, (int) this.locZ, 0);
}
}
}
if (this.ticksLived % 20 == 0) {
this.heal(1.0F, EntityRegainHealthEvent.RegainReason.REGEN); // CraftBukkit
}
}
}
public void bZ() {
this.s(220);
this.setHealth(this.getMaxHealth() / 3.0F);
}
public void ar() {}
public int aU() {
return 4;
}
private double u(int i) {
if (i <= 0) {
return this.locX;
} else {
float f = (this.aM + (float) (180 * (i - 1))) / 180.0F * 3.1415927F;
float f1 = MathHelper.cos(f);
return this.locX + (double) f1 * 1.3D;
}
}
private double v(int i) {
return i <= 0 ? this.locY + 3.0D : this.locY + 2.2D;
}
private double w(int i) {
if (i <= 0) {
return this.locZ;
} else {
float f = (this.aM + (float) (180 * (i - 1))) / 180.0F * 3.1415927F;
float f1 = MathHelper.sin(f);
return this.locZ + (double) f1 * 1.3D;
}
}
private float b(float f, float f1, float f2) {
float f3 = MathHelper.g(f1 - f);
if (f3 > f2) {
f3 = f2;
}
if (f3 < -f2) {
f3 = -f2;
}
return f + f3;
}
private void a(int i, EntityLiving entityliving) {
this.a(i, entityliving.locX, entityliving.locY + (double) entityliving.getHeadHeight() * 0.5D, entityliving.locZ, i == 0 && this.random.nextFloat() < 0.001F);
}
private void a(int i, double d0, double d1, double d2, boolean flag) {
this.world.a((EntityHuman) null, 1014, (int) this.locX, (int) this.locY, (int) this.locZ, 0);
double d3 = this.u(i);
double d4 = this.v(i);
double d5 = this.w(i);
double d6 = d0 - d3;
double d7 = d1 - d4;
double d8 = d2 - d5;
EntityWitherSkull entitywitherskull = new EntityWitherSkull(this.world, this, d6, d7, d8);
if (flag) {
entitywitherskull.a(true);
}
entitywitherskull.locY = d4;
entitywitherskull.locX = d3;
entitywitherskull.locZ = d5;
this.world.addEntity(entitywitherskull);
}
public void a(EntityLiving entityliving, float f) {
this.a(0, entityliving);
}
public boolean damageEntity(DamageSource damagesource, float f) {
if (this.isInvulnerable()) {
return false;
} else if (damagesource == DamageSource.DROWN) {
return false;
} else if (this.ca() > 0) {
return false;
} else {
Entity entity;
if (this.cb()) {
entity = damagesource.i();
if (entity instanceof EntityArrow) {
return false;
}
}
entity = damagesource.getEntity();
if (entity != null && !(entity instanceof EntityHuman) && entity instanceof EntityLiving && ((EntityLiving) entity).getMonsterType() == this.getMonsterType()) {
return false;
} else {
if (this.bv <= 0) {
this.bv = 20;
}
for (int i = 0; i < this.bu.length; ++i) {
this.bu[i] += 3;
}
return super.damageEntity(damagesource, f);
}
}
}
protected void dropDeathLoot(boolean flag, int i) {
this.a(Items.NETHER_STAR, 1);
if (!this.world.isStatic) {
Iterator iterator = this.world.a(EntityHuman.class, this.boundingBox.grow(50.0D, 100.0D, 50.0D)).iterator();
while (iterator.hasNext()) {
EntityHuman entityhuman = (EntityHuman) iterator.next();
entityhuman.a((Statistic) AchievementList.J);
}
}
}
protected void w() {
this.aU = 0;
}
protected void b(float f) {}
public void addEffect(MobEffect mobeffect) {}
protected boolean bj() {
return true;
}
protected void aC() {
super.aC();
this.getAttributeInstance(GenericAttributes.a).setValue(300.0D);
this.getAttributeInstance(GenericAttributes.d).setValue(0.6000000238418579D);
this.getAttributeInstance(GenericAttributes.b).setValue(40.0D);
}
public int ca() {
return this.datawatcher.getInt(20);
}
public void s(int i) {
this.datawatcher.watch(20, Integer.valueOf(i));
}
public int t(int i) {
return this.datawatcher.getInt(17 + i);
}
public void b(int i, int j) {
this.datawatcher.watch(17 + i, Integer.valueOf(j));
}
public boolean cb() {
return this.getHealth() <= this.getMaxHealth() / 2.0F;
}
public EnumMonsterType getMonsterType() {
return EnumMonsterType.UNDEAD;
}
public void mount(Entity entity) {
this.vehicle = null;
}
}