--- a/net/minecraft/world/level/block/RespawnAnchorBlock.java
+++ b/net/minecraft/world/level/block/RespawnAnchorBlock.java
@@ -2,11 +2,15 @@
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableList.Builder;
+import com.google.common.collect.UnmodifiableIterator;
 import com.mojang.serialization.MapCodec;
+import java.util.Objects;
 import java.util.Optional;
+import java.util.stream.Stream;
 import javax.annotation.Nullable;
 import net.minecraft.core.BlockPos;
 import net.minecraft.core.Direction;
+import net.minecraft.core.Holder;
 import net.minecraft.core.Vec3i;
 import net.minecraft.core.particles.ParticleTypes;
 import net.minecraft.server.level.ServerPlayer;
@@ -41,57 +45,40 @@
 import net.minecraft.world.phys.Vec3;
 
 public class RespawnAnchorBlock extends Block {
+
     public static final MapCodec<RespawnAnchorBlock> CODEC = simpleCodec(RespawnAnchorBlock::new);
     public static final int MIN_CHARGES = 0;
     public static final int MAX_CHARGES = 4;
     public static final IntegerProperty CHARGE = BlockStateProperties.RESPAWN_ANCHOR_CHARGES;
-    private static final ImmutableList<Vec3i> RESPAWN_HORIZONTAL_OFFSETS = ImmutableList.of(
-        new Vec3i(0, 0, -1),
-        new Vec3i(-1, 0, 0),
-        new Vec3i(0, 0, 1),
-        new Vec3i(1, 0, 0),
-        new Vec3i(-1, 0, -1),
-        new Vec3i(1, 0, -1),
-        new Vec3i(-1, 0, 1),
-        new Vec3i(1, 0, 1)
-    );
-    private static final ImmutableList<Vec3i> RESPAWN_OFFSETS = new Builder<Vec3i>()
-        .addAll(RESPAWN_HORIZONTAL_OFFSETS)
-        .addAll(RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::below).iterator())
-        .addAll(RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::above).iterator())
-        .add(new Vec3i(0, 1, 0))
-        .build();
+    private static final ImmutableList<Vec3i> RESPAWN_HORIZONTAL_OFFSETS = ImmutableList.of(new Vec3i(0, 0, -1), new Vec3i(-1, 0, 0), new Vec3i(0, 0, 1), new Vec3i(1, 0, 0), new Vec3i(-1, 0, -1), new Vec3i(1, 0, -1), new Vec3i(-1, 0, 1), new Vec3i(1, 0, 1));
+    private static final ImmutableList<Vec3i> RESPAWN_OFFSETS = (new Builder()).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::below).iterator()).addAll(RespawnAnchorBlock.RESPAWN_HORIZONTAL_OFFSETS.stream().map(Vec3i::above).iterator()).add(new Vec3i(0, 1, 0)).build();
 
     @Override
     public MapCodec<RespawnAnchorBlock> codec() {
-        return CODEC;
+        return RespawnAnchorBlock.CODEC;
     }
 
     public RespawnAnchorBlock(BlockBehaviour.Properties settings) {
         super(settings);
-        this.registerDefaultState(this.stateDefinition.any().setValue(CHARGE, Integer.valueOf(0)));
+        this.registerDefaultState((BlockState) ((BlockState) this.stateDefinition.any()).setValue(RespawnAnchorBlock.CHARGE, 0));
     }
 
     @Override
-    protected ItemInteractionResult useItemOn(
-        ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit
-    ) {
-        if (isRespawnFuel(stack) && canBeCharged(state)) {
-            charge(player, world, pos, state);
+    protected ItemInteractionResult useItemOn(ItemStack stack, BlockState state, Level world, BlockPos pos, Player player, InteractionHand hand, BlockHitResult hit) {
+        if (RespawnAnchorBlock.isRespawnFuel(stack) && RespawnAnchorBlock.canBeCharged(state)) {
+            RespawnAnchorBlock.charge(player, world, pos, state);
             stack.consume(1, player);
             return ItemInteractionResult.sidedSuccess(world.isClientSide);
         } else {
-            return hand == InteractionHand.MAIN_HAND && isRespawnFuel(player.getItemInHand(InteractionHand.OFF_HAND)) && canBeCharged(state)
-                ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION
-                : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
+            return hand == InteractionHand.MAIN_HAND && RespawnAnchorBlock.isRespawnFuel(player.getItemInHand(InteractionHand.OFF_HAND)) && RespawnAnchorBlock.canBeCharged(state) ? ItemInteractionResult.SKIP_DEFAULT_BLOCK_INTERACTION : ItemInteractionResult.PASS_TO_DEFAULT_BLOCK_INTERACTION;
         }
     }
 
     @Override
     protected InteractionResult useWithoutItem(BlockState state, Level world, BlockPos pos, Player player, BlockHitResult hit) {
-        if (state.getValue(CHARGE) == 0) {
+        if ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) == 0) {
             return InteractionResult.PASS;
-        } else if (!canSetSpawn(world)) {
+        } else if (!RespawnAnchorBlock.canSetSpawn(world)) {
             if (!world.isClientSide) {
                 this.explode(state, world, pos);
             }
@@ -99,20 +86,17 @@
             return InteractionResult.sidedSuccess(world.isClientSide);
         } else {
             if (!world.isClientSide) {
-                ServerPlayer serverPlayer = (ServerPlayer)player;
-                if (serverPlayer.getRespawnDimension() != world.dimension() || !pos.equals(serverPlayer.getRespawnPosition())) {
-                    serverPlayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true);
-                    world.playSound(
-                        null,
-                        (double)pos.getX() + 0.5,
-                        (double)pos.getY() + 0.5,
-                        (double)pos.getZ() + 0.5,
-                        SoundEvents.RESPAWN_ANCHOR_SET_SPAWN,
-                        SoundSource.BLOCKS,
-                        1.0F,
-                        1.0F
-                    );
+                ServerPlayer entityplayer = (ServerPlayer) player;
+
+                if (entityplayer.getRespawnDimension() != world.dimension() || !pos.equals(entityplayer.getRespawnPosition())) {
+                    if (entityplayer.setRespawnPosition(world.dimension(), pos, 0.0F, false, true, com.destroystokyo.paper.event.player.PlayerSetSpawnEvent.Cause.RESPAWN_ANCHOR)) { // Paper - Add PlayerSetSpawnEvent
+                    world.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_SET_SPAWN, SoundSource.BLOCKS, 1.0F, 1.0F);
                     return InteractionResult.SUCCESS;
+                    // Paper start - Add PlayerSetSpawnEvent
+                    } else {
+                        return InteractionResult.FAIL;
+                    }
+                    // Paper end - Add PlayerSetSpawnEvent
                 }
             }
 
@@ -125,42 +109,48 @@
     }
 
     private static boolean canBeCharged(BlockState state) {
-        return state.getValue(CHARGE) < 4;
+        return (Integer) state.getValue(RespawnAnchorBlock.CHARGE) < 4;
     }
 
     private static boolean isWaterThatWouldFlow(BlockPos pos, Level world) {
-        FluidState fluidState = world.getFluidState(pos);
-        if (!fluidState.is(FluidTags.WATER)) {
+        FluidState fluid = world.getFluidState(pos);
+
+        if (!fluid.is(FluidTags.WATER)) {
             return false;
-        } else if (fluidState.isSource()) {
+        } else if (fluid.isSource()) {
             return true;
         } else {
-            float f = (float)fluidState.getAmount();
+            float f = (float) fluid.getAmount();
+
             if (f < 2.0F) {
                 return false;
             } else {
-                FluidState fluidState2 = world.getFluidState(pos.below());
-                return !fluidState2.is(FluidTags.WATER);
+                FluidState fluid1 = world.getFluidState(pos.below());
+
+                return !fluid1.is(FluidTags.WATER);
             }
         }
     }
 
-    private void explode(BlockState state, Level world, BlockPos explodedPos) {
+    private void explode(BlockState state, Level world, final BlockPos explodedPos) {
+        org.bukkit.block.BlockState blockState = org.bukkit.craftbukkit.block.CraftBlock.at(world, explodedPos).getState(); // CraftBukkit - capture BlockState before remove block
         world.removeBlock(explodedPos, false);
-        boolean bl = Direction.Plane.HORIZONTAL.stream().map(explodedPos::relative).anyMatch(pos -> isWaterThatWouldFlow(pos, world));
-        final boolean bl2 = bl || world.getFluidState(explodedPos.above()).is(FluidTags.WATER);
-        ExplosionDamageCalculator explosionDamageCalculator = new ExplosionDamageCalculator() {
+        Stream<Direction> stream = Direction.Plane.HORIZONTAL.stream(); // CraftBukkit - decompile error
+
+        Objects.requireNonNull(explodedPos);
+        boolean flag = stream.map(explodedPos::relative).anyMatch((blockposition1) -> {
+            return RespawnAnchorBlock.isWaterThatWouldFlow(blockposition1, world);
+        });
+        final boolean flag1 = flag || world.getFluidState(explodedPos.above()).is(FluidTags.WATER);
+        ExplosionDamageCalculator explosiondamagecalculator = new ExplosionDamageCalculator() { // CraftBukkit - decompile error
             @Override
-            public Optional<Float> getBlockExplosionResistance(
-                Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState
-            ) {
-                return pos.equals(explodedPos) && bl2
-                    ? Optional.of(Blocks.WATER.getExplosionResistance())
-                    : super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState);
+            public Optional<Float> getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState) {
+                return pos.equals(explodedPos) && flag1 ? Optional.of(Blocks.WATER.getExplosionResistance()) : super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState);
             }
         };
-        Vec3 vec3 = explodedPos.getCenter();
-        world.explode(null, world.damageSources().badRespawnPointExplosion(vec3), explosionDamageCalculator, vec3, 5.0F, true, Level.ExplosionInteraction.BLOCK);
+        Vec3 vec3d = explodedPos.getCenter();
+
+        world.explode((Entity) null, world.damageSources().badRespawnPointExplosion(vec3d, blockState), explosiondamagecalculator, vec3d, 5.0F, true, Level.ExplosionInteraction.BLOCK); // CraftBukkit - add state
     }
 
     public static boolean canSetSpawn(Level world) {
@@ -168,39 +158,32 @@
     }
 
     public static void charge(@Nullable Entity charger, Level world, BlockPos pos, BlockState state) {
-        BlockState blockState = state.setValue(CHARGE, Integer.valueOf(state.getValue(CHARGE) + 1));
-        world.setBlock(pos, blockState, 3);
-        world.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(charger, blockState));
-        world.playSound(
-            null,
-            (double)pos.getX() + 0.5,
-            (double)pos.getY() + 0.5,
-            (double)pos.getZ() + 0.5,
-            SoundEvents.RESPAWN_ANCHOR_CHARGE,
-            SoundSource.BLOCKS,
-            1.0F,
-            1.0F
-        );
+        BlockState iblockdata1 = (BlockState) state.setValue(RespawnAnchorBlock.CHARGE, (Integer) state.getValue(RespawnAnchorBlock.CHARGE) + 1);
+
+        world.setBlock(pos, iblockdata1, 3);
+        world.gameEvent((Holder) GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(charger, iblockdata1));
+        world.playSound((Player) null, (double) pos.getX() + 0.5D, (double) pos.getY() + 0.5D, (double) pos.getZ() + 0.5D, SoundEvents.RESPAWN_ANCHOR_CHARGE, SoundSource.BLOCKS, 1.0F, 1.0F);
     }
 
     @Override
     public void animateTick(BlockState state, Level world, BlockPos pos, RandomSource random) {
-        if (state.getValue(CHARGE) != 0) {
+        if ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) != 0) {
             if (random.nextInt(100) == 0) {
                 world.playLocalSound(pos, SoundEvents.RESPAWN_ANCHOR_AMBIENT, SoundSource.BLOCKS, 1.0F, 1.0F, false);
             }
 
-            double d = (double)pos.getX() + 0.5 + (0.5 - random.nextDouble());
-            double e = (double)pos.getY() + 1.0;
-            double f = (double)pos.getZ() + 0.5 + (0.5 - random.nextDouble());
-            double g = (double)random.nextFloat() * 0.04;
-            world.addParticle(ParticleTypes.REVERSE_PORTAL, d, e, f, 0.0, g, 0.0);
+            double d0 = (double) pos.getX() + 0.5D + (0.5D - random.nextDouble());
+            double d1 = (double) pos.getY() + 1.0D;
+            double d2 = (double) pos.getZ() + 0.5D + (0.5D - random.nextDouble());
+            double d3 = (double) random.nextFloat() * 0.04D;
+
+            world.addParticle(ParticleTypes.REVERSE_PORTAL, d0, d1, d2, 0.0D, d3, 0.0D);
         }
     }
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(CHARGE);
+        builder.add(RespawnAnchorBlock.CHARGE);
     }
 
     @Override
@@ -209,31 +192,38 @@
     }
 
     public static int getScaledChargeLevel(BlockState state, int maxLevel) {
-        return Mth.floor((float)(state.getValue(CHARGE) - 0) / 4.0F * (float)maxLevel);
+        return Mth.floor((float) ((Integer) state.getValue(RespawnAnchorBlock.CHARGE) - 0) / 4.0F * (float) maxLevel);
     }
 
     @Override
     protected int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) {
-        return getScaledChargeLevel(state, 15);
+        return RespawnAnchorBlock.getScaledChargeLevel(state, 15);
     }
 
     public static Optional<Vec3> findStandUpPosition(EntityType<?> entity, CollisionGetter world, BlockPos pos) {
-        Optional<Vec3> optional = findStandUpPosition(entity, world, pos, true);
-        return optional.isPresent() ? optional : findStandUpPosition(entity, world, pos, false);
+        Optional<Vec3> optional = RespawnAnchorBlock.findStandUpPosition(entity, world, pos, true);
+
+        return optional.isPresent() ? optional : RespawnAnchorBlock.findStandUpPosition(entity, world, pos, false);
     }
 
     private static Optional<Vec3> findStandUpPosition(EntityType<?> entity, CollisionGetter world, BlockPos pos, boolean ignoreInvalidPos) {
-        BlockPos.MutableBlockPos mutableBlockPos = new BlockPos.MutableBlockPos();
+        BlockPos.MutableBlockPos blockposition_mutableblockposition = new BlockPos.MutableBlockPos();
+        UnmodifiableIterator unmodifiableiterator = RespawnAnchorBlock.RESPAWN_OFFSETS.iterator();
 
-        for (Vec3i vec3i : RESPAWN_OFFSETS) {
-            mutableBlockPos.set(pos).move(vec3i);
-            Vec3 vec3 = DismountHelper.findSafeDismountLocation(entity, world, mutableBlockPos, ignoreInvalidPos);
-            if (vec3 != null) {
-                return Optional.of(vec3);
+        Vec3 vec3d;
+
+        do {
+            if (!unmodifiableiterator.hasNext()) {
+                return Optional.empty();
             }
-        }
 
-        return Optional.empty();
+            Vec3i baseblockposition = (Vec3i) unmodifiableiterator.next();
+
+            blockposition_mutableblockposition.set(pos).move(baseblockposition);
+            vec3d = DismountHelper.findSafeDismountLocation(entity, world, blockposition_mutableblockposition, ignoreInvalidPos);
+        } while (vec3d == null);
+
+        return Optional.of(vec3d);
     }
 
     @Override
