--- a/net/minecraft/world/entity/decoration/ItemFrame.java
+++ b/net/minecraft/world/entity/decoration/ItemFrame.java
@@ -3,6 +3,7 @@
 import com.mojang.logging.LogUtils;
 import java.util.OptionalInt;
 import javax.annotation.Nullable;
+import io.papermc.paper.event.player.PlayerItemFrameChangeEvent; // Paper
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Direction;
 import net.minecraft.nbt.CompoundTag;
@@ -40,15 +41,17 @@
 import org.slf4j.Logger;
 
 public class ItemFrame extends HangingEntity {
+
     private static final Logger LOGGER = LogUtils.getLogger();
     public static final EntityDataAccessor<ItemStack> DATA_ITEM = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.ITEM_STACK);
     public static final EntityDataAccessor<Integer> DATA_ROTATION = SynchedEntityData.defineId(ItemFrame.class, EntityDataSerializers.INT);
     public static final int NUM_ROTATIONS = 8;
-    public float dropChance = 1.0F;
+    public float dropChance;
     public boolean fixed;
 
     public ItemFrame(EntityType<? extends ItemFrame> type, Level world) {
         super(type, world);
+        this.dropChance = 1.0F;
     }
 
     public ItemFrame(Level world, BlockPos pos, Direction facing) {
@@ -57,6 +60,7 @@
 
     public ItemFrame(EntityType<? extends ItemFrame> type, Level world, BlockPos pos, Direction facing) {
         super(type, world, pos);
+        this.dropChance = 1.0F;
         this.setDirection(facing);
     }
 
@@ -67,8 +71,8 @@
 
     @Override
     protected void defineSynchedData() {
-        this.getEntityData().define(DATA_ITEM, ItemStack.EMPTY);
-        this.getEntityData().define(DATA_ROTATION, 0);
+        this.getEntityData().define(ItemFrame.DATA_ITEM, ItemStack.EMPTY);
+        this.getEntityData().define(ItemFrame.DATA_ROTATION, 0);
     }
 
     @Override
@@ -77,9 +81,9 @@
         this.direction = facing;
         if (facing.getAxis().isHorizontal()) {
             this.setXRot(0.0F);
-            this.setYRot((float)(this.direction.get2DDataValue() * 90));
+            this.setYRot((float) (this.direction.get2DDataValue() * 90));
         } else {
-            this.setXRot((float)(-90 * facing.getAxisDirection().getStep()));
+            this.setXRot((float) (-90 * facing.getAxisDirection().getStep()));
             this.setYRot(0.0F);
         }
 
@@ -91,42 +95,57 @@
     @Override
     protected void recalculateBoundingBox() {
         if (this.direction != null) {
-            double d = 0.46875D;
-            double e = (double)this.pos.getX() + 0.5D - (double)this.direction.getStepX() * 0.46875D;
-            double f = (double)this.pos.getY() + 0.5D - (double)this.direction.getStepY() * 0.46875D;
-            double g = (double)this.pos.getZ() + 0.5D - (double)this.direction.getStepZ() * 0.46875D;
-            this.setPosRaw(e, f, g);
-            double h = (double)this.getWidth();
-            double i = (double)this.getHeight();
-            double j = (double)this.getWidth();
-            Direction.Axis axis = this.direction.getAxis();
-            switch (axis) {
+            // CraftBukkit start code moved in to calculateBoundingBox
+            this.setBoundingBox(ItemFrame.calculateBoundingBox(this, this.pos, this.direction, this.getWidth(), this.getHeight()));
+            // CraftBukkit end
+        }
+    }
+
+    // CraftBukkit start - break out BB calc into own method
+    public static AABB calculateBoundingBox(@Nullable Entity entity, BlockPos blockPosition, Direction direction, int width, int height) {
+        {
+            double d0 = 0.46875D;
+            double d1 = (double) blockPosition.getX() + 0.5D - (double) direction.getStepX() * 0.46875D;
+            double d2 = (double) blockPosition.getY() + 0.5D - (double) direction.getStepY() * 0.46875D;
+            double d3 = (double) blockPosition.getZ() + 0.5D - (double) direction.getStepZ() * 0.46875D;
+
+            if (entity != null) {
+                entity.setPosRaw(d1, d2, d3);
+            }
+            double d4 = (double) width;
+            double d5 = (double) height;
+            double d6 = (double) width;
+            Direction.Axis enumdirection_enumaxis = direction.getAxis();
+
+            switch (enumdirection_enumaxis) {
                 case X:
-                    h = 1.0D;
+                    d4 = 1.0D;
                     break;
                 case Y:
-                    i = 1.0D;
+                    d5 = 1.0D;
                     break;
                 case Z:
-                    j = 1.0D;
+                    d6 = 1.0D;
             }
 
-            h /= 32.0D;
-            i /= 32.0D;
-            j /= 32.0D;
-            this.setBoundingBox(new AABB(e - h, f - i, g - j, e + h, f + i, g + j));
+            d4 /= 32.0D;
+            d5 /= 32.0D;
+            d6 /= 32.0D;
+            return new AABB(d1 - d4, d2 - d5, d3 - d6, d1 + d4, d2 + d5, d3 + d6);
         }
     }
+    // CraftBukkit end
 
     @Override
     public boolean survives() {
         if (this.fixed) {
             return true;
-        } else if (!this.level.noCollision(this)) {
+        } else if (!this.level.noCollision((Entity) this)) {
             return false;
         } else {
-            BlockState blockState = this.level.getBlockState(this.pos.relative(this.direction.getOpposite()));
-            return blockState.getMaterial().isSolid() || this.direction.getAxis().isHorizontal() && DiodeBlock.isDiode(blockState) ? this.level.getEntities(this, this.getBoundingBox(), HANGING_ENTITY).isEmpty() : false;
+            BlockState iblockdata = this.level.getBlockState(this.pos.relative(this.direction.getOpposite()));
+
+            return !iblockdata.getMaterial().isSolid() && (!this.direction.getAxis().isHorizontal() || !DiodeBlock.isDiode(iblockdata)) ? false : this.level.getEntities((Entity) this, this.getBoundingBox(), ItemFrame.HANGING_ENTITY).isEmpty();
         }
     }
 
@@ -165,6 +184,18 @@
             return false;
         } else if (!source.isExplosion() && !this.getItem().isEmpty()) {
             if (!this.level.isClientSide) {
+                // CraftBukkit start - fire EntityDamageEvent
+                if (org.bukkit.craftbukkit.v1_19_R2.event.CraftEventFactory.handleNonLivingEntityDamageEvent(this, source, amount, false) || this.isRemoved()) {
+                    return true;
+                }
+                // CraftBukkit end
+                // Paper start - call PlayerItemFrameChangeEvent
+                if (source.getEntity() instanceof Player player) {
+                    var event = new PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), this.getItem().asBukkitCopy(), PlayerItemFrameChangeEvent.ItemFrameChangeAction.REMOVE);
+                    if (!event.callEvent()) return true; // return true here because you aren't cancelling the damage, just the change
+                    this.setItem(ItemStack.fromBukkitCopy(event.getItemStack()), false);
+                }
+                // Paper end
                 this.dropItem(source.getEntity(), false);
                 this.playSound(this.getRemoveItemSound(), 1.0F, 1.0F);
             }
@@ -191,9 +222,10 @@
 
     @Override
     public boolean shouldRenderAtSqrDistance(double distance) {
-        double d = 16.0D;
-        d *= 64.0D * getViewScale();
-        return distance < d * d;
+        double d1 = 16.0D;
+
+        d1 *= 64.0D * getViewScale();
+        return distance < d1 * d1;
     }
 
     @Override
@@ -217,18 +249,20 @@
 
     private void dropItem(@Nullable Entity entity, boolean alwaysDrop) {
         if (!this.fixed) {
-            ItemStack itemStack = this.getItem();
+            ItemStack itemstack = this.getItem();
+
             this.setItem(ItemStack.EMPTY);
             if (!this.level.getGameRules().getBoolean(GameRules.RULE_DOENTITYDROPS)) {
                 if (entity == null) {
-                    this.removeFramedMap(itemStack);
+                    this.removeFramedMap(itemstack);
                 }
 
             } else {
                 if (entity instanceof Player) {
-                    Player player = (Player)entity;
-                    if (player.getAbilities().instabuild) {
-                        this.removeFramedMap(itemStack);
+                    Player entityhuman = (Player) entity;
+
+                    if (entityhuman.getAbilities().instabuild) {
+                        this.removeFramedMap(itemstack);
                         return;
                     }
                 }
@@ -237,11 +271,11 @@
                     this.spawnAtLocation(this.getFrameItemStack());
                 }
 
-                if (!itemStack.isEmpty()) {
-                    itemStack = itemStack.copy();
-                    this.removeFramedMap(itemStack);
+                if (!itemstack.isEmpty()) {
+                    itemstack = itemstack.copy();
+                    this.removeFramedMap(itemstack);
                     if (this.random.nextFloat() < this.dropChance) {
-                        this.spawnAtLocation(itemStack);
+                        this.spawnAtLocation(itemstack);
                     }
                 }
 
@@ -249,26 +283,36 @@
         }
     }
 
-    private void removeFramedMap(ItemStack itemStack) {
-        this.getFramedMapId().ifPresent((i) -> {
-            MapItemSavedData mapItemSavedData = MapItem.getSavedData(i, this.level);
-            if (mapItemSavedData != null) {
-                mapItemSavedData.removedFromFrame(this.pos, this.getId());
-                mapItemSavedData.setDirty(true);
+    private void removeFramedMap(ItemStack itemstack) {
+        // Paper start - fix MC-252817 (green map markers do not disappear)
+        this.getFramedMapIdFromItem(itemstack).ifPresent((i) -> {
+            // Paper end
+            MapItemSavedData worldmap = MapItem.getSavedData(i, this.level);
+
+            if (worldmap != null) {
+                worldmap.removedFromFrame(this.pos, this.getId());
+                worldmap.setDirty(true);
             }
 
         });
-        itemStack.setEntityRepresentation((Entity)null);
+        itemstack.setEntityRepresentation((Entity) null);
     }
 
     public ItemStack getItem() {
-        return this.getEntityData().get(DATA_ITEM);
+        return (ItemStack) this.getEntityData().get(ItemFrame.DATA_ITEM);
     }
 
     public OptionalInt getFramedMapId() {
-        ItemStack itemStack = this.getItem();
-        if (itemStack.is(Items.FILLED_MAP)) {
-            Integer integer = MapItem.getMapId(itemStack);
+        ItemStack itemstack = this.getItem();
+        // Paper start - fix MC-252817 (green map markers do not disappear)
+        return this.getFramedMapIdFromItem(itemstack);
+    }
+
+    public OptionalInt getFramedMapIdFromItem(ItemStack itemstack) {
+        // Paper end
+        if (itemstack.is(Items.FILLED_MAP)) {
+            Integer integer = MapItem.getMapId(itemstack);
+
             if (integer != null) {
                 return OptionalInt.of(integer);
             }
@@ -286,18 +330,24 @@
     }
 
     public void setItem(ItemStack value, boolean update) {
-        if (!value.isEmpty()) {
-            value = value.copy();
-            value.setCount(1);
+        // CraftBukkit start
+        this.setItem(value, update, true);
+    }
+
+    public void setItem(ItemStack itemstack, boolean flag, boolean playSound) {
+        // CraftBukkit end
+        if (!itemstack.isEmpty()) {
+            itemstack = itemstack.copy();
+            itemstack.setCount(1);
         }
 
-        this.onItemChanged(value);
-        this.getEntityData().set(DATA_ITEM, value);
-        if (!value.isEmpty()) {
+        this.onItemChanged(itemstack);
+        this.getEntityData().set(ItemFrame.DATA_ITEM, itemstack);
+        if (!itemstack.isEmpty() && flag && playSound) { // CraftBukkit // Paper - only play sound when update flag is set
             this.playSound(this.getAddItemSound(), 1.0F, 1.0F);
         }
 
-        if (update && this.pos != null) {
+        if (flag && this.pos != null) {
             this.level.updateNeighbourForOutputSignal(this.pos, Blocks.AIR);
         }
 
@@ -325,7 +375,7 @@
 
     @Override
     public void onSyncedDataUpdated(EntityDataAccessor<?> data) {
-        if (data.equals(DATA_ITEM)) {
+        if (data.equals(ItemFrame.DATA_ITEM)) {
             this.onItemChanged(this.getItem());
         }
 
@@ -340,7 +390,7 @@
     }
 
     public int getRotation() {
-        return this.getEntityData().get(DATA_ROTATION);
+        return (Integer) this.getEntityData().get(ItemFrame.DATA_ROTATION);
     }
 
     public void setRotation(int value) {
@@ -348,7 +398,7 @@
     }
 
     private void setRotation(int value, boolean updateComparators) {
-        this.getEntityData().set(DATA_ROTATION, value % 8);
+        this.getEntityData().set(ItemFrame.DATA_ROTATION, value % 8);
         if (updateComparators && this.pos != null) {
             this.level.updateNeighbourForOutputSignal(this.pos, Blocks.AIR);
         }
@@ -360,11 +410,11 @@
         super.addAdditionalSaveData(nbt);
         if (!this.getItem().isEmpty()) {
             nbt.put("Item", this.getItem().save(new CompoundTag()));
-            nbt.putByte("ItemRotation", (byte)this.getRotation());
+            nbt.putByte("ItemRotation", (byte) this.getRotation());
             nbt.putFloat("ItemDropChance", this.dropChance);
         }
 
-        nbt.putByte("Facing", (byte)this.direction.get3DDataValue());
+        nbt.putByte("Facing", (byte) this.direction.get3DDataValue());
         nbt.putBoolean("Invisible", this.isInvisible());
         nbt.putBoolean("Fixed", this.fixed);
     }
@@ -372,19 +422,22 @@
     @Override
     public void readAdditionalSaveData(CompoundTag nbt) {
         super.readAdditionalSaveData(nbt);
-        CompoundTag compoundTag = nbt.getCompound("Item");
-        if (compoundTag != null && !compoundTag.isEmpty()) {
-            ItemStack itemStack = ItemStack.of(compoundTag);
-            if (itemStack.isEmpty()) {
-                LOGGER.warn("Unable to load item from: {}", (Object)compoundTag);
+        CompoundTag nbttagcompound1 = nbt.getCompound("Item");
+
+        if (nbttagcompound1 != null && !nbttagcompound1.isEmpty()) {
+            ItemStack itemstack = ItemStack.of(nbttagcompound1);
+
+            if (itemstack.isEmpty()) {
+                ItemFrame.LOGGER.warn("Unable to load item from: {}", nbttagcompound1);
             }
 
-            ItemStack itemStack2 = this.getItem();
-            if (!itemStack2.isEmpty() && !ItemStack.matches(itemStack, itemStack2)) {
-                this.removeFramedMap(itemStack2);
+            ItemStack itemstack1 = this.getItem();
+
+            if (!itemstack1.isEmpty() && !ItemStack.matches(itemstack, itemstack1)) {
+                this.removeFramedMap(itemstack1);
             }
 
-            this.setItem(itemStack, false);
+            this.setItem(itemstack, false);
             this.setRotation(nbt.getByte("ItemRotation"), false);
             if (nbt.contains("ItemDropChance", 99)) {
                 this.dropChance = nbt.getFloat("ItemDropChance");
@@ -398,34 +451,45 @@
 
     @Override
     public InteractionResult interact(Player player, InteractionHand hand) {
-        ItemStack itemStack = player.getItemInHand(hand);
-        boolean bl = !this.getItem().isEmpty();
-        boolean bl2 = !itemStack.isEmpty();
+        ItemStack itemstack = player.getItemInHand(hand);
+        boolean flag = !this.getItem().isEmpty();
+        boolean flag1 = !itemstack.isEmpty();
+
         if (this.fixed) {
             return InteractionResult.PASS;
         } else if (!this.level.isClientSide) {
-            if (!bl) {
-                if (bl2 && !this.isRemoved()) {
-                    if (itemStack.is(Items.FILLED_MAP)) {
-                        MapItemSavedData mapItemSavedData = MapItem.getSavedData(itemStack, this.level);
-                        if (mapItemSavedData != null && mapItemSavedData.isTrackedCountOverLimit(256)) {
+            if (!flag) {
+                if (flag1 && !this.isRemoved()) {
+                    if (itemstack.is(Items.FILLED_MAP)) {
+                        MapItemSavedData worldmap = MapItem.getSavedData(itemstack, this.level);
+
+                        if (worldmap != null && worldmap.isTrackedCountOverLimit(256)) {
                             return InteractionResult.FAIL;
                         }
                     }
-
-                    this.setItem(itemStack);
+                    // Paper start - call PlayerItemFrameChangeEvent
+                    var event = new PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), itemstack.asBukkitCopy(), PlayerItemFrameChangeEvent.ItemFrameChangeAction.PLACE);
+                    if (!event.callEvent()) return InteractionResult.FAIL;
+                    this.setItem(ItemStack.fromBukkitCopy(event.getItemStack()));
+                    // this.setItem(itemstack);
+                    // Paper end
                     if (!player.getAbilities().instabuild) {
-                        itemStack.shrink(1);
+                        itemstack.shrink(1);
                     }
                 }
             } else {
+                // Paper start - call PlayerItemFrameChangeEvent
+                var event = new PlayerItemFrameChangeEvent((org.bukkit.entity.Player) player.getBukkitEntity(), (org.bukkit.entity.ItemFrame) this.getBukkitEntity(), this.getItem().asBukkitCopy(), PlayerItemFrameChangeEvent.ItemFrameChangeAction.ROTATE);
+                if (!event.callEvent()) return InteractionResult.FAIL;
+                setItem(ItemStack.fromBukkitCopy(event.getItemStack()), false, false);
+                // Paper end
                 this.playSound(this.getRotateItemSound(), 1.0F, 1.0F);
                 this.setRotation(this.getRotation() + 1);
             }
 
             return InteractionResult.CONSUME;
         } else {
-            return !bl && !bl2 ? InteractionResult.PASS : InteractionResult.SUCCESS;
+            return !flag && !flag1 ? InteractionResult.PASS : InteractionResult.SUCCESS;
         }
     }
 
@@ -450,8 +514,9 @@
 
     @Override
     public ItemStack getPickResult() {
-        ItemStack itemStack = this.getItem();
-        return itemStack.isEmpty() ? this.getFrameItemStack() : itemStack.copy();
+        ItemStack itemstack = this.getItem();
+
+        return itemstack.isEmpty() ? this.getFrameItemStack() : itemstack.copy();
     }
 
     protected ItemStack getFrameItemStack() {
@@ -460,8 +525,9 @@
 
     @Override
     public float getVisualRotationYInDegrees() {
-        Direction direction = this.getDirection();
-        int i = direction.getAxis().isVertical() ? 90 * direction.getAxisDirection().getStep() : 0;
-        return (float)Mth.wrapDegrees(180 + direction.get2DDataValue() * 90 + this.getRotation() * 45 + i);
+        Direction enumdirection = this.getDirection();
+        int i = enumdirection.getAxis().isVertical() ? 90 * enumdirection.getAxisDirection().getStep() : 0;
+
+        return (float) Mth.wrapDegrees(180 + enumdirection.get2DDataValue() * 90 + this.getRotation() * 45 + i);
     }
 }
