Search code examples
javaminecraft-fabric

2-Tall Minecraft Block with same interaction on both Blocks


Thank you for any help in advance and sorry if this way to simple.

Versioning: MC 1.19.3, Fabric JSON is either a singular one for 2 Tall Block or a Top and Bottom Half

So i want to create a GUI displaying Block, which is 2 Blocks tall. I got the Collision working, but it's still rendering only and not interactable/eats Blocks when placed from above.

I have read about Custom Entities and or Tiling (Like with doors), but nothing for something simple like my issue.

My current working Class looks as follows and works for the bottom Block. I am using the singular JSON currently.

public class VendingMachineBlock extends Block {
    private static final VoxelShape SHAPE = Block.createCuboidShape(0, 0, 0, 16, 32, 16);

    public VendingMachineBlock() {
        super(Settings.of(Material.METAL)
                .nonOpaque()
                .strength(4.0f)
                .requiresTool()
                .sounds(BlockSoundGroup.METAL)
        );
    }

    public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        return SHAPE;
    }

    public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
        return SHAPE;
    }

    @Override
    public boolean canReplace(BlockState state, ItemPlacementContext context) {
        BlockPos pos = context.getBlockPos();
        if (context.getWorld().getBlockState(pos.down()).isOf(this)) {
            // Prevent block placement in the top part of the VendingMachineBlock
            return false;
        }
        return super.canReplace(state, context);
    }

    @Override
    public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
        double relativeHitY = hit.getPos().y - pos.getY();
        if (relativeHitY > 0.5 || relativeHitY < 0) {
            // Player is interacting with the top or bottom part of the VendingMachineBlock
            if (!world.isClient) {
                player.sendMessage(Text.of("Hello, world!"), false);
            }
            return ActionResult.SUCCESS;
        }
        return super.onUse(state, world, pos, player, hand, hit);
    }
}

I have looked at various videos and even asked Bing AI to find resources for me, but neither the official Docs nor the videos have shown a solution for this "simple" issue. Most of what i have found were dynamic animations of floating blocks above, or far outdated stuff.

Thanks again for reading and sorry if i am just unknowledged. Just trying to get startet with Java and MC Modding again.

All the best, Cap


Solution

  • You can't make a 2-block-tall block. You have to make two separate blocks or block states - one for the top and one for the bottom.

    For example, the game only calls your block's canReplace function when your block is replaced. It doesn't call it if the player replaces the air block on top of your block because that's not your block. So you have to put one of your blocks in that spot and not try to pretend there's one when there isn't.

    Your block has a GUI, so it probably has a bunch of tile entity data. You will find it convenient to pick one half (e.g. the bottom) to store the data, and make the top one be a completely boring block that, when you right-click it, acts like you right-clicked the bottom one instead. And if one half sees that the other half is missing, it breaks.