--- a/net/minecraft/world/entity/decoration/ArmorStand.java
+++ b/net/minecraft/world/entity/decoration/ArmorStand.java
@@ -1,5 +1,7 @@
 package net.minecraft.world.entity.decoration;
 
+import java.util.Iterator;
+import java.util.List;
 import java.util.function.Predicate;
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
@@ -22,13 +24,11 @@
 import net.minecraft.world.entity.Entity;
 import net.minecraft.world.entity.EntityDimensions;
 import net.minecraft.world.entity.EntityType;
-import net.minecraft.world.entity.EquipmentSlot;
 import net.minecraft.world.entity.HumanoidArm;
 import net.minecraft.world.entity.LightningBolt;
 import net.minecraft.world.entity.LivingEntity;
 import net.minecraft.world.entity.Mob;
 import net.minecraft.world.entity.Pose;
-import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.entity.projectile.AbstractArrow;
 import net.minecraft.world.entity.vehicle.AbstractMinecart;
 import net.minecraft.world.item.ItemStack;
@@ -41,8 +41,16 @@
 import net.minecraft.world.level.material.PushReaction;
 import net.minecraft.world.phys.AABB;
 import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.craftbukkit.v1_20_R2.CraftEquipmentSlot;
+import org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.event.player.PlayerArmorStandManipulateEvent;
+// CraftBukkit end
 
 public class ArmorStand extends LivingEntity {
+
     public static final int WOBBLE_TIME = 5;
     private static final boolean ENABLE_ARMS = true;
     private static final Rotations DEFAULT_HEAD_POSE = new Rotations(0.0F, 0.0F, 0.0F);
@@ -71,22 +79,38 @@
     public static final EntityDataAccessor<Rotations> DATA_LEFT_LEG_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS);
     public static final EntityDataAccessor<Rotations> DATA_RIGHT_LEG_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS);
     private static final Predicate<Entity> RIDABLE_MINECARTS = (entity) -> {
-        return entity instanceof AbstractMinecart && ((AbstractMinecart)entity).getMinecartType() == AbstractMinecart.Type.RIDEABLE;
+        return entity instanceof AbstractMinecart && ((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.Type.RIDEABLE;
     };
-    private final NonNullList<ItemStack> handItems = NonNullList.withSize(2, ItemStack.EMPTY);
-    private final NonNullList<ItemStack> armorItems = NonNullList.withSize(4, ItemStack.EMPTY);
+    private final NonNullList<ItemStack> handItems;
+    private final NonNullList<ItemStack> armorItems;
     private boolean invisible;
     public long lastHit;
     public int disabledSlots;
-    public Rotations headPose = DEFAULT_HEAD_POSE;
-    public Rotations bodyPose = DEFAULT_BODY_POSE;
-    public Rotations leftArmPose = DEFAULT_LEFT_ARM_POSE;
-    public Rotations rightArmPose = DEFAULT_RIGHT_ARM_POSE;
-    public Rotations leftLegPose = DEFAULT_LEFT_LEG_POSE;
-    public Rotations rightLegPose = DEFAULT_RIGHT_LEG_POSE;
+    public Rotations headPose;
+    public Rotations bodyPose;
+    public Rotations leftArmPose;
+    public Rotations rightArmPose;
+    public Rotations leftLegPose;
+    public Rotations rightLegPose;
+    public boolean canMove = true; // Paper
+    // Paper start - Allow ArmorStands not to tick
+    public boolean canTick = true;
+    public boolean canTickSetByAPI = false;
+    private boolean noTickPoseDirty = false;
+    private boolean noTickEquipmentDirty = false;
+    // Paper end
 
     public ArmorStand(EntityType<? extends ArmorStand> type, Level world) {
         super(type, world);
+        if (world != null) this.canTick = world.paperConfig().entities.armorStands.tick; // Paper - armour stand ticking
+        this.handItems = NonNullList.withSize(2, ItemStack.EMPTY);
+        this.armorItems = NonNullList.withSize(4, ItemStack.EMPTY);
+        this.headPose = ArmorStand.DEFAULT_HEAD_POSE;
+        this.bodyPose = ArmorStand.DEFAULT_BODY_POSE;
+        this.leftArmPose = ArmorStand.DEFAULT_LEFT_ARM_POSE;
+        this.rightArmPose = ArmorStand.DEFAULT_RIGHT_ARM_POSE;
+        this.leftLegPose = ArmorStand.DEFAULT_LEFT_LEG_POSE;
+        this.rightLegPose = ArmorStand.DEFAULT_RIGHT_LEG_POSE;
         this.setMaxUpStep(0.0F);
     }
 
@@ -95,13 +119,21 @@
         this.setPos(x, y, z);
     }
 
+    // CraftBukkit start - SPIGOT-3607, SPIGOT-3637
+    @Override
+    public float getBukkitYaw() {
+        return this.getYRot();
+    }
+    // CraftBukkit end
+
     @Override
     public void refreshDimensions() {
-        double d = this.getX();
-        double e = this.getY();
-        double f = this.getZ();
+        double d0 = this.getX();
+        double d1 = this.getY();
+        double d2 = this.getZ();
+
         super.refreshDimensions();
-        this.setPos(d, e, f);
+        this.setPos(d0, d1, d2);
     }
 
     private boolean hasPhysics() {
@@ -116,13 +148,13 @@
     @Override
     protected void defineSynchedData() {
         super.defineSynchedData();
-        this.entityData.define(DATA_CLIENT_FLAGS, (byte)0);
-        this.entityData.define(DATA_HEAD_POSE, DEFAULT_HEAD_POSE);
-        this.entityData.define(DATA_BODY_POSE, DEFAULT_BODY_POSE);
-        this.entityData.define(DATA_LEFT_ARM_POSE, DEFAULT_LEFT_ARM_POSE);
-        this.entityData.define(DATA_RIGHT_ARM_POSE, DEFAULT_RIGHT_ARM_POSE);
-        this.entityData.define(DATA_LEFT_LEG_POSE, DEFAULT_LEFT_LEG_POSE);
-        this.entityData.define(DATA_RIGHT_LEG_POSE, DEFAULT_RIGHT_LEG_POSE);
+        this.entityData.define(ArmorStand.DATA_CLIENT_FLAGS, (byte) 0);
+        this.entityData.define(ArmorStand.DATA_HEAD_POSE, ArmorStand.DEFAULT_HEAD_POSE);
+        this.entityData.define(ArmorStand.DATA_BODY_POSE, ArmorStand.DEFAULT_BODY_POSE);
+        this.entityData.define(ArmorStand.DATA_LEFT_ARM_POSE, ArmorStand.DEFAULT_LEFT_ARM_POSE);
+        this.entityData.define(ArmorStand.DATA_RIGHT_ARM_POSE, ArmorStand.DEFAULT_RIGHT_ARM_POSE);
+        this.entityData.define(ArmorStand.DATA_LEFT_LEG_POSE, ArmorStand.DEFAULT_LEFT_LEG_POSE);
+        this.entityData.define(ArmorStand.DATA_RIGHT_LEG_POSE, ArmorStand.DEFAULT_RIGHT_LEG_POSE);
     }
 
     @Override
@@ -136,63 +168,76 @@
     }
 
     @Override
-    public ItemStack getItemBySlot(EquipmentSlot slot) {
+    public ItemStack getItemBySlot(net.minecraft.world.entity.EquipmentSlot slot) {
         switch (slot.getType()) {
             case HAND:
-                return this.handItems.get(slot.getIndex());
+                return (ItemStack) this.handItems.get(slot.getIndex());
             case ARMOR:
-                return this.armorItems.get(slot.getIndex());
+                return (ItemStack) this.armorItems.get(slot.getIndex());
             default:
                 return ItemStack.EMPTY;
         }
     }
 
     @Override
-    public void setItemSlot(EquipmentSlot slot, ItemStack stack) {
-        this.verifyEquippedItem(stack);
-        switch (slot.getType()) {
+    public void setItemSlot(net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack) {
+        // CraftBukkit start
+        this.setItemSlot(slot, stack, false);
+    }
+
+    @Override
+    public void setItemSlot(net.minecraft.world.entity.EquipmentSlot enumitemslot, ItemStack itemstack, boolean silent) {
+        // CraftBukkit end
+        this.verifyEquippedItem(itemstack);
+        switch (enumitemslot.getType()) {
             case HAND:
-                this.onEquipItem(slot, this.handItems.set(slot.getIndex(), stack), stack);
+                this.onEquipItem(enumitemslot, (ItemStack) this.handItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit
                 break;
             case ARMOR:
-                this.onEquipItem(slot, this.armorItems.set(slot.getIndex(), stack), stack);
+                this.onEquipItem(enumitemslot, (ItemStack) this.armorItems.set(enumitemslot.getIndex(), itemstack), itemstack, silent); // CraftBukkit
         }
 
+        this.noTickEquipmentDirty = true; // Paper - Allow equipment to be updated even when tick disabled
     }
 
     @Override
     public boolean canTakeItem(ItemStack stack) {
-        EquipmentSlot equipmentSlot = Mob.getEquipmentSlotForItem(stack);
-        return this.getItemBySlot(equipmentSlot).isEmpty() && !this.isDisabled(equipmentSlot);
+        net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(stack);
+
+        return this.getItemBySlot(enumitemslot).isEmpty() && !this.isDisabled(enumitemslot);
     }
 
     @Override
     public void addAdditionalSaveData(CompoundTag nbt) {
         super.addAdditionalSaveData(nbt);
-        ListTag listTag = new ListTag();
+        ListTag nbttaglist = new ListTag();
 
-        for(ItemStack itemStack : this.armorItems) {
-            CompoundTag compoundTag = new CompoundTag();
-            if (!itemStack.isEmpty()) {
-                itemStack.save(compoundTag);
-            }
+        CompoundTag nbttagcompound1;
 
-            listTag.add(compoundTag);
+        for (Iterator iterator = this.armorItems.iterator(); iterator.hasNext(); nbttaglist.add(nbttagcompound1)) {
+            ItemStack itemstack = (ItemStack) iterator.next();
+
+            nbttagcompound1 = new CompoundTag();
+            if (!itemstack.isEmpty()) {
+                itemstack.save(nbttagcompound1);
+            }
         }
 
-        nbt.put("ArmorItems", listTag);
-        ListTag listTag2 = new ListTag();
+        nbt.put("ArmorItems", nbttaglist);
+        ListTag nbttaglist1 = new ListTag();
 
-        for(ItemStack itemStack2 : this.handItems) {
-            CompoundTag compoundTag2 = new CompoundTag();
-            if (!itemStack2.isEmpty()) {
-                itemStack2.save(compoundTag2);
-            }
+        CompoundTag nbttagcompound2;
 
-            listTag2.add(compoundTag2);
+        for (Iterator iterator1 = this.handItems.iterator(); iterator1.hasNext(); nbttaglist1.add(nbttagcompound2)) {
+            ItemStack itemstack1 = (ItemStack) iterator1.next();
+
+            nbttagcompound2 = new CompoundTag();
+            if (!itemstack1.isEmpty()) {
+                itemstack1.save(nbttagcompound2);
+            }
         }
 
-        nbt.put("HandItems", listTag2);
+        nbt.put("HandItems", nbttaglist1);
         nbt.putBoolean("Invisible", this.isInvisible());
         nbt.putBoolean("Small", this.isSmall());
         nbt.putBoolean("ShowArms", this.isShowArms());
@@ -203,24 +248,28 @@
         }
 
         nbt.put("Pose", this.writePose());
+        if (this.canTickSetByAPI) nbt.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - persist no tick setting
     }
 
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
+        ListTag nbttaglist;
+        int i;
+
         if (nbt.contains("ArmorItems", 9)) {
-            ListTag listTag = nbt.getList("ArmorItems", 10);
+            nbttaglist = nbt.getList("ArmorItems", 10);
 
-            for(int i = 0; i < this.armorItems.size(); ++i) {
-                this.armorItems.set(i, ItemStack.of(listTag.getCompound(i)));
+            for (i = 0; i < this.armorItems.size(); ++i) {
+                this.armorItems.set(i, ItemStack.of(nbttaglist.getCompound(i)));
             }
         }
 
         if (nbt.contains("HandItems", 9)) {
-            ListTag listTag2 = nbt.getList("HandItems", 10);
+            nbttaglist = nbt.getList("HandItems", 10);
 
-            for(int j = 0; j < this.handItems.size(); ++j) {
-                this.handItems.set(j, ItemStack.of(listTag2.getCompound(j)));
+            for (i = 0; i < this.handItems.size(); ++i) {
+                this.handItems.set(i, ItemStack.of(nbttaglist.getCompound(i)));
             }
         }
 
@@ -231,66 +280,85 @@
         this.setNoBasePlate(nbt.getBoolean("NoBasePlate"));
         this.setMarker(nbt.getBoolean("Marker"));
         this.noPhysics = !this.hasPhysics();
-        CompoundTag compoundTag = nbt.getCompound("Pose");
-        this.readPose(compoundTag);
+        // Paper start - persist no tick
+        if (nbt.contains("Paper.CanTickOverride")) {
+            this.canTick = nbt.getBoolean("Paper.CanTickOverride");
+            this.canTickSetByAPI = true;
+        }
+        // Paper end
+        CompoundTag nbttagcompound1 = nbt.getCompound("Pose");
+
+        this.readPose(nbttagcompound1);
     }
 
     private void readPose(CompoundTag nbt) {
-        ListTag listTag = nbt.getList("Head", 5);
-        this.setHeadPose(listTag.isEmpty() ? DEFAULT_HEAD_POSE : new Rotations(listTag));
-        ListTag listTag2 = nbt.getList("Body", 5);
-        this.setBodyPose(listTag2.isEmpty() ? DEFAULT_BODY_POSE : new Rotations(listTag2));
-        ListTag listTag3 = nbt.getList("LeftArm", 5);
-        this.setLeftArmPose(listTag3.isEmpty() ? DEFAULT_LEFT_ARM_POSE : new Rotations(listTag3));
-        ListTag listTag4 = nbt.getList("RightArm", 5);
-        this.setRightArmPose(listTag4.isEmpty() ? DEFAULT_RIGHT_ARM_POSE : new Rotations(listTag4));
-        ListTag listTag5 = nbt.getList("LeftLeg", 5);
-        this.setLeftLegPose(listTag5.isEmpty() ? DEFAULT_LEFT_LEG_POSE : new Rotations(listTag5));
-        ListTag listTag6 = nbt.getList("RightLeg", 5);
-        this.setRightLegPose(listTag6.isEmpty() ? DEFAULT_RIGHT_LEG_POSE : new Rotations(listTag6));
+        ListTag nbttaglist = nbt.getList("Head", 5);
+
+        this.setHeadPose(nbttaglist.isEmpty() ? ArmorStand.DEFAULT_HEAD_POSE : new Rotations(nbttaglist));
+        ListTag nbttaglist1 = nbt.getList("Body", 5);
+
+        this.setBodyPose(nbttaglist1.isEmpty() ? ArmorStand.DEFAULT_BODY_POSE : new Rotations(nbttaglist1));
+        ListTag nbttaglist2 = nbt.getList("LeftArm", 5);
+
+        this.setLeftArmPose(nbttaglist2.isEmpty() ? ArmorStand.DEFAULT_LEFT_ARM_POSE : new Rotations(nbttaglist2));
+        ListTag nbttaglist3 = nbt.getList("RightArm", 5);
+
+        this.setRightArmPose(nbttaglist3.isEmpty() ? ArmorStand.DEFAULT_RIGHT_ARM_POSE : new Rotations(nbttaglist3));
+        ListTag nbttaglist4 = nbt.getList("LeftLeg", 5);
+
+        this.setLeftLegPose(nbttaglist4.isEmpty() ? ArmorStand.DEFAULT_LEFT_LEG_POSE : new Rotations(nbttaglist4));
+        ListTag nbttaglist5 = nbt.getList("RightLeg", 5);
+
+        this.setRightLegPose(nbttaglist5.isEmpty() ? ArmorStand.DEFAULT_RIGHT_LEG_POSE : new Rotations(nbttaglist5));
     }
 
     private CompoundTag writePose() {
-        CompoundTag compoundTag = new CompoundTag();
-        if (!DEFAULT_HEAD_POSE.equals(this.headPose)) {
-            compoundTag.put("Head", this.headPose.save());
+        CompoundTag nbttagcompound = new CompoundTag();
+
+        if (!ArmorStand.DEFAULT_HEAD_POSE.equals(this.headPose)) {
+            nbttagcompound.put("Head", this.headPose.save());
         }
 
-        if (!DEFAULT_BODY_POSE.equals(this.bodyPose)) {
-            compoundTag.put("Body", this.bodyPose.save());
+        if (!ArmorStand.DEFAULT_BODY_POSE.equals(this.bodyPose)) {
+            nbttagcompound.put("Body", this.bodyPose.save());
         }
 
-        if (!DEFAULT_LEFT_ARM_POSE.equals(this.leftArmPose)) {
-            compoundTag.put("LeftArm", this.leftArmPose.save());
+        if (!ArmorStand.DEFAULT_LEFT_ARM_POSE.equals(this.leftArmPose)) {
+            nbttagcompound.put("LeftArm", this.leftArmPose.save());
         }
 
-        if (!DEFAULT_RIGHT_ARM_POSE.equals(this.rightArmPose)) {
-            compoundTag.put("RightArm", this.rightArmPose.save());
+        if (!ArmorStand.DEFAULT_RIGHT_ARM_POSE.equals(this.rightArmPose)) {
+            nbttagcompound.put("RightArm", this.rightArmPose.save());
         }
 
-        if (!DEFAULT_LEFT_LEG_POSE.equals(this.leftLegPose)) {
-            compoundTag.put("LeftLeg", this.leftLegPose.save());
+        if (!ArmorStand.DEFAULT_LEFT_LEG_POSE.equals(this.leftLegPose)) {
+            nbttagcompound.put("LeftLeg", this.leftLegPose.save());
         }
 
-        if (!DEFAULT_RIGHT_LEG_POSE.equals(this.rightLegPose)) {
-            compoundTag.put("RightLeg", this.rightLegPose.save());
+        if (!ArmorStand.DEFAULT_RIGHT_LEG_POSE.equals(this.rightLegPose)) {
+            nbttagcompound.put("RightLeg", this.rightLegPose.save());
         }
 
-        return compoundTag;
+        return nbttagcompound;
     }
 
     @Override
-    public boolean isPushable() {
+    public boolean isCollidable(boolean ignoreClimbing) { // Paper
         return false;
     }
 
     @Override
-    protected void doPush(Entity entity) {
-    }
+    protected void doPush(Entity entity) {}
 
     @Override
     protected void pushEntities() {
-        for(Entity entity : this.level().getEntities(this, this.getBoundingBox(), RIDABLE_MINECARTS)) {
+        if (!this.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return; // Paper
+        List<AbstractMinecart> list = this.level().getEntitiesOfClass(AbstractMinecart.class, this.getBoundingBox(), ArmorStand.RIDABLE_MINECARTS); // Paper - optimise collisions
+        Iterator iterator = list.iterator();
+
+        while (iterator.hasNext()) {
+            Entity entity = (Entity) iterator.next();
+
             if (this.distanceToSqr(entity) <= 0.2D) {
                 entity.push(this);
             }
@@ -299,31 +367,34 @@
     }
 
     @Override
-    public InteractionResult interactAt(Player player, Vec3 hitPos, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        if (!this.isMarker() && !itemStack.is(Items.NAME_TAG)) {
+    public InteractionResult interactAt(net.minecraft.world.entity.player.Player player, Vec3 hitPos, InteractionHand hand) {
+        ItemStack itemstack = player.getItemInHand(hand);
+
+        if (!this.isMarker() && !itemstack.is(Items.NAME_TAG)) {
             if (player.isSpectator()) {
                 return InteractionResult.SUCCESS;
             } else if (player.level().isClientSide) {
                 return InteractionResult.CONSUME;
             } else {
-                EquipmentSlot equipmentSlot = Mob.getEquipmentSlotForItem(itemStack);
-                if (itemStack.isEmpty()) {
-                    EquipmentSlot equipmentSlot2 = this.getClickedSlot(hitPos);
-                    EquipmentSlot equipmentSlot3 = this.isDisabled(equipmentSlot2) ? equipmentSlot : equipmentSlot2;
-                    if (this.hasItemInSlot(equipmentSlot3) && this.swapItem(player, equipmentSlot3, itemStack, hand)) {
+                net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack);
+
+                if (itemstack.isEmpty()) {
+                    net.minecraft.world.entity.EquipmentSlot enumitemslot1 = this.getClickedSlot(hitPos);
+                    net.minecraft.world.entity.EquipmentSlot enumitemslot2 = this.isDisabled(enumitemslot1) ? enumitemslot : enumitemslot1;
+
+                    if (this.hasItemInSlot(enumitemslot2) && this.swapItem(player, enumitemslot2, itemstack, hand)) {
                         return InteractionResult.SUCCESS;
                     }
                 } else {
-                    if (this.isDisabled(equipmentSlot)) {
+                    if (this.isDisabled(enumitemslot)) {
                         return InteractionResult.FAIL;
                     }
 
-                    if (equipmentSlot.getType() == EquipmentSlot.Type.HAND && !this.isShowArms()) {
+                    if (enumitemslot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms()) {
                         return InteractionResult.FAIL;
                     }
 
-                    if (this.swapItem(player, equipmentSlot, itemStack, hand)) {
+                    if (this.swapItem(player, enumitemslot, itemstack, hand)) {
                         return InteractionResult.SUCCESS;
                     }
                 }
@@ -335,41 +406,61 @@
         }
     }
 
-    private EquipmentSlot getClickedSlot(Vec3 hitPos) {
-        EquipmentSlot equipmentSlot = EquipmentSlot.MAINHAND;
-        boolean bl = this.isSmall();
-        double d = bl ? hitPos.y * 2.0D : hitPos.y;
-        EquipmentSlot equipmentSlot2 = EquipmentSlot.FEET;
-        if (d >= 0.1D && d < 0.1D + (bl ? 0.8D : 0.45D) && this.hasItemInSlot(equipmentSlot2)) {
-            equipmentSlot = EquipmentSlot.FEET;
-        } else if (d >= 0.9D + (bl ? 0.3D : 0.0D) && d < 0.9D + (bl ? 1.0D : 0.7D) && this.hasItemInSlot(EquipmentSlot.CHEST)) {
-            equipmentSlot = EquipmentSlot.CHEST;
-        } else if (d >= 0.4D && d < 0.4D + (bl ? 1.0D : 0.8D) && this.hasItemInSlot(EquipmentSlot.LEGS)) {
-            equipmentSlot = EquipmentSlot.LEGS;
-        } else if (d >= 1.6D && this.hasItemInSlot(EquipmentSlot.HEAD)) {
-            equipmentSlot = EquipmentSlot.HEAD;
-        } else if (!this.hasItemInSlot(EquipmentSlot.MAINHAND) && this.hasItemInSlot(EquipmentSlot.OFFHAND)) {
-            equipmentSlot = EquipmentSlot.OFFHAND;
+    private net.minecraft.world.entity.EquipmentSlot getClickedSlot(Vec3 hitPos) {
+        net.minecraft.world.entity.EquipmentSlot enumitemslot = net.minecraft.world.entity.EquipmentSlot.MAINHAND;
+        boolean flag = this.isSmall();
+        double d0 = flag ? hitPos.y * 2.0D : hitPos.y;
+        net.minecraft.world.entity.EquipmentSlot enumitemslot1 = net.minecraft.world.entity.EquipmentSlot.FEET;
+
+        if (d0 >= 0.1D && d0 < 0.1D + (flag ? 0.8D : 0.45D) && this.hasItemInSlot(enumitemslot1)) {
+            enumitemslot = net.minecraft.world.entity.EquipmentSlot.FEET;
+        } else if (d0 >= 0.9D + (flag ? 0.3D : 0.0D) && d0 < 0.9D + (flag ? 1.0D : 0.7D) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.CHEST)) {
+            enumitemslot = net.minecraft.world.entity.EquipmentSlot.CHEST;
+        } else if (d0 >= 0.4D && d0 < 0.4D + (flag ? 1.0D : 0.8D) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.LEGS)) {
+            enumitemslot = net.minecraft.world.entity.EquipmentSlot.LEGS;
+        } else if (d0 >= 1.6D && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.HEAD)) {
+            enumitemslot = net.minecraft.world.entity.EquipmentSlot.HEAD;
+        } else if (!this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.MAINHAND) && this.hasItemInSlot(net.minecraft.world.entity.EquipmentSlot.OFFHAND)) {
+            enumitemslot = net.minecraft.world.entity.EquipmentSlot.OFFHAND;
         }
 
-        return equipmentSlot;
+        return enumitemslot;
     }
 
-    public boolean isDisabled(EquipmentSlot slot) {
-        return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == EquipmentSlot.Type.HAND && !this.isShowArms();
+    public boolean isDisabled(net.minecraft.world.entity.EquipmentSlot slot) {
+        return (this.disabledSlots & 1 << slot.getFilterFlag()) != 0 || slot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms();
     }
 
-    private boolean swapItem(Player player, EquipmentSlot slot, ItemStack stack, InteractionHand hand) {
-        ItemStack itemStack = this.getItemBySlot(slot);
-        if (!itemStack.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 8) != 0) {
+    private boolean swapItem(net.minecraft.world.entity.player.Player player, net.minecraft.world.entity.EquipmentSlot slot, ItemStack stack, InteractionHand hand) {
+        ItemStack itemstack1 = this.getItemBySlot(slot);
+
+        if (!itemstack1.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 8) != 0) {
             return false;
-        } else if (itemStack.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 16) != 0) {
+        } else if (itemstack1.isEmpty() && (this.disabledSlots & 1 << slot.getFilterFlag() + 16) != 0) {
             return false;
-        } else if (player.getAbilities().instabuild && itemStack.isEmpty() && !stack.isEmpty()) {
+            // CraftBukkit start
+        } else {
+            org.bukkit.inventory.ItemStack armorStandItem = CraftItemStack.asCraftMirror(itemstack1);
+            org.bukkit.inventory.ItemStack playerHeldItem = CraftItemStack.asCraftMirror(stack);
+
+            Player player1 = (Player) player.getBukkitEntity();
+            org.bukkit.entity.ArmorStand self = (org.bukkit.entity.ArmorStand) this.getBukkitEntity();
+
+            EquipmentSlot slot1 = CraftEquipmentSlot.getSlot(slot);
+            EquipmentSlot hand1 = CraftEquipmentSlot.getHand(hand);
+            PlayerArmorStandManipulateEvent armorStandManipulateEvent = new PlayerArmorStandManipulateEvent(player1, self, playerHeldItem, armorStandItem, slot1, hand1);
+            this.level().getCraftServer().getPluginManager().callEvent(armorStandManipulateEvent);
+
+            if (armorStandManipulateEvent.isCancelled()) {
+                return true;
+            }
+
+        if (player.getAbilities().instabuild && itemstack1.isEmpty() && !stack.isEmpty()) {
+            // CraftBukkit end
             this.setItemSlot(slot, stack.copyWithCount(1));
             return true;
         } else if (!stack.isEmpty() && stack.getCount() > 1) {
-            if (!itemStack.isEmpty()) {
+            if (!itemstack1.isEmpty()) {
                 return false;
             } else {
                 this.setItemSlot(slot, stack.split(1));
@@ -377,21 +468,34 @@
             }
         } else {
             this.setItemSlot(slot, stack);
-            player.setItemInHand(hand, itemStack);
+            player.setItemInHand(hand, itemstack1);
             return true;
         }
+        } // CraftBukkit
     }
 
     @Override
     public boolean hurt(DamageSource source, float amount) {
         if (!this.level().isClientSide && !this.isRemoved()) {
             if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) {
+                // CraftBukkit start
+                if (org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) {
+                    return false;
+                }
+                // CraftBukkit end
                 this.kill();
                 return false;
-            } else if (!this.isInvulnerableTo(source) && !this.invisible && !this.isMarker()) {
+            } else if (!this.isInvulnerableTo(source) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit
+                // CraftBukkit start
+                if (org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, true, this.invisible)) {
+                    return false;
+                }
+                // CraftBukkit end
                 if (source.is(DamageTypeTags.IS_EXPLOSION)) {
-                    this.brokenByAnything(source);
-                    this.kill();
+                    // Paper start - avoid duplicate event call
+                    org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(source);
+                    if (!event.isCancelled()) this.kill(false);
+                    // Paper end
                     return false;
                 } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) {
                     if (this.isOnFire()) {
@@ -405,15 +509,18 @@
                     this.causeDamage(source, 4.0F);
                     return false;
                 } else {
-                    boolean bl = "player".equals(source.getMsgId());
-                    boolean bl2 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS);
-                    if (!bl && !bl2) {
+                    boolean flag = "player".equals(source.getMsgId());
+                    boolean flag1 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS);
+
+                    if (!flag && !flag1) {
                         return false;
                     } else {
-                        Entity var6 = source.getEntity();
-                        if (var6 instanceof Player) {
-                            Player player = (Player)var6;
-                            if (!player.getAbilities().mayBuild) {
+                        Entity entity = source.getEntity();
+
+                        if (entity instanceof net.minecraft.world.entity.player.Player) {
+                            net.minecraft.world.entity.player.Player entityhuman = (net.minecraft.world.entity.player.Player) entity;
+
+                            if (!entityhuman.getAbilities().mayBuild) {
                                 return false;
                             }
                         }
@@ -422,25 +529,31 @@
                             this.playBrokenSound();
                             this.showBreakingParticles();
                             this.kill();
-                            var6 = source.getDirectEntity();
-                            if (var6 instanceof AbstractArrow) {
-                                AbstractArrow abstractArrow = (AbstractArrow)var6;
-                                if (abstractArrow.getPierceLevel() > 0) {
-                                    return true;
+                            entity = source.getDirectEntity();
+                            boolean flag2;
+
+                            if (entity instanceof AbstractArrow) {
+                                AbstractArrow entityarrow = (AbstractArrow) entity;
+
+                                if (entityarrow.getPierceLevel() > 0) {
+                                    flag2 = true;
+                                    return flag2;
                                 }
                             }
 
-                            return false;
+                            flag2 = false;
+                            return flag2;
                         } else {
-                            long l = this.level().getGameTime();
-                            if (l - this.lastHit > 5L && !bl2) {
-                                this.level().broadcastEntityEvent(this, (byte)32);
+                            long i = this.level().getGameTime();
+
+                            if (i - this.lastHit > 5L && !flag1) {
+                                this.level().broadcastEntityEvent(this, (byte) 32);
                                 this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
-                                this.lastHit = l;
+                                this.lastHit = i;
                             } else {
-                                this.brokenByPlayer(source);
+                                org.bukkit.event.entity.EntityDeathEvent event = this.brokenByPlayer(source); // Paper
                                 this.showBreakingParticles();
-                                this.kill();
+                                if (!event.isCancelled()) this.kill(false); // Paper - we still need to kill to follow vanilla logic (emit the game event etc...)
                             }
 
                             return true;
@@ -470,69 +583,78 @@
 
     @Override
     public boolean shouldRenderAtSqrDistance(double distance) {
-        double d = this.getBoundingBox().getSize() * 4.0D;
-        if (Double.isNaN(d) || d == 0.0D) {
-            d = 4.0D;
+        double d1 = this.getBoundingBox().getSize() * 4.0D;
+
+        if (Double.isNaN(d1) || d1 == 0.0D) {
+            d1 = 4.0D;
         }
 
-        d *= 64.0D;
-        return distance < d * d;
+        d1 *= 64.0D;
+        return distance < d1 * d1;
     }
 
     private void showBreakingParticles() {
         if (this.level() instanceof ServerLevel) {
-            ((ServerLevel)this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.OAK_PLANKS.defaultBlockState()), this.getX(), this.getY(0.6666666666666666D), this.getZ(), 10, (double)(this.getBbWidth() / 4.0F), (double)(this.getBbHeight() / 4.0F), (double)(this.getBbWidth() / 4.0F), 0.05D);
+            ((ServerLevel) this.level()).sendParticles(new BlockParticleOption(ParticleTypes.BLOCK, Blocks.OAK_PLANKS.defaultBlockState()), this.getX(), this.getY(0.6666666666666666D), this.getZ(), 10, (double) (this.getBbWidth() / 4.0F), (double) (this.getBbHeight() / 4.0F), (double) (this.getBbWidth() / 4.0F), 0.05D);
         }
 
     }
 
     private void causeDamage(DamageSource damageSource, float amount) {
-        float f = this.getHealth();
-        f -= amount;
-        if (f <= 0.5F) {
-            this.brokenByAnything(damageSource);
-            this.kill();
+        float f1 = this.getHealth();
+
+        f1 -= amount;
+        if (f1 <= 0.5F) {
+            // Paper start - avoid duplicate event call
+            org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(damageSource);
+            if (!event.isCancelled()) this.kill(false);
+            // Paper end
         } else {
-            this.setHealth(f);
+            this.setHealth(f1);
             this.gameEvent(GameEvent.ENTITY_DAMAGE, damageSource.getEntity());
         }
 
     }
 
-    private void brokenByPlayer(DamageSource damageSource) {
-        ItemStack itemStack = new ItemStack(Items.ARMOR_STAND);
+    private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(DamageSource damageSource) { // Paper
+        ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
+
         if (this.hasCustomName()) {
-            itemStack.setHoverName(this.getCustomName());
+            itemstack.setHoverName(this.getCustomName());
         }
 
-        Block.popResource(this.level(), this.blockPosition(), itemStack);
-        this.brokenByAnything(damageSource);
+        drops.add(org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack.asBukkitCopy(itemstack)); // CraftBukkit - add to drops
+        return this.brokenByAnything(damageSource); // Paper
     }
 
-    private void brokenByAnything(DamageSource damageSource) {
+    private org.bukkit.event.entity.EntityDeathEvent brokenByAnything(DamageSource damageSource) { // Paper
         this.playBrokenSound();
-        this.dropAllDeathLoot(damageSource);
+        // this.dropAllDeathLoot(damagesource); // CraftBukkit - moved down
 
-        for(int i = 0; i < this.handItems.size(); ++i) {
-            ItemStack itemStack = this.handItems.get(i);
-            if (!itemStack.isEmpty()) {
-                Block.popResource(this.level(), this.blockPosition().above(), itemStack);
+        ItemStack itemstack;
+        int i;
+
+        for (i = 0; i < this.handItems.size(); ++i) {
+            itemstack = (ItemStack) this.handItems.get(i);
+            if (!itemstack.isEmpty()) {
+                drops.add(org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
                 this.handItems.set(i, ItemStack.EMPTY);
             }
         }
 
-        for(int j = 0; j < this.armorItems.size(); ++j) {
-            ItemStack itemStack2 = this.armorItems.get(j);
-            if (!itemStack2.isEmpty()) {
-                Block.popResource(this.level(), this.blockPosition().above(), itemStack2);
-                this.armorItems.set(j, ItemStack.EMPTY);
+        for (i = 0; i < this.armorItems.size(); ++i) {
+            itemstack = (ItemStack) this.armorItems.get(i);
+            if (!itemstack.isEmpty()) {
+                drops.add(org.bukkit.craftbukkit.v1_20_R2.inventory.CraftItemStack.asCraftMirror(itemstack)); // CraftBukkit - add to drops // Paper - mirror so we can destroy it later - though this call site was safe
+                this.armorItems.set(i, ItemStack.EMPTY);
             }
         }
+        return this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above // Paper
 
     }
 
     private void playBrokenSound() {
-        this.level().playSound((Player)null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_BREAK, this.getSoundSource(), 1.0F, 1.0F);
+        this.level().playSound((net.minecraft.world.entity.player.Player) null, this.getX(), this.getY(), this.getZ(), SoundEvents.ARMOR_STAND_BREAK, this.getSoundSource(), 1.0F, 1.0F);
     }
 
     @Override
@@ -568,35 +690,63 @@
 
     @Override
     public void tick() {
+        // Paper start
+        if (!this.canTick) {
+            if (this.noTickPoseDirty) {
+                this.noTickPoseDirty = false;
+                this.updatePose();
+            }
+
+            if (this.noTickEquipmentDirty) {
+                this.noTickEquipmentDirty = false;
+                this.detectEquipmentUpdatesPublic();
+            }
+
+            return;
+        }
+        // Paper end
+
         super.tick();
-        Rotations rotations = this.entityData.get(DATA_HEAD_POSE);
-        if (!this.headPose.equals(rotations)) {
-            this.setHeadPose(rotations);
+        // Paper start - Split into separate method
+        updatePose();
+    }
+
+    public void updatePose() {
+        // Paper end
+        Rotations vector3f = (Rotations) this.entityData.get(ArmorStand.DATA_HEAD_POSE);
+
+        if (!this.headPose.equals(vector3f)) {
+            this.setHeadPose(vector3f);
         }
 
-        Rotations rotations2 = this.entityData.get(DATA_BODY_POSE);
-        if (!this.bodyPose.equals(rotations2)) {
-            this.setBodyPose(rotations2);
+        Rotations vector3f1 = (Rotations) this.entityData.get(ArmorStand.DATA_BODY_POSE);
+
+        if (!this.bodyPose.equals(vector3f1)) {
+            this.setBodyPose(vector3f1);
         }
 
-        Rotations rotations3 = this.entityData.get(DATA_LEFT_ARM_POSE);
-        if (!this.leftArmPose.equals(rotations3)) {
-            this.setLeftArmPose(rotations3);
+        Rotations vector3f2 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_ARM_POSE);
+
+        if (!this.leftArmPose.equals(vector3f2)) {
+            this.setLeftArmPose(vector3f2);
         }
 
-        Rotations rotations4 = this.entityData.get(DATA_RIGHT_ARM_POSE);
-        if (!this.rightArmPose.equals(rotations4)) {
-            this.setRightArmPose(rotations4);
+        Rotations vector3f3 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_ARM_POSE);
+
+        if (!this.rightArmPose.equals(vector3f3)) {
+            this.setRightArmPose(vector3f3);
         }
 
-        Rotations rotations5 = this.entityData.get(DATA_LEFT_LEG_POSE);
-        if (!this.leftLegPose.equals(rotations5)) {
-            this.setLeftLegPose(rotations5);
+        Rotations vector3f4 = (Rotations) this.entityData.get(ArmorStand.DATA_LEFT_LEG_POSE);
+
+        if (!this.leftLegPose.equals(vector3f4)) {
+            this.setLeftLegPose(vector3f4);
         }
 
-        Rotations rotations6 = this.entityData.get(DATA_RIGHT_LEG_POSE);
-        if (!this.rightLegPose.equals(rotations6)) {
-            this.setRightLegPose(rotations6);
+        Rotations vector3f5 = (Rotations) this.entityData.get(ArmorStand.DATA_RIGHT_LEG_POSE);
+
+        if (!this.rightLegPose.equals(vector3f5)) {
+            this.setRightLegPose(vector3f5);
         }
 
     }
@@ -617,8 +767,25 @@
         return this.isSmall();
     }
 
+    // CraftBukkit start
+    @Override
+    public boolean shouldDropExperience() {
+        return true; // MC-157395, SPIGOT-5193 even baby (small) armor stands should drop
+    }
+    // CraftBukkit end
+
     @Override
     public void kill() {
+        // Paper start
+        kill(true);
+    }
+
+    public void kill(boolean callEvent) {
+        if (callEvent) {
+        // Paper end
+        org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.v1_20_R2.event.CraftEventFactory.callEntityDeathEvent(this, drops); // CraftBukkit - call event // Paper - make cancellable
+        if (event.isCancelled()) return; // Paper - make cancellable
+        } // Paper
         this.remove(Entity.RemovalReason.KILLED);
         this.gameEvent(GameEvent.ENTITY_DIE);
     }
@@ -639,42 +806,42 @@
     }
 
     public void setSmall(boolean small) {
-        this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 1, small));
+        this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 1, small));
     }
 
     public boolean isSmall() {
-        return (this.entityData.get(DATA_CLIENT_FLAGS) & 1) != 0;
+        return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 1) != 0;
     }
 
     public void setShowArms(boolean showArms) {
-        this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 4, showArms));
+        this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 4, showArms));
     }
 
     public boolean isShowArms() {
-        return (this.entityData.get(DATA_CLIENT_FLAGS) & 4) != 0;
+        return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 4) != 0;
     }
 
     public void setNoBasePlate(boolean hideBasePlate) {
-        this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 8, hideBasePlate));
+        this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 8, hideBasePlate));
     }
 
     public boolean isNoBasePlate() {
-        return (this.entityData.get(DATA_CLIENT_FLAGS) & 8) != 0;
+        return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 8) != 0;
     }
 
     public void setMarker(boolean marker) {
-        this.entityData.set(DATA_CLIENT_FLAGS, this.setBit(this.entityData.get(DATA_CLIENT_FLAGS), 16, marker));
+        this.entityData.set(ArmorStand.DATA_CLIENT_FLAGS, this.setBit((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS), 16, marker));
     }
 
     public boolean isMarker() {
-        return (this.entityData.get(DATA_CLIENT_FLAGS) & 16) != 0;
+        return ((Byte) this.entityData.get(ArmorStand.DATA_CLIENT_FLAGS) & 16) != 0;
     }
 
     private byte setBit(byte value, int bitField, boolean set) {
         if (set) {
-            value = (byte)(value | bitField);
+            value = (byte) (value | bitField);
         } else {
-            value = (byte)(value & ~bitField);
+            value = (byte) (value & ~bitField);
         }
 
         return value;
@@ -682,32 +849,38 @@
 
     public void setHeadPose(Rotations angle) {
         this.headPose = angle;
-        this.entityData.set(DATA_HEAD_POSE, angle);
+        this.entityData.set(ArmorStand.DATA_HEAD_POSE, angle);
+        this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
     }
 
     public void setBodyPose(Rotations angle) {
         this.bodyPose = angle;
-        this.entityData.set(DATA_BODY_POSE, angle);
+        this.entityData.set(ArmorStand.DATA_BODY_POSE, angle);
+        this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
     }
 
     public void setLeftArmPose(Rotations angle) {
         this.leftArmPose = angle;
-        this.entityData.set(DATA_LEFT_ARM_POSE, angle);
+        this.entityData.set(ArmorStand.DATA_LEFT_ARM_POSE, angle);
+        this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
     }
 
     public void setRightArmPose(Rotations angle) {
         this.rightArmPose = angle;
-        this.entityData.set(DATA_RIGHT_ARM_POSE, angle);
+        this.entityData.set(ArmorStand.DATA_RIGHT_ARM_POSE, angle);
+        this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
     }
 
     public void setLeftLegPose(Rotations angle) {
         this.leftLegPose = angle;
-        this.entityData.set(DATA_LEFT_LEG_POSE, angle);
+        this.entityData.set(ArmorStand.DATA_LEFT_LEG_POSE, angle);
+        this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
     }
 
     public void setRightLegPose(Rotations angle) {
         this.rightLegPose = angle;
-        this.entityData.set(DATA_RIGHT_LEG_POSE, angle);
+        this.entityData.set(ArmorStand.DATA_RIGHT_LEG_POSE, angle);
+        this.noTickPoseDirty = true; // Paper - Allow updates when not ticking
     }
 
     public Rotations getHeadPose() {
@@ -741,7 +914,7 @@
 
     @Override
     public boolean skipAttackInteraction(Entity attacker) {
-        return attacker instanceof Player && !this.level().mayInteract((Player)attacker, this.blockPosition());
+        return attacker instanceof net.minecraft.world.entity.player.Player && !this.level().mayInteract((net.minecraft.world.entity.player.Player) attacker, this.blockPosition());
     }
 
     @Override
@@ -767,8 +940,7 @@
     }
 
     @Override
-    public void thunderHit(ServerLevel world, LightningBolt lightning) {
-    }
+    public void thunderHit(ServerLevel world, LightningBolt lightning) {}
 
     @Override
     public boolean isAffectedByPotions() {
@@ -777,7 +949,7 @@
 
     @Override
     public void onSyncedDataUpdated(EntityDataAccessor<?> data) {
-        if (DATA_CLIENT_FLAGS.equals(data)) {
+        if (ArmorStand.DATA_CLIENT_FLAGS.equals(data)) {
             this.refreshDimensions();
             this.blocksBuilding = !this.isMarker();
         }
@@ -796,33 +968,32 @@
     }
 
     private EntityDimensions getDimensionsMarker(boolean marker) {
-        if (marker) {
-            return MARKER_DIMENSIONS;
-        } else {
-            return this.isBaby() ? BABY_DIMENSIONS : this.getType().getDimensions();
-        }
+        return marker ? ArmorStand.MARKER_DIMENSIONS : (this.isBaby() ? ArmorStand.BABY_DIMENSIONS : this.getType().getDimensions());
     }
 
     @Override
     public Vec3 getLightProbePosition(float tickDelta) {
         if (this.isMarker()) {
-            AABB aABB = this.getDimensionsMarker(false).makeBoundingBox(this.position());
-            BlockPos blockPos = this.blockPosition();
+            AABB axisalignedbb = this.getDimensionsMarker(false).makeBoundingBox(this.position());
+            BlockPos blockposition = this.blockPosition();
             int i = Integer.MIN_VALUE;
+            Iterator iterator = BlockPos.betweenClosed(BlockPos.containing(axisalignedbb.minX, axisalignedbb.minY, axisalignedbb.minZ), BlockPos.containing(axisalignedbb.maxX, axisalignedbb.maxY, axisalignedbb.maxZ)).iterator();
+
+            while (iterator.hasNext()) {
+                BlockPos blockposition1 = (BlockPos) iterator.next();
+                int j = Math.max(this.level().getBrightness(LightLayer.BLOCK, blockposition1), this.level().getBrightness(LightLayer.SKY, blockposition1));
 
-            for(BlockPos blockPos2 : BlockPos.betweenClosed(BlockPos.containing(aABB.minX, aABB.minY, aABB.minZ), BlockPos.containing(aABB.maxX, aABB.maxY, aABB.maxZ))) {
-                int j = Math.max(this.level().getBrightness(LightLayer.BLOCK, blockPos2), this.level().getBrightness(LightLayer.SKY, blockPos2));
                 if (j == 15) {
-                    return Vec3.atCenterOf(blockPos2);
+                    return Vec3.atCenterOf(blockposition1);
                 }
 
                 if (j > i) {
                     i = j;
-                    blockPos = blockPos2.immutable();
+                    blockposition = blockposition1.immutable();
                 }
             }
 
-            return Vec3.atCenterOf(blockPos);
+            return Vec3.atCenterOf(blockposition);
         } else {
             return super.getLightProbePosition(tickDelta);
         }
@@ -837,4 +1008,20 @@
     public boolean canBeSeenByAnyone() {
         return !this.isInvisible() && !this.isMarker();
     }
+
+    // Paper start
+    @Override
+    public void move(net.minecraft.world.entity.MoverType type, Vec3 movement) {
+        if (this.canMove) {
+            super.move(type, movement);
+        }
+    }
+
+    // Paper start
+    @Override
+    public boolean canBreatheUnderwater() { // Skips a bit of damage handling code, probably a micro-optimization
+        return true;
+    }
+    // Paper end
+    // Paper end
 }
