diff options
Diffstat (limited to 'patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch')
-rw-r--r-- | patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch | 921 |
1 files changed, 921 insertions, 0 deletions
diff --git a/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch new file mode 100644 index 0000000000..55799925f7 --- /dev/null +++ b/patch-remap/mache-spigotflower-stripped/net/minecraft/world/entity/LivingEntity.java.patch @@ -0,0 +1,921 @@ +--- a/net/minecraft/world/entity/LivingEntity.java ++++ b/net/minecraft/world/entity/LivingEntity.java +@@ -119,6 +120,26 @@ + import net.minecraft.world.scores.PlayerTeam; + import org.slf4j.Logger; + ++// CraftBukkit start ++import java.util.ArrayList; ++import java.util.HashSet; ++import java.util.Set; ++import com.google.common.base.Function; ++import org.bukkit.Location; ++import org.bukkit.craftbukkit.attribute.CraftAttributeMap; ++import org.bukkit.craftbukkit.event.CraftEventFactory; ++import org.bukkit.craftbukkit.inventory.CraftItemStack; ++import org.bukkit.entity.Player; ++import org.bukkit.event.entity.ArrowBodyCountChangeEvent; ++import org.bukkit.event.entity.EntityDamageEvent; ++import org.bukkit.event.entity.EntityDamageEvent.DamageModifier; ++import org.bukkit.event.entity.EntityPotionEffectEvent; ++import org.bukkit.event.entity.EntityRegainHealthEvent; ++import org.bukkit.event.entity.EntityResurrectEvent; ++import org.bukkit.event.entity.EntityTeleportEvent; ++import org.bukkit.event.player.PlayerItemConsumeEvent; ++// CraftBukkit end ++ + public abstract class LivingEntity extends Entity implements Attackable { + + private static final Logger LOGGER = LogUtils.getLogger(); +@@ -226,9 +247,23 @@ + private float swimAmountO; + protected Brain<?> brain; + private boolean skipDropExperience; ++ // CraftBukkit start ++ public int expToDrop; ++ public boolean forceDrops; ++ public ArrayList<org.bukkit.inventory.ItemStack> drops = new ArrayList<org.bukkit.inventory.ItemStack>(); ++ public final org.bukkit.craftbukkit.attribute.CraftAttributeMap craftAttributes; ++ public boolean collides = true; ++ public Set<UUID> collidableExemptions = new HashSet<>(); ++ public boolean bukkitPickUpLoot; + +- protected LivingEntity(EntityType<? extends LivingEntity> entitytype, Level level) { +- super(entitytype, level); ++ @Override ++ public float getBukkitYaw() { ++ return getYHeadRot(); ++ } ++ // CraftBukkit end ++ ++ protected LivingEntity(EntityType<? extends LivingEntity> entityType, Level level) { ++ super(entityType, level); + this.lastHandItemStacks = NonNullList.withSize(2, ItemStack.EMPTY); + this.lastArmorItemStacks = NonNullList.withSize(4, ItemStack.EMPTY); + this.discardFriction = false; +@@ -237,8 +272,10 @@ + this.effectsDirty = true; + this.useItem = ItemStack.EMPTY; + this.lastClimbablePos = Optional.empty(); +- this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entitytype)); +- this.setHealth(this.getMaxHealth()); ++ this.attributes = new AttributeMap(DefaultAttributes.getSupplier(entityType)); ++ this.craftAttributes = new CraftAttributeMap(attributes); // CraftBukkit ++ // CraftBukkit - setHealth(getMaxHealth()) inlined and simplified to skip the instanceof check for EntityPlayer, as getBukkitEntity() is not initialized in constructor ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, (float) this.getAttribute(Attributes.MAX_HEALTH).getValue()); + this.blocksBuilding = true; + this.rotA = (float) ((Math.random() + 1.0D) * 0.009999999776482582D); + this.reapplyPosition(); +@@ -320,7 +354,13 @@ + double d7 = Math.min((double) (0.2F + f / 15.0F), 2.5D); + int i = (int) (150.0D * d7); + +- ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, blockstate), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ // CraftBukkit start - visiblity api ++ if (this instanceof ServerPlayer) { ++ ((ServerLevel) this.level()).sendParticles((ServerPlayer) this, new BlockParticleOption(ParticleTypes.BLOCK, onGround), this.getX(), this.getY(), this.getZ(), i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D, false); ++ } else { ++ ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, onGround), d1, d2, d3, i, 0.0D, 0.0D, 0.0D, 0.15000000596046448D); ++ } ++ // CraftBukkit end + } + + super.checkFallDamage(d0, flag, blockstate, blockpos); +@@ -677,15 +714,21 @@ + return true; + } + +- public void onEquipItem(EquipmentSlot equipmentslot, ItemStack itemstack, ItemStack itemstack1) { ++ public void onEquipItem(EquipmentSlot slot, ItemStack oldItem, ItemStack newItem) { ++ // CraftBukkit start ++ onEquipItem(slot, oldItem, newItem, false); ++ } ++ ++ public void onEquipItem(EquipmentSlot enumitemslot, ItemStack itemstack, ItemStack itemstack1, boolean silent) { ++ // CraftBukkit end + boolean flag = itemstack1.isEmpty() && itemstack.isEmpty(); + + if (!flag && !ItemStack.isSameItemSameTags(itemstack, itemstack1) && !this.firstTick) { + Equipable equipable = Equipable.get(itemstack1); + + if (!this.level().isClientSide() && !this.isSpectator()) { +- if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == equipmentslot) { +- this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); ++ if (!this.isSilent() && equipable != null && equipable.getEquipmentSlot() == enumitemslot && !silent) { // CraftBukkit ++ this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), equipable.getEquipSound(), this.getSoundSource(), 1.0F, 1.0F); + } + + if (this.doesEmitEquipEvent(equipmentslot)) { +@@ -761,9 +801,16 @@ + } + } + +- if (compoundtag.contains("Health", 99)) { +- this.setHealth(compoundtag.getFloat("Health")); ++ // CraftBukkit start ++ if (compound.contains("Bukkit.MaxHealth")) { ++ Tag nbtbase = compound.get("Bukkit.MaxHealth"); ++ if (nbtbase.getId() == 5) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((FloatTag) nbtbase).getAsDouble()); ++ } else if (nbtbase.getId() == 3) { ++ this.getAttribute(Attributes.MAX_HEALTH).setBaseValue(((IntTag) nbtbase).getAsDouble()); ++ } + } ++ // CraftBukkit end + + this.hurtTime = compoundtag.getShort("HurtTime"); + this.deathTime = compoundtag.getShort("DeathTime"); +@@ -798,9 +849,32 @@ + + } + ++ // CraftBukkit start ++ private boolean isTickingEffects = false; ++ private List<ProcessableEffect> effectsToProcess = Lists.newArrayList(); ++ ++ private static class ProcessableEffect { ++ ++ private MobEffect type; ++ private MobEffectInstance effect; ++ private final EntityPotionEffectEvent.Cause cause; ++ ++ private ProcessableEffect(MobEffectInstance effect, EntityPotionEffectEvent.Cause cause) { ++ this.effect = effect; ++ this.cause = cause; ++ } ++ ++ private ProcessableEffect(MobEffect type, EntityPotionEffectEvent.Cause cause) { ++ this.type = type; ++ this.cause = cause; ++ } ++ } ++ // CraftBukkit end ++ + protected void tickEffects() { + Iterator iterator = this.activeEffects.keySet().iterator(); + ++ isTickingEffects = true; // CraftBukkit + try { + while (iterator.hasNext()) { + MobEffect mobeffect = (MobEffect) iterator.next(); +@@ -810,6 +884,12 @@ + this.onEffectUpdated(mobeffectinstance, true, (Entity) null); + })) { + if (!this.level().isClientSide) { ++ // CraftBukkit start ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect, null, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.EXPIRATION); ++ if (event.isCancelled()) { ++ continue; ++ } ++ // CraftBukkit end + iterator.remove(); + this.onEffectRemoved(mobeffectinstance); + } +@@ -820,6 +900,17 @@ + } catch (ConcurrentModificationException concurrentmodificationexception) { + ; + } ++ // CraftBukkit start ++ isTickingEffects = false; ++ for (ProcessableEffect e : effectsToProcess) { ++ if (e.effect != null) { ++ addEffect(e.effect, e.cause); ++ } else { ++ removeEffect(e.type, e.cause); ++ } ++ } ++ effectsToProcess.clear(); ++ // CraftBukkit end + + if (this.effectsDirty) { + if (!this.level().isClientSide) { +@@ -946,7 +1037,13 @@ + this.entityData.set(LivingEntity.DATA_EFFECT_COLOR_ID, 0); + } + ++ // CraftBukkit start + public boolean removeAllEffects() { ++ return removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeAllEffects(EntityPotionEffectEvent.Cause cause) { ++ // CraftBukkit end + if (this.level().isClientSide) { + return false; + } else { +@@ -955,7 +1052,14 @@ + boolean flag; + + for (flag = false; iterator.hasNext(); flag = true) { +- this.onEffectRemoved((MobEffectInstance) iterator.next()); ++ // CraftBukkit start ++ MobEffectInstance effect = (MobEffectInstance) iterator.next(); ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause, EntityPotionEffectEvent.Action.CLEARED); ++ if (event.isCancelled()) { ++ continue; ++ } ++ this.onEffectRemoved(effect); ++ // CraftBukkit end + iterator.remove(); + } + +@@ -984,19 +1088,49 @@ + return this.addEffect(mobeffectinstance, (Entity) null); + } + +- public boolean addEffect(MobEffectInstance mobeffectinstance, @Nullable Entity entity) { +- if (!this.canBeAffected(mobeffectinstance)) { ++ // CraftBukkit start ++ public boolean addEffect(MobEffectInstance mobeffect, EntityPotionEffectEvent.Cause cause) { ++ return this.addEffect(mobeffect, (Entity) null, cause); ++ } ++ ++ public boolean addEffect(MobEffectInstance effectInstance, @Nullable Entity entity) { ++ return this.addEffect(effectInstance, entity, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean addEffect(MobEffectInstance mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) { ++ if (isTickingEffects) { ++ effectsToProcess.add(new ProcessableEffect(mobeffect, cause)); ++ return true; ++ } ++ // CraftBukkit end ++ ++ if (!this.canBeAffected(mobeffect)) { + return false; + } else { + MobEffectInstance mobeffectinstance1 = (MobEffectInstance) this.activeEffects.get(mobeffectinstance.getEffect()); + boolean flag = false; + +- if (mobeffectinstance1 == null) { +- this.activeEffects.put(mobeffectinstance.getEffect(), mobeffectinstance); +- this.onEffectAdded(mobeffectinstance, entity); ++ // CraftBukkit start ++ boolean override = false; ++ if (mobeffect1 != null) { ++ override = new MobEffectInstance(mobeffect1).update(mobeffect); ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, mobeffect1, mobeffect, cause, override); ++ if (event.isCancelled()) { ++ return false; ++ } ++ // CraftBukkit end ++ ++ if (mobeffect1 == null) { ++ this.activeEffects.put(mobeffect.getEffect(), mobeffect); ++ this.onEffectAdded(mobeffect, entity); + flag = true; +- } else if (mobeffectinstance1.update(mobeffectinstance)) { +- this.onEffectUpdated(mobeffectinstance1, true, entity); ++ // CraftBukkit start ++ } else if (event.isOverride()) { ++ mobeffect1.update(mobeffect); ++ this.onEffectUpdated(mobeffect1, true, entity); ++ // CraftBukkit end + flag = true; + } + +@@ -1034,6 +1168,7 @@ + return this.getMobType() == MobType.UNDEAD; + } + ++ // CraftBukkit start + @Nullable + public MobEffectInstance removeEffectNoUpdate(@Nullable MobEffect mobeffect) { + return (MobEffectInstance) this.activeEffects.remove(mobeffect); +@@ -1042,8 +1181,29 @@ + public boolean removeEffect(MobEffect mobeffect) { + MobEffectInstance mobeffectinstance = this.removeEffectNoUpdate(mobeffect); + +- if (mobeffectinstance != null) { +- this.onEffectRemoved(mobeffectinstance); ++ MobEffectInstance effect = this.activeEffects.get(mobeffectlist); ++ if (effect == null) { ++ return null; ++ } ++ ++ EntityPotionEffectEvent event = CraftEventFactory.callEntityPotionEffectChangeEvent(this, effect, null, cause); ++ if (event.isCancelled()) { ++ return null; ++ } ++ ++ return (MobEffectInstance) this.activeEffects.remove(mobeffectlist); ++ } ++ ++ public boolean removeEffect(MobEffect effect) { ++ return removeEffect(effect, org.bukkit.event.entity.EntityPotionEffectEvent.Cause.UNKNOWN); ++ } ++ ++ public boolean removeEffect(MobEffect mobeffectlist, EntityPotionEffectEvent.Cause cause) { ++ MobEffectInstance mobeffect = this.c(mobeffectlist, cause); ++ // CraftBukkit end ++ ++ if (mobeffect != null) { ++ this.onEffectRemoved(mobeffect); + return true; + } else { + return false; +@@ -1138,21 +1298,56 @@ + + } + +- public void heal(float f) { ++ // CraftBukkit start - Delegate so we can handle providing a reason for health being regained ++ public void heal(float healAmount) { ++ heal(healAmount, EntityRegainHealthEvent.RegainReason.CUSTOM); ++ } ++ ++ public void heal(float f, EntityRegainHealthEvent.RegainReason regainReason) { + float f1 = this.getHealth(); + + if (f1 > 0.0F) { +- this.setHealth(f1 + f); ++ EntityRegainHealthEvent event = new EntityRegainHealthEvent(this.getBukkitEntity(), f, regainReason); ++ // Suppress during worldgen ++ if (this.valid) { ++ this.level().getCraftServer().getPluginManager().callEvent(event); ++ } ++ ++ if (!event.isCancelled()) { ++ this.setHealth((float) (this.getHealth() + event.getAmount())); ++ } ++ // CraftBukkit end + } + + } + + public float getHealth() { ++ // CraftBukkit start - Use unscaled health ++ if (this instanceof ServerPlayer) { ++ return (float) ((ServerPlayer) this).getBukkitEntity().getHealth(); ++ } ++ // CraftBukkit end + return (Float) this.entityData.get(LivingEntity.DATA_HEALTH_ID); + } + +- public void setHealth(float f) { +- this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(f, 0.0F, this.getMaxHealth())); ++ public void setHealth(float health) { ++ // CraftBukkit start - Handle scaled health ++ if (this instanceof ServerPlayer) { ++ org.bukkit.craftbukkit.entity.CraftPlayer player = ((ServerPlayer) this).getBukkitEntity(); ++ // Squeeze ++ if (health < 0.0F) { ++ player.setRealHealth(0.0D); ++ } else if (health > player.getMaxHealth()) { ++ player.setRealHealth(player.getMaxHealth()); ++ } else { ++ player.setRealHealth(health); ++ } ++ ++ player.updateScaledHealth(false); ++ return; ++ } ++ // CraftBukkit end ++ this.entityData.set(LivingEntity.DATA_HEALTH_ID, Mth.clamp(health, 0.0F, this.getMaxHealth())); + } + + public boolean isDeadOrDying() { +@@ -1166,7 +1360,7 @@ + return false; + } else if (this.level().isClientSide) { + return false; +- } else if (this.isDeadOrDying()) { ++ } else if (this.isRemoved() || this.dead || this.getHealth() <= 0.0F) { // CraftBukkit - Don't allow entities that got set to dead/killed elsewhere to get damaged and die + return false; + } else if (damagesource.is(DamageTypeTags.IS_FIRE) && this.hasEffect(MobEffects.FIRE_RESISTANCE)) { + return false; +@@ -1180,12 +1374,13 @@ + boolean flag = false; + float f2 = 0.0F; + +- if (f > 0.0F && this.isDamageSourceBlocked(damagesource)) { +- this.hurtCurrentlyUsedShield(f); +- f2 = f; +- f = 0.0F; +- if (!damagesource.is(DamageTypeTags.IS_PROJECTILE)) { +- Entity entity = damagesource.getDirectEntity(); ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && amount > 0.0F && this.isDamageSourceBlocked(source)) { ++ this.hurtCurrentlyUsedShield(amount); ++ f2 = amount; ++ amount = 0.0F; ++ if (!source.is(DamageTypeTags.IS_PROJECTILE)) { ++ Entity entity = source.getDirectEntity(); + + if (entity instanceof LivingEntity) { + LivingEntity livingentity = (LivingEntity) entity; +@@ -1204,25 +1399,35 @@ + this.walkAnimation.setSpeed(1.5F); + boolean flag1 = true; + +- if ((float) this.invulnerableTime > 10.0F && !damagesource.is(DamageTypeTags.BYPASSES_COOLDOWN)) { +- if (f <= this.lastHurt) { ++ if ((float) this.invulnerableTime > (float) this.invulnerableDuration / 2.0F && !source.is(DamageTypeTags.BYPASSES_COOLDOWN)) { // CraftBukkit - restore use of maxNoDamageTicks ++ if (amount <= this.lastHurt) { + return false; + } + +- this.actuallyHurt(damagesource, f - this.lastHurt); +- this.lastHurt = f; ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount - this.lastHurt)) { ++ return false; ++ } ++ // CraftBukkit end ++ this.lastHurt = amount; + flag1 = false; + } else { +- this.lastHurt = f; +- this.invulnerableTime = 20; +- this.actuallyHurt(damagesource, f); ++ // CraftBukkit start ++ if (!this.damageEntity0(source, amount)) { ++ return false; ++ } ++ this.lastHurt = amount; ++ this.invulnerableTime = this.invulnerableDuration; // CraftBukkit - restore use of maxNoDamageTicks ++ // this.damageEntity0(damagesource, f); ++ // CraftBukkit end + this.hurtDuration = 10; + this.hurtTime = this.hurtDuration; + } + +- if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { +- this.hurtHelmet(damagesource, f); +- f *= 0.75F; ++ // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ if (false && source.is(DamageTypeTags.DAMAGES_HELMET) && !this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ this.hurtHelmet(source, amount); ++ amount *= 0.75F; + } + + Entity entity1 = damagesource.getEntity(); +@@ -1338,13 +1543,17 @@ + InteractionHand[] ainteractionhand = InteractionHand.values(); + int i = ainteractionhand.length; + ++ // CraftBukkit start ++ EnumHand hand = null; ++ ItemStack itemstack1 = ItemStack.EMPTY; + for (int j = 0; j < i; ++j) { + InteractionHand interactionhand = ainteractionhand[j]; + ItemStack itemstack1 = this.getItemInHand(interactionhand); + + if (itemstack1.is(Items.TOTEM_OF_UNDYING)) { ++ hand = enumhand; // CraftBukkit + itemstack = itemstack1.copy(); +- itemstack1.shrink(1); ++ // itemstack1.subtract(1); // CraftBukkit + break; + } + } +@@ -1353,16 +1563,26 @@ + if (this instanceof ServerPlayer) { + ServerPlayer serverplayer = (ServerPlayer) this; + +- serverplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); +- CriteriaTriggers.USED_TOTEM.trigger(serverplayer, itemstack); ++ if (!event.isCancelled()) { ++ if (!itemstack1.isEmpty()) { ++ itemstack1.shrink(1); ++ } ++ if (itemstack != null && this instanceof ServerPlayer) { ++ // CraftBukkit end ++ ServerPlayer entityplayer = (ServerPlayer) this; ++ ++ entityplayer.awardStat(Stats.ITEM_USED.get(Items.TOTEM_OF_UNDYING)); ++ CriteriaTriggers.USED_TOTEM.trigger(entityplayer, itemstack); + this.gameEvent(GameEvent.ITEM_INTERACT_FINISH); + } + + this.setHealth(1.0F); +- this.removeAllEffects(); +- this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1)); +- this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0)); ++ // CraftBukkit start ++ this.removeAllEffects(org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.REGENERATION, 900, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.ABSORPTION, 100, 1), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ this.addEffect(new MobEffectInstance(MobEffects.FIRE_RESISTANCE, 800, 0), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TOTEM); ++ // CraftBukkit end + this.level().broadcastEntityEvent(this, (byte) 35); + } + +@@ -1472,16 +1692,24 @@ + BlockPos blockpos = this.blockPosition(); + BlockState blockstate = Blocks.WITHER_ROSE.defaultBlockState(); + +- if (this.level().getBlockState(blockpos).isAir() && blockstate.canSurvive(this.level(), blockpos)) { +- this.level().setBlock(blockpos, blockstate, 3); +- flag = true; ++ if (this.level().getBlockState(blockposition).isAir() && iblockdata.canSurvive(this.level(), blockposition)) { ++ // CraftBukkit start - call EntityBlockFormEvent for Wither Rose ++ flag = org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockFormEvent(this.level(), blockposition, iblockdata, 3, this); ++ // CraftBukkit end + } + } + + if (!flag) { + ItemEntity itementity = new ItemEntity(this.level(), this.getX(), this.getY(), this.getZ(), new ItemStack(Items.WITHER_ROSE)); + +- this.level().addFreshEntity(itementity); ++ // CraftBukkit start ++ org.bukkit.event.entity.EntityDropItemEvent event = new org.bukkit.event.entity.EntityDropItemEvent(this.getBukkitEntity(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); ++ CraftEventFactory.callEvent(event); ++ if (event.isCancelled()) { ++ return; ++ } ++ // CraftBukkit end ++ this.level().addFreshEntity(entityitem); + } + } + +@@ -1500,22 +1728,38 @@ + + boolean flag = this.lastHurtByPlayerTime > 0; + ++ this.dropEquipment(); // CraftBukkit - from below + if (this.shouldDropLoot() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT)) { + this.dropFromLootTable(damagesource, flag); + this.dropCustomDeathLoot(damagesource, i, flag); + } ++ // CraftBukkit start - Call death event ++ CraftEventFactory.callEntityDeathEvent(this, this.drops); ++ this.drops = new ArrayList<>(); ++ // CraftBukkit end + +- this.dropEquipment(); ++ // this.dropInventory();// CraftBukkit - moved up + this.dropExperience(); + } + + protected void dropEquipment() {} + +- protected void dropExperience() { ++ // CraftBukkit start ++ public int getExpReward() { + if (this.level() instanceof ServerLevel && !this.wasExperienceConsumed() && (this.isAlwaysExperienceDropper() || this.lastHurtByPlayerTime > 0 && this.shouldDropExperience() && this.level().getGameRules().getBoolean(GameRules.RULE_DOMOBLOOT))) { + ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.getExperienceReward()); + } ++ } ++ // CraftBukkit end + ++ protected void dropExperience() { ++ // CraftBukkit start - Update getExpReward() above if the removed if() changes! ++ if (true && !(this instanceof net.minecraft.world.entity.boss.enderdragon.EnderDragon)) { // CraftBukkit - SPIGOT-2420: Special case ender dragon will drop the xp over time ++ ExperienceOrb.award((ServerLevel) this.level(), this.position(), this.expToDrop); ++ this.expToDrop = 0; ++ } ++ // CraftBukkit end ++ + } + + protected void dropCustomDeathLoot(DamageSource damagesource, int i, boolean flag) {} +@@ -1606,6 +1853,28 @@ + return itemstack.getEatingSound(); + } + ++ // CraftBukkit start - Add delegate methods ++ public SoundEvent getHurtSound0(DamageSource damagesource) { ++ return getHurtSound(damagesource); ++ } ++ ++ public SoundEvent getDeathSound0() { ++ return getDeathSound(); ++ } ++ ++ public SoundEvent getFallDamageSound0(int fallHeight) { ++ return getFallDamageSound(fallHeight); ++ } ++ ++ public SoundEvent getDrinkingSound0(ItemStack itemstack) { ++ return getDrinkingSound(itemstack); ++ } ++ ++ public SoundEvent getEatingSound0(ItemStack itemstack) { ++ return getEatingSound(itemstack); ++ } ++ // CraftBukkit end ++ + public Optional<BlockPos> getLastClimbablePos() { + return this.lastClimbablePos; + } +@@ -1654,9 +1921,14 @@ + int i = this.calculateFallDamage(f, f1); + + if (i > 0) { ++ // CraftBukkit start ++ if (!this.hurt(source, (float) i)) { ++ return true; ++ } ++ // CraftBukkit end + this.playSound(this.getFallDamageSound(i), 1.0F, 1.0F); + this.playBlockFallSound(); +- this.hurt(damagesource, (float) i); ++ // this.damageEntity(damagesource, (float) i); // CraftBukkit - moved up + return true; + } else { + return flag; +@@ -1707,10 +1978,10 @@ + + protected void hurtCurrentlyUsedShield(float f) {} + +- protected float getDamageAfterArmorAbsorb(DamageSource damagesource, float f) { +- if (!damagesource.is(DamageTypeTags.BYPASSES_ARMOR)) { +- this.hurtArmor(damagesource, f); +- f = CombatRules.getDamageAfterAbsorb(f, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); ++ protected float getDamageAfterArmorAbsorb(DamageSource damageSource, float damageAmount) { ++ if (!damageSource.is(DamageTypeTags.BYPASSES_ARMOR)) { ++ // this.hurtArmor(damagesource, f); // CraftBukkit - Moved into damageEntity0(DamageSource, float) ++ damageAmount = CombatRules.getDamageAfterAbsorb(damageAmount, (float) this.getArmorValue(), (float) this.getAttributeValue(Attributes.ARMOR_TOUGHNESS)); + } + + return f; +@@ -1722,7 +1993,8 @@ + } else { + int i; + +- if (this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damagesource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { ++ // CraftBukkit - Moved to damageEntity0(DamageSource, float) ++ if (false && this.hasEffect(MobEffects.DAMAGE_RESISTANCE) && !damageSource.is(DamageTypeTags.BYPASSES_RESISTANCE)) { + i = (this.getEffect(MobEffects.DAMAGE_RESISTANCE).getAmplifier() + 1) * 5; + int j = 25 - i; + float f1 = f * (float) j; +@@ -1755,11 +2027,16 @@ + } + } + +- protected void actuallyHurt(DamageSource damagesource, float f) { +- if (!this.isInvulnerableTo(damagesource)) { +- f = this.getDamageAfterArmorAbsorb(damagesource, f); +- f = this.getDamageAfterMagicAbsorb(damagesource, f); +- float f1 = f; ++ // CraftBukkit start ++ protected boolean damageEntity0(final DamageSource damagesource, float f) { // void -> boolean, add final ++ if (!this.isInvulnerableTo(damagesource)) { ++ final boolean human = this instanceof net.minecraft.world.entity.player.Player; ++ float originalDamage = f; ++ Function<Double, Double> hardHat = new Function<Double, Double>() { ++ @Override ++ public Double apply(Double f) { ++ if (damagesource.is(DamageTypeTags.DAMAGES_HELMET) && !LivingEntity.this.getItemBySlot(EquipmentSlot.HEAD).isEmpty()) { ++ return -(f - (f * 0.75F)); + + f = Math.max(f - this.getAbsorptionAmount(), 0.0F); + this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f)); +@@ -1775,13 +2156,47 @@ + } + } + +- if (f != 0.0F) { ++ if (f > 0 || !human) { ++ if (human) { ++ // PAIL: Be sure to drag all this code from the EntityHuman subclass each update. ++ ((net.minecraft.world.entity.player.Player) this).causeFoodExhaustion(damagesource.getFoodExhaustion(), org.bukkit.event.entity.EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent ++ if (f < 3.4028235E37F) { ++ ((net.minecraft.world.entity.player.Player) this).awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F)); ++ } ++ } ++ // CraftBukkit end + this.getCombatTracker().recordDamage(damagesource, f); + this.setHealth(this.getHealth() - f); +- this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ // CraftBukkit start ++ if (!human) { ++ this.setAbsorptionAmount(this.getAbsorptionAmount() - f); ++ } + this.gameEvent(GameEvent.ENTITY_DAMAGE); ++ ++ return true; ++ } else { ++ // Duplicate triggers if blocking ++ if (event.getDamage(DamageModifier.BLOCKING) < 0) { ++ if (this instanceof ServerPlayer) { ++ CriteriaTriggers.ENTITY_HURT_PLAYER.trigger((ServerPlayer) this, damagesource, f, originalDamage, true); ++ f2 = (float) -event.getDamage(DamageModifier.BLOCKING); ++ if (f2 > 0.0F && f2 < 3.4028235E37F) { ++ ((ServerPlayer) this).awardStat(Stats.DAMAGE_BLOCKED_BY_SHIELD, Math.round(originalDamage * 10.0F)); ++ } ++ } ++ ++ if (damagesource.getEntity() instanceof ServerPlayer) { ++ CriteriaTriggers.PLAYER_HURT_ENTITY.trigger((ServerPlayer) damagesource.getEntity(), this, damagesource, f, originalDamage, true); ++ } ++ ++ return false; ++ } else { ++ return originalDamage > 0; ++ } ++ // CraftBukkit end + } + } ++ return false; // CraftBukkit + } + + public CombatTracker getCombatTracker() { +@@ -1805,10 +2220,20 @@ + return (Integer) this.entityData.get(LivingEntity.DATA_ARROW_COUNT_ID); + } + +- public final void setArrowCount(int i) { +- this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, i); ++ public final void setArrowCount(int count) { ++ // CraftBukkit start ++ setArrowCount(count, false); + } + ++ public final void setArrowCount(int i, boolean flag) { ++ ArrowBodyCountChangeEvent event = CraftEventFactory.callArrowBodyCountChangeEvent(this, getArrowCount(), i, flag); ++ if (event.isCancelled()) { ++ return; ++ } ++ this.entityData.set(LivingEntity.DATA_ARROW_COUNT_ID, event.getNewAmount()); ++ } ++ // CraftBukkit end ++ + public final int getStingerCount() { + return (Integer) this.entityData.get(LivingEntity.DATA_STINGER_COUNT_ID); + } +@@ -2053,6 +2474,12 @@ + + public abstract ItemStack getItemBySlot(EquipmentSlot slot); + ++ // CraftBukkit start ++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) { ++ this.setItemSlot(enumitemslot, itemstack); ++ } ++ // CraftBukkit end ++ + @Override + @Override + public abstract void setItemSlot(EquipmentSlot slot, ItemStack stack); +@@ -2291,6 +2714,7 @@ + } + + if (this.onGround() && !this.level().isClientSide) { ++ if (getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) // CraftBukkit + this.setSharedFlag(7, false); + } + } else { +@@ -2462,7 +2885,7 @@ + } + } + +- this.detectEquipmentUpdates(); ++ this.detectEquipmentUpdatesPublic(); // CraftBukkit + if (this.tickCount % 20 == 0) { + this.getCombatTracker().recheckStatus(); + } +@@ -2559,7 +2982,7 @@ + this.refreshDirtyAttributes(); + } + +- private void detectEquipmentUpdates() { ++ public void detectEquipmentUpdatesPublic() { // CraftBukkit + Map<EquipmentSlot, ItemStack> map = this.collectEquipmentChanges(); + + if (map != null) { +@@ -2861,6 +3284,7 @@ + } + + if (!this.level().isClientSide) { ++ if (flag != this.getSharedFlag(7) && !CraftEventFactory.callToggleGlideEvent(this, flag).isCancelled()) // CraftBukkit + this.setSharedFlag(7, flag); + } + +@@ -3062,16 +3475,22 @@ + @Override + @Override + public boolean isPickable() { +- return !this.isRemoved(); ++ return !this.isRemoved() && this.collides; // CraftBukkit + } + + @Override + @Override + public boolean isPushable() { +- return this.isAlive() && !this.isSpectator() && !this.onClimbable(); ++ return this.isAlive() && !this.isSpectator() && !this.onClimbable() && this.collides; // CraftBukkit + } + ++ // CraftBukkit start - collidable API + @Override ++ public boolean canCollideWithBukkit(Entity entity) { ++ return isPushable() && this.collides != this.collidableExemptions.contains(entity.getUUID()); ++ } ++ // CraftBukkit end ++ + @Override + public float getYHeadRot() { + return this.yHeadRot; +@@ -3271,8 +3684,27 @@ + } else { + if (!this.useItem.isEmpty() && this.isUsingItem()) { + this.triggerItemUseEffects(this.useItem, 16); +- ItemStack itemstack = this.useItem.finishUsingItem(this.level(), this); ++ // CraftBukkit start - fire PlayerItemConsumeEvent ++ ItemStack itemstack; ++ if (this instanceof ServerPlayer) { ++ org.bukkit.inventory.ItemStack craftItem = CraftItemStack.asBukkitCopy(this.useItem); ++ org.bukkit.inventory.EquipmentSlot hand = org.bukkit.craftbukkit.CraftEquipmentSlot.getHand(enumhand); ++ PlayerItemConsumeEvent event = new PlayerItemConsumeEvent((Player) this.getBukkitEntity(), craftItem, hand); ++ this.level().getCraftServer().getPluginManager().callEvent(event); + ++ if (event.isCancelled()) { ++ // Update client ++ ((ServerPlayer) this).getBukkitEntity().updateInventory(); ++ ((ServerPlayer) this).getBukkitEntity().updateScaledHealth(); ++ return; ++ } ++ ++ itemstack = (craftItem.equals(event.getItem())) ? this.useItem.finishUsingItem(this.level(), this) : CraftItemStack.asNMSCopy(event.getItem()).finishUsingItem(this.level(), this); ++ } else { ++ itemstack = this.useItem.finishUsingItem(this.level(), this); ++ } ++ // CraftBukkit end ++ + if (itemstack != this.useItem) { + this.setItemInHand(interactionhand, itemstack); + } +@@ -3349,7 +3780,13 @@ + return this.fallFlyTicks; + } + +- public boolean randomTeleport(double d0, double d1, double d2, boolean flag) { ++ public boolean randomTeleport(double x, double d1, double y, boolean flag) { ++ // CraftBukkit start ++ return randomTeleport(x, d1, y, flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN).orElse(false); ++ } ++ ++ public Optional<Boolean> randomTeleport(double d0, double d1, double d2, boolean flag, org.bukkit.event.player.PlayerTeleportEvent.TeleportCause cause) { ++ // CraftBukkit end + double d3 = this.getX(); + double d4 = this.getY(); + double d5 = this.getZ(); +@@ -3374,16 +3811,41 @@ + } + + if (flag2) { +- this.teleportTo(d0, d6, d2); +- if (level.noCollision((Entity) this) && !level.containsAnyLiquid(this.getBoundingBox())) { ++ // CraftBukkit start - Teleport event ++ // this.teleportTo(d0, d6, d2); ++ ++ // first set position, to check if the place to teleport is valid ++ this.setPos(d0, d6, d2); ++ if (world.noCollision((Entity) this) && !world.containsAnyLiquid(this.getBoundingBox())) { + flag1 = true; + } ++ // now revert and call event if the teleport place is valid ++ this.setPos(d3, d4, d5); ++ ++ if (flag1) { ++ if (!(this instanceof ServerPlayer)) { ++ EntityTeleportEvent teleport = new EntityTeleportEvent(this.getBukkitEntity(), new Location(this.level().getWorld(), d3, d4, d5), new Location(this.level().getWorld(), d0, d6, d2)); ++ this.level().getCraftServer().getPluginManager().callEvent(teleport); ++ if (!teleport.isCancelled()) { ++ Location to = teleport.getTo(); ++ this.teleportTo(to.getX(), to.getY(), to.getZ()); ++ } else { ++ return Optional.empty(); ++ } ++ } else { ++ // player teleport event is called in the underlining code ++ if (((ServerPlayer) this).connection.teleport(d0, d6, d2, this.getYRot(), this.getXRot(), java.util.Collections.emptySet(), cause)) { ++ return Optional.empty(); ++ } ++ } ++ } ++ // CraftBukkit end + } + } + + if (!flag1) { +- this.teleportTo(d3, d4, d5); +- return false; ++ // this.enderTeleportTo(d3, d4, d5); // CraftBukkit - already set the location back ++ return Optional.of(false); // CraftBukkit + } else { + if (flag) { + level.broadcastEntityEvent(this, (byte) 46); +@@ -3395,7 +3857,7 @@ + pathfindermob.getNavigation().stop(); + } + +- return true; ++ return Optional.of(true); // CraftBukkit + } + } + +@@ -3570,7 +4028,7 @@ + Pair<MobEffectInstance, Float> pair = (Pair) iterator.next(); + + if (!level.isClientSide && pair.getFirst() != null && level.random.nextFloat() < (Float) pair.getSecond()) { +- livingentity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst())); ++ livingEntity.addEffect(new MobEffectInstance((MobEffectInstance) pair.getFirst()), EntityPotionEffectEvent.Cause.FOOD); // CraftBukkit + } + } + } |