Something that’s important to understand for non-full-cube blocks is the concept of their shape.
The image that you see on the screen (when a block is rendered) is determined by the block model (i.e. the model json file). But Minecraft also uses a number of other ‘shapes’ to control the interaction of the block with its environment and with the player. Unlike block models, which are defined using a configuration file (json), these other shapes are defined in the code for the Block class itself.
The class which describes a block’s shape is VoxelShape, which you can visualise as a 3-dimensional grid where each grid location (“voxel”) is either full or empty. Minecraft uses code to build up the VoxelShape from 3D rectangular boxes (cuboids);
|VoxelShape being built up from two components using VoxelShapes.or()|
Creating a VoxelShape with holes using VoxelShapes.combineAndSimplify() with IBooleanFunction.ONLY_FIRST
The coordinate system for the VoxelShape is the same as for models, i.e. a 1x1x1 cubic metre block is 16 x 16 x 16.
VoxelShape coordinate system
Minecraft uses four different types of shape to characterise the block:
This is the “default” shape of the block. It is the shape used to draw the outline of the block when your player is directly looking at it. In most cases, this is the shape used for the other three types of block shapes as well.
|Examples of BlockState.getShape()|
|The BlockState.getCollisionShape() for fences and walls is higher than the block. This stops players and entities from jumping over.|
The render shape is used for lighting and shadows purposes and for rendering shortcuts (hiding block faces which the player can’t see). In most cases this is the same as the default shape, but for a few (Skull, Fence) it is different. I’m not sure of the reason.
|BlockState.getShape() in red, compared with BlockState.getRenderShape() which is empty.|
RayTrace is the name of the algorithm that Minecraft uses to determine what object the player is looking at when the player uses an item or tries to mine a block. The algorithm determines which block the player is affecting, as well as the face of the block (east, north, up, etc) being clicked. For a few blocks (Cauldron, Composter, Hopper, Scaffold) the RayTraceShape is used to modify the raytrace algorithm to return a different result. I’m not sure why that’s important.
|Composter BlockState.getShape() in red compared with the BlockState.getRayTraceShape() in purple.|