diff --git a/build-data/paper.at b/build-data/paper.at index 6e0efb1ce2fa..7a3d0cb42e2b 100644 --- a/build-data/paper.at +++ b/build-data/paper.at @@ -628,6 +628,7 @@ public net.minecraft.world.level.block.entity.BarrelBlockEntity playSound(Lnet/m public net.minecraft.world.level.block.entity.BarrelBlockEntity updateBlockState(Lnet/minecraft/world/level/block/state/BlockState;Z)V public net.minecraft.world.level.block.entity.BaseContainerBlockEntity lockKey public net.minecraft.world.level.block.entity.BaseContainerBlockEntity name +public net.minecraft.world.level.block.entity.BeaconBlockEntity MAX_LEVELS public net.minecraft.world.level.block.entity.BeaconBlockEntity levels public net.minecraft.world.level.block.entity.BeaconBlockEntity lockKey public net.minecraft.world.level.block.entity.BeaconBlockEntity name diff --git a/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch b/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch index 06b1bf622dd2..971d0ec0546e 100644 --- a/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/inventory/BeaconMenu.java.patch @@ -64,7 +64,7 @@ return stillValid(this.access, player, Blocks.BEACON); } -@@ -143,13 +_,30 @@ +@@ -143,13 +_,53 @@ public @Nullable Holder getSecondaryEffect() { return decodeEffect(this.beaconData.get(2)); } @@ -75,11 +75,34 @@ + // Paper end - Add PlayerChangeBeaconEffectEvent - public void updateEffects(final Optional> primary, final Optional> secondary) { -+ public void updateEffects(final Optional> primary, Optional> secondary) { // Paper - fix MC-174630 - make non-final ++ public void updateEffects(Optional> primary, Optional> secondary) { // Paper - fix MC-174630 - make non-final + // 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(); + } ++ if (!(this.access.getWorld().getBlockEntity(this.access.getPosition()) instanceof net.minecraft.world.level.block.entity.BeaconBlockEntity beaconEntity)) { ++ return; ++ } ++ // Only max level beacon is allowed to have a secondary effect ++ if (beaconEntity.levels != net.minecraft.world.level.block.entity.BeaconBlockEntity.MAX_LEVELS) { ++ secondary = Optional.empty(); ++ } ++ if (primary.isPresent()) { ++ boolean primaryAllowed = false; ++ // Regeneration can never be the primary effect, so we only check up until the second to last level ++ for (int i = 0; i < Math.min(beaconEntity.levels, net.minecraft.world.level.block.entity.BeaconBlockEntity.MAX_LEVELS - 1); i++) { ++ java.util.List> allowedEffects = net.minecraft.world.level.block.entity.BeaconBlockEntity.BEACON_EFFECTS.get(i); ++ if (allowedEffects.contains(primary.get())) { ++ primaryAllowed = true; ++ break; ++ } ++ } ++ if (!primaryAllowed) { ++ // Secondary must always be cleared: a beacon can't have just a secondary effect ++ primary = Optional.empty(); ++ secondary = Optional.empty(); ++ } ++ } + // Paper end if (this.paymentSlot.hasItem()) { - this.beaconData.set(1, encodeEffect(primary.orElse(null)));