private static final AxisAlignedBB R_LEG = new AxisAlignedBB(0.25, 0, 0.375, 0.5, 0.75, 0.625);
private static final AxisAlignedBB L_LEG = new AxisAlignedBB(0.5, 0, 0.375, 0.75, 0.75, 0.625);
private static final AxisAlignedBB L_ARM = new AxisAlignedBB(0.75, 0.75, 0.375, 1, 1.5, 0.625);
private static final AxisAlignedBB R_ARM = new AxisAlignedBB(0, 0.75, 0.375, 0.25, 1.5, 0.625);
private static final AxisAlignedBB CHEST = new AxisAlignedBB(0.25, 0.75, 0.375, 0.75, 1.5, 0.625);
private static final AxisAlignedBB HEAD = new AxisAlignedBB(0.25, 1.5, 0.25, 0.75, 2, 0.75);
/**
* AxisAlignedBBs and methods getBoundingBox, collisionRayTrace, and collisionRayTrace generated using MrCrayfish's Model Creator <a href="https://mrcrayfish.com/tools?id=mc">https://mrcrayfish.com/tools?id=mc</a>
*/
private static final List<AxisAlignedBB> COLLISION_BOXES = Lists.newArrayList(R_LEG, L_LEG, L_ARM, R_ARM, CHEST, HEAD);
private static final AxisAlignedBB BOUNDING_BOX = new AxisAlignedBB(0, 0, 0.25, 1, 2, 0.75);

@Override
public AxisAlignedBB getBoundingBox(IBlockState state, IBlockAccess source, BlockPos pos)
{
    return BOUNDING_BOX;
}

@Override
public void addCollisionBoxToList(IBlockState state, World world, BlockPos pos, AxisAlignedBB entityBox, List<AxisAlignedBB> collidingBoxes, @Nullable Entity entity, boolean isActualState)
{
    entityBox = entityBox.offset(-pos.getX(), -pos.getY(), -pos.getZ());
    for (AxisAlignedBB box : COLLISION_BOXES)
    {
        if (entityBox.intersects(box))
            collidingBoxes.add(box.offset(pos));
    }
}

@Override
@Nullable
public RayTraceResult collisionRayTrace(IBlockState state, World world, BlockPos pos, Vec3d start, Vec3d end)
{
    double distanceSq;
    double distanceSqShortest = Double.POSITIVE_INFINITY;
    RayTraceResult resultClosest = null;
    RayTraceResult result;
    start = start.subtract(pos.getX(), pos.getY(), pos.getZ());
    end = end.subtract(pos.getX(), pos.getY(), pos.getZ());
    for (AxisAlignedBB box : COLLISION_BOXES)
    {
        result = box.calculateIntercept(start, end);
        if (result == null)
            continue;

        distanceSq = result.hitVec.squareDistanceTo(start);
        if (distanceSq < distanceSqShortest)
        {
            distanceSqShortest = distanceSq;
            resultClosest = result;
        }
    }
    return resultClosest == null ? null : new RayTraceResult(RayTraceResult.Type.BLOCK, resultClosest.hitVec.addVector(pos.getX(), pos.getY(), pos.getZ()), resultClosest.sideHit, pos);
}