--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -2,7 +2,9 @@
 
 import com.mojang.serialization.MapCodec;
 import it.unimi.dsi.fastutil.floats.Float2FloatFunction;
+import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.function.BiPredicate;
 import java.util.function.Supplier;
@@ -43,6 +45,7 @@
 import net.minecraft.world.level.block.state.properties.ChestType;
 import net.minecraft.world.level.block.state.properties.DirectionProperty;
 import net.minecraft.world.level.block.state.properties.EnumProperty;
+import net.minecraft.world.level.material.Fluid;
 import net.minecraft.world.level.material.FluidState;
 import net.minecraft.world.level.material.Fluids;
 import net.minecraft.world.level.pathfinder.PathComputationType;
@@ -52,25 +55,28 @@
 import net.minecraft.world.phys.shapes.VoxelShape;
 
 public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements SimpleWaterloggedBlock {
-    public static final MapCodec<ChestBlock> CODEC = simpleCodec(settings -> new ChestBlock(settings, () -> BlockEntityType.CHEST));
+
+    public static final MapCodec<ChestBlock> CODEC = simpleCodec((blockbase_info) -> {
+        return new ChestBlock(blockbase_info, () -> {
+            return BlockEntityType.CHEST;
+        });
+    });
     public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
     public static final EnumProperty<ChestType> TYPE = BlockStateProperties.CHEST_TYPE;
     public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
     public static final int EVENT_SET_OPEN_COUNT = 1;
     protected static final int AABB_OFFSET = 1;
     protected static final int AABB_HEIGHT = 14;
-    protected static final VoxelShape NORTH_AABB = Block.box(1.0, 0.0, 0.0, 15.0, 14.0, 15.0);
-    protected static final VoxelShape SOUTH_AABB = Block.box(1.0, 0.0, 1.0, 15.0, 14.0, 16.0);
-    protected static final VoxelShape WEST_AABB = Block.box(0.0, 0.0, 1.0, 15.0, 14.0, 15.0);
-    protected static final VoxelShape EAST_AABB = Block.box(1.0, 0.0, 1.0, 16.0, 14.0, 15.0);
-    protected static final VoxelShape AABB = Block.box(1.0, 0.0, 1.0, 15.0, 14.0, 15.0);
+    protected static final VoxelShape NORTH_AABB = Block.box(1.0D, 0.0D, 0.0D, 15.0D, 14.0D, 15.0D);
+    protected static final VoxelShape SOUTH_AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 16.0D);
+    protected static final VoxelShape WEST_AABB = Block.box(0.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D);
+    protected static final VoxelShape EAST_AABB = Block.box(1.0D, 0.0D, 1.0D, 16.0D, 14.0D, 15.0D);
+    protected static final VoxelShape AABB = Block.box(1.0D, 0.0D, 1.0D, 15.0D, 14.0D, 15.0D);
     private static final DoubleBlockCombiner.Combiner<ChestBlockEntity, Optional<Container>> CHEST_COMBINER = new DoubleBlockCombiner.Combiner<ChestBlockEntity, Optional<Container>>() {
-        @Override
         public Optional<Container> acceptDouble(ChestBlockEntity first, ChestBlockEntity second) {
             return Optional.of(new CompoundContainer(first, second));
         }
 
-        @Override
         public Optional<Container> acceptSingle(ChestBlockEntity single) {
             return Optional.of(single);
         }
@@ -81,34 +87,12 @@
         }
     };
     private static final DoubleBlockCombiner.Combiner<ChestBlockEntity, Optional<MenuProvider>> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner<ChestBlockEntity, Optional<MenuProvider>>() {
-        @Override
-        public Optional<MenuProvider> acceptDouble(ChestBlockEntity first, ChestBlockEntity second) {
-            final Container container = new CompoundContainer(first, second);
-            return Optional.of(new MenuProvider() {
-                @Nullable
-                @Override
-                public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
-                    if (first.canOpen(player) && second.canOpen(player)) {
-                        first.unpackLootTable(playerInventory.player);
-                        second.unpackLootTable(playerInventory.player);
-                        return ChestMenu.sixRows(syncId, playerInventory, container);
-                    } else {
-                        return null;
-                    }
-                }
+        public Optional<MenuProvider> acceptDouble(final ChestBlockEntity first, final ChestBlockEntity second) {
+            final CompoundContainer inventorylargechest = new CompoundContainer(first, second);
 
-                @Override
-                public Component getDisplayName() {
-                    if (first.hasCustomName()) {
-                        return first.getDisplayName();
-                    } else {
-                        return (Component)(second.hasCustomName() ? second.getDisplayName() : Component.translatable("container.chestDouble"));
-                    }
-                }
-            });
+            return Optional.of(new DoubleInventory(first, second, inventorylargechest)); // CraftBukkit // CraftBukkit - decompile error
         }
 
-        @Override
         public Optional<MenuProvider> acceptSingle(ChestBlockEntity single) {
             return Optional.of(single);
         }
@@ -119,25 +103,52 @@
         }
     };
 
+    // CraftBukkit start
+    public static class DoubleInventory implements MenuProvider {
+
+        private final ChestBlockEntity tileentitychest;
+        private final ChestBlockEntity tileentitychest1;
+        public final CompoundContainer inventorylargechest;
+
+        public DoubleInventory(ChestBlockEntity tileentitychest, ChestBlockEntity tileentitychest1, CompoundContainer inventorylargechest) {
+            this.tileentitychest = tileentitychest;
+            this.tileentitychest1 = tileentitychest1;
+            this.inventorylargechest = inventorylargechest;
+        }
+
+        @Nullable
+        @Override
+        public AbstractContainerMenu createMenu(int syncId, Inventory playerInventory, Player player) {
+            if (this.tileentitychest.canOpen(player) && this.tileentitychest1.canOpen(player)) {
+                this.tileentitychest.unpackLootTable(playerInventory.player);
+                this.tileentitychest1.unpackLootTable(playerInventory.player);
+                return ChestMenu.sixRows(syncId, playerInventory, this.inventorylargechest);
+            } else {
+                return null;
+            }
+        }
+
+        @Override
+        public Component getDisplayName() {
+            return (Component) (this.tileentitychest.hasCustomName() ? this.tileentitychest.getDisplayName() : (this.tileentitychest1.hasCustomName() ? this.tileentitychest1.getDisplayName() : Component.translatable("container.chestDouble")));
+        }
+    };
+    // CraftBukkit end
+
     @Override
     public MapCodec<? extends ChestBlock> codec() {
-        return CODEC;
+        return ChestBlock.CODEC;
     }
 
     protected ChestBlock(BlockBehaviour.Properties settings, Supplier<BlockEntityType<? extends ChestBlockEntity>> entityTypeSupplier) {
         super(settings, entityTypeSupplier);
-        this.registerDefaultState(
-            this.stateDefinition.any().setValue(FACING, Direction.NORTH).setValue(TYPE, ChestType.SINGLE).setValue(WATERLOGGED, Boolean.valueOf(false))
-        );
+        this.registerDefaultState((BlockState) ((BlockState) ((BlockState) ((BlockState) this.stateDefinition.any()).setValue(ChestBlock.FACING, Direction.NORTH)).setValue(ChestBlock.TYPE, ChestType.SINGLE)).setValue(ChestBlock.WATERLOGGED, false));
     }
 
     public static DoubleBlockCombiner.BlockType getBlockType(BlockState state) {
-        ChestType chestType = state.getValue(TYPE);
-        if (chestType == ChestType.SINGLE) {
-            return DoubleBlockCombiner.BlockType.SINGLE;
-        } else {
-            return chestType == ChestType.RIGHT ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND;
-        }
+        ChestType blockpropertychesttype = (ChestType) state.getValue(ChestBlock.TYPE);
+
+        return blockpropertychesttype == ChestType.SINGLE ? DoubleBlockCombiner.BlockType.SINGLE : (blockpropertychesttype == ChestType.RIGHT ? DoubleBlockCombiner.BlockType.FIRST : DoubleBlockCombiner.BlockType.SECOND);
     }
 
     @Override
@@ -147,20 +158,18 @@
 
     @Override
     protected BlockState updateShape(BlockState state, Direction direction, BlockState neighborState, LevelAccessor world, BlockPos pos, BlockPos neighborPos) {
-        if (state.getValue(WATERLOGGED)) {
-            world.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(world));
+        if ((Boolean) state.getValue(ChestBlock.WATERLOGGED)) {
+            world.scheduleTick(pos, (Fluid) Fluids.WATER, Fluids.WATER.getTickDelay(world));
         }
 
-        if (neighborState.is(this) && direction.getAxis().isHorizontal()) {
-            ChestType chestType = neighborState.getValue(TYPE);
-            if (state.getValue(TYPE) == ChestType.SINGLE
-                && chestType != ChestType.SINGLE
-                && state.getValue(FACING) == neighborState.getValue(FACING)
-                && getConnectedDirection(neighborState) == direction.getOpposite()) {
-                return state.setValue(TYPE, chestType.getOpposite());
+        if (neighborState.is((Block) this) && direction.getAxis().isHorizontal()) {
+            ChestType blockpropertychesttype = (ChestType) neighborState.getValue(ChestBlock.TYPE);
+
+            if (state.getValue(ChestBlock.TYPE) == ChestType.SINGLE && blockpropertychesttype != ChestType.SINGLE && state.getValue(ChestBlock.FACING) == neighborState.getValue(ChestBlock.FACING) && ChestBlock.getConnectedDirection(neighborState) == direction.getOpposite()) {
+                return (BlockState) state.setValue(ChestBlock.TYPE, blockpropertychesttype.getOpposite());
             }
-        } else if (getConnectedDirection(state) == direction) {
-            return state.setValue(TYPE, ChestType.SINGLE);
+        } else if (ChestBlock.getConnectedDirection(state) == direction) {
+            return (BlockState) state.setValue(ChestBlock.TYPE, ChestType.SINGLE);
         }
 
         return super.updateShape(state, direction, neighborState, world, pos, neighborPos);
@@ -168,66 +177,67 @@
 
     @Override
     protected VoxelShape getShape(BlockState state, BlockGetter world, BlockPos pos, CollisionContext context) {
-        if (state.getValue(TYPE) == ChestType.SINGLE) {
-            return AABB;
+        if (state.getValue(ChestBlock.TYPE) == ChestType.SINGLE) {
+            return ChestBlock.AABB;
         } else {
-            switch (getConnectedDirection(state)) {
+            switch (ChestBlock.getConnectedDirection(state)) {
                 case NORTH:
                 default:
-                    return NORTH_AABB;
+                    return ChestBlock.NORTH_AABB;
                 case SOUTH:
-                    return SOUTH_AABB;
+                    return ChestBlock.SOUTH_AABB;
                 case WEST:
-                    return WEST_AABB;
+                    return ChestBlock.WEST_AABB;
                 case EAST:
-                    return EAST_AABB;
+                    return ChestBlock.EAST_AABB;
             }
         }
     }
 
     public static Direction getConnectedDirection(BlockState state) {
-        Direction direction = state.getValue(FACING);
-        return state.getValue(TYPE) == ChestType.LEFT ? direction.getClockWise() : direction.getCounterClockWise();
+        Direction enumdirection = (Direction) state.getValue(ChestBlock.FACING);
+
+        return state.getValue(ChestBlock.TYPE) == ChestType.LEFT ? enumdirection.getClockWise() : enumdirection.getCounterClockWise();
     }
 
     @Override
     public BlockState getStateForPlacement(BlockPlaceContext ctx) {
-        ChestType chestType = ChestType.SINGLE;
-        Direction direction = ctx.getHorizontalDirection().getOpposite();
-        FluidState fluidState = ctx.getLevel().getFluidState(ctx.getClickedPos());
-        boolean bl = ctx.isSecondaryUseActive();
-        Direction direction2 = ctx.getClickedFace();
-        if (direction2.getAxis().isHorizontal() && bl) {
-            Direction direction3 = this.candidatePartnerFacing(ctx, direction2.getOpposite());
-            if (direction3 != null && direction3.getAxis() != direction2.getAxis()) {
-                direction = direction3;
-                chestType = direction3.getCounterClockWise() == direction2.getOpposite() ? ChestType.RIGHT : ChestType.LEFT;
+        ChestType blockpropertychesttype = ChestType.SINGLE;
+        Direction enumdirection = ctx.getHorizontalDirection().getOpposite();
+        FluidState fluid = ctx.getLevel().getFluidState(ctx.getClickedPos());
+        boolean flag = ctx.isSecondaryUseActive();
+        Direction enumdirection1 = ctx.getClickedFace();
+
+        if (enumdirection1.getAxis().isHorizontal() && flag) {
+            Direction enumdirection2 = this.candidatePartnerFacing(ctx, enumdirection1.getOpposite());
+
+            if (enumdirection2 != null && enumdirection2.getAxis() != enumdirection1.getAxis()) {
+                enumdirection = enumdirection2;
+                blockpropertychesttype = enumdirection2.getCounterClockWise() == enumdirection1.getOpposite() ? ChestType.RIGHT : ChestType.LEFT;
             }
         }
 
-        if (chestType == ChestType.SINGLE && !bl) {
-            if (direction == this.candidatePartnerFacing(ctx, direction.getClockWise())) {
-                chestType = ChestType.LEFT;
-            } else if (direction == this.candidatePartnerFacing(ctx, direction.getCounterClockWise())) {
-                chestType = ChestType.RIGHT;
+        if (blockpropertychesttype == ChestType.SINGLE && !flag) {
+            if (enumdirection == this.candidatePartnerFacing(ctx, enumdirection.getClockWise())) {
+                blockpropertychesttype = ChestType.LEFT;
+            } else if (enumdirection == this.candidatePartnerFacing(ctx, enumdirection.getCounterClockWise())) {
+                blockpropertychesttype = ChestType.RIGHT;
             }
         }
 
-        return this.defaultBlockState()
-            .setValue(FACING, direction)
-            .setValue(TYPE, chestType)
-            .setValue(WATERLOGGED, Boolean.valueOf(fluidState.getType() == Fluids.WATER));
+        return (BlockState) ((BlockState) ((BlockState) this.defaultBlockState().setValue(ChestBlock.FACING, enumdirection)).setValue(ChestBlock.TYPE, blockpropertychesttype)).setValue(ChestBlock.WATERLOGGED, fluid.getType() == Fluids.WATER);
     }
 
     @Override
     protected FluidState getFluidState(BlockState state) {
-        return state.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
+        return (Boolean) state.getValue(ChestBlock.WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(state);
     }
 
     @Nullable
     private Direction candidatePartnerFacing(BlockPlaceContext ctx, Direction dir) {
-        BlockState blockState = ctx.getLevel().getBlockState(ctx.getClickedPos().relative(dir));
-        return blockState.is(this) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null;
+        BlockState iblockdata = ctx.getLevel().getBlockState(ctx.getClickedPos().relative(dir));
+
+        return iblockdata.is((Block) this) && iblockdata.getValue(ChestBlock.TYPE) == ChestType.SINGLE ? (Direction) iblockdata.getValue(ChestBlock.FACING) : null;
     }
 
     @Override
@@ -241,9 +251,9 @@
         if (world.isClientSide) {
             return InteractionResult.SUCCESS;
         } else {
-            MenuProvider menuProvider = this.getMenuProvider(state, world, pos);
-            if (menuProvider != null) {
-                player.openMenu(menuProvider);
+            MenuProvider itileinventory = this.getMenuProvider(state, world, pos);
+
+            if (itileinventory != null && player.openMenu(itileinventory).isPresent()) { // Paper - Fix InventoryOpenEvent cancellation
                 player.awardStat(this.getOpenChestStat());
                 PiglinAi.angerNearbyPiglins(player, true);
             }
@@ -257,49 +267,61 @@
     }
 
     public BlockEntityType<? extends ChestBlockEntity> blockEntityType() {
-        return this.blockEntityType.get();
+        return (BlockEntityType) this.blockEntityType.get();
     }
 
     @Nullable
     public static Container getContainer(ChestBlock block, BlockState state, Level world, BlockPos pos, boolean ignoreBlocked) {
-        return block.combine(state, world, pos, ignoreBlocked).apply(CHEST_COMBINER).orElse(null);
+        return (Container) ((Optional) block.combine(state, world, pos, ignoreBlocked).apply(ChestBlock.CHEST_COMBINER)).orElse((Object) null);
     }
 
     @Override
     public DoubleBlockCombiner.NeighborCombineResult<? extends ChestBlockEntity> combine(BlockState state, Level world, BlockPos pos, boolean ignoreBlocked) {
-        BiPredicate<LevelAccessor, BlockPos> biPredicate;
+        BiPredicate<LevelAccessor, BlockPos> bipredicate; // CraftBukkit - decompile error
+
         if (ignoreBlocked) {
-            biPredicate = (worldx, posx) -> false;
+            bipredicate = (generatoraccess, blockposition1) -> {
+                return false;
+            };
         } else {
-            biPredicate = ChestBlock::isChestBlockedAt;
+            bipredicate = ChestBlock::isChestBlockedAt;
         }
 
-        return DoubleBlockCombiner.combineWithNeigbour(
-            this.blockEntityType.get(), ChestBlock::getBlockType, ChestBlock::getConnectedDirection, FACING, state, world, pos, biPredicate
-        );
+        return DoubleBlockCombiner.combineWithNeigbour((BlockEntityType) this.blockEntityType.get(), ChestBlock::getBlockType, ChestBlock::getConnectedDirection, ChestBlock.FACING, state, world, pos, bipredicate);
     }
 
     @Nullable
     @Override
     public MenuProvider getMenuProvider(BlockState state, Level world, BlockPos pos) {
-        return this.combine(state, world, pos, false).apply(MENU_PROVIDER_COMBINER).orElse(null);
+        // CraftBukkit start
+        return this.getMenuProvider(state, world, pos, false);
     }
 
-    public static DoubleBlockCombiner.Combiner<ChestBlockEntity, Float2FloatFunction> opennessCombiner(LidBlockEntity progress) {
+    @Nullable
+    public MenuProvider getMenuProvider(BlockState iblockdata, Level world, BlockPos blockposition, boolean ignoreObstructions) {
+        return (MenuProvider) ((Optional) this.combine(iblockdata, world, blockposition, ignoreObstructions).apply(ChestBlock.MENU_PROVIDER_COMBINER)).orElse((Object) null);
+        // CraftBukkit end
+    }
+
+    public static DoubleBlockCombiner.Combiner<ChestBlockEntity, Float2FloatFunction> opennessCombiner(final LidBlockEntity progress) {
         return new DoubleBlockCombiner.Combiner<ChestBlockEntity, Float2FloatFunction>() {
-            @Override
             public Float2FloatFunction acceptDouble(ChestBlockEntity first, ChestBlockEntity second) {
-                return tickDelta -> Math.max(first.getOpenNess(tickDelta), second.getOpenNess(tickDelta));
+                return (f) -> {
+                    return Math.max(first.getOpenNess(f), second.getOpenNess(f));
+                };
             }
 
-            @Override
             public Float2FloatFunction acceptSingle(ChestBlockEntity single) {
+                Objects.requireNonNull(single);
                 return single::getOpenNess;
             }
 
             @Override
             public Float2FloatFunction acceptNone() {
-                return progress::getOpenNess;
+                LidBlockEntity lidblockentity1 = progress;
+
+                Objects.requireNonNull(progress);
+                return lidblockentity1::getOpenNess;
             }
         };
     }
@@ -316,24 +338,30 @@
     }
 
     public static boolean isChestBlockedAt(LevelAccessor world, BlockPos pos) {
-        return isBlockedChestByBlock(world, pos) || isCatSittingOnChest(world, pos);
+        return ChestBlock.isBlockedChestByBlock(world, pos) || ChestBlock.isCatSittingOnChest(world, pos);
     }
 
     public static boolean isBlockedChestByBlock(BlockGetter world, BlockPos pos) {
-        BlockPos blockPos = pos.above();
-        return world.getBlockState(blockPos).isRedstoneConductor(world, blockPos);
+        BlockPos blockposition1 = pos.above();
+
+        return world.getBlockState(blockposition1).isRedstoneConductor(world, blockposition1);
     }
 
     private static boolean isCatSittingOnChest(LevelAccessor world, BlockPos pos) {
-        List<Cat> list = world.getEntitiesOfClass(
-            Cat.class,
-            new AABB(
-                (double)pos.getX(), (double)(pos.getY() + 1), (double)pos.getZ(), (double)(pos.getX() + 1), (double)(pos.getY() + 2), (double)(pos.getZ() + 1)
-            )
-        );
+        // Paper start - Option to disable chest cat detection
+        if (world.getMinecraftWorld().paperConfig().entities.behavior.disableChestCatDetection) {
+            return false;
+        }
+        // Paper end - Option to disable chest cat detection
+        List<Cat> list = world.getEntitiesOfClass(Cat.class, new AABB((double) pos.getX(), (double) (pos.getY() + 1), (double) pos.getZ(), (double) (pos.getX() + 1), (double) (pos.getY() + 2), (double) (pos.getZ() + 1)));
+
         if (!list.isEmpty()) {
-            for (Cat cat : list) {
-                if (cat.isInSittingPose()) {
+            Iterator iterator = list.iterator();
+
+            while (iterator.hasNext()) {
+                Cat entitycat = (Cat) iterator.next();
+
+                if (entitycat.isInSittingPose()) {
                     return true;
                 }
             }
@@ -349,22 +377,22 @@
 
     @Override
     protected int getAnalogOutputSignal(BlockState state, Level world, BlockPos pos) {
-        return AbstractContainerMenu.getRedstoneSignalFromContainer(getContainer(this, state, world, pos, false));
+        return AbstractContainerMenu.getRedstoneSignalFromContainer(ChestBlock.getContainer(this, state, world, pos, false));
     }
 
     @Override
     protected BlockState rotate(BlockState state, Rotation rotation) {
-        return state.setValue(FACING, rotation.rotate(state.getValue(FACING)));
+        return (BlockState) state.setValue(ChestBlock.FACING, rotation.rotate((Direction) state.getValue(ChestBlock.FACING)));
     }
 
     @Override
     protected BlockState mirror(BlockState state, Mirror mirror) {
-        return state.rotate(mirror.getRotation(state.getValue(FACING)));
+        return state.rotate(mirror.getRotation((Direction) state.getValue(ChestBlock.FACING)));
     }
 
     @Override
     protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
-        builder.add(FACING, TYPE, WATERLOGGED);
+        builder.add(ChestBlock.FACING, ChestBlock.TYPE, ChestBlock.WATERLOGGED);
     }
 
     @Override
@@ -374,9 +402,11 @@
 
     @Override
     protected void tick(BlockState state, ServerLevel world, BlockPos pos, RandomSource random) {
-        BlockEntity blockEntity = world.getBlockEntity(pos);
-        if (blockEntity instanceof ChestBlockEntity) {
-            ((ChestBlockEntity)blockEntity).recheckOpen();
+        BlockEntity tileentity = world.getBlockEntity(pos);
+
+        if (tileentity instanceof ChestBlockEntity) {
+            ((ChestBlockEntity) tileentity).recheckOpen();
         }
+
     }
 }
