--- 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;
@@ -23,7 +25,6 @@
 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;
@@ -31,7 +32,6 @@
 import net.minecraft.world.entity.Pose;
 import net.minecraft.world.entity.ai.attributes.AttributeSupplier;
 import net.minecraft.world.entity.ai.attributes.Attributes;
-import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.entity.vehicle.AbstractMinecart;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.item.Items;
@@ -44,8 +44,17 @@
 import net.minecraft.world.level.material.PushReaction;
 import net.minecraft.world.phys.AABB;
 import net.minecraft.world.phys.Vec3;
+// CraftBukkit start
+import org.bukkit.event.entity.EntityRemoveEvent;
+import org.bukkit.inventory.EquipmentSlot;
+import org.bukkit.craftbukkit.CraftEquipmentSlot;
+import org.bukkit.craftbukkit.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);
@@ -56,10 +65,10 @@
     private static final Rotations DEFAULT_RIGHT_LEG_POSE = new Rotations(1.0F, 0.0F, 1.0F);
     private static final EntityDimensions MARKER_DIMENSIONS = EntityDimensions.fixed(0.0F, 0.0F);
     private static final EntityDimensions BABY_DIMENSIONS = EntityType.ARMOR_STAND.getDimensions().scale(0.5F).withEyeHeight(0.9875F);
-    private static final double FEET_OFFSET = 0.1;
-    private static final double CHEST_OFFSET = 0.9;
-    private static final double LEGS_OFFSET = 0.4;
-    private static final double HEAD_OFFSET = 1.6;
+    private static final double FEET_OFFSET = 0.1D;
+    private static final double CHEST_OFFSET = 0.9D;
+    private static final double LEGS_OFFSET = 0.4D;
+    private static final double HEAD_OFFSET = 1.6D;
     public static final int DISABLE_TAKING_OFFSET = 8;
     public static final int DISABLE_PUTTING_OFFSET = 16;
     public static final int CLIENT_FLAG_SMALL = 1;
@@ -73,22 +82,39 @@
     public static final EntityDataAccessor<Rotations> DATA_RIGHT_ARM_POSE = SynchedEntityData.defineId(ArmorStand.class, EntityDataSerializers.ROTATIONS);
     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 -> 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 static final Predicate<Entity> RIDABLE_MINECARTS = (entity) -> {
+        return entity instanceof AbstractMinecart && ((AbstractMinecart) entity).getMinecartType() == AbstractMinecart.Type.RIDEABLE;
+    };
+    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 - Allow ArmorStands not to tick
 
     public ArmorStand(EntityType<? extends ArmorStand> type, Level world) {
         super(type, world);
+        if (world != null) this.canTick = world.paperConfig().entities.armorStands.tick; // Paper - Allow ArmorStands not to tick
+        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;
     }
 
     public ArmorStand(Level world, double x, double y, double z) {
@@ -97,16 +123,24 @@
     }
 
     public static AttributeSupplier.Builder createAttributes() {
-        return createLivingAttributes().add(Attributes.STEP_HEIGHT, 0.0);
+        return createLivingAttributes().add(Attributes.STEP_HEIGHT, 0.0D);
+    }
+
+    // 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() {
@@ -121,13 +155,13 @@
     @Override
     protected void defineSynchedData(SynchedEntityData.Builder builder) {
         super.defineSynchedData(builder);
-        builder.define(DATA_CLIENT_FLAGS, (byte)0);
-        builder.define(DATA_HEAD_POSE, DEFAULT_HEAD_POSE);
-        builder.define(DATA_BODY_POSE, DEFAULT_BODY_POSE);
-        builder.define(DATA_LEFT_ARM_POSE, DEFAULT_LEFT_ARM_POSE);
-        builder.define(DATA_RIGHT_ARM_POSE, DEFAULT_RIGHT_ARM_POSE);
-        builder.define(DATA_LEFT_LEG_POSE, DEFAULT_LEFT_LEG_POSE);
-        builder.define(DATA_RIGHT_LEG_POSE, DEFAULT_RIGHT_LEG_POSE);
+        builder.define(ArmorStand.DATA_CLIENT_FLAGS, (byte) 0);
+        builder.define(ArmorStand.DATA_HEAD_POSE, ArmorStand.DEFAULT_HEAD_POSE);
+        builder.define(ArmorStand.DATA_BODY_POSE, ArmorStand.DEFAULT_BODY_POSE);
+        builder.define(ArmorStand.DATA_LEFT_ARM_POSE, ArmorStand.DEFAULT_LEFT_ARM_POSE);
+        builder.define(ArmorStand.DATA_RIGHT_ARM_POSE, ArmorStand.DEFAULT_RIGHT_ARM_POSE);
+        builder.define(ArmorStand.DATA_LEFT_LEG_POSE, ArmorStand.DEFAULT_LEFT_LEG_POSE);
+        builder.define(ArmorStand.DATA_RIGHT_LEG_POSE, ArmorStand.DEFAULT_RIGHT_LEG_POSE);
     }
 
     @Override
@@ -141,57 +175,73 @@
     }
 
     @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 boolean canUseSlot(EquipmentSlot slot) {
-        return slot != EquipmentSlot.BODY;
+    public boolean canUseSlot(net.minecraft.world.entity.EquipmentSlot slot) {
+        return slot != net.minecraft.world.entity.EquipmentSlot.BODY;
     }
 
     @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 ArmorStands not to tick; Still update equipment
     }
 
     @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();
+        Iterator iterator = this.armorItems.iterator();
 
-        for (ItemStack itemStack : this.armorItems) {
-            listTag.add(itemStack.saveOptional(this.registryAccess()));
+        while (iterator.hasNext()) {
+            ItemStack itemstack = (ItemStack) iterator.next();
+
+            nbttaglist.add(itemstack.saveOptional(this.registryAccess()));
         }
 
-        nbt.put("ArmorItems", listTag);
-        ListTag listTag2 = new ListTag();
+        nbt.put("ArmorItems", nbttaglist);
+        ListTag nbttaglist1 = new ListTag();
+        Iterator iterator1 = this.handItems.iterator();
 
-        for (ItemStack itemStack2 : this.handItems) {
-            listTag2.add(itemStack2.saveOptional(this.registryAccess()));
+        while (iterator1.hasNext()) {
+            ItemStack itemstack1 = (ItemStack) iterator1.next();
+
+            nbttaglist1.add(itemstack1.saveOptional(this.registryAccess()));
         }
 
-        nbt.put("HandItems", listTag2);
+        nbt.put("HandItems", nbttaglist1);
         nbt.putBoolean("Invisible", this.isInvisible());
         nbt.putBoolean("Small", this.isSmall());
         nbt.putBoolean("ShowArms", this.isShowArms());
@@ -202,26 +252,31 @@
         }
 
         nbt.put("Pose", this.writePose());
+        if (this.canTickSetByAPI) nbt.putBoolean("Paper.CanTickOverride", this.canTick); // Paper - Allow ArmorStands not to tick
     }
 
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
+        ListTag nbttaglist;
+        CompoundTag nbttagcompound1;
+        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++) {
-                CompoundTag compoundTag = listTag.getCompound(i);
-                this.armorItems.set(i, ItemStack.parseOptional(this.registryAccess(), compoundTag));
+            for (i = 0; i < this.armorItems.size(); ++i) {
+                nbttagcompound1 = nbttaglist.getCompound(i);
+                this.armorItems.set(i, ItemStack.parseOptional(this.registryAccess(), nbttagcompound1));
             }
         }
 
         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++) {
-                CompoundTag compoundTag2 = listTag2.getCompound(j);
-                this.handItems.set(j, ItemStack.parseOptional(this.registryAccess(), compoundTag2));
+            for (i = 0; i < this.handItems.size(); ++i) {
+                nbttagcompound1 = nbttaglist.getCompound(i);
+                this.handItems.set(i, ItemStack.parseOptional(this.registryAccess(), nbttagcompound1));
             }
         }
 
@@ -232,206 +287,278 @@
         this.setNoBasePlate(nbt.getBoolean("NoBasePlate"));
         this.setMarker(nbt.getBoolean("Marker"));
         this.noPhysics = !this.hasPhysics();
-        CompoundTag compoundTag3 = nbt.getCompound("Pose");
-        this.readPose(compoundTag3);
+        // Paper start - Allow ArmorStands not to tick
+        if (nbt.contains("Paper.CanTickOverride")) {
+            this.canTick = nbt.getBoolean("Paper.CanTickOverride");
+            this.canTickSetByAPI = true;
+        }
+        // Paper end - Allow ArmorStands not to tick
+        CompoundTag nbttagcompound2 = nbt.getCompound("Pose");
+
+        this.readPose(nbttagcompound2);
     }
 
     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 - Climbing should not bypass cramming gamerule
         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.distanceToSqr(entity) <= 0.2) {
+        if (!this.level().paperConfig().entities.armorStands.doCollisionEntityLookups) return; // Paper - Option to prevent armor stands from doing entity lookups
+        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);
             }
         }
+
     }
 
     @Override
-    public InteractionResult interactAt(Player player, Vec3 hitPos, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        if (this.isMarker() || itemStack.is(Items.NAME_TAG)) {
-            return InteractionResult.PASS;
-        } else 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)) {
-                    return InteractionResult.SUCCESS;
-                }
+    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 {
-                if (this.isDisabled(equipmentSlot)) {
-                    return InteractionResult.FAIL;
-                }
+                net.minecraft.world.entity.EquipmentSlot enumitemslot = Mob.getEquipmentSlotForItem(itemstack);
 
-                if (equipmentSlot.getType() == EquipmentSlot.Type.HAND && !this.isShowArms()) {
-                    return InteractionResult.FAIL;
-                }
+                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.swapItem(player, equipmentSlot, itemStack, hand)) {
-                    return InteractionResult.SUCCESS;
+                    if (this.hasItemInSlot(enumitemslot2) && this.swapItem(player, enumitemslot2, itemstack, hand)) {
+                        return InteractionResult.SUCCESS;
+                    }
+                } else {
+                    if (this.isDisabled(enumitemslot)) {
+                        return InteractionResult.FAIL;
+                    }
+
+                    if (enumitemslot.getType() == net.minecraft.world.entity.EquipmentSlot.Type.HAND && !this.isShowArms()) {
+                        return InteractionResult.FAIL;
+                    }
+
+                    if (this.swapItem(player, enumitemslot, itemstack, hand)) {
+                        return InteractionResult.SUCCESS;
+                    }
                 }
-            }
 
+                return InteractionResult.PASS;
+            }
+        } else {
             return InteractionResult.PASS;
         }
     }
 
-    private EquipmentSlot getClickedSlot(Vec3 hitPos) {
-        EquipmentSlot equipmentSlot = EquipmentSlot.MAINHAND;
-        boolean bl = this.isSmall();
-        double d = hitPos.y / (double)(this.getScale() * this.getAgeScale());
-        EquipmentSlot equipmentSlot2 = EquipmentSlot.FEET;
-        if (d >= 0.1 && d < 0.1 + (bl ? 0.8 : 0.45) && this.hasItemInSlot(equipmentSlot2)) {
-            equipmentSlot = EquipmentSlot.FEET;
-        } else if (d >= 0.9 + (bl ? 0.3 : 0.0) && d < 0.9 + (bl ? 1.0 : 0.7) && this.hasItemInSlot(EquipmentSlot.CHEST)) {
-            equipmentSlot = EquipmentSlot.CHEST;
-        } else if (d >= 0.4 && d < 0.4 + (bl ? 1.0 : 0.8) && this.hasItemInSlot(EquipmentSlot.LEGS)) {
-            equipmentSlot = EquipmentSlot.LEGS;
-        } else if (d >= 1.6 && 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 = hitPos.y / (double) (this.getScale() * this.getAgeScale());
+        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.hasInfiniteMaterials() && 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.hasInfiniteMaterials() && itemstack1.isEmpty() && !stack.isEmpty()) {
+            // CraftBukkit end
             this.setItemSlot(slot, stack.copyWithCount(1));
             return true;
-        } else if (stack.isEmpty() || stack.getCount() <= 1) {
-            this.setItemSlot(slot, stack);
-            player.setItemInHand(hand, itemStack);
-            return true;
-        } else if (!itemStack.isEmpty()) {
-            return false;
+        } else if (!stack.isEmpty() && stack.getCount() > 1) {
+            if (!itemstack1.isEmpty()) {
+                return false;
+            } else {
+                this.setItemSlot(slot, stack.split(1));
+                return true;
+            }
         } else {
-            this.setItemSlot(slot, stack.split(1));
+            this.setItemSlot(slot, stack);
+            player.setItemInHand(hand, itemstack1);
             return true;
         }
+        } // CraftBukkit
     }
 
     @Override
     public boolean hurt(DamageSource source, float amount) {
-        if (this.level().isClientSide || this.isRemoved()) {
-            return false;
-        } else if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) {
-            this.kill();
-            return false;
-        } else if (this.isInvulnerableTo(source) || this.invisible || this.isMarker()) {
-            return false;
-        } else if (source.is(DamageTypeTags.IS_EXPLOSION)) {
-            this.brokenByAnything(source);
-            this.kill();
-            return false;
-        } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) {
-            if (this.isOnFire()) {
-                this.causeDamage(source, 0.15F);
-            } else {
-                this.igniteForSeconds(5);
-            }
-
-            return false;
-        } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) {
-            this.causeDamage(source, 4.0F);
-            return false;
-        } else {
-            boolean bl = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND);
-            boolean bl2 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS);
-            if (!bl && !bl2) {
+        if (!this.level().isClientSide && !this.isRemoved()) {
+            if (source.is(DamageTypeTags.BYPASSES_INVULNERABILITY)) {
+                // CraftBukkit start
+                if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount)) {
+                    return false;
+                }
+                this.kill(source); // CraftBukkit
+                // CraftBukkit end
                 return false;
-            } else {
-                if (source.getEntity() instanceof Player player && !player.getAbilities().mayBuild) {
+            } else if (!this.isInvulnerableTo(source) && (true || !this.invisible) && !this.isMarker()) { // CraftBukkit
+                // CraftBukkit start
+                if (org.bukkit.craftbukkit.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, true, this.invisible)) {
                     return false;
                 }
+                // CraftBukkit end
+                if (source.is(DamageTypeTags.IS_EXPLOSION)) {
+                    // Paper start - avoid duplicate event call
+                    org.bukkit.event.entity.EntityDeathEvent event = this.brokenByAnything(source);
+                    if (!event.isCancelled()) this.kill(source, false); // CraftBukkit
+                    // Paper end
+                    return false;
+                } else if (source.is(DamageTypeTags.IGNITES_ARMOR_STANDS)) {
+                    if (this.isOnFire()) {
+                        this.causeDamage(source, 0.15F);
+                    } else {
+                        this.igniteForSeconds(5);
+                    }
 
-                if (source.isCreativePlayer()) {
-                    this.playBrokenSound();
-                    this.showBreakingParticles();
-                    this.kill();
-                    return true;
+                    return false;
+                } else if (source.is(DamageTypeTags.BURNS_ARMOR_STANDS) && this.getHealth() > 0.5F) {
+                    this.causeDamage(source, 4.0F);
+                    return false;
                 } else {
-                    long l = this.level().getGameTime();
-                    if (l - this.lastHit > 5L && !bl2) {
-                        this.level().broadcastEntityEvent(this, (byte)32);
-                        this.gameEvent(GameEvent.ENTITY_DAMAGE, source.getEntity());
-                        this.lastHit = l;
+                    boolean flag = source.is(DamageTypeTags.CAN_BREAK_ARMOR_STAND);
+                    boolean flag1 = source.is(DamageTypeTags.ALWAYS_KILLS_ARMOR_STANDS);
+
+                    if (!flag && !flag1) {
+                        return false;
                     } else {
-                        this.brokenByPlayer(source);
-                        this.showBreakingParticles();
-                        this.kill();
-                    }
+                        Entity entity = source.getEntity();
 
-                    return true;
+                        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;
+                            }
+                        }
+
+                        if (source.isCreativePlayer()) {
+                            this.playBrokenSound();
+                            this.showBreakingParticles();
+                            this.kill(source); // CraftBukkit
+                            return true;
+                        } else {
+                            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 = i;
+                            } else {
+                                org.bukkit.event.entity.EntityDeathEvent event = this.brokenByPlayer(source); // Paper
+                                this.showBreakingParticles();
+                                if (!event.isCancelled()) this.kill(source, false); // Paper - we still need to kill to follow vanilla logic (emit the game event etc...)
+                            }
+
+                            return true;
+                        }
+                    }
                 }
+            } else {
+                return false;
             }
+        } else {
+            return false;
         }
     }
 
@@ -445,78 +572,80 @@
         } else {
             super.handleEntityEvent(status);
         }
+
     }
 
     @Override
     public boolean shouldRenderAtSqrDistance(double distance) {
-        double d = this.getBoundingBox().getSize() * 4.0;
-        if (Double.isNaN(d) || d == 0.0) {
-            d = 4.0;
+        double d1 = this.getBoundingBox().getSize() * 4.0D;
+
+        if (Double.isNaN(d1) || d1 == 0.0D) {
+            d1 = 4.0D;
         }
 
-        d *= 64.0;
-        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.6666666666666666),
-                    this.getZ(),
-                    10,
-                    (double)(this.getBbWidth() / 4.0F),
-                    (double)(this.getBbHeight() / 4.0F),
-                    (double)(this.getBbWidth() / 4.0F),
-                    0.05
-                );
+            ((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(damageSource, false); // CraftBukkit
+            // 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);
-        itemStack.set(DataComponents.CUSTOM_NAME, this.getCustomName());
-        Block.popResource(this.level(), this.blockPosition(), itemStack);
-        this.brokenByAnything(damageSource);
+    private org.bukkit.event.entity.EntityDeathEvent brokenByPlayer(DamageSource damageSource) { // Paper
+        ItemStack itemstack = new ItemStack(Items.ARMOR_STAND);
+
+        itemstack.set(DataComponents.CUSTOM_NAME, this.getCustomName());
+        this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior
+        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()) {
+                this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
                 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()) {
+                this.drops.add(new DefaultDrop(itemstack, stack -> Block.popResource(this.level(), this.blockPosition().above(), stack))); // CraftBukkit - add to drops // Paper - Restore vanilla drops behavior; mirror so we can destroy it later - though this call site was safe & spawn drops correctly
+                this.armorItems.set(i, ItemStack.EMPTY);
             }
         }
+        return this.dropAllDeathLoot(damageSource); // CraftBukkit - moved from above // Paper
+
     }
 
     private void playBrokenSound() {
-        this.level().playSound(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
@@ -547,36 +676,65 @@
 
     @Override
     public void tick() {
+        // Paper start - Allow ArmorStands not to tick
+        if (!this.canTick) {
+            if (this.noTickPoseDirty) {
+                this.noTickPoseDirty = false;
+                this.updatePose();
+            }
+
+            if (this.noTickEquipmentDirty) {
+                this.noTickEquipmentDirty = false;
+                this.detectEquipmentUpdatesPublic();
+            }
+
+            return;
+        }
+        // Paper end - Allow ArmorStands not to tick
+
         super.tick();
-        Rotations rotations = this.entityData.get(DATA_HEAD_POSE);
-        if (!this.headPose.equals(rotations)) {
-            this.setHeadPose(rotations);
+        // Paper start - Allow ArmorStands not to tick
+        updatePose();
+    }
+
+    public void updatePose() {
+        // Paper end - Allow ArmorStands not to tick
+        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);
         }
+
     }
 
     @Override
@@ -595,9 +753,31 @@
         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() {
-        this.remove(Entity.RemovalReason.KILLED);
+        // CraftBukkit start - pass DamageSource for kill
+        this.kill(null);
+    }
+
+    public void kill(DamageSource damageSource) {
+        // Paper start - make cancellable
+        this.kill(damageSource, true);
+    }
+    public void kill(DamageSource damageSource, boolean callEvent) {
+        if (callEvent) {
+            org.bukkit.event.entity.EntityDeathEvent event = org.bukkit.craftbukkit.event.CraftEventFactory.callEntityDeathEvent(this, (damageSource == null ? this.damageSources().genericKill() : damageSource), this.drops); // CraftBukkit - call event
+            if (event.isCancelled()) return;
+        }
+        // Paper end
+        this.remove(Entity.RemovalReason.KILLED, EntityRemoveEvent.Cause.DEATH); // CraftBukkit - add Bukkit remove cause
+        // CraftBukkit end
         this.gameEvent(GameEvent.ENTITY_DIE);
     }
 
@@ -617,42 +797,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;
@@ -660,32 +840,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() {
@@ -719,7 +905,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
@@ -745,8 +931,7 @@
     }
 
     @Override
-    public void thunderHit(ServerLevel world, LightningBolt lightning) {
-    }
+    public void thunderHit(ServerLevel world, LightningBolt lightning) {}
 
     @Override
     public boolean isAffectedByPotions() {
@@ -755,7 +940,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();
         }
@@ -774,35 +959,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);
         }
@@ -817,4 +999,13 @@
     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 end
 }
