--- a/net/minecraft/world/inventory/BeaconMenu.java
+++ b/net/minecraft/world/inventory/BeaconMenu.java
@@ -8,12 +8,16 @@
 import net.minecraft.world.Container;
 import net.minecraft.world.SimpleContainer;
 import net.minecraft.world.effect.MobEffect;
+import net.minecraft.world.entity.player.Inventory;
 import net.minecraft.world.entity.player.Player;
 import net.minecraft.world.item.ItemStack;
 import net.minecraft.world.level.Level;
 import net.minecraft.world.level.block.Blocks;
+import org.bukkit.craftbukkit.inventory.CraftInventoryView;
+// CraftBukkit end
 
 public class BeaconMenu extends AbstractContainerMenu {
+
     private static final int PAYMENT_SLOT = 0;
     private static final int SLOT_COUNT = 1;
     private static final int DATA_COUNT = 3;
@@ -22,20 +26,14 @@
     private static final int USE_ROW_SLOT_START = 28;
     private static final int USE_ROW_SLOT_END = 37;
     private static final int NO_EFFECT = 0;
-    private final Container beacon = new SimpleContainer(1) {
-        @Override
-        public boolean canPlaceItem(int slot, ItemStack stack) {
-            return stack.is(ItemTags.BEACON_PAYMENT_ITEMS);
-        }
-
-        @Override
-        public int getMaxStackSize() {
-            return 1;
-        }
-    };
+    private final Container beacon;
     private final BeaconMenu.PaymentSlot paymentSlot;
     private final ContainerLevelAccess access;
     private final ContainerData beaconData;
+    // CraftBukkit start
+    private CraftInventoryView bukkitEntity = null;
+    private Inventory player;
+    // CraftBukkit end
 
     public BeaconMenu(int syncId, Container inventory) {
         this(syncId, inventory, new SimpleContainerData(3), ContainerLevelAccess.NULL);
@@ -43,39 +41,63 @@
 
     public BeaconMenu(int syncId, Container inventory, ContainerData propertyDelegate, ContainerLevelAccess context) {
         super(MenuType.BEACON, syncId);
+        this.player = (Inventory) inventory; // CraftBukkit - TODO: check this
+        this.beacon = new SimpleContainer(this.createBlockHolder(context), 1) { // CraftBukkit - decompile error // Paper - Add missing InventoryHolders
+            @Override
+            public boolean canPlaceItem(int slot, ItemStack stack) {
+                return stack.is(ItemTags.BEACON_PAYMENT_ITEMS);
+            }
+
+            @Override
+            public int getMaxStackSize() {
+                return 1;
+            }
+            // Paper start - Fix inventories returning null Locations
+            @Override
+            public org.bukkit.Location getLocation() {
+                return context.getLocation();
+            }
+            // Paper end - Fix inventories returning null Locations
+        };
         checkContainerDataCount(propertyDelegate, 3);
         this.beaconData = propertyDelegate;
         this.access = context;
-        this.paymentSlot = new BeaconMenu.PaymentSlot(this.beacon, 0, 136, 110);
+        this.paymentSlot = new BeaconMenu.PaymentSlot(this, this.beacon, 0, 136, 110);
         this.addSlot(this.paymentSlot);
         this.addDataSlots(propertyDelegate);
-        int i = 36;
-        int j = 137;
+        boolean flag = true;
+        boolean flag1 = true;
 
-        for (int k = 0; k < 3; k++) {
-            for (int l = 0; l < 9; l++) {
-                this.addSlot(new Slot(inventory, l + k * 9 + 9, 36 + l * 18, 137 + k * 18));
+        int j;
+
+        for (j = 0; j < 3; ++j) {
+            for (int k = 0; k < 9; ++k) {
+                this.addSlot(new Slot(inventory, k + j * 9 + 9, 36 + k * 18, 137 + j * 18));
             }
         }
 
-        for (int m = 0; m < 9; m++) {
-            this.addSlot(new Slot(inventory, m, 36 + m * 18, 195));
+        for (j = 0; j < 9; ++j) {
+            this.addSlot(new Slot(inventory, j, 36 + j * 18, 195));
         }
+
     }
 
     @Override
     public void removed(Player player) {
         super.removed(player);
         if (!player.level().isClientSide) {
-            ItemStack itemStack = this.paymentSlot.remove(this.paymentSlot.getMaxStackSize());
-            if (!itemStack.isEmpty()) {
-                player.drop(itemStack, false);
+            ItemStack itemstack = this.paymentSlot.remove(this.paymentSlot.getMaxStackSize());
+
+            if (!itemstack.isEmpty()) {
+                player.drop(itemstack, false);
             }
+
         }
     }
 
     @Override
     public boolean stillValid(Player player) {
+        if (!this.checkReachable) return true; // CraftBukkit
         return stillValid(this.access, player, Blocks.BEACON);
     }
 
@@ -87,47 +109,49 @@
 
     @Override
     public ItemStack quickMoveStack(Player player, int slot) {
-        ItemStack itemStack = ItemStack.EMPTY;
-        Slot slot2 = this.slots.get(slot);
-        if (slot2 != null && slot2.hasItem()) {
-            ItemStack itemStack2 = slot2.getItem();
-            itemStack = itemStack2.copy();
+        ItemStack itemstack = ItemStack.EMPTY;
+        Slot slot1 = (Slot) this.slots.get(slot);
+
+        if (slot1 != null && slot1.hasItem()) {
+            ItemStack itemstack1 = slot1.getItem();
+
+            itemstack = itemstack1.copy();
             if (slot == 0) {
-                if (!this.moveItemStackTo(itemStack2, 1, 37, true)) {
+                if (!this.moveItemStackTo(itemstack1, 1, 37, true)) {
                     return ItemStack.EMPTY;
                 }
 
-                slot2.onQuickCraft(itemStack2, itemStack);
-            } else if (!this.paymentSlot.hasItem() && this.paymentSlot.mayPlace(itemStack2) && itemStack2.getCount() == 1) {
-                if (!this.moveItemStackTo(itemStack2, 0, 1, false)) {
+                slot1.onQuickCraft(itemstack1, itemstack);
+            } else if (!this.paymentSlot.hasItem() && this.paymentSlot.mayPlace(itemstack1) && itemstack1.getCount() == 1) {
+                if (!this.moveItemStackTo(itemstack1, 0, 1, false)) {
                     return ItemStack.EMPTY;
                 }
             } else if (slot >= 1 && slot < 28) {
-                if (!this.moveItemStackTo(itemStack2, 28, 37, false)) {
+                if (!this.moveItemStackTo(itemstack1, 28, 37, false)) {
                     return ItemStack.EMPTY;
                 }
             } else if (slot >= 28 && slot < 37) {
-                if (!this.moveItemStackTo(itemStack2, 1, 28, false)) {
+                if (!this.moveItemStackTo(itemstack1, 1, 28, false)) {
                     return ItemStack.EMPTY;
                 }
-            } else if (!this.moveItemStackTo(itemStack2, 1, 37, false)) {
+            } else if (!this.moveItemStackTo(itemstack1, 1, 37, false)) {
                 return ItemStack.EMPTY;
             }
 
-            if (itemStack2.isEmpty()) {
-                slot2.setByPlayer(ItemStack.EMPTY);
+            if (itemstack1.isEmpty()) {
+                slot1.setByPlayer(ItemStack.EMPTY);
             } else {
-                slot2.setChanged();
+                slot1.setChanged();
             }
 
-            if (itemStack2.getCount() == itemStack.getCount()) {
+            if (itemstack1.getCount() == itemstack.getCount()) {
                 return ItemStack.EMPTY;
             }
 
-            slot2.onTake(player, itemStack2);
+            slot1.onTake(player, itemstack1);
         }
 
-        return itemStack;
+        return itemstack;
     }
 
     public int getLevels() {
@@ -140,35 +164,55 @@
 
     @Nullable
     public static Holder<MobEffect> decodeEffect(int id) {
-        return id == 0 ? null : BuiltInRegistries.MOB_EFFECT.asHolderIdMap().byId(id - 1);
+        return id == 0 ? null : (Holder) BuiltInRegistries.MOB_EFFECT.asHolderIdMap().byId(id - 1);
     }
 
     @Nullable
     public Holder<MobEffect> getPrimaryEffect() {
-        return decodeEffect(this.beaconData.get(1));
+        return BeaconMenu.decodeEffect(this.beaconData.get(1));
     }
 
     @Nullable
     public Holder<MobEffect> getSecondaryEffect() {
-        return decodeEffect(this.beaconData.get(2));
+        return BeaconMenu.decodeEffect(this.beaconData.get(2));
+    }
+
+    // Paper start - Add PlayerChangeBeaconEffectEvent
+    private static @Nullable org.bukkit.potion.PotionEffectType convert(Optional<Holder<MobEffect>> optionalEffect) {
+        return optionalEffect.map(org.bukkit.craftbukkit.potion.CraftPotionEffectType::minecraftHolderToBukkit).orElse(null);
     }
+    // Paper end - Add PlayerChangeBeaconEffectEvent
 
     public void updateEffects(Optional<Holder<MobEffect>> primary, Optional<Holder<MobEffect>> secondary) {
+        // Paper start - fix MC-174630 - validate secondary power
+        if (secondary.isPresent() && secondary.get() != net.minecraft.world.effect.MobEffects.REGENERATION && (primary.isPresent() && secondary.get() != primary.get())) {
+            secondary = Optional.empty();
+        }
+        // Paper end
         if (this.paymentSlot.hasItem()) {
-            this.beaconData.set(1, encodeEffect(primary.orElse(null)));
-            this.beaconData.set(2, encodeEffect(secondary.orElse(null)));
+            // Paper start - Add PlayerChangeBeaconEffectEvent
+            io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent event = new io.papermc.paper.event.player.PlayerChangeBeaconEffectEvent((org.bukkit.entity.Player) this.player.player.getBukkitEntity(), convert(primary), convert(secondary), this.access.getLocation().getBlock());
+            if (event.callEvent()) {
+                // Paper end - Add PlayerChangeBeaconEffectEvent
+                this.beaconData.set(1, BeaconMenu.encodeEffect(event.getPrimary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getPrimary())));// CraftBukkit - decompile error
+                this.beaconData.set(2, BeaconMenu.encodeEffect(event.getSecondary() == null ? null : org.bukkit.craftbukkit.potion.CraftPotionEffectType.bukkitToMinecraftHolder(event.getSecondary())));// CraftBukkit - decompile error
+            if (event.willConsumeItem()) { // Paper
             this.paymentSlot.remove(1);
+            } // Paper
             this.access.execute(Level::blockEntityChanged);
+            } // Paper end - Add PlayerChangeBeaconEffectEvent
         }
+
     }
 
     public boolean hasPayment() {
         return !this.beacon.getItem(0).isEmpty();
     }
 
-    class PaymentSlot extends Slot {
-        public PaymentSlot(final Container inventory, final int index, final int x, final int y) {
-            super(inventory, index, x, y);
+    private class PaymentSlot extends Slot {
+
+        public PaymentSlot(final BeaconMenu inventory, final Container index, final int x, final int y, final int k) {
+            super(index, x, y, k);
         }
 
         @Override
@@ -181,4 +225,17 @@
             return 1;
         }
     }
+
+    // CraftBukkit start
+    @Override
+    public CraftInventoryView getBukkitView() {
+        if (this.bukkitEntity != null) {
+            return this.bukkitEntity;
+        }
+
+        org.bukkit.craftbukkit.inventory.CraftInventory inventory = new org.bukkit.craftbukkit.inventory.CraftInventoryBeacon(this.beacon);
+        this.bukkitEntity = new CraftInventoryView(this.player.player.getBukkitEntity(), inventory, this);
+        return this.bukkitEntity;
+    }
+    // CraftBukkit end
 }
