--- a/net/minecraft/world/inventory/CartographyTableMenu.java
+++ b/net/minecraft/world/inventory/CartographyTableMenu.java
@@ -15,6 +_,21 @@
 import net.minecraft.world.level.saveddata.maps.MapItemSavedData;
 
 public class CartographyTableMenu extends AbstractContainerMenu {
+    // CraftBukkit start
+    private @javax.annotation.Nullable org.bukkit.craftbukkit.inventory.CraftInventoryView view = null;
+    private final org.bukkit.entity.Player player;
+
+    @Override
+    public org.bukkit.craftbukkit.inventory.CraftInventoryView getBukkitView() {
+        if (this.view != null) {
+            return this.view;
+        }
+
+        org.bukkit.craftbukkit.inventory.CraftInventoryCartography inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryCartography(this.container, this.resultContainer);
+        this.view = new org.bukkit.craftbukkit.inventory.CraftInventoryView<>(this.player, inventory, this);
+        return this.view;
+    }
+    // CraftBukkit end
     public static final int MAP_SLOT = 0;
     public static final int ADDITIONAL_SLOT = 1;
     public static final int RESULT_SLOT = 2;
@@ -24,20 +_,8 @@
     private static final int USE_ROW_SLOT_END = 39;
     private final ContainerLevelAccess access;
     long lastSoundTime;
-    public final Container container = new SimpleContainer(2) {
-        @Override
-        public void setChanged() {
-            CartographyTableMenu.this.slotsChanged(this);
-            super.setChanged();
-        }
-    };
-    private final ResultContainer resultContainer = new ResultContainer() {
-        @Override
-        public void setChanged() {
-            CartographyTableMenu.this.slotsChanged(this);
-            super.setChanged();
-        }
-    };
+    public final Container container; // Paper - Add missing InventoryHolders - move down
+    private final ResultContainer resultContainer; // Paper - Add missing InventoryHolders - move down
 
     public CartographyTableMenu(int containerId, Inventory playerInventory) {
         this(containerId, playerInventory, ContainerLevelAccess.NULL);
@@ -45,6 +_,34 @@
 
     public CartographyTableMenu(int containerId, Inventory playerInventory, final ContainerLevelAccess access) {
         super(MenuType.CARTOGRAPHY_TABLE, containerId);
+        // Paper start - Add missing InventoryHolders - move down
+        this.container = new SimpleContainer(this.createBlockHolder(access), 2) {
+            @Override
+            public void setChanged() {
+                CartographyTableMenu.this.slotsChanged(this);
+                super.setChanged();
+            }
+            // CraftBukkit start
+            @Override
+            public org.bukkit.Location getLocation() {
+                return access.getLocation();
+            }
+            // CraftBukkit end
+        };
+        this.resultContainer = new ResultContainer(this.createBlockHolder(access)) {
+            @Override
+            public void setChanged() {
+                // CartographyTableMenu.this.slotsChanged(this); // Paper - Add CartographyItemEvent - do not recompute results if the result slot changes - allows to set the result slot via api
+                super.setChanged();
+            }
+            // CraftBukkit start
+            @Override
+            public org.bukkit.Location getLocation() {
+                return access.getLocation();
+            }
+            // CraftBukkit end
+        };
+        // Paper end - Add missing InventoryHolders - move down
         this.access = access;
         this.addSlot(new Slot(this.container, 0, 15, 15) {
             @Override
@@ -80,10 +_,12 @@
             }
         });
         this.addStandardInventorySlots(playerInventory, 8, 84);
+        this.player = (org.bukkit.entity.Player) playerInventory.player.getBukkitEntity(); // CraftBukkit
     }
 
     @Override
     public boolean stillValid(Player player) {
+        if (!this.checkReachable) return true; // CraftBukkit
         return stillValid(this.access, player, Blocks.CARTOGRAPHY_TABLE);
     }
 
@@ -99,6 +_,7 @@
         } else {
             this.resultContainer.removeItemNoUpdate(2);
         }
+        org.bukkit.craftbukkit.event.CraftEventFactory.callPrepareResultEvent(this, RESULT_SLOT); // Paper - Add PrepareResultEvent
     }
 
     private void setupResultSlot(ItemStack map, ItemStack firstSlotStack, ItemStack resultOutput) {
