// Path: src/main/java/dev/gigaherz/enderrift/automation/AggregatorBlock.java
// public abstract class AggregatorBlock<T extends AggregatorBlockEntity> extends BaseEntityBlock
// {
//     protected AggregatorBlock(Properties properties)
//     {
//         super(properties);
//     }
// 
//     public RenderShape getRenderShape(BlockState p_49232_) {
//         return RenderShape.MODEL;
//     }
// 
//     @org.jetbrains.annotations.Nullable
//     @Override
//     public abstract BlockEntity newBlockEntity(BlockPos p_153215_, BlockState p_153216_);
// 
//     @Nullable
//     @Override
//     public abstract <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType<T> p_153214_);
// 
//     @Deprecated
//     @Override
//     public void neighborChanged(BlockState state, Level world, BlockPos pos, Block otherBlock, BlockPos otherPos, boolean isMoving)
//     {
//         super.neighborChanged(state, world, pos, otherBlock, otherPos, isMoving);
// 
//         BlockEntity teSelf = world.getBlockEntity(pos);
//         if (!(teSelf instanceof AggregatorBlockEntity))
//             return;
//         ((AggregatorBlockEntity) teSelf).updateNeighbours();
//     }
// 
//     @Override
//     public void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbor)
//     {
//         super.onNeighborChange(state, world, pos, neighbor);
// 
//         recheckNeighbour(world, pos, neighbor);
//     }
// 
//     protected void recheckNeighbour(BlockGetter world, BlockPos pos, BlockPos neighbor)
//     {
//         Direction side = null;
//         if (neighbor.equals(pos.east())) side = Direction.EAST;
//         if (neighbor.equals(pos.west())) side = Direction.WEST;
//         if (neighbor.equals(pos.north())) side = Direction.NORTH;
//         if (neighbor.equals(pos.south())) side = Direction.SOUTH;
//         if (neighbor.equals(pos.above())) side = Direction.UP;
//         if (neighbor.equals(pos.below())) side = Direction.DOWN;
// 
//         if (side != null && isAutomatable(world, pos, side))
//         {
//             BlockEntity teSelf = world.getBlockEntity(pos);
//             if (!(teSelf instanceof AggregatorBlockEntity))
//                 return;
//             ((AggregatorBlockEntity) teSelf).updateConnectedInventories();
//         }
//     }
// 
//     protected boolean isAutomatable(BlockGetter worldIn, BlockPos pos, Direction facing)
//     {
//         var te = worldIn.getBlockEntity(pos.relative(facing));
// 
//         return te != null && AutomationHelper.isAutomatable(te, facing.getOpposite());
//     }
// 
//     protected boolean isConnectableAutomation(BlockGetter worldIn, BlockPos pos, Direction facing)
//     {
//         var te = worldIn.getBlockEntity(pos.relative(facing));
// 
//         if (te == null)
//             return false;
// 
//         if (te instanceof AggregatorBlockEntity)
//             return true;
// 
//         return AutomationHelper.isAutomatable(te, facing.getOpposite());
//     }
// }


import com.google.common.collect.ImmutableMap;
import dev.gigaherz.enderrift.automation.AggregatorBlock;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.InteractionResult;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import javax.annotation.Nullable;
    @Override
    public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit)
    {
        BlockEntity tileEntity = worldIn.getBlockEntity(pos);

        if (!(tileEntity instanceof BrowserBlockEntity) || player.isShiftKeyDown())
            return InteractionResult.FAIL;

        if (player.level.isClientSide)
            return InteractionResult.SUCCESS;

        if (crafting)
            openCraftingBrowser(player, (BrowserBlockEntity) tileEntity);
        else
            openBrowser(player, (BrowserBlockEntity) tileEntity);

        return InteractionResult.SUCCESS;
    }

    private void openBrowser(Player player, BrowserBlockEntity tileEntity)
    {
        player.openMenu(new SimpleMenuProvider(
                (id, playerInventory, playerEntity) -> new BrowserContainer(id, tileEntity, playerInventory),
                new TranslatableComponent("container.enderrift.browser")));
    }

    private void openCraftingBrowser(Player player, BrowserBlockEntity tileEntity)
    {
        player.openMenu(new SimpleMenuProvider(
                (id, playerInventory, playerEntity) -> new CraftingBrowserContainer(id, tileEntity, playerInventory),
// Path: src/main/java/dev/gigaherz/enderrift/automation/AggregatorBlock.java
// public abstract class AggregatorBlock<T extends AggregatorBlockEntity> extends BaseEntityBlock
// {
//     protected AggregatorBlock(Properties properties)
//     {
//         super(properties);
//     }
// 
//     public RenderShape getRenderShape(BlockState p_49232_) {
//         return RenderShape.MODEL;
//     }
// 
//     @org.jetbrains.annotations.Nullable
//     @Override
//     public abstract BlockEntity newBlockEntity(BlockPos p_153215_, BlockState p_153216_);
// 
//     @Nullable
//     @Override
//     public abstract <T extends BlockEntity> BlockEntityTicker<T> getTicker(Level p_153212_, BlockState p_153213_, BlockEntityType<T> p_153214_);
// 
//     @Deprecated
//     @Override
//     public void neighborChanged(BlockState state, Level world, BlockPos pos, Block otherBlock, BlockPos otherPos, boolean isMoving)
//     {
//         super.neighborChanged(state, world, pos, otherBlock, otherPos, isMoving);
// 
//         BlockEntity teSelf = world.getBlockEntity(pos);
//         if (!(teSelf instanceof AggregatorBlockEntity))
//             return;
//         ((AggregatorBlockEntity) teSelf).updateNeighbours();
//     }
// 
//     @Override
//     public void onNeighborChange(BlockState state, LevelReader world, BlockPos pos, BlockPos neighbor)
//     {
//         super.onNeighborChange(state, world, pos, neighbor);
// 
//         recheckNeighbour(world, pos, neighbor);
//     }
// 
//     protected void recheckNeighbour(BlockGetter world, BlockPos pos, BlockPos neighbor)
//     {
//         Direction side = null;
//         if (neighbor.equals(pos.east())) side = Direction.EAST;
//         if (neighbor.equals(pos.west())) side = Direction.WEST;
//         if (neighbor.equals(pos.north())) side = Direction.NORTH;
//         if (neighbor.equals(pos.south())) side = Direction.SOUTH;
//         if (neighbor.equals(pos.above())) side = Direction.UP;
//         if (neighbor.equals(pos.below())) side = Direction.DOWN;
// 
//         if (side != null && isAutomatable(world, pos, side))
//         {
//             BlockEntity teSelf = world.getBlockEntity(pos);
//             if (!(teSelf instanceof AggregatorBlockEntity))
//                 return;
//             ((AggregatorBlockEntity) teSelf).updateConnectedInventories();
//         }
//     }
// 
//     protected boolean isAutomatable(BlockGetter worldIn, BlockPos pos, Direction facing)
//     {
//         var te = worldIn.getBlockEntity(pos.relative(facing));
// 
//         return te != null && AutomationHelper.isAutomatable(te, facing.getOpposite());
//     }
// 
//     protected boolean isConnectableAutomation(BlockGetter worldIn, BlockPos pos, Direction facing)
//     {
//         var te = worldIn.getBlockEntity(pos.relative(facing));
// 
//         if (te == null)
//             return false;
// 
//         if (te instanceof AggregatorBlockEntity)
//             return true;
// 
//         return AutomationHelper.isAutomatable(te, facing.getOpposite());
//     }
// }


// Path: src/main/java/dev/gigaherz/enderrift/automation/browser/BrowserBlock.java
import com.google.common.collect.ImmutableMap;
import dev.gigaherz.enderrift.automation.AggregatorBlock;
import net.minecraft.world.level.block.BaseEntityBlock;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntityTicker;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.SimpleMenuProvider;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.block.state.properties.DirectionProperty;
import net.minecraft.world.level.block.state.StateDefinition;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.InteractionResult;
import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.core.BlockPos;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
import javax.annotation.Nullable;

    @Override
    public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit)
    {
        BlockEntity tileEntity = worldIn.getBlockEntity(pos);

        if (!(tileEntity instanceof BrowserBlockEntity) || player.isShiftKeyDown())
            return InteractionResult.FAIL;

        if (player.level.isClientSide)
            return InteractionResult.SUCCESS;

        if (crafting)
            openCraftingBrowser(player, (BrowserBlockEntity) tileEntity);
        else
            openBrowser(player, (BrowserBlockEntity) tileEntity);

        return InteractionResult.SUCCESS;
    }

    private void openBrowser(Player player, BrowserBlockEntity tileEntity)
    {
        player.openMenu(new SimpleMenuProvider(
                (id, playerInventory, playerEntity) -> new BrowserContainer(id, tileEntity, playerInventory),
                new TranslatableComponent("container.enderrift.browser")));
    }

    private void openCraftingBrowser(Player player, BrowserBlockEntity tileEntity)
    {
        player.openMenu(new SimpleMenuProvider(
                (id, playerInventory, playerEntity) -> new CraftingBrowserContainer(id, tileEntity, playerInventory),
                new TranslatableComponent("container.enderrift.crafting_browser")));