aboutsummaryrefslogtreecommitdiffhomepage
path: root/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch
diff options
context:
space:
mode:
Diffstat (limited to 'patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch')
-rw-r--r--patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch2421
1 files changed, 2421 insertions, 0 deletions
diff --git a/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch b/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch
new file mode 100644
index 0000000000..ed43de2db3
--- /dev/null
+++ b/patch-remap/mache-vineflower/net/minecraft/world/entity/player/Player.java.patch
@@ -0,0 +1,2421 @@
+--- a/net/minecraft/world/entity/player/Player.java
++++ b/net/minecraft/world/entity/player/Player.java
+@@ -6,9 +6,12 @@
+ import com.mojang.authlib.GameProfile;
+ import com.mojang.datafixers.util.Either;
+ import com.mojang.logging.LogUtils;
++import com.mojang.serialization.DataResult;
+ import java.util.Collection;
++import java.util.Iterator;
+ import java.util.List;
+ import java.util.Map;
++import java.util.Objects;
+ import java.util.Optional;
+ import java.util.OptionalInt;
+ import java.util.function.Predicate;
+@@ -29,7 +32,6 @@
+ import net.minecraft.network.chat.ClickEvent;
+ import net.minecraft.network.chat.Component;
+ import net.minecraft.network.chat.MutableComponent;
+-import net.minecraft.network.chat.Style;
+ import net.minecraft.network.protocol.game.ClientboundSetEntityMotionPacket;
+ import net.minecraft.network.syncher.EntityDataAccessor;
+ import net.minecraft.network.syncher.EntityDataSerializers;
+@@ -49,23 +51,23 @@
+ import net.minecraft.util.Unit;
+ import net.minecraft.world.Container;
+ import net.minecraft.world.Difficulty;
+-import net.minecraft.world.InteractionHand;
++import net.minecraft.world.EnumHand;
++import net.minecraft.world.ITileInventory;
+ import net.minecraft.world.InteractionResult;
+-import net.minecraft.world.MenuProvider;
+ import net.minecraft.world.damagesource.DamageSource;
+ import net.minecraft.world.effect.MobEffectInstance;
+ import net.minecraft.world.effect.MobEffectUtil;
+ import net.minecraft.world.effect.MobEffects;
+ import net.minecraft.world.entity.Entity;
+ import net.minecraft.world.entity.EntityDimensions;
++import net.minecraft.world.entity.EntityPose;
+ import net.minecraft.world.entity.EntityType;
++import net.minecraft.world.entity.EnumMonsterType;
++import net.minecraft.world.entity.EnumMoveType;
+ import net.minecraft.world.entity.EquipmentSlot;
+ import net.minecraft.world.entity.HumanoidArm;
+ import net.minecraft.world.entity.LivingEntity;
+ import net.minecraft.world.entity.Mob;
+-import net.minecraft.world.entity.MobType;
+-import net.minecraft.world.entity.MoverType;
+-import net.minecraft.world.entity.Pose;
+ import net.minecraft.world.entity.SlotAccess;
+ import net.minecraft.world.entity.TamableAnimal;
+ import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
+@@ -102,17 +104,27 @@
+ import net.minecraft.world.level.block.entity.JigsawBlockEntity;
+ import net.minecraft.world.level.block.entity.SignBlockEntity;
+ import net.minecraft.world.level.block.entity.StructureBlockEntity;
+-import net.minecraft.world.level.block.state.BlockState;
++import net.minecraft.world.level.block.state.IBlockData;
+ import net.minecraft.world.level.block.state.pattern.BlockInWorld;
+ import net.minecraft.world.level.gameevent.GameEvent;
+ import net.minecraft.world.phys.AABB;
+ import net.minecraft.world.phys.Vec3;
+ import net.minecraft.world.scores.PlayerTeam;
+ import net.minecraft.world.scores.Scoreboard;
+-import net.minecraft.world.scores.Team;
+ import org.slf4j.Logger;
++import org.bukkit.craftbukkit.entity.CraftHumanEntity;
++import org.bukkit.craftbukkit.event.CraftEventFactory;
++import org.bukkit.craftbukkit.util.CraftVector;
++import org.bukkit.entity.Item;
++import org.bukkit.event.entity.CreatureSpawnEvent;
++import org.bukkit.event.entity.EntityCombustByEntityEvent;
++import org.bukkit.event.entity.EntityExhaustionEvent;
++import org.bukkit.event.player.PlayerDropItemEvent;
++import org.bukkit.event.player.PlayerVelocityEvent;
++// CraftBukkit end
+
+ public abstract class Player extends LivingEntity {
++
+ private static final Logger LOGGER = LogUtils.getLogger();
+ public static final int MAX_NAME_LENGTH = 16;
+ public static final HumanoidArm DEFAULT_MAIN_HAND = HumanoidArm.RIGHT;
+@@ -126,15 +138,8 @@
+ public static final float SWIMMING_BB_HEIGHT = 0.6F;
+ public static final float DEFAULT_EYE_HEIGHT = 1.62F;
+ public static final EntityDimensions STANDING_DIMENSIONS = EntityDimensions.scalable(0.6F, 1.8F);
+- private static final Map<Pose, EntityDimensions> POSES = ImmutableMap.<Pose, EntityDimensions>builder()
+- .put(Pose.STANDING, STANDING_DIMENSIONS)
+- .put(Pose.SLEEPING, SLEEPING_DIMENSIONS)
+- .put(Pose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F))
+- .put(Pose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F))
+- .put(Pose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F))
+- .put(Pose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F))
+- .put(Pose.DYING, EntityDimensions.fixed(0.2F, 0.2F))
+- .build();
++ // CraftBukkit - decompile error
++ private static final Map<EntityPose, EntityDimensions> POSES = ImmutableMap.<EntityPose, EntityDimensions>builder().put(EntityPose.STANDING, Player.STANDING_DIMENSIONS).put(EntityPose.SLEEPING, Player.SLEEPING_DIMENSIONS).put(EntityPose.FALL_FLYING, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.SWIMMING, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.SPIN_ATTACK, EntityDimensions.scalable(0.6F, 0.6F)).put(EntityPose.CROUCHING, EntityDimensions.scalable(0.6F, 1.5F)).put(EntityPose.DYING, EntityDimensions.fixed(0.2F, 0.2F)).build();
+ private static final EntityDataAccessor<Float> DATA_PLAYER_ABSORPTION_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.FLOAT);
+ private static final EntityDataAccessor<Integer> DATA_SCORE_ID = SynchedEntityData.defineId(Player.class, EntityDataSerializers.INT);
+ protected static final EntityDataAccessor<Byte> DATA_PLAYER_MODE_CUSTOMISATION = SynchedEntityData.defineId(Player.class, EntityDataSerializers.BYTE);
+@@ -143,10 +148,10 @@
+ protected static final EntityDataAccessor<CompoundTag> DATA_SHOULDER_RIGHT = SynchedEntityData.defineId(Player.class, EntityDataSerializers.COMPOUND_TAG);
+ private long timeEntitySatOnShoulder;
+ private final Inventory inventory = new Inventory(this);
+- protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer();
++ protected PlayerEnderChestContainer enderChestInventory = new PlayerEnderChestContainer(this); // CraftBukkit - add "this" to constructor
+ public final InventoryMenu inventoryMenu;
+ public AbstractContainerMenu containerMenu;
+- protected FoodData foodData = new FoodData();
++ protected FoodData foodData = new FoodData(this); // CraftBukkit - add "this" to constructor
+ protected int jumpTriggerTime;
+ public float oBob;
+ public float bob;
+@@ -157,31 +162,44 @@
+ public double xCloak;
+ public double yCloak;
+ public double zCloak;
+- private int sleepCounter;
++ public int sleepCounter;
+ protected boolean wasUnderwater;
+ private final Abilities abilities = new Abilities();
+ public int experienceLevel;
+ public int totalExperience;
+ public float experienceProgress;
+- protected int enchantmentSeed;
++ public int enchantmentSeed;
+ protected final float defaultFlySpeed = 0.02F;
+ private int lastLevelUpTime;
+ private final GameProfile gameProfile;
+ private boolean reducedDebugInfo;
+- private ItemStack lastItemInMainHand = ItemStack.EMPTY;
+- private final ItemCooldowns cooldowns = this.createItemCooldowns();
+- private Optional<GlobalPos> lastDeathLocation = Optional.empty();
++ private ItemStack lastItemInMainHand;
++ private final ItemCooldowns cooldowns;
++ private Optional<GlobalPos> lastDeathLocation;
+ @Nullable
+ public FishingHook fishing;
+ protected float hurtDir;
+
++ // CraftBukkit start
++ public boolean fauxSleeping;
++ public int oldLevel = -1;
++
++ @Override
++ public CraftHumanEntity getBukkitEntity() {
++ return (CraftHumanEntity) super.getBukkitEntity();
++ }
++ // CraftBukkit end
++
+ public Player(Level level, BlockPos pos, float yRot, GameProfile gameProfile) {
+ super(EntityType.PLAYER, level);
++ this.lastItemInMainHand = ItemStack.EMPTY;
++ this.cooldowns = this.createItemCooldowns();
++ this.lastDeathLocation = Optional.empty();
+ this.setUUID(gameProfile.getId());
+ this.gameProfile = gameProfile;
+ this.inventoryMenu = new InventoryMenu(this.inventory, !level.isClientSide, this);
+ this.containerMenu = this.inventoryMenu;
+- this.moveTo((double)pos.getX() + 0.5, (double)(pos.getY() + 1), (double)pos.getZ() + 0.5, yRot, 0.0F);
++ this.moveTo((double) pos.getX() + 0.5D, (double) (pos.getY() + 1), (double) pos.getZ() + 0.5D, yRot, 0.0F);
+ this.rotOffs = 180.0F;
+ }
+
+@@ -193,29 +211,25 @@
+ } else if (this.mayBuild()) {
+ return false;
+ } else {
+- ItemStack mainHandItem = this.getMainHandItem();
+- return mainHandItem.isEmpty()
+- || !mainHandItem.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, pos, false));
++ ItemStack itemstack = this.getMainHandItem();
++
++ return itemstack.isEmpty() || !itemstack.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, pos, false));
+ }
+ }
+
+ public static AttributeSupplier.Builder createAttributes() {
+- return LivingEntity.createLivingAttributes()
+- .add(Attributes.ATTACK_DAMAGE, 1.0)
+- .add(Attributes.MOVEMENT_SPEED, 0.1F)
+- .add(Attributes.ATTACK_SPEED)
+- .add(Attributes.LUCK);
++ return LivingEntity.createLivingAttributes().add(Attributes.ATTACK_DAMAGE, 1.0D).add(Attributes.MOVEMENT_SPEED, 0.10000000149011612D).add(Attributes.ATTACK_SPEED).add(Attributes.LUCK);
+ }
+
+ @Override
+ protected void defineSynchedData() {
+ super.defineSynchedData();
+- this.entityData.define(DATA_PLAYER_ABSORPTION_ID, 0.0F);
+- this.entityData.define(DATA_SCORE_ID, 0);
+- this.entityData.define(DATA_PLAYER_MODE_CUSTOMISATION, (byte)0);
+- this.entityData.define(DATA_PLAYER_MAIN_HAND, (byte)DEFAULT_MAIN_HAND.getId());
+- this.entityData.define(DATA_SHOULDER_LEFT, new CompoundTag());
+- this.entityData.define(DATA_SHOULDER_RIGHT, new CompoundTag());
++ this.entityData.define(Player.DATA_PLAYER_ABSORPTION_ID, 0.0F);
++ this.entityData.define(Player.DATA_SCORE_ID, 0);
++ this.entityData.define(Player.DATA_PLAYER_MODE_CUSTOMISATION, (byte) 0);
++ this.entityData.define(Player.DATA_PLAYER_MAIN_HAND, (byte) Player.DEFAULT_MAIN_HAND.getId());
++ this.entityData.define(Player.DATA_SHOULDER_LEFT, new CompoundTag());
++ this.entityData.define(Player.DATA_SHOULDER_RIGHT, new CompoundTag());
+ }
+
+ @Override
+@@ -226,11 +240,11 @@
+ }
+
+ if (this.takeXpDelay > 0) {
+- this.takeXpDelay--;
++ --this.takeXpDelay;
+ }
+
+ if (this.isSleeping()) {
+- this.sleepCounter++;
++ ++this.sleepCounter;
+ if (this.sleepCounter > 100) {
+ this.sleepCounter = 100;
+ }
+@@ -239,7 +253,7 @@
+ this.stopSleepInBed(false, true);
+ }
+ } else if (this.sleepCounter > 0) {
+- this.sleepCounter++;
++ ++this.sleepCounter;
+ if (this.sleepCounter >= 110) {
+ this.sleepCounter = 0;
+ }
+@@ -271,20 +285,22 @@
+ }
+
+ int i = 29999999;
+- double d = Mth.clamp(this.getX(), -2.9999999E7, 2.9999999E7);
+- double d1 = Mth.clamp(this.getZ(), -2.9999999E7, 2.9999999E7);
+- if (d != this.getX() || d1 != this.getZ()) {
+- this.setPos(d, this.getY(), d1);
++ double d0 = Mth.clamp(this.getX(), -2.9999999E7D, 2.9999999E7D);
++ double d1 = Mth.clamp(this.getZ(), -2.9999999E7D, 2.9999999E7D);
++
++ if (d0 != this.getX() || d1 != this.getZ()) {
++ this.setPos(d0, this.getY(), d1);
+ }
+
+- this.attackStrengthTicker++;
+- ItemStack mainHandItem = this.getMainHandItem();
+- if (!ItemStack.matches(this.lastItemInMainHand, mainHandItem)) {
+- if (!ItemStack.isSameItem(this.lastItemInMainHand, mainHandItem)) {
++ ++this.attackStrengthTicker;
++ ItemStack itemstack = this.getMainHandItem();
++
++ if (!ItemStack.matches(this.lastItemInMainHand, itemstack)) {
++ if (!ItemStack.isSameItem(this.lastItemInMainHand, itemstack)) {
+ this.resetAttackStrengthTicker();
+ }
+
+- this.lastItemInMainHand = mainHandItem.copy();
++ this.lastItemInMainHand = itemstack.copy();
+ }
+
+ this.turtleHelmetTick();
+@@ -315,10 +331,12 @@
+ }
+
+ private void turtleHelmetTick() {
+- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.HEAD);
+- if (itemBySlot.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) {
+- this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true));
++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.HEAD);
++
++ if (itemstack.is(Items.TURTLE_HELMET) && !this.isEyeInFluid(FluidTags.WATER)) {
++ this.addEffect(new MobEffectInstance(MobEffects.WATER_BREATHING, 200, 0, false, false, true), org.bukkit.event.entity.EntityPotionEffectEvent.Cause.TURTLE_HELMET); // CraftBukkit
+ }
++
+ }
+
+ protected ItemCooldowns createItemCooldowns() {
+@@ -329,87 +347,87 @@
+ this.xCloakO = this.xCloak;
+ this.yCloakO = this.yCloak;
+ this.zCloakO = this.zCloak;
+- double d = this.getX() - this.xCloak;
++ double d0 = this.getX() - this.xCloak;
+ double d1 = this.getY() - this.yCloak;
+ double d2 = this.getZ() - this.zCloak;
+- double d3 = 10.0;
+- if (d > 10.0) {
++ double d3 = 10.0D;
++
++ if (d0 > 10.0D) {
+ this.xCloak = this.getX();
+ this.xCloakO = this.xCloak;
+ }
+
+- if (d2 > 10.0) {
++ if (d2 > 10.0D) {
+ this.zCloak = this.getZ();
+ this.zCloakO = this.zCloak;
+ }
+
+- if (d1 > 10.0) {
++ if (d1 > 10.0D) {
+ this.yCloak = this.getY();
+ this.yCloakO = this.yCloak;
+ }
+
+- if (d < -10.0) {
++ if (d0 < -10.0D) {
+ this.xCloak = this.getX();
+ this.xCloakO = this.xCloak;
+ }
+
+- if (d2 < -10.0) {
++ if (d2 < -10.0D) {
+ this.zCloak = this.getZ();
+ this.zCloakO = this.zCloak;
+ }
+
+- if (d1 < -10.0) {
++ if (d1 < -10.0D) {
+ this.yCloak = this.getY();
+ this.yCloakO = this.yCloak;
+ }
+
+- this.xCloak += d * 0.25;
+- this.zCloak += d2 * 0.25;
+- this.yCloak += d1 * 0.25;
++ this.xCloak += d0 * 0.25D;
++ this.zCloak += d2 * 0.25D;
++ this.yCloak += d1 * 0.25D;
+ }
+
+ protected void updatePlayerPose() {
+- if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.SWIMMING)) {
+- Pose pose;
++ if (this.canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose.SWIMMING)) {
++ EntityPose entitypose;
++
+ if (this.isFallFlying()) {
+- pose = Pose.FALL_FLYING;
++ entitypose = EntityPose.FALL_FLYING;
+ } else if (this.isSleeping()) {
+- pose = Pose.SLEEPING;
++ entitypose = EntityPose.SLEEPING;
+ } else if (this.isSwimming()) {
+- pose = Pose.SWIMMING;
++ entitypose = EntityPose.SWIMMING;
+ } else if (this.isAutoSpinAttack()) {
+- pose = Pose.SPIN_ATTACK;
++ entitypose = EntityPose.SPIN_ATTACK;
+ } else if (this.isShiftKeyDown() && !this.abilities.flying) {
+- pose = Pose.CROUCHING;
++ entitypose = EntityPose.CROUCHING;
+ } else {
+- pose = Pose.STANDING;
++ entitypose = EntityPose.STANDING;
+ }
+
+- Pose pose1;
+- if (this.isSpectator() || this.isPassenger() || this.canPlayerFitWithinBlocksAndEntitiesWhen(pose)) {
+- pose1 = pose;
+- } else if (this.canPlayerFitWithinBlocksAndEntitiesWhen(Pose.CROUCHING)) {
+- pose1 = Pose.CROUCHING;
++ EntityPose entitypose1;
++
++ if (!this.isSpectator() && !this.isPassenger() && !this.canPlayerFitWithinBlocksAndEntitiesWhen(entitypose)) {
++ if (this.canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose.CROUCHING)) {
++ entitypose1 = EntityPose.CROUCHING;
++ } else {
++ entitypose1 = EntityPose.SWIMMING;
++ }
+ } else {
+- pose1 = Pose.SWIMMING;
++ entitypose1 = entitypose;
+ }
+
+- this.setPose(pose1);
++ this.setPose(entitypose1);
+ }
+ }
+
+- protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(Pose pose) {
+- return this.level().noCollision(this, this.getDimensions(pose).makeBoundingBox(this.position()).deflate(1.0E-7));
++ protected boolean canPlayerFitWithinBlocksAndEntitiesWhen(EntityPose entitypose) {
++ return this.level().noCollision(this, this.getDimensions(entitypose).makeBoundingBox(this.position()).deflate(1.0E-7D));
+ }
+
+ @Override
+ public int getPortalWaitTime() {
+- return Math.max(
+- 1,
+- this.level()
+- .getGameRules()
+- .getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY)
+- );
++ return Math.max(1, this.level().getGameRules().getInt(this.abilities.invulnerable ? GameRules.RULE_PLAYERS_NETHER_PORTAL_CREATIVE_DELAY : GameRules.RULE_PLAYERS_NETHER_PORTAL_DEFAULT_DELAY));
+ }
+
+ @Override
+@@ -437,8 +455,7 @@
+ this.level().playSound(this, this.getX(), this.getY(), this.getZ(), sound, this.getSoundSource(), volume, pitch);
+ }
+
+- public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) {
+- }
++ public void playNotifySound(SoundEvent sound, SoundSource source, float volume, float pitch) {}
+
+ @Override
+ public SoundSource getSoundSource() {
+@@ -446,7 +463,7 @@
+ }
+
+ @Override
+- protected int getFireImmuneTicks() {
++ public int getFireImmuneTicks() {
+ return 20;
+ }
+
+@@ -463,30 +480,38 @@
+ } else {
+ super.handleEntityEvent(id);
+ }
++
+ }
+
+ private void addParticlesAroundSelf(ParticleOptions particleOption) {
+- for (int i = 0; i < 5; i++) {
+- double d = this.random.nextGaussian() * 0.02;
+- double d1 = this.random.nextGaussian() * 0.02;
+- double d2 = this.random.nextGaussian() * 0.02;
+- this.level().addParticle(particleOption, this.getRandomX(1.0), this.getRandomY() + 1.0, this.getRandomZ(1.0), d, d1, d2);
++ for (int i = 0; i < 5; ++i) {
++ double d0 = this.random.nextGaussian() * 0.02D;
++ double d1 = this.random.nextGaussian() * 0.02D;
++ double d2 = this.random.nextGaussian() * 0.02D;
++
++ this.level().addParticle(particleOption, this.getRandomX(1.0D), this.getRandomY() + 1.0D, this.getRandomZ(1.0D), d0, d1, d2);
+ }
++
+ }
+
+- protected void closeContainer() {
++ public void closeContainer() {
+ this.containerMenu = this.inventoryMenu;
+ }
+
+- protected void doCloseContainer() {
+- }
++ protected void doCloseContainer() {}
+
+ @Override
+ public void rideTick() {
+ if (!this.level().isClientSide && this.wantsToStopRiding() && this.isPassenger()) {
+ this.stopRiding();
+- this.setShiftKeyDown(false);
+- } else {
++ // CraftBukkit start - SPIGOT-7316: no longer passenger, dismount and return
++ if (!this.isPassenger()) {
++ this.setShiftKeyDown(false);
++ return;
++ }
++ }
++ {
++ // CraftBukkit end
+ super.rideTick();
+ this.oBob = this.bob;
+ this.bob = 0.0F;
+@@ -503,12 +528,13 @@
+ @Override
+ public void aiStep() {
+ if (this.jumpTriggerTime > 0) {
+- this.jumpTriggerTime--;
++ --this.jumpTriggerTime;
+ }
+
+ if (this.level().getDifficulty() == Difficulty.PEACEFUL && this.level().getGameRules().getBoolean(GameRules.RULE_NATURAL_REGENERATION)) {
+ if (this.getHealth() < this.getMaxHealth() && this.tickCount % 20 == 0) {
+- this.heal(1.0F);
++ // CraftBukkit - added regain reason of "REGEN" for filtering purposes.
++ this.heal(1.0F, org.bukkit.event.entity.EntityRegainHealthEvent.RegainReason.REGEN);
+ }
+
+ if (this.foodData.needsFood() && this.tickCount % 10 == 0) {
+@@ -519,36 +545,41 @@
+ this.inventory.tick();
+ this.oBob = this.bob;
+ super.aiStep();
+- this.setSpeed((float)this.getAttributeValue(Attributes.MOVEMENT_SPEED));
++ this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED));
+ float f;
++
+ if (this.onGround() && !this.isDeadOrDying() && !this.isSwimming()) {
+- f = Math.min(0.1F, (float)this.getDeltaMovement().horizontalDistance());
++ f = Math.min(0.1F, (float) this.getDeltaMovement().horizontalDistance());
+ } else {
+ f = 0.0F;
+ }
+
+- this.bob = this.bob + (f - this.bob) * 0.4F;
++ this.bob += (f - this.bob) * 0.4F;
+ if (this.getHealth() > 0.0F && !this.isSpectator()) {
+- AABB aABB;
++ AABB axisalignedbb;
++
+ if (this.isPassenger() && !this.getVehicle().isRemoved()) {
+- aABB = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0, 0.0, 1.0);
++ axisalignedbb = this.getBoundingBox().minmax(this.getVehicle().getBoundingBox()).inflate(1.0D, 0.0D, 1.0D);
+ } else {
+- aABB = this.getBoundingBox().inflate(1.0, 0.5, 1.0);
++ axisalignedbb = this.getBoundingBox().inflate(1.0D, 0.5D, 1.0D);
+ }
+
+- List<Entity> entities = this.level().getEntities(this, aABB);
+- List<Entity> list = Lists.newArrayList();
++ List<Entity> list = this.level().getEntities(this, axisalignedbb);
++ List<Entity> list1 = Lists.newArrayList();
++ Iterator iterator = list.iterator();
+
+- for (Entity entity : entities) {
++ while (iterator.hasNext()) {
++ Entity entity = (Entity) iterator.next();
++
+ if (entity.getType() == EntityType.EXPERIENCE_ORB) {
+- list.add(entity);
++ list1.add(entity);
+ } else if (!entity.isRemoved()) {
+ this.touch(entity);
+ }
+ }
+
+- if (!list.isEmpty()) {
+- this.touch(Util.getRandom(list, this.random));
++ if (!list1.isEmpty()) {
++ this.touch((Entity) Util.getRandom((List) list1, this.random));
+ }
+ }
+
+@@ -557,31 +588,23 @@
+ if (!this.level().isClientSide && (this.fallDistance > 0.5F || this.isInWater()) || this.abilities.flying || this.isSleeping() || this.isInPowderSnow) {
+ this.removeEntitiesOnShoulder();
+ }
++
+ }
+
+ private void playShoulderEntityAmbientSound(@Nullable CompoundTag entityCompound) {
+ if (entityCompound != null && (!entityCompound.contains("Silent") || !entityCompound.getBoolean("Silent")) && this.level().random.nextInt(200) == 0) {
+- String string = entityCompound.getString("id");
+- EntityType.byString(string)
+- .filter(entityType -> entityType == EntityType.PARROT)
+- .ifPresent(
+- entityType -> {
+- if (!Parrot.imitateNearbyMobs(this.level(), this)) {
+- this.level()
+- .playSound(
+- null,
+- this.getX(),
+- this.getY(),
+- this.getZ(),
+- Parrot.getAmbient(this.level(), this.level().random),
+- this.getSoundSource(),
+- 1.0F,
+- Parrot.getPitch(this.level().random)
+- );
+- }
+- }
+- );
++ String s = entityCompound.getString("id");
++
++ EntityType.byString(s).filter((entitytypes) -> {
++ return entitytypes == EntityType.PARROT;
++ }).ifPresent((entitytypes) -> {
++ if (!Parrot.imitateNearbyMobs(this.level(), this)) {
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), Parrot.getAmbient(this.level(), this.level().random), this.getSoundSource(), 1.0F, Parrot.getPitch(this.level().random));
++ }
++
++ });
+ }
++
+ }
+
+ private void touch(Entity entity) {
+@@ -589,16 +612,17 @@
+ }
+
+ public int getScore() {
+- return this.entityData.get(DATA_SCORE_ID);
++ return (Integer) this.entityData.get(Player.DATA_SCORE_ID);
+ }
+
+ public void setScore(int score) {
+- this.entityData.set(DATA_SCORE_ID, score);
++ this.entityData.set(Player.DATA_SCORE_ID, score);
+ }
+
+ public void increaseScore(int score) {
+- int score1 = this.getScore();
+- this.entityData.set(DATA_SCORE_ID, score1 + score);
++ int j = this.getScore();
++
++ this.entityData.set(Player.DATA_SCORE_ID, j + score);
+ }
+
+ public void startAutoSpinAttack(int attackTicks) {
+@@ -607,6 +631,7 @@
+ this.removeEntitiesOnShoulder();
+ this.setLivingEntityFlag(4, true);
+ }
++
+ }
+
+ @Override
+@@ -618,13 +643,9 @@
+ }
+
+ if (cause != null) {
+- this.setDeltaMovement(
+- (double)(-Mth.cos((this.getHurtDir() + this.getYRot()) * (float) (Math.PI / 180.0)) * 0.1F),
+- 0.1F,
+- (double)(-Mth.sin((this.getHurtDir() + this.getYRot()) * (float) (Math.PI / 180.0)) * 0.1F)
+- );
++ this.setDeltaMovement((double) (-Mth.cos((this.getHurtDir() + this.getYRot()) * 0.017453292F) * 0.1F), 0.10000000149011612D, (double) (-Mth.sin((this.getHurtDir() + this.getYRot()) * 0.017453292F) * 0.1F));
+ } else {
+- this.setDeltaMovement(0.0, 0.1, 0.0);
++ this.setDeltaMovement(0.0D, 0.1D, 0.0D);
+ }
+
+ this.awardStat(Stats.DEATHS);
+@@ -642,15 +663,18 @@
+ this.destroyVanishingCursedItems();
+ this.inventory.dropAll();
+ }
++
+ }
+
+ protected void destroyVanishingCursedItems() {
+- for (int i = 0; i < this.inventory.getContainerSize(); i++) {
+- ItemStack item = this.inventory.getItem(i);
+- if (!item.isEmpty() && EnchantmentHelper.hasVanishingCurse(item)) {
++ for (int i = 0; i < this.inventory.getContainerSize(); ++i) {
++ ItemStack itemstack = this.inventory.getItem(i);
++
++ if (!itemstack.isEmpty() && EnchantmentHelper.hasVanishingCurse(itemstack)) {
+ this.inventory.removeItemNoUpdate(i);
+ }
+ }
++
+ }
+
+ @Override
+@@ -670,78 +694,127 @@
+
+ @Nullable
+ public ItemEntity drop(ItemStack droppedItem, boolean dropAround, boolean includeThrowerName) {
+- if (droppedItem.isEmpty()) {
++ // CraftBukkit start - SPIGOT-2942: Add boolean to call event
++ return drop(droppedItem, dropAround, includeThrowerName, true);
++ }
++
++ @Nullable
++ public ItemEntity drop(ItemStack itemstack, boolean flag, boolean flag1, boolean callEvent) {
++ // CraftBukkit end
++ if (itemstack.isEmpty()) {
+ return null;
+ } else {
+ if (this.level().isClientSide) {
+- this.swing(InteractionHand.MAIN_HAND);
++ this.swing(EnumHand.MAIN_HAND);
+ }
+
+- double d = this.getEyeY() - 0.3F;
+- ItemEntity itemEntity = new ItemEntity(this.level(), this.getX(), d, this.getZ(), droppedItem);
+- itemEntity.setPickUpDelay(40);
+- if (includeThrowerName) {
+- itemEntity.setThrower(this);
++ double d0 = this.getEyeY() - 0.30000001192092896D;
++ ItemEntity entityitem = new ItemEntity(this.level(), this.getX(), d0, this.getZ(), itemstack);
++
++ entityitem.setPickUpDelay(40);
++ if (flag1) {
++ entityitem.setThrower(this);
+ }
+
+- if (dropAround) {
+- float f = this.random.nextFloat() * 0.5F;
+- float f1 = this.random.nextFloat() * (float) (Math.PI * 2);
+- itemEntity.setDeltaMovement((double)(-Mth.sin(f1) * f), 0.2F, (double)(Mth.cos(f1) * f));
++ float f;
++ float f1;
++
++ if (flag) {
++ f = this.random.nextFloat() * 0.5F;
++ f1 = this.random.nextFloat() * 6.2831855F;
++ entityitem.setDeltaMovement((double) (-Mth.sin(f1) * f), 0.20000000298023224D, (double) (Mth.cos(f1) * f));
+ } else {
+- float f = 0.3F;
+- float f1 = Mth.sin(this.getXRot() * (float) (Math.PI / 180.0));
+- float cos = Mth.cos(this.getXRot() * (float) (Math.PI / 180.0));
+- float sin = Mth.sin(this.getYRot() * (float) (Math.PI / 180.0));
+- float cos1 = Mth.cos(this.getYRot() * (float) (Math.PI / 180.0));
+- float f2 = this.random.nextFloat() * (float) (Math.PI * 2);
+- float f3 = 0.02F * this.random.nextFloat();
+- itemEntity.setDeltaMovement(
+- (double)(-sin * cos * 0.3F) + Math.cos((double)f2) * (double)f3,
+- (double)(-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F),
+- (double)(cos1 * cos * 0.3F) + Math.sin((double)f2) * (double)f3
+- );
++ f = 0.3F;
++ f1 = Mth.sin(this.getXRot() * 0.017453292F);
++ float f2 = Mth.cos(this.getXRot() * 0.017453292F);
++ float f3 = Mth.sin(this.getYRot() * 0.017453292F);
++ float f4 = Mth.cos(this.getYRot() * 0.017453292F);
++ float f5 = this.random.nextFloat() * 6.2831855F;
++ float f6 = 0.02F * this.random.nextFloat();
++
++ entityitem.setDeltaMovement((double) (-f3 * f2 * 0.3F) + Math.cos((double) f5) * (double) f6, (double) (-f1 * 0.3F + 0.1F + (this.random.nextFloat() - this.random.nextFloat()) * 0.1F), (double) (f4 * f2 * 0.3F) + Math.sin((double) f5) * (double) f6);
+ }
+
+- return itemEntity;
++ // CraftBukkit start - fire PlayerDropItemEvent
++ if (!callEvent) { // SPIGOT-2942: Add boolean to call event
++ return entityitem;
++ }
++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) this.getBukkitEntity();
++ Item drop = (Item) entityitem.getBukkitEntity();
++
++ PlayerDropItemEvent event = new PlayerDropItemEvent(player, drop);
++ this.level().getCraftServer().getPluginManager().callEvent(event);
++
++ if (event.isCancelled()) {
++ org.bukkit.inventory.ItemStack cur = player.getInventory().getItemInHand();
++ if (flag1 && (cur == null || cur.getAmount() == 0)) {
++ // The complete stack was dropped
++ player.getInventory().setItemInHand(drop.getItemStack());
++ } else if (flag1 && cur.isSimilar(drop.getItemStack()) && cur.getAmount() < cur.getMaxStackSize() && drop.getItemStack().getAmount() == 1) {
++ // Only one item is dropped
++ cur.setAmount(cur.getAmount() + 1);
++ player.getInventory().setItemInHand(cur);
++ } else {
++ // Fallback
++ player.getInventory().addItem(drop.getItemStack());
++ }
++ return null;
++ }
++ // CraftBukkit end
++
++ return entityitem;
+ }
+ }
+
+- public float getDestroySpeed(BlockState state) {
+- float destroySpeed = this.inventory.getDestroySpeed(state);
+- if (destroySpeed > 1.0F) {
+- int blockEfficiency = EnchantmentHelper.getBlockEfficiency(this);
+- ItemStack mainHandItem = this.getMainHandItem();
+- if (blockEfficiency > 0 && !mainHandItem.isEmpty()) {
+- destroySpeed += (float)(blockEfficiency * blockEfficiency + 1);
++ public float getDestroySpeed(IBlockData state) {
++ float f = this.inventory.getDestroySpeed(state);
++
++ if (f > 1.0F) {
++ int i = EnchantmentHelper.getBlockEfficiency(this);
++ ItemStack itemstack = this.getMainHandItem();
++
++ if (i > 0 && !itemstack.isEmpty()) {
++ f += (float) (i * i + 1);
+ }
+ }
+
+ if (MobEffectUtil.hasDigSpeed(this)) {
+- destroySpeed *= 1.0F + (float)(MobEffectUtil.getDigSpeedAmplification(this) + 1) * 0.2F;
++ f *= 1.0F + (float) (MobEffectUtil.getDigSpeedAmplification(this) + 1) * 0.2F;
+ }
+
+ if (this.hasEffect(MobEffects.DIG_SLOWDOWN)) {
+- destroySpeed *= switch (this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) {
+- case 0 -> 0.3F;
+- case 1 -> 0.09F;
+- case 2 -> 0.0027F;
+- default -> 8.1E-4F;
+- };
++ float f1;
++
++ switch (this.getEffect(MobEffects.DIG_SLOWDOWN).getAmplifier()) {
++ case 0:
++ f1 = 0.3F;
++ break;
++ case 1:
++ f1 = 0.09F;
++ break;
++ case 2:
++ f1 = 0.0027F;
++ break;
++ case 3:
++ default:
++ f1 = 8.1E-4F;
++ }
++
++ f *= f1;
+ }
+
+ if (this.isEyeInFluid(FluidTags.WATER) && !EnchantmentHelper.hasAquaAffinity(this)) {
+- destroySpeed /= 5.0F;
++ f /= 5.0F;
+ }
+
+ if (!this.onGround()) {
+- destroySpeed /= 5.0F;
++ f /= 5.0F;
+ }
+
+- return destroySpeed;
++ return f;
+ }
+
+- public boolean hasCorrectToolForDrops(BlockState state) {
++ public boolean hasCorrectToolForDrops(IBlockData state) {
+ return !state.requiresCorrectToolForDrops() || this.inventory.getSelected().isCorrectToolForDrops(state);
+ }
+
+@@ -749,8 +822,9 @@
+ public void readAdditionalSaveData(CompoundTag compound) {
+ super.readAdditionalSaveData(compound);
+ this.setUUID(this.gameProfile.getId());
+- ListTag list = compound.getList("Inventory", 10);
+- this.inventory.load(list);
++ ListTag nbttaglist = compound.getList("Inventory", 10);
++
++ this.inventory.load(nbttaglist);
+ this.inventory.selected = compound.getInt("SelectedItemSlot");
+ this.sleepCounter = compound.getShort("SleepTimer");
+ this.experienceProgress = compound.getFloat("XpP");
+@@ -764,7 +838,7 @@
+ this.setScore(compound.getInt("Score"));
+ this.foodData.readAdditionalSaveData(compound);
+ this.abilities.loadSaveData(compound);
+- this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double)this.abilities.getWalkingSpeed());
++ this.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue((double) this.abilities.getWalkingSpeed());
+ if (compound.contains("EnderItems", 9)) {
+ this.enderChestInventory.fromTag(compound.getList("EnderItems", 10));
+ }
+@@ -778,8 +852,13 @@
+ }
+
+ if (compound.contains("LastDeathLocation", 10)) {
+- this.setLastDeathLocation(GlobalPos.CODEC.parse(NbtOps.INSTANCE, compound.get("LastDeathLocation")).resultOrPartial(LOGGER::error));
++ DataResult<GlobalPos> dataresult = GlobalPos.CODEC.parse(NbtOps.INSTANCE, compound.get("LastDeathLocation")); // CraftBukkit - decompile error
++ Logger logger = Player.LOGGER;
++
++ Objects.requireNonNull(logger);
++ this.setLastDeathLocation(dataresult.resultOrPartial(logger::error));
+ }
++
+ }
+
+ @Override
+@@ -788,7 +867,7 @@
+ NbtUtils.addCurrentDataVersion(compound);
+ compound.put("Inventory", this.inventory.save(new ListTag()));
+ compound.putInt("SelectedItemSlot", this.inventory.selected);
+- compound.putShort("SleepTimer", (short)this.sleepCounter);
++ compound.putShort("SleepTimer", (short) this.sleepCounter);
+ compound.putFloat("XpP", this.experienceProgress);
+ compound.putInt("XpLevel", this.experienceLevel);
+ compound.putInt("XpTotal", this.totalExperience);
+@@ -805,24 +884,20 @@
+ compound.put("ShoulderEntityRight", this.getShoulderEntityRight());
+ }
+
+- this.getLastDeathLocation()
+- .flatMap(globalPos -> GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, globalPos).resultOrPartial(LOGGER::error))
+- .ifPresent(tag -> compound.put("LastDeathLocation", tag));
++ this.getLastDeathLocation().flatMap((globalpos) -> {
++ DataResult<Tag> dataresult = GlobalPos.CODEC.encodeStart(NbtOps.INSTANCE, globalpos); // CraftBukkit - decompile error
++ Logger logger = Player.LOGGER;
++
++ Objects.requireNonNull(logger);
++ return dataresult.resultOrPartial(logger::error);
++ }).ifPresent((nbtbase) -> {
++ compound.put("LastDeathLocation", nbtbase);
++ });
+ }
+
+ @Override
+ public boolean isInvulnerableTo(DamageSource source) {
+- if (super.isInvulnerableTo(source)) {
+- return true;
+- } else if (source.is(DamageTypeTags.IS_DROWNING)) {
+- return !this.level().getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE);
+- } else if (source.is(DamageTypeTags.IS_FALL)) {
+- return !this.level().getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE);
+- } else {
+- return source.is(DamageTypeTags.IS_FIRE)
+- ? !this.level().getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE)
+- : source.is(DamageTypeTags.IS_FREEZING) && !this.level().getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE);
+- }
++ return super.isInvulnerableTo(source) ? true : (source.is(DamageTypeTags.IS_DROWNING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_DROWNING_DAMAGE) : (source.is(DamageTypeTags.IS_FALL) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FALL_DAMAGE) : (source.is(DamageTypeTags.IS_FIRE) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FIRE_DAMAGE) : (source.is(DamageTypeTags.IS_FREEZING) ? !this.level().getGameRules().getBoolean(GameRules.RULE_FREEZE_DAMAGE) : false))));
+ }
+
+ @Override
+@@ -837,12 +912,12 @@
+ return false;
+ } else {
+ if (!this.level().isClientSide) {
+- this.removeEntitiesOnShoulder();
++ // this.removeEntitiesOnShoulder(); // CraftBukkit - moved down
+ }
+
+ if (source.scalesWithDifficulty()) {
+ if (this.level().getDifficulty() == Difficulty.PEACEFUL) {
+- amount = 0.0F;
++ return false; // CraftBukkit - f = 0.0f -> return false
+ }
+
+ if (this.level().getDifficulty() == Difficulty.EASY) {
+@@ -854,7 +929,13 @@
+ }
+ }
+
+- return amount != 0.0F && super.hurt(source, amount);
++ // CraftBukkit start - Don't filter out 0 damage
++ boolean damaged = super.hurt(source, amount);
++ if (damaged) {
++ this.removeEntitiesOnShoulder();
++ }
++ return damaged;
++ // CraftBukkit end
+ }
+ }
+ }
+@@ -865,6 +946,7 @@
+ if (entity.canDisableShield()) {
+ this.disableShield(true);
+ }
++
+ }
+
+ @Override
+@@ -873,9 +955,29 @@
+ }
+
+ public boolean canHarmPlayer(Player other) {
+- Team team = this.getTeam();
+- Team team1 = other.getTeam();
+- return team == null || !team.isAlliedTo(team1) || team.isAllowFriendlyFire();
++ // CraftBukkit start - Change to check OTHER player's scoreboard team according to API
++ // To summarize this method's logic, it's "Can parameter hurt this"
++ org.bukkit.scoreboard.Team team;
++ if (other instanceof ServerPlayer) {
++ ServerPlayer thatPlayer = (ServerPlayer) other;
++ team = thatPlayer.getBukkitEntity().getScoreboard().getPlayerTeam(thatPlayer.getBukkitEntity());
++ if (team == null || team.allowFriendlyFire()) {
++ return true;
++ }
++ } else {
++ // This should never be called, but is implemented anyway
++ org.bukkit.OfflinePlayer thisPlayer = other.level().getCraftServer().getOfflinePlayer(other.getScoreboardName());
++ team = other.level().getCraftServer().getScoreboardManager().getMainScoreboard().getPlayerTeam(thisPlayer);
++ if (team == null || team.allowFriendlyFire()) {
++ return true;
++ }
++ }
++
++ if (this instanceof ServerPlayer) {
++ return !team.hasPlayer(((ServerPlayer) this).getBukkitEntity());
++ }
++ return !team.hasPlayer(this.level().getCraftServer().getOfflinePlayer(this.getScoreboardName()));
++ // CraftBukkit end
+ }
+
+ @Override
+@@ -897,10 +999,13 @@
+
+ if (damage >= 3.0F) {
+ int i = 1 + Mth.floor(damage);
+- InteractionHand usedItemHand = this.getUsedItemHand();
+- this.useItem.hurtAndBreak(i, this, player -> player.broadcastBreakEvent(usedItemHand));
++ EnumHand enumhand = this.getUsedItemHand();
++
++ this.useItem.hurtAndBreak(i, this, (entityhuman) -> {
++ entityhuman.broadcastBreakEvent(enumhand);
++ });
+ if (this.useItem.isEmpty()) {
+- if (usedItemHand == InteractionHand.MAIN_HAND) {
++ if (enumhand == EnumHand.MAIN_HAND) {
+ this.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
+ } else {
+ this.setItemSlot(EquipmentSlot.OFFHAND, ItemStack.EMPTY);
+@@ -910,32 +1015,42 @@
+ this.playSound(SoundEvents.SHIELD_BREAK, 0.8F, 0.8F + this.level().random.nextFloat() * 0.4F);
+ }
+ }
++
+ }
+ }
+
++ // CraftBukkit start
+ @Override
+- protected void actuallyHurt(DamageSource damageSrc, float damageAmount) {
+- if (!this.isInvulnerableTo(damageSrc)) {
+- damageAmount = this.getDamageAfterArmorAbsorb(damageSrc, damageAmount);
+- damageAmount = this.getDamageAfterMagicAbsorb(damageSrc, damageAmount);
+- float var7 = Math.max(damageAmount - this.getAbsorptionAmount(), 0.0F);
+- this.setAbsorptionAmount(this.getAbsorptionAmount() - (damageAmount - var7));
+- float f1 = damageAmount - var7;
+- if (f1 > 0.0F && f1 < 3.4028235E37F) {
+- this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f1 * 10.0F));
++ protected boolean damageEntity0(DamageSource damagesource, float f) { // void -> boolean
++ if (true) {
++ return super.damageEntity0(damagesource, f);
++ }
++ // CraftBukkit end
++ if (!this.isInvulnerableTo(damagesource)) {
++ f = this.getDamageAfterArmorAbsorb(damagesource, f);
++ f = this.getDamageAfterMagicAbsorb(damagesource, f);
++ float f1 = f;
++
++ f = Math.max(f - this.getAbsorptionAmount(), 0.0F);
++ this.setAbsorptionAmount(this.getAbsorptionAmount() - (f1 - f));
++ float f2 = f1 - f;
++
++ if (f2 > 0.0F && f2 < 3.4028235E37F) {
++ this.awardStat(Stats.DAMAGE_ABSORBED, Math.round(f2 * 10.0F));
+ }
+
+- if (var7 != 0.0F) {
+- this.causeFoodExhaustion(damageSrc.getFoodExhaustion());
+- this.getCombatTracker().recordDamage(damageSrc, var7);
+- this.setHealth(this.getHealth() - var7);
+- if (var7 < 3.4028235E37F) {
+- this.awardStat(Stats.DAMAGE_TAKEN, Math.round(var7 * 10.0F));
++ if (f != 0.0F) {
++ this.causeFoodExhaustion(damagesource.getFoodExhaustion(), EntityExhaustionEvent.ExhaustionReason.DAMAGED); // CraftBukkit - EntityExhaustionEvent
++ this.getCombatTracker().recordDamage(damagesource, f);
++ this.setHealth(this.getHealth() - f);
++ if (f < 3.4028235E37F) {
++ this.awardStat(Stats.DAMAGE_TAKEN, Math.round(f * 10.0F));
+ }
+
+ this.gameEvent(GameEvent.ENTITY_DAMAGE);
+ }
+ }
++ return false; // CraftBukkit
+ }
+
+ @Override
+@@ -947,65 +1062,59 @@
+ return false;
+ }
+
+- public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) {
+- }
++ public void openTextEdit(SignBlockEntity signEntity, boolean isFrontText) {}
+
+- public void openMinecartCommandBlock(BaseCommandBlock commandEntity) {
+- }
++ public void openMinecartCommandBlock(BaseCommandBlock commandEntity) {}
+
+- public void openCommandBlock(CommandBlockEntity commandBlockEntity) {
+- }
++ public void openCommandBlock(CommandBlockEntity commandBlockEntity) {}
+
+- public void openStructureBlock(StructureBlockEntity structureEntity) {
+- }
++ public void openStructureBlock(StructureBlockEntity structureEntity) {}
+
+- public void openJigsawBlock(JigsawBlockEntity jigsawBlockEntity) {
+- }
++ public void openJigsawBlock(JigsawBlockEntity jigsawBlockEntity) {}
+
+- public void openHorseInventory(AbstractHorse horse, Container inventory) {
+- }
++ public void openHorseInventory(AbstractHorse horse, Container inventory) {}
+
+- public OptionalInt openMenu(@Nullable MenuProvider menu) {
++ public OptionalInt openMenu(@Nullable ITileInventory menu) {
+ return OptionalInt.empty();
+ }
+
+- public void sendMerchantOffers(int containerId, MerchantOffers offers, int villagerLevel, int villagerXp, boolean showProgress, boolean canRestock) {
+- }
++ public void sendMerchantOffers(int containerId, MerchantOffers offers, int villagerLevel, int villagerXp, boolean showProgress, boolean canRestock) {}
+
+- public void openItemGui(ItemStack stack, InteractionHand hand) {
+- }
++ public void openItemGui(ItemStack stack, EnumHand hand) {}
+
+- public InteractionResult interactOn(Entity entityToInteractOn, InteractionHand hand) {
++ public InteractionResult interactOn(Entity entityToInteractOn, EnumHand hand) {
+ if (this.isSpectator()) {
+- if (entityToInteractOn instanceof MenuProvider) {
+- this.openMenu((MenuProvider)entityToInteractOn);
++ if (entityToInteractOn instanceof ITileInventory) {
++ this.openMenu((ITileInventory) entityToInteractOn);
+ }
+
+ return InteractionResult.PASS;
+ } else {
+- ItemStack itemInHand = this.getItemInHand(hand);
+- ItemStack itemStack = itemInHand.copy();
+- InteractionResult interactionResult = entityToInteractOn.interact(this, hand);
+- if (interactionResult.consumesAction()) {
+- if (this.abilities.instabuild && itemInHand == this.getItemInHand(hand) && itemInHand.getCount() < itemStack.getCount()) {
+- itemInHand.setCount(itemStack.getCount());
++ ItemStack itemstack = this.getItemInHand(hand);
++ ItemStack itemstack1 = itemstack.copy();
++ InteractionResult enuminteractionresult = entityToInteractOn.interact(this, hand);
++
++ if (enuminteractionresult.consumesAction()) {
++ if (this.abilities.instabuild && itemstack == this.getItemInHand(hand) && itemstack.getCount() < itemstack1.getCount()) {
++ itemstack.setCount(itemstack1.getCount());
+ }
+
+- return interactionResult;
++ return enuminteractionresult;
+ } else {
+- if (!itemInHand.isEmpty() && entityToInteractOn instanceof LivingEntity) {
++ if (!itemstack.isEmpty() && entityToInteractOn instanceof LivingEntity) {
+ if (this.abilities.instabuild) {
+- itemInHand = itemStack;
++ itemstack = itemstack1;
+ }
+
+- InteractionResult interactionResult1 = itemInHand.interactLivingEntity(this, (LivingEntity)entityToInteractOn, hand);
+- if (interactionResult1.consumesAction()) {
+- this.level().gameEvent(GameEvent.ENTITY_INTERACT, entityToInteractOn.position(), GameEvent.Context.of(this));
+- if (itemInHand.isEmpty() && !this.abilities.instabuild) {
++ InteractionResult enuminteractionresult1 = itemstack.interactLivingEntity(this, (LivingEntity) entityToInteractOn, hand);
++
++ if (enuminteractionresult1.consumesAction()) {
++ this.level().gameEvent(GameEvent.ENTITY_INTERACT, entityToInteractOn.position(), GameEvent.Context.of((Entity) this));
++ if (itemstack.isEmpty() && !this.abilities.instabuild) {
+ this.setItemInHand(hand, ItemStack.EMPTY);
+ }
+
+- return interactionResult1;
++ return enuminteractionresult1;
+ }
+ }
+
+@@ -1036,242 +1145,259 @@
+ }
+
+ @Override
+- protected Vec3 maybeBackOffFromEdge(Vec3 vec, MoverType mover) {
+- if (!this.abilities.flying
+- && vec.y <= 0.0
+- && (mover == MoverType.SELF || mover == MoverType.PLAYER)
+- && this.isStayingOnGroundSurface()
+- && this.isAboveGround()) {
+- double d = vec.x;
++ protected Vec3 maybeBackOffFromEdge(Vec3 vec, EnumMoveType mover) {
++ if (!this.abilities.flying && vec.y <= 0.0D && (mover == EnumMoveType.SELF || mover == EnumMoveType.PLAYER) && this.isStayingOnGroundSurface() && this.isAboveGround()) {
++ double d0 = vec.x;
+ double d1 = vec.z;
+- double d2 = 0.05;
++ double d2 = 0.05D;
+
+- while (d != 0.0 && this.level().noCollision(this, this.getBoundingBox().move(d, (double)(-this.maxUpStep()), 0.0))) {
+- if (d < 0.05 && d >= -0.05) {
+- d = 0.0;
+- } else if (d > 0.0) {
+- d -= 0.05;
++ while (d0 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(d0, (double) (-this.maxUpStep()), 0.0D))) {
++ if (d0 < 0.05D && d0 >= -0.05D) {
++ d0 = 0.0D;
++ } else if (d0 > 0.0D) {
++ d0 -= 0.05D;
+ } else {
+- d += 0.05;
++ d0 += 0.05D;
+ }
+ }
+
+- while (d1 != 0.0 && this.level().noCollision(this, this.getBoundingBox().move(0.0, (double)(-this.maxUpStep()), d1))) {
+- if (d1 < 0.05 && d1 >= -0.05) {
+- d1 = 0.0;
+- } else if (d1 > 0.0) {
+- d1 -= 0.05;
++ while (d1 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(0.0D, (double) (-this.maxUpStep()), d1))) {
++ if (d1 < 0.05D && d1 >= -0.05D) {
++ d1 = 0.0D;
++ } else if (d1 > 0.0D) {
++ d1 -= 0.05D;
+ } else {
+- d1 += 0.05;
++ d1 += 0.05D;
+ }
+ }
+
+- while (d != 0.0 && d1 != 0.0 && this.level().noCollision(this, this.getBoundingBox().move(d, (double)(-this.maxUpStep()), d1))) {
+- if (d < 0.05 && d >= -0.05) {
+- d = 0.0;
+- } else if (d > 0.0) {
+- d -= 0.05;
++ while (d0 != 0.0D && d1 != 0.0D && this.level().noCollision(this, this.getBoundingBox().move(d0, (double) (-this.maxUpStep()), d1))) {
++ if (d0 < 0.05D && d0 >= -0.05D) {
++ d0 = 0.0D;
++ } else if (d0 > 0.0D) {
++ d0 -= 0.05D;
+ } else {
+- d += 0.05;
++ d0 += 0.05D;
+ }
+
+- if (d1 < 0.05 && d1 >= -0.05) {
+- d1 = 0.0;
+- } else if (d1 > 0.0) {
+- d1 -= 0.05;
++ if (d1 < 0.05D && d1 >= -0.05D) {
++ d1 = 0.0D;
++ } else if (d1 > 0.0D) {
++ d1 -= 0.05D;
+ } else {
+- d1 += 0.05;
++ d1 += 0.05D;
+ }
+ }
+
+- vec = new Vec3(d, vec.y, d1);
++ vec = new Vec3(d0, vec.y, d1);
+ }
+
+ return vec;
+ }
+
+ private boolean isAboveGround() {
+- return this.onGround()
+- || this.fallDistance < this.maxUpStep()
+- && !this.level().noCollision(this, this.getBoundingBox().move(0.0, (double)(this.fallDistance - this.maxUpStep()), 0.0));
++ return this.onGround() || this.fallDistance < this.maxUpStep() && !this.level().noCollision(this, this.getBoundingBox().move(0.0D, (double) (this.fallDistance - this.maxUpStep()), 0.0D));
+ }
+
+ public void attack(Entity target) {
+ if (target.isAttackable()) {
+ if (!target.skipAttackInteraction(this)) {
+- float f = (float)this.getAttributeValue(Attributes.ATTACK_DAMAGE);
+- float damageBonus;
++ float f = (float) this.getAttributeValue(Attributes.ATTACK_DAMAGE);
++ float f1;
++
+ if (target instanceof LivingEntity) {
+- damageBonus = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity)target).getMobType());
++ f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), ((LivingEntity) target).getMobType());
+ } else {
+- damageBonus = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), MobType.UNDEFINED);
++ f1 = EnchantmentHelper.getDamageBonus(this.getMainHandItem(), EnumMonsterType.UNDEFINED);
+ }
+
+- float attackStrengthScale = this.getAttackStrengthScale(0.5F);
+- float var21 = f * (0.2F + attackStrengthScale * attackStrengthScale * 0.8F);
+- float var23 = damageBonus * attackStrengthScale;
+- this.resetAttackStrengthTicker();
+- if (var21 > 0.0F || var23 > 0.0F) {
+- boolean flag = attackStrengthScale > 0.9F;
++ float f2 = this.getAttackStrengthScale(0.5F);
++
++ f *= 0.2F + f2 * f2 * 0.8F;
++ f1 *= f2;
++ // this.resetAttackCooldown(); // CraftBukkit - Moved to EntityLiving to reset the cooldown after the damage is dealt
++ if (f > 0.0F || f1 > 0.0F) {
++ boolean flag = f2 > 0.9F;
+ boolean flag1 = false;
+- int i = 0;
+- int var24 = i + EnchantmentHelper.getKnockbackBonus(this);
++ byte b0 = 0;
++ int i = b0 + EnchantmentHelper.getKnockbackBonus(this);
++
+ if (this.isSprinting() && flag) {
+- this.level()
+- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F);
+- var24++;
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_KNOCKBACK, this.getSoundSource(), 1.0F, 1.0F);
++ ++i;
+ flag1 = true;
+ }
+
+- boolean flag2 = flag
+- && this.fallDistance > 0.0F
+- && !this.onGround()
+- && !this.onClimbable()
+- && !this.isInWater()
+- && !this.hasEffect(MobEffects.BLINDNESS)
+- && !this.isPassenger()
+- && target instanceof LivingEntity;
++ boolean flag2 = flag && this.fallDistance > 0.0F && !this.onGround() && !this.onClimbable() && !this.isInWater() && !this.hasEffect(MobEffects.BLINDNESS) && !this.isPassenger() && target instanceof LivingEntity;
++
+ flag2 = flag2 && !this.isSprinting();
+ if (flag2) {
+- var21 *= 1.5F;
++ f *= 1.5F;
+ }
+
+- f = var21 + var23;
++ f += f1;
+ boolean flag3 = false;
+- double d = (double)(this.walkDist - this.walkDistO);
+- if (flag && !flag2 && !flag1 && this.onGround() && d < (double)this.getSpeed()) {
+- ItemStack itemInHand = this.getItemInHand(InteractionHand.MAIN_HAND);
+- if (itemInHand.getItem() instanceof SwordItem) {
++ double d0 = (double) (this.walkDist - this.walkDistO);
++
++ if (flag && !flag2 && !flag1 && this.onGround() && d0 < (double) this.getSpeed()) {
++ ItemStack itemstack = this.getItemInHand(EnumHand.MAIN_HAND);
++
++ if (itemstack.getItem() instanceof SwordItem) {
+ flag3 = true;
+ }
+ }
+
+- float f1 = 0.0F;
++ float f3 = 0.0F;
+ boolean flag4 = false;
+- int fireAspect = EnchantmentHelper.getFireAspect(this);
++ int j = EnchantmentHelper.getFireAspect(this);
++
+ if (target instanceof LivingEntity) {
+- f1 = ((LivingEntity)target).getHealth();
+- if (fireAspect > 0 && !target.isOnFire()) {
+- flag4 = true;
+- target.setSecondsOnFire(1);
++ f3 = ((LivingEntity) target).getHealth();
++ if (j > 0 && !target.isOnFire()) {
++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item
++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), 1);
++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent);
++
++ if (!combustEvent.isCancelled()) {
++ flag4 = true;
++ target.setSecondsOnFire(combustEvent.getDuration(), false);
++ }
++ // CraftBukkit end
+ }
+ }
+
+- Vec3 deltaMovement = target.getDeltaMovement();
++ Vec3 vec3d = target.getDeltaMovement();
+ boolean flag5 = target.hurt(this.damageSources().playerAttack(this), f);
++
+ if (flag5) {
+- if (var24 > 0) {
++ if (i > 0) {
+ if (target instanceof LivingEntity) {
+- ((LivingEntity)target)
+- .knockback(
+- (double)((float)var24 * 0.5F),
+- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)),
+- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)))
+- );
++ ((LivingEntity) target).knockback((double) ((float) i * 0.5F), (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)));
+ } else {
+- target.push(
+- (double)(-Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)) * (float)var24 * 0.5F),
+- 0.1,
+- (double)(Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)) * (float)var24 * 0.5F)
+- );
++ target.push((double) (-Mth.sin(this.getYRot() * 0.017453292F) * (float) i * 0.5F), 0.1D, (double) (Mth.cos(this.getYRot() * 0.017453292F) * (float) i * 0.5F));
+ }
+
+- this.setDeltaMovement(this.getDeltaMovement().multiply(0.6, 1.0, 0.6));
++ this.setDeltaMovement(this.getDeltaMovement().multiply(0.6D, 1.0D, 0.6D));
+ this.setSprinting(false);
+ }
+
+ if (flag3) {
+- float f2 = 1.0F + EnchantmentHelper.getSweepingDamageRatio(this) * f;
++ float f4 = 1.0F + EnchantmentHelper.getSweepingDamageRatio(this) * f;
++ List<LivingEntity> list = this.level().getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0D, 0.25D, 1.0D));
++ Iterator iterator = list.iterator();
+
+- for (LivingEntity livingEntity : this.level()
+- .getEntitiesOfClass(LivingEntity.class, target.getBoundingBox().inflate(1.0, 0.25, 1.0))) {
+- if (livingEntity != this
+- && livingEntity != target
+- && !this.isAlliedTo(livingEntity)
+- && (!(livingEntity instanceof ArmorStand) || !((ArmorStand)livingEntity).isMarker())
+- && this.distanceToSqr(livingEntity) < 9.0) {
+- livingEntity.knockback(
+- 0.4F,
+- (double)Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)),
+- (double)(-Mth.cos(this.getYRot() * (float) (Math.PI / 180.0)))
+- );
+- livingEntity.hurt(this.damageSources().playerAttack(this), f2);
++ while (iterator.hasNext()) {
++ LivingEntity entityliving = (LivingEntity) iterator.next();
++
++ if (entityliving != this && entityliving != target && !this.isAlliedTo((Entity) entityliving) && (!(entityliving instanceof ArmorStand) || !((ArmorStand) entityliving).isMarker()) && this.distanceToSqr((Entity) entityliving) < 9.0D) {
++ // CraftBukkit start - Only apply knockback if the damage hits
++ if (entityliving.hurt(this.damageSources().playerAttack(this).sweep(), f4)) {
++ entityliving.knockback(0.4000000059604645D, (double) Mth.sin(this.getYRot() * 0.017453292F), (double) (-Mth.cos(this.getYRot() * 0.017453292F)));
++ }
++ // CraftBukkit end
+ }
+ }
+
+- this.level()
+- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F);
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_SWEEP, this.getSoundSource(), 1.0F, 1.0F);
+ this.sweepAttack();
+ }
+
+ if (target instanceof ServerPlayer && target.hurtMarked) {
+- ((ServerPlayer)target).connection.send(new ClientboundSetEntityMotionPacket(target));
++ // CraftBukkit start - Add Velocity Event
++ boolean cancelled = false;
++ org.bukkit.entity.Player player = (org.bukkit.entity.Player) target.getBukkitEntity();
++ org.bukkit.util.Vector velocity = CraftVector.toBukkit(vec3d);
++
++ PlayerVelocityEvent event = new PlayerVelocityEvent(player, velocity.clone());
++ this.level().getCraftServer().getPluginManager().callEvent(event);
++
++ if (event.isCancelled()) {
++ cancelled = true;
++ } else if (!velocity.equals(event.getVelocity())) {
++ player.setVelocity(event.getVelocity());
++ }
++
++ if (!cancelled) {
++ ((ServerPlayer) target).connection.send(new ClientboundSetEntityMotionPacket(target));
+ target.hurtMarked = false;
+- target.setDeltaMovement(deltaMovement);
++ target.setDeltaMovement(vec3d);
++ }
++ // CraftBukkit end
+ }
+
+ if (flag2) {
+- this.level()
+- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F);
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_CRIT, this.getSoundSource(), 1.0F, 1.0F);
+ this.crit(target);
+ }
+
+ if (!flag2 && !flag3) {
+ if (flag) {
+- this.level()
+- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F);
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_STRONG, this.getSoundSource(), 1.0F, 1.0F);
+ } else {
+- this.level()
+- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F);
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_WEAK, this.getSoundSource(), 1.0F, 1.0F);
+ }
+ }
+
+- if (var23 > 0.0F) {
++ if (f1 > 0.0F) {
+ this.magicCrit(target);
+ }
+
+ this.setLastHurtMob(target);
+ if (target instanceof LivingEntity) {
+- EnchantmentHelper.doPostHurtEffects((LivingEntity)target, this);
++ EnchantmentHelper.doPostHurtEffects((LivingEntity) target, this);
+ }
+
+ EnchantmentHelper.doPostDamageEffects(this, target);
+- ItemStack mainHandItem = this.getMainHandItem();
+- Entity entity = target;
++ ItemStack itemstack1 = this.getMainHandItem();
++ Object object = target;
++
+ if (target instanceof EnderDragonPart) {
+- entity = ((EnderDragonPart)target).parentMob;
++ object = ((EnderDragonPart) target).parentMob;
+ }
+
+- if (!this.level().isClientSide && !mainHandItem.isEmpty() && entity instanceof LivingEntity) {
+- mainHandItem.hurtEnemy((LivingEntity)entity, this);
+- if (mainHandItem.isEmpty()) {
+- this.setItemInHand(InteractionHand.MAIN_HAND, ItemStack.EMPTY);
++ if (!this.level().isClientSide && !itemstack1.isEmpty() && object instanceof LivingEntity) {
++ itemstack1.hurtEnemy((LivingEntity) object, this);
++ if (itemstack1.isEmpty()) {
++ this.setItemInHand(EnumHand.MAIN_HAND, ItemStack.EMPTY);
+ }
+ }
+
+ if (target instanceof LivingEntity) {
+- float f3 = f1 - ((LivingEntity)target).getHealth();
+- this.awardStat(Stats.DAMAGE_DEALT, Math.round(f3 * 10.0F));
+- if (fireAspect > 0) {
+- target.setSecondsOnFire(fireAspect * 4);
++ float f5 = f3 - ((LivingEntity) target).getHealth();
++
++ this.awardStat(Stats.DAMAGE_DEALT, Math.round(f5 * 10.0F));
++ if (j > 0) {
++ // CraftBukkit start - Call a combust event when somebody hits with a fire enchanted item
++ EntityCombustByEntityEvent combustEvent = new EntityCombustByEntityEvent(this.getBukkitEntity(), target.getBukkitEntity(), j * 4);
++ org.bukkit.Bukkit.getPluginManager().callEvent(combustEvent);
++
++ if (!combustEvent.isCancelled()) {
++ target.setSecondsOnFire(combustEvent.getDuration(), false);
++ }
++ // CraftBukkit end
+ }
+
+- if (this.level() instanceof ServerLevel && f3 > 2.0F) {
+- int i1 = (int)((double)f3 * 0.5);
+- ((ServerLevel)this.level())
+- .sendParticles(ParticleTypes.DAMAGE_INDICATOR, target.getX(), target.getY(0.5), target.getZ(), i1, 0.1, 0.0, 0.1, 0.2);
++ if (this.level() instanceof ServerLevel && f5 > 2.0F) {
++ int k = (int) ((double) f5 * 0.5D);
++
++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.DAMAGE_INDICATOR, target.getX(), target.getY(0.5D), target.getZ(), k, 0.1D, 0.0D, 0.1D, 0.2D);
+ }
+ }
+
+- this.causeFoodExhaustion(0.1F);
++ this.causeFoodExhaustion(0.1F, EntityExhaustionEvent.ExhaustionReason.ATTACK); // CraftBukkit - EntityExhaustionEvent
+ } else {
+- this.level()
+- .playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F);
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_ATTACK_NODAMAGE, this.getSoundSource(), 1.0F, 1.0F);
+ if (flag4) {
+ target.clearFire();
+ }
++ // CraftBukkit start - resync on cancelled event
++ if (this instanceof ServerPlayer) {
++ ((ServerPlayer) this).getBukkitEntity().updateInventory();
++ }
++ // CraftBukkit end
+ }
+ }
++
+ }
+ }
+ }
+@@ -1282,7 +1408,8 @@
+ }
+
+ public void disableShield(boolean becauseOfAxe) {
+- float f = 0.25F + (float)EnchantmentHelper.getBlockEfficiency(this) * 0.05F;
++ float f = 0.25F + (float) EnchantmentHelper.getBlockEfficiency(this) * 0.05F;
++
+ if (becauseOfAxe) {
+ f += 0.75F;
+ }
+@@ -1290,27 +1417,27 @@
+ if (this.random.nextFloat() < f) {
+ this.getCooldowns().addCooldown(Items.SHIELD, 100);
+ this.stopUsingItem();
+- this.level().broadcastEntityEvent(this, (byte)30);
++ this.level().broadcastEntityEvent(this, (byte) 30);
+ }
+- }
+
+- public void crit(Entity entityHit) {
+ }
+
+- public void magicCrit(Entity entityHit) {
+- }
++ public void crit(Entity entityHit) {}
+
++ public void magicCrit(Entity entityHit) {}
++
+ public void sweepAttack() {
+- double d = (double)(-Mth.sin(this.getYRot() * (float) (Math.PI / 180.0)));
+- double d1 = (double)Mth.cos(this.getYRot() * (float) (Math.PI / 180.0));
++ double d0 = (double) (-Mth.sin(this.getYRot() * 0.017453292F));
++ double d1 = (double) Mth.cos(this.getYRot() * 0.017453292F);
++
+ if (this.level() instanceof ServerLevel) {
+- ((ServerLevel)this.level()).sendParticles(ParticleTypes.SWEEP_ATTACK, this.getX() + d, this.getY(0.5), this.getZ() + d1, 0, d, 0.0, d1, 0.0);
++ ((ServerLevel) this.level()).sendParticles(ParticleTypes.SWEEP_ATTACK, this.getX() + d0, this.getY(0.5D), this.getZ() + d1, 0, d0, 0.0D, d1, 0.0D);
+ }
+- }
+
+- public void respawn() {
+ }
+
++ public void respawn() {}
++
+ @Override
+ public void remove(Entity.RemovalReason reason) {
+ super.remove(reason);
+@@ -1318,6 +1445,7 @@
+ if (this.containerMenu != null && this.hasContainerOpen()) {
+ this.doCloseContainer();
+ }
++
+ }
+
+ public boolean isLocalPlayer() {
+@@ -1336,15 +1464,20 @@
+ return this.abilities;
+ }
+
+- public void updateTutorialInventoryAction(ItemStack carried, ItemStack clicked, ClickAction action) {
+- }
++ public void updateTutorialInventoryAction(ItemStack carried, ItemStack clicked, ClickAction action) {}
+
+ public boolean hasContainerOpen() {
+ return this.containerMenu != this.inventoryMenu;
+ }
+
+ public Either<Player.BedSleepingProblem, Unit> startSleepInBed(BlockPos bedPos) {
+- this.startSleeping(bedPos);
++ // CraftBukkit start
++ return this.startSleepInBed(bedPos, false);
++ }
++
++ public Either<Player.BedSleepingProblem, Unit> startSleepInBed(BlockPos blockposition, boolean force) {
++ // CraftBukkit end
++ this.startSleeping(blockposition);
+ this.sleepCounter = 0;
+ return Either.right(Unit.INSTANCE);
+ }
+@@ -1352,7 +1485,7 @@
+ public void stopSleepInBed(boolean wakeImmediately, boolean updateLevelForSleepingPlayers) {
+ super.stopSleeping();
+ if (this.level() instanceof ServerLevel && updateLevelForSleepingPlayers) {
+- ((ServerLevel)this.level()).updateSleepingPlayerList();
++ ((ServerLevel) this.level()).updateSleepingPlayerList();
+ }
+
+ this.sleepCounter = wakeImmediately ? 0 : 100;
+@@ -1363,33 +1496,28 @@
+ this.stopSleepInBed(true, true);
+ }
+
+- public static Optional<Vec3> findRespawnPositionAndUseSpawnBlock(
+- ServerLevel serverLevel, BlockPos spawnBlockPos, float playerOrientation, boolean isRespawnForced, boolean respawnAfterWinningTheGame
+- ) {
+- BlockState blockState = serverLevel.getBlockState(spawnBlockPos);
+- Block block = blockState.getBlock();
+- if (block instanceof RespawnAnchorBlock
+- && (isRespawnForced || blockState.getValue(RespawnAnchorBlock.CHARGE) > 0)
+- && RespawnAnchorBlock.canSetSpawn(serverLevel)) {
++ public static Optional<Vec3> findRespawnPositionAndUseSpawnBlock(ServerLevel serverLevel, BlockPos spawnBlockPos, float playerOrientation, boolean isRespawnForced, boolean respawnAfterWinningTheGame) {
++ IBlockData iblockdata = serverLevel.getBlockState(spawnBlockPos);
++ Block block = iblockdata.getBlock();
++
++ if (block instanceof RespawnAnchorBlock && (isRespawnForced || (Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) > 0) && RespawnAnchorBlock.canSetSpawn(serverLevel)) {
+ Optional<Vec3> optional = RespawnAnchorBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos);
++
+ if (!isRespawnForced && !respawnAfterWinningTheGame && optional.isPresent()) {
+- serverLevel.setBlock(
+- spawnBlockPos, blockState.setValue(RespawnAnchorBlock.CHARGE, Integer.valueOf(blockState.getValue(RespawnAnchorBlock.CHARGE) - 1)), 3
+- );
++ serverLevel.setBlock(spawnBlockPos, (IBlockData) iblockdata.setValue(RespawnAnchorBlock.CHARGE, (Integer) iblockdata.getValue(RespawnAnchorBlock.CHARGE) - 1), 3);
+ }
+
+ return optional;
+ } else if (block instanceof BedBlock && BedBlock.canSetSpawn(serverLevel)) {
+- return BedBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos, blockState.getValue(BedBlock.FACING), playerOrientation);
++ return BedBlock.findStandUpPosition(EntityType.PLAYER, serverLevel, spawnBlockPos, (Direction) iblockdata.getValue(BedBlock.FACING), playerOrientation);
+ } else if (!isRespawnForced) {
+ return Optional.empty();
+ } else {
+- boolean isPossibleToRespawnInThis = block.isPossibleToRespawnInThis(blockState);
+- BlockState blockState1 = serverLevel.getBlockState(spawnBlockPos.above());
+- boolean isPossibleToRespawnInThis1 = blockState1.getBlock().isPossibleToRespawnInThis(blockState1);
+- return isPossibleToRespawnInThis && isPossibleToRespawnInThis1
+- ? Optional.of(new Vec3((double)spawnBlockPos.getX() + 0.5, (double)spawnBlockPos.getY() + 0.1, (double)spawnBlockPos.getZ() + 0.5))
+- : Optional.empty();
++ boolean flag2 = block.isPossibleToRespawnInThis(iblockdata);
++ IBlockData iblockdata1 = serverLevel.getBlockState(spawnBlockPos.above());
++ boolean flag3 = iblockdata1.getBlock().isPossibleToRespawnInThis(iblockdata1);
++
++ return flag2 && flag3 ? Optional.of(new Vec3((double) spawnBlockPos.getX() + 0.5D, (double) spawnBlockPos.getY() + 0.1D, (double) spawnBlockPos.getZ() + 0.5D)) : Optional.empty();
+ }
+ }
+
+@@ -1401,8 +1529,7 @@
+ return this.sleepCounter;
+ }
+
+- public void displayClientMessage(Component chatComponent, boolean actionBar) {
+- }
++ public void displayClientMessage(Component chatComponent, boolean actionBar) {}
+
+ public void awardStat(ResourceLocation statKey) {
+ this.awardStat(Stats.CUSTOM.get(statKey));
+@@ -1416,21 +1543,17 @@
+ this.awardStat(stat, 1);
+ }
+
+- public void awardStat(Stat<?> stat, int increment) {
+- }
++ public void awardStat(Stat<?> stat, int increment) {}
+
+- public void resetStat(Stat<?> stat) {
+- }
++ public void resetStat(Stat<?> stat) {}
+
+ public int awardRecipes(Collection<RecipeHolder<?>> recipes) {
+ return 0;
+ }
+
+- public void triggerRecipeCrafted(RecipeHolder<?> recipeHolder, List<ItemStack> list) {
+- }
++ public void triggerRecipeCrafted(RecipeHolder<?> recipeholder, List<ItemStack> list) {}
+
+- public void awardRecipesByKey(List<ResourceLocation> list) {
+- }
++ public void awardRecipesByKey(List<ResourceLocation> list) {}
+
+ public int resetRecipes(Collection<RecipeHolder<?>> recipes) {
+ return 0;
+@@ -1441,35 +1564,44 @@
+ super.jumpFromGround();
+ this.awardStat(Stats.JUMP);
+ if (this.isSprinting()) {
+- this.causeFoodExhaustion(0.2F);
++ this.causeFoodExhaustion(0.2F, EntityExhaustionEvent.ExhaustionReason.JUMP_SPRINT); // CraftBukkit - EntityExhaustionEvent
+ } else {
+- this.causeFoodExhaustion(0.05F);
++ this.causeFoodExhaustion(0.05F, EntityExhaustionEvent.ExhaustionReason.JUMP); // CraftBukkit - EntityExhaustionEvent
+ }
++
+ }
+
+ @Override
+ public void travel(Vec3 travelVector) {
++ double d0;
++
+ if (this.isSwimming() && !this.isPassenger()) {
+- double d = this.getLookAngle().y;
+- double d1 = d < -0.2 ? 0.085 : 0.06;
+- if (d <= 0.0
+- || this.jumping
+- || !this.level().getBlockState(BlockPos.containing(this.getX(), this.getY() + 1.0 - 0.1, this.getZ())).getFluidState().isEmpty()) {
+- Vec3 deltaMovement = this.getDeltaMovement();
+- this.setDeltaMovement(deltaMovement.add(0.0, (d - deltaMovement.y) * d1, 0.0));
++ d0 = this.getLookAngle().y;
++ double d1 = d0 < -0.2D ? 0.085D : 0.06D;
++
++ if (d0 <= 0.0D || this.jumping || !this.level().getBlockState(BlockPos.containing(this.getX(), this.getY() + 1.0D - 0.1D, this.getZ())).getFluidState().isEmpty()) {
++ Vec3 vec3d1 = this.getDeltaMovement();
++
++ this.setDeltaMovement(vec3d1.add(0.0D, (d0 - vec3d1.y) * d1, 0.0D));
+ }
+ }
+
+ if (this.abilities.flying && !this.isPassenger()) {
+- double d = this.getDeltaMovement().y;
++ d0 = this.getDeltaMovement().y;
+ super.travel(travelVector);
+- Vec3 deltaMovement1 = this.getDeltaMovement();
+- this.setDeltaMovement(deltaMovement1.x, d * 0.6, deltaMovement1.z);
++ Vec3 vec3d2 = this.getDeltaMovement();
++
++ this.setDeltaMovement(vec3d2.x, d0 * 0.6D, vec3d2.z);
+ this.resetFallDistance();
+- this.setSharedFlag(7, false);
++ // CraftBukkit start
++ if (getSharedFlag(7) && !org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) {
++ this.setSharedFlag(7, false);
++ }
++ // CraftBukkit end
+ } else {
+ super.travel(travelVector);
+ }
++
+ }
+
+ @Override
+@@ -1479,6 +1611,7 @@
+ } else {
+ super.updateSwimming();
+ }
++
+ }
+
+ protected boolean freeAt(BlockPos pos) {
+@@ -1487,7 +1620,7 @@
+
+ @Override
+ public float getSpeed() {
+- return (float)this.getAttributeValue(Attributes.MOVEMENT_SPEED);
++ return (float) this.getAttributeValue(Attributes.MOVEMENT_SPEED);
+ }
+
+ @Override
+@@ -1496,7 +1629,7 @@
+ return false;
+ } else {
+ if (fallDistance >= 2.0F) {
+- this.awardStat(Stats.FALL_ONE_CM, (int)Math.round((double)fallDistance * 100.0));
++ this.awardStat(Stats.FALL_ONE_CM, (int) Math.round((double) fallDistance * 100.0D));
+ }
+
+ return super.causeFallDamage(fallDistance, multiplier, source);
+@@ -1505,8 +1638,9 @@
+
+ public boolean tryToStartFallFlying() {
+ if (!this.onGround() && !this.isFallFlying() && !this.isInWater() && !this.hasEffect(MobEffects.LEVITATION)) {
+- ItemStack itemBySlot = this.getItemBySlot(EquipmentSlot.CHEST);
+- if (itemBySlot.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(itemBySlot)) {
++ ItemStack itemstack = this.getItemBySlot(EquipmentSlot.CHEST);
++
++ if (itemstack.is(Items.ELYTRA) && ElytraItem.isFlyEnabled(itemstack)) {
+ this.startFallFlying();
+ return true;
+ }
+@@ -1516,12 +1650,24 @@
+ }
+
+ public void startFallFlying() {
+- this.setSharedFlag(7, true);
++ // CraftBukkit start
++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, true).isCancelled()) {
++ this.setSharedFlag(7, true);
++ } else {
++ // SPIGOT-5542: must toggle like below
++ this.setSharedFlag(7, true);
++ this.setSharedFlag(7, false);
++ }
++ // CraftBukkit end
+ }
+
+ public void stopFallFlying() {
++ // CraftBukkit start
++ if (!org.bukkit.craftbukkit.event.CraftEventFactory.callToggleGlideEvent(this, false).isCancelled()) {
+ this.setSharedFlag(7, true);
+ this.setSharedFlag(7, false);
++ }
++ // CraftBukkit end
+ }
+
+ @Override
+@@ -1529,31 +1675,35 @@
+ if (!this.isSpectator()) {
+ super.doWaterSplashEffect();
+ }
++
+ }
+
+ @Override
+- protected void playStepSound(BlockPos pos, BlockState state) {
++ protected void playStepSound(BlockPos pos, IBlockData state) {
+ if (this.isInWater()) {
+ this.waterSwimSound();
+ this.playMuffledStepSound(state);
+ } else {
+- BlockPos primaryStepSoundBlockPos = this.getPrimaryStepSoundBlockPos(pos);
+- if (!pos.equals(primaryStepSoundBlockPos)) {
+- BlockState blockState = this.level().getBlockState(primaryStepSoundBlockPos);
+- if (blockState.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) {
+- this.playCombinationStepSounds(blockState, state);
++ BlockPos blockposition1 = this.getPrimaryStepSoundBlockPos(pos);
++
++ if (!pos.equals(blockposition1)) {
++ IBlockData iblockdata1 = this.level().getBlockState(blockposition1);
++
++ if (iblockdata1.is(BlockTags.COMBINATION_STEP_SOUND_BLOCKS)) {
++ this.playCombinationStepSounds(iblockdata1, state);
+ } else {
+- super.playStepSound(primaryStepSoundBlockPos, blockState);
++ super.playStepSound(blockposition1, iblockdata1);
+ }
+ } else {
+ super.playStepSound(pos, state);
+ }
+ }
++
+ }
+
+ @Override
+- public LivingEntity.Fallsounds getFallSounds() {
+- return new LivingEntity.Fallsounds(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL);
++ public LivingEntity.a getFallSounds() {
++ return new LivingEntity.a(SoundEvents.PLAYER_SMALL_FALL, SoundEvents.PLAYER_BIG_FALL);
+ }
+
+ @Override
+@@ -1563,22 +1713,24 @@
+ }
+
+ @Override
+- public void makeStuckInBlock(BlockState state, Vec3 motionMultiplier) {
++ public void makeStuckInBlock(IBlockData state, Vec3 motionMultiplier) {
+ if (!this.abilities.flying) {
+ super.makeStuckInBlock(state, motionMultiplier);
+ }
++
+ }
+
+ public void giveExperiencePoints(int xpPoints) {
+ this.increaseScore(xpPoints);
+- this.experienceProgress = this.experienceProgress + (float)xpPoints / (float)this.getXpNeededForNextLevel();
++ this.experienceProgress += (float) xpPoints / (float) this.getXpNeededForNextLevel();
+ this.totalExperience = Mth.clamp(this.totalExperience + xpPoints, 0, Integer.MAX_VALUE);
+
+ while (this.experienceProgress < 0.0F) {
+- float f = this.experienceProgress * (float)this.getXpNeededForNextLevel();
++ float f = this.experienceProgress * (float) this.getXpNeededForNextLevel();
++
+ if (this.experienceLevel > 0) {
+ this.giveExperienceLevels(-1);
+- this.experienceProgress = 1.0F + f / (float)this.getXpNeededForNextLevel();
++ this.experienceProgress = 1.0F + f / (float) this.getXpNeededForNextLevel();
+ } else {
+ this.giveExperienceLevels(-1);
+ this.experienceProgress = 0.0F;
+@@ -1586,10 +1738,11 @@
+ }
+
+ while (this.experienceProgress >= 1.0F) {
+- this.experienceProgress = (this.experienceProgress - 1.0F) * (float)this.getXpNeededForNextLevel();
++ this.experienceProgress = (this.experienceProgress - 1.0F) * (float) this.getXpNeededForNextLevel();
+ this.giveExperienceLevels(1);
+- this.experienceProgress = this.experienceProgress / (float)this.getXpNeededForNextLevel();
++ this.experienceProgress /= (float) this.getXpNeededForNextLevel();
+ }
++
+ }
+
+ public int getEnchantmentSeed() {
+@@ -1615,26 +1768,36 @@
+ this.totalExperience = 0;
+ }
+
+- if (levels > 0 && this.experienceLevel % 5 == 0 && (float)this.lastLevelUpTime < (float)this.tickCount - 100.0F) {
+- float f = this.experienceLevel > 30 ? 1.0F : (float)this.experienceLevel / 30.0F;
+- this.level().playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_LEVELUP, this.getSoundSource(), f * 0.75F, 1.0F);
++ if (levels > 0 && this.experienceLevel % 5 == 0 && (float) this.lastLevelUpTime < (float) this.tickCount - 100.0F) {
++ float f = this.experienceLevel > 30 ? 1.0F : (float) this.experienceLevel / 30.0F;
++
++ this.level().playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_LEVELUP, this.getSoundSource(), f * 0.75F, 1.0F);
+ this.lastLevelUpTime = this.tickCount;
+ }
++
+ }
+
+ public int getXpNeededForNextLevel() {
+- if (this.experienceLevel >= 30) {
+- return 112 + (this.experienceLevel - 30) * 9;
+- } else {
+- return this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2;
+- }
++ return this.experienceLevel >= 30 ? 112 + (this.experienceLevel - 30) * 9 : (this.experienceLevel >= 15 ? 37 + (this.experienceLevel - 15) * 5 : 7 + this.experienceLevel * 2);
+ }
+
++ // CraftBukkit start
+ public void causeFoodExhaustion(float exhaustion) {
++ this.causeFoodExhaustion(exhaustion, EntityExhaustionEvent.ExhaustionReason.UNKNOWN);
++ }
++
++ public void causeFoodExhaustion(float f, EntityExhaustionEvent.ExhaustionReason reason) {
++ // CraftBukkit end
+ if (!this.abilities.invulnerable) {
+ if (!this.level().isClientSide) {
+- this.foodData.addExhaustion(exhaustion);
++ // CraftBukkit start
++ EntityExhaustionEvent event = CraftEventFactory.callPlayerExhaustionEvent(this, reason, f);
++ if (!event.isCancelled()) {
++ this.foodData.addExhaustion(event.getExhaustion());
++ }
++ // CraftBukkit end
+ }
++
+ }
+ }
+
+@@ -1662,9 +1825,10 @@
+ if (this.abilities.mayBuild) {
+ return true;
+ } else {
+- BlockPos blockPos = pos.relative(facing.getOpposite());
+- BlockInWorld blockInWorld = new BlockInWorld(this.level(), blockPos, false);
+- return stack.hasAdventureModePlaceTagForBlock(this.level().registryAccess().registryOrThrow(Registries.BLOCK), blockInWorld);
++ BlockPos blockposition1 = pos.relative(facing.getOpposite());
++ BlockInWorld shapedetectorblock = new BlockInWorld(this.level(), blockposition1, false);
++
++ return stack.hasAdventureModePlaceTagForBlock(this.level().registryAccess().registryOrThrow(Registries.BLOCK), shapedetectorblock);
+ }
+ }
+
+@@ -1672,6 +1836,7 @@
+ public int getExperienceReward() {
+ if (!this.level().getGameRules().getBoolean(GameRules.RULE_KEEPINVENTORY) && !this.isSpectator()) {
+ int i = this.experienceLevel * 7;
++
+ return i > 100 ? 100 : i;
+ } else {
+ return 0;
+@@ -1690,11 +1855,10 @@
+
+ @Override
+ protected Entity.MovementEmission getMovementEmission() {
+- return this.abilities.flying || this.onGround() && this.isDiscrete() ? Entity.MovementEmission.NONE : Entity.MovementEmission.ALL;
++ return !this.abilities.flying && (!this.onGround() || !this.isDiscrete()) ? Entity.MovementEmission.ALL : Entity.MovementEmission.NONE;
+ }
+
+- public void onUpdateAbilities() {
+- }
++ public void onUpdateAbilities() {}
+
+ @Override
+ public Component getName() {
+@@ -1707,30 +1871,32 @@
+
+ @Override
+ public ItemStack getItemBySlot(EquipmentSlot slot) {
+- if (slot == EquipmentSlot.MAINHAND) {
+- return this.inventory.getSelected();
+- } else if (slot == EquipmentSlot.OFFHAND) {
+- return this.inventory.offhand.get(0);
+- } else {
+- return slot.getType() == EquipmentSlot.Type.ARMOR ? this.inventory.armor.get(slot.getIndex()) : ItemStack.EMPTY;
+- }
++ return slot == EquipmentSlot.MAINHAND ? this.inventory.getSelected() : (slot == EquipmentSlot.OFFHAND ? (ItemStack) this.inventory.offhand.get(0) : (slot.getType() == EquipmentSlot.Function.ARMOR ? (ItemStack) this.inventory.armor.get(slot.getIndex()) : ItemStack.EMPTY));
+ }
+
+ @Override
+ protected boolean doesEmitEquipEvent(EquipmentSlot slot) {
+- return slot.getType() == EquipmentSlot.Type.ARMOR;
++ return slot.getType() == EquipmentSlot.Function.ARMOR;
+ }
+
+ @Override
+ public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
+- this.verifyEquippedItem(stack);
+- if (slot == EquipmentSlot.MAINHAND) {
+- this.onEquipItem(slot, this.inventory.items.set(this.inventory.selected, stack), stack);
+- } else if (slot == EquipmentSlot.OFFHAND) {
+- this.onEquipItem(slot, this.inventory.offhand.set(0, stack), stack);
+- } else if (slot.getType() == EquipmentSlot.Type.ARMOR) {
+- this.onEquipItem(slot, this.inventory.armor.set(slot.getIndex(), stack), stack);
++ // CraftBukkit start
++ setItemSlot(slot, stack, false);
++ }
++
++ @Override
++ public void setItemSlot(EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) {
++ // CraftBukkit end
++ this.verifyEquippedItem(itemstack);
++ if (enumitemslot == EquipmentSlot.MAINHAND) {
++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.items.set(this.inventory.selected, itemstack), itemstack, silent); // CraftBukkit
++ } else if (enumitemslot == EquipmentSlot.OFFHAND) {
++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.offhand.set(0, itemstack), itemstack, silent); // CraftBukkit
++ } else if (enumitemslot.getType() == EquipmentSlot.Function.ARMOR) {
++ this.onEquipItem(enumitemslot, (ItemStack) this.inventory.armor.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit
+ }
++
+ }
+
+ public boolean addItem(ItemStack stack) {
+@@ -1739,7 +1905,7 @@
+
+ @Override
+ public Iterable<ItemStack> getHandSlots() {
+- return Lists.newArrayList(this.getMainHandItem(), this.getOffhandItem());
++ return Lists.newArrayList(new ItemStack[]{this.getMainHandItem(), this.getOffhandItem()});
+ }
+
+ @Override
+@@ -1748,16 +1914,18 @@
+ }
+
+ public boolean setEntityOnShoulder(CompoundTag entityCompound) {
+- if (this.isPassenger() || !this.onGround() || this.isInWater() || this.isInPowderSnow) {
+- return false;
+- } else if (this.getShoulderEntityLeft().isEmpty()) {
+- this.setShoulderEntityLeft(entityCompound);
+- this.timeEntitySatOnShoulder = this.level().getGameTime();
+- return true;
+- } else if (this.getShoulderEntityRight().isEmpty()) {
+- this.setShoulderEntityRight(entityCompound);
+- this.timeEntitySatOnShoulder = this.level().getGameTime();
+- return true;
++ if (!this.isPassenger() && this.onGround() && !this.isInWater() && !this.isInPowderSnow) {
++ if (this.getShoulderEntityLeft().isEmpty()) {
++ this.setShoulderEntityLeft(entityCompound);
++ this.timeEntitySatOnShoulder = this.level().getGameTime();
++ return true;
++ } else if (this.getShoulderEntityRight().isEmpty()) {
++ this.setShoulderEntityRight(entityCompound);
++ this.timeEntitySatOnShoulder = this.level().getGameTime();
++ return true;
++ } else {
++ return false;
++ }
+ } else {
+ return false;
+ }
+@@ -1765,24 +1933,31 @@
+
+ protected void removeEntitiesOnShoulder() {
+ if (this.timeEntitySatOnShoulder + 20L < this.level().getGameTime()) {
+- this.respawnEntityOnShoulder(this.getShoulderEntityLeft());
+- this.setShoulderEntityLeft(new CompoundTag());
+- this.respawnEntityOnShoulder(this.getShoulderEntityRight());
+- this.setShoulderEntityRight(new CompoundTag());
++ // CraftBukkit start
++ if (this.respawnEntityOnShoulder(this.getShoulderEntityLeft())) {
++ this.setShoulderEntityLeft(new CompoundTag());
++ }
++ if (this.respawnEntityOnShoulder(this.getShoulderEntityRight())) {
++ this.setShoulderEntityRight(new CompoundTag());
++ }
++ // CraftBukkit end
+ }
++
+ }
+
+- private void respawnEntityOnShoulder(CompoundTag entityCompound) {
+- if (!this.level().isClientSide && !entityCompound.isEmpty()) {
+- EntityType.create(entityCompound, this.level()).ifPresent(entity -> {
++ private boolean respawnEntityOnShoulder(CompoundTag nbttagcompound) { // CraftBukkit void->boolean
++ if (!this.level().isClientSide && !nbttagcompound.isEmpty()) {
++ return EntityType.create(nbttagcompound, this.level()).map((entity) -> { // CraftBukkit
+ if (entity instanceof TamableAnimal) {
+- ((TamableAnimal)entity).setOwnerUUID(this.uuid);
++ ((TamableAnimal) entity).setOwnerUUID(this.uuid);
+ }
+
+- entity.setPos(this.getX(), this.getY() + 0.7F, this.getZ());
+- ((ServerLevel)this.level()).addWithUUID(entity);
+- });
++ entity.setPos(this.getX(), this.getY() + 0.699999988079071D, this.getZ());
++ return ((ServerLevel) this.level()).addWithUUID(entity, CreatureSpawnEvent.SpawnReason.SHOULDER_ENTITY); // CraftBukkit
++ }).orElse(true); // CraftBukkit
+ }
++
++ return true; // CraftBukkit
+ }
+
+ @Override
+@@ -1811,17 +1986,17 @@
+
+ @Override
+ public Component getDisplayName() {
+- MutableComponent mutableComponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName());
+- return this.decorateDisplayNameComponent(mutableComponent);
++ MutableComponent ichatmutablecomponent = PlayerTeam.formatNameForTeam(this.getTeam(), this.getName());
++
++ return this.decorateDisplayNameComponent(ichatmutablecomponent);
+ }
+
+ private MutableComponent decorateDisplayNameComponent(MutableComponent displayName) {
+- String name = this.getGameProfile().getName();
+- return displayName.withStyle(
+- style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tell " + name + " "))
+- .withHoverEvent(this.createHoverEvent())
+- .withInsertion(name)
+- );
++ String s = this.getGameProfile().getName();
++
++ return displayName.withStyle((chatmodifier) -> {
++ return chatmodifier.withClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, "/tell " + s + " ")).withHoverEvent(this.createHoverEvent()).withInsertion(s);
++ });
+ }
+
+ @Override
+@@ -1830,7 +2005,7 @@
+ }
+
+ @Override
+- public float getStandingEyeHeight(Pose pose, EntityDimensions size) {
++ public float getStandingEyeHeight(EntityPose pose, EntityDimensions size) {
+ switch (pose) {
+ case SWIMMING:
+ case FALL_FLYING:
+@@ -1845,16 +2020,16 @@
+
+ @Override
+ protected void internalSetAbsorptionAmount(float f) {
+- this.getEntityData().set(DATA_PLAYER_ABSORPTION_ID, f);
++ this.getEntityData().set(Player.DATA_PLAYER_ABSORPTION_ID, f);
+ }
+
+ @Override
+ public float getAbsorptionAmount() {
+- return this.getEntityData().get(DATA_PLAYER_ABSORPTION_ID);
++ return (Float) this.getEntityData().get(Player.DATA_PLAYER_ABSORPTION_ID);
+ }
+
+ public boolean isModelPartShown(PlayerModelPart part) {
+- return (this.getEntityData().get(DATA_PLAYER_MODE_CUSTOMISATION) & part.getMask()) == part.getMask();
++ return ((Byte) this.getEntityData().get(Player.DATA_PLAYER_MODE_CUSTOMISATION) & part.getMask()) == part.getMask();
+ }
+
+ @Override
+@@ -1862,8 +2037,9 @@
+ if (slot >= 0 && slot < this.inventory.items.size()) {
+ return SlotAccess.forContainer(this.inventory, slot);
+ } else {
+- int i = slot - 200;
+- return i >= 0 && i < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, i) : super.getSlot(slot);
++ int j = slot - 200;
++
++ return j >= 0 && j < this.enderChestInventory.getContainerSize() ? SlotAccess.forContainer(this.enderChestInventory, j) : super.getSlot(slot);
+ }
+ }
+
+@@ -1882,35 +2058,35 @@
+
+ @Override
+ public HumanoidArm getMainArm() {
+- return this.entityData.get(DATA_PLAYER_MAIN_HAND) == 0 ? HumanoidArm.LEFT : HumanoidArm.RIGHT;
++ return (Byte) this.entityData.get(Player.DATA_PLAYER_MAIN_HAND) == 0 ? HumanoidArm.LEFT : HumanoidArm.RIGHT;
+ }
+
+ public void setMainArm(HumanoidArm hand) {
+- this.entityData.set(DATA_PLAYER_MAIN_HAND, (byte)(hand == HumanoidArm.LEFT ? 0 : 1));
++ this.entityData.set(Player.DATA_PLAYER_MAIN_HAND, (byte) (hand == HumanoidArm.LEFT ? 0 : 1));
+ }
+
+ public CompoundTag getShoulderEntityLeft() {
+- return this.entityData.get(DATA_SHOULDER_LEFT);
++ return (CompoundTag) this.entityData.get(Player.DATA_SHOULDER_LEFT);
+ }
+
+- protected void setShoulderEntityLeft(CompoundTag entityCompound) {
+- this.entityData.set(DATA_SHOULDER_LEFT, entityCompound);
++ public void setShoulderEntityLeft(CompoundTag entityCompound) {
++ this.entityData.set(Player.DATA_SHOULDER_LEFT, entityCompound);
+ }
+
+ public CompoundTag getShoulderEntityRight() {
+- return this.entityData.get(DATA_SHOULDER_RIGHT);
++ return (CompoundTag) this.entityData.get(Player.DATA_SHOULDER_RIGHT);
+ }
+
+- protected void setShoulderEntityRight(CompoundTag entityCompound) {
+- this.entityData.set(DATA_SHOULDER_RIGHT, entityCompound);
++ public void setShoulderEntityRight(CompoundTag entityCompound) {
++ this.entityData.set(Player.DATA_SHOULDER_RIGHT, entityCompound);
+ }
+
+ public float getCurrentItemAttackStrengthDelay() {
+- return (float)(1.0 / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0);
++ return (float) (1.0D / this.getAttributeValue(Attributes.ATTACK_SPEED) * 20.0D);
+ }
+
+ public float getAttackStrengthScale(float adjustTicks) {
+- return Mth.clamp(((float)this.attackStrengthTicker + adjustTicks) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F);
++ return Mth.clamp(((float) this.attackStrengthTicker + adjustTicks) / this.getCurrentItemAttackStrengthDelay(), 0.0F, 1.0F);
+ }
+
+ public void resetAttackStrengthTicker() {
+@@ -1927,7 +2103,7 @@
+ }
+
+ public float getLuck() {
+- return (float)this.getAttributeValue(Attributes.LUCK);
++ return (float) this.getAttributeValue(Attributes.LUCK);
+ }
+
+ public boolean canUseGameMasterBlocks() {
+@@ -1936,18 +2112,19 @@
+
+ @Override
+ public boolean canTakeItem(ItemStack itemstack) {
+- EquipmentSlot equipmentSlotForItem = Mob.getEquipmentSlotForItem(itemstack);
+- return this.getItemBySlot(equipmentSlotForItem).isEmpty();
++ EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack);
++
++ return this.getItemBySlot(enumitemslot).isEmpty();
+ }
+
+ @Override
+- public EntityDimensions getDimensions(Pose pose) {
+- return POSES.getOrDefault(pose, STANDING_DIMENSIONS);
++ public EntityDimensions getDimensions(EntityPose pose) {
++ return (EntityDimensions) Player.POSES.getOrDefault(pose, Player.STANDING_DIMENSIONS);
+ }
+
+ @Override
+- public ImmutableList<Pose> getDismountPoses() {
+- return ImmutableList.of(Pose.STANDING, Pose.CROUCHING, Pose.SWIMMING);
++ public ImmutableList<EntityPose> getDismountPoses() {
++ return ImmutableList.of(EntityPose.STANDING, EntityPose.CROUCHING, EntityPose.SWIMMING);
+ }
+
+ @Override
+@@ -1955,17 +2132,19 @@
+ if (!(shootable.getItem() instanceof ProjectileWeaponItem)) {
+ return ItemStack.EMPTY;
+ } else {
+- Predicate<ItemStack> supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getSupportedHeldProjectiles();
+- ItemStack heldProjectile = ProjectileWeaponItem.getHeldProjectile(this, supportedHeldProjectiles);
+- if (!heldProjectile.isEmpty()) {
+- return heldProjectile;
++ Predicate<ItemStack> predicate = ((ProjectileWeaponItem) shootable.getItem()).getSupportedHeldProjectiles();
++ ItemStack itemstack1 = ProjectileWeaponItem.getHeldProjectile(this, predicate);
++
++ if (!itemstack1.isEmpty()) {
++ return itemstack1;
+ } else {
+- supportedHeldProjectiles = ((ProjectileWeaponItem)shootable.getItem()).getAllSupportedProjectiles();
++ predicate = ((ProjectileWeaponItem) shootable.getItem()).getAllSupportedProjectiles();
+
+- for (int i = 0; i < this.inventory.getContainerSize(); i++) {
+- ItemStack item = this.inventory.getItem(i);
+- if (supportedHeldProjectiles.test(item)) {
+- return item;
++ for (int i = 0; i < this.inventory.getContainerSize(); ++i) {
++ ItemStack itemstack2 = this.inventory.getItem(i);
++
++ if (predicate.test(itemstack2)) {
++ return itemstack2;
+ }
+ }
+
+@@ -1978,45 +2157,53 @@
+ public ItemStack eat(Level level, ItemStack food) {
+ this.getFoodData().eat(food.getItem(), food);
+ this.awardStat(Stats.ITEM_USED.get(food.getItem()));
+- level.playSound(null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F);
++ level.playSound((Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.PLAYER_BURP, SoundSource.PLAYERS, 0.5F, level.random.nextFloat() * 0.1F + 0.9F);
+ if (this instanceof ServerPlayer) {
+- CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer)this, food);
++ CriteriaTriggers.CONSUME_ITEM.trigger((ServerPlayer) this, food);
+ }
+
+ return super.eat(level, food);
+ }
+
+ @Override
+- protected boolean shouldRemoveSoulSpeed(BlockState state) {
++ protected boolean shouldRemoveSoulSpeed(IBlockData state) {
+ return this.abilities.flying || super.shouldRemoveSoulSpeed(state);
+ }
+
+ @Override
+ public Vec3 getRopeHoldPosition(float partialTicks) {
+- double d = 0.22 * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0 : 1.0);
+- float f = Mth.lerp(partialTicks * 0.5F, this.getXRot(), this.xRotO) * (float) (Math.PI / 180.0);
+- float f1 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * (float) (Math.PI / 180.0);
+- if (this.isFallFlying() || this.isAutoSpinAttack()) {
+- Vec3 viewVector = this.getViewVector(partialTicks);
+- Vec3 deltaMovement = this.getDeltaMovement();
+- double d1 = deltaMovement.horizontalDistanceSqr();
+- double d2 = viewVector.horizontalDistanceSqr();
+- float f2;
+- if (d1 > 0.0 && d2 > 0.0) {
+- double d3 = (deltaMovement.x * viewVector.x + deltaMovement.z * viewVector.z) / Math.sqrt(d1 * d2);
+- double d4 = deltaMovement.x * viewVector.z - deltaMovement.z * viewVector.x;
+- f2 = (float)(Math.signum(d4) * Math.acos(d3));
++ double d0 = 0.22D * (this.getMainArm() == HumanoidArm.RIGHT ? -1.0D : 1.0D);
++ float f1 = Mth.lerp(partialTicks * 0.5F, this.getXRot(), this.xRotO) * 0.017453292F;
++ float f2 = Mth.lerp(partialTicks, this.yBodyRotO, this.yBodyRot) * 0.017453292F;
++ double d1;
++
++ if (!this.isFallFlying() && !this.isAutoSpinAttack()) {
++ if (this.isVisuallySwimming()) {
++ return this.getPosition(partialTicks).add((new Vec3(d0, 0.2D, -0.15D)).xRot(-f1).yRot(-f2));
+ } else {
+- f2 = 0.0F;
+- }
++ double d2 = this.getBoundingBox().getYsize() - 1.0D;
+
+- return this.getPosition(partialTicks).add(new Vec3(d, -0.11, 0.85).zRot(-f2).xRot(-f).yRot(-f1));
+- } else if (this.isVisuallySwimming()) {
+- return this.getPosition(partialTicks).add(new Vec3(d, 0.2, -0.15).xRot(-f).yRot(-f1));
++ d1 = this.isCrouching() ? -0.2D : 0.07D;
++ return this.getPosition(partialTicks).add((new Vec3(d0, d2, d1)).yRot(-f2));
++ }
+ } else {
+- double d5 = this.getBoundingBox().getYsize() - 1.0;
+- double d1 = this.isCrouching() ? -0.2 : 0.07;
+- return this.getPosition(partialTicks).add(new Vec3(d, d5, d1).yRot(-f1));
++ Vec3 vec3d = this.getViewVector(partialTicks);
++ Vec3 vec3d1 = this.getDeltaMovement();
++
++ d1 = vec3d1.horizontalDistanceSqr();
++ double d3 = vec3d.horizontalDistanceSqr();
++ float f3;
++
++ if (d1 > 0.0D && d3 > 0.0D) {
++ double d4 = (vec3d1.x * vec3d.x + vec3d1.z * vec3d.z) / Math.sqrt(d1 * d3);
++ double d5 = vec3d1.x * vec3d.z - vec3d1.z * vec3d.x;
++
++ f3 = (float) (Math.signum(d5) * Math.acos(d4));
++ } else {
++ f3 = 0.0F;
++ }
++
++ return this.getPosition(partialTicks).add((new Vec3(d0, -0.11D, 0.85D)).zRot(-f3).xRot(-f1).yRot(-f2));
+ }
+ }
+
+@@ -2060,15 +2247,13 @@
+
+ @Override
+ protected float getFlyingSpeed() {
+- if (this.abilities.flying && !this.isPassenger()) {
+- return this.isSprinting() ? this.abilities.getFlyingSpeed() * 2.0F : this.abilities.getFlyingSpeed();
+- } else {
+- return this.isSprinting() ? 0.025999999F : 0.02F;
+- }
++ return this.abilities.flying && !this.isPassenger() ? (this.isSprinting() ? this.abilities.getFlyingSpeed() * 2.0F : this.abilities.getFlyingSpeed()) : (this.isSprinting() ? 0.025999999F : 0.02F);
+ }
+
+- public static boolean isValidUsername(String string) {
+- return string.length() <= 16 && string.chars().filter(i -> i <= 32 || i >= 127).findAny().isEmpty();
++ public static boolean isValidUsername(String s) {
++ return s.length() > 16 ? false : s.chars().filter((i) -> {
++ return i <= 32 || i >= 127;
++ }).findAny().isEmpty();
+ }
+
+ public static float getPickRange(boolean flag) {
+@@ -2076,13 +2261,9 @@
+ }
+
+ public static enum BedSleepingProblem {
+- NOT_POSSIBLE_HERE,
+- NOT_POSSIBLE_NOW(Component.translatable("block.minecraft.bed.no_sleep")),
+- TOO_FAR_AWAY(Component.translatable("block.minecraft.bed.too_far_away")),
+- OBSTRUCTED(Component.translatable("block.minecraft.bed.obstructed")),
+- OTHER_PROBLEM,
+- NOT_SAFE(Component.translatable("block.minecraft.bed.not_safe"));
+
++ NOT_POSSIBLE_HERE, NOT_POSSIBLE_NOW(Component.translatable("block.minecraft.bed.no_sleep")), TOO_FAR_AWAY(Component.translatable("block.minecraft.bed.too_far_away")), OBSTRUCTED(Component.translatable("block.minecraft.bed.obstructed")), OTHER_PROBLEM, NOT_SAFE(Component.translatable("block.minecraft.bed.not_safe"));
++
+ @Nullable
+ private final Component message;
+
+@@ -2090,8 +2271,8 @@
+ this.message = null;
+ }
+
+- private BedSleepingProblem(Component message) {
+- this.message = message;
++ private BedSleepingProblem(Component ichatbasecomponent) {
++ this.message = ichatbasecomponent;
+ }
+
+ @Nullable