--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -1,7 +1,9 @@
 package net.minecraft.world.level.block;
 
 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;
@@ -45,6 +47,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;
@@ -54,6 +57,7 @@
 import net.minecraft.world.phys.shapes.VoxelShape;
 
 public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements SimpleWaterloggedBlock {
+
     public static final DirectionProperty FACING = HorizontalDirectionalBlock.FACING;
     public static final EnumProperty<ChestType> TYPE = BlockStateProperties.CHEST_TYPE;
     public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
@@ -66,12 +70,10 @@
     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);
         }
@@ -82,34 +84,12 @@
         }
     };
     private static final DoubleBlockCombiner.Combiner<ChestBlockEntity, Optional<MenuProvider>> MENU_PROVIDER_COMBINER = new DoubleBlockCombiner.Combiner<ChestBlockEntity, Optional<MenuProvider>>() {
-        @Override
         public Optional<MenuProvider> acceptDouble(final ChestBlockEntity first, final ChestBlockEntity second) {
-            final Container container = new CompoundContainer(first, second);
-            return Optional.of(new MenuProvider() {
-                @Nullable
-                @Override
-                public AbstractContainerMenu createMenu(int syncId, Inventory inv, Player player) {
-                    if (first.canOpen(player) && second.canOpen(player)) {
-                        first.unpackLootTable(inv.player);
-                        second.unpackLootTable(inv.player);
-                        return ChestMenu.sixRows(syncId, inv, container);
-                    } else {
-                        return null;
-                    }
-                }
+            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
         }
 
-        @Override
         public Optional<MenuProvider> acceptSingle(ChestBlockEntity single) {
             return Optional.of(single);
         }
@@ -120,18 +100,47 @@
         }
     };
 
+    // 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 inv, Player player) {
+            if (this.tileentitychest.canOpen(player) && this.tileentitychest1.canOpen(player)) {
+                this.tileentitychest.unpackLootTable(inv.player);
+                this.tileentitychest1.unpackLootTable(inv.player);
+                return ChestMenu.sixRows(syncId, inv, 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
+
     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
@@ -141,17 +150,18 @@
 
     @Override
     public 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);
@@ -159,71 +169,76 @@
 
     @Override
     public 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
     public 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
     public void setPlacedBy(Level world, BlockPos pos, BlockState state, LivingEntity placer, ItemStack itemStack) {
         if (itemStack.hasCustomHoverName()) {
-            BlockEntity blockEntity = world.getBlockEntity(pos);
-            if (blockEntity instanceof ChestBlockEntity) {
-                ((ChestBlockEntity)blockEntity).setCustomName(itemStack.getHoverName());
+            BlockEntity tileentity = world.getBlockEntity(pos);
+
+            if (tileentity instanceof ChestBlockEntity) {
+                ((ChestBlockEntity) tileentity).setCustomName(itemStack.getHoverName());
             }
         }
 
@@ -232,9 +247,10 @@
     @Override
     public void onRemove(BlockState state, Level world, BlockPos pos, BlockState newState, boolean moved) {
         if (!state.is(newState.getBlock())) {
-            BlockEntity blockEntity = world.getBlockEntity(pos);
-            if (blockEntity instanceof Container) {
-                Containers.dropContents(world, pos, (Container)blockEntity);
+            BlockEntity tileentity = world.getBlockEntity(pos);
+
+            if (tileentity instanceof Container) {
+                Containers.dropContents(world, pos, (Container) tileentity);
                 world.updateNeighbourForOutputSignal(pos, this);
             }
 
@@ -247,9 +263,10 @@
         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);
                 player.awardStat(this.getOpenChestStat());
                 PiglinAi.angerNearbyPiglins(player, true);
             }
@@ -263,51 +280,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).<Optional<Container>>apply(CHEST_COMBINER).orElse((Container)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) -> {
+            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).<Optional<MenuProvider>>apply(MENU_PROVIDER_COMBINER).orElse((MenuProvider)null);
+        // CraftBukkit start
+        return this.getMenuProvider(state, world, pos, false);
+    }
+
+    @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) -> {
-                    return 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;
             }
         };
     }
@@ -324,19 +351,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);
     }
 
     private 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
+        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;
                 }
             }
@@ -352,22 +390,22 @@
 
     @Override
     public 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
     public 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
     public 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
@@ -377,9 +415,10 @@
 
     @Override
     public 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();
         }
 
     }
