diff --git a/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java b/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java index a3c2a8a..e392679 100644 --- a/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java +++ b/src/main/java/io/github/cottonmc/templates/block/TemplateSlopeBlock.java @@ -1,39 +1,49 @@ package io.github.cottonmc.templates.block; import io.github.cottonmc.templates.Templates; +import io.github.cottonmc.templates.util.StairShapeMaker; import net.minecraft.block.Block; import net.minecraft.block.BlockState; import net.minecraft.block.ShapeContext; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.enums.BlockHalf; import net.minecraft.item.ItemPlacementContext; import net.minecraft.state.StateManager; import net.minecraft.state.property.DirectionProperty; +import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; import net.minecraft.util.shape.VoxelShape; -import net.minecraft.util.shape.VoxelShapes; import net.minecraft.world.BlockView; import javax.annotation.Nullable; public class TemplateSlopeBlock extends TemplateBlock { public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; + public static final EnumProperty HALF = Properties.BLOCK_HALF; - public static final VoxelShape BASE = VoxelShapes.cuboid(0f, 0f, 0f, 1f, 0.5f, 1f); - public static final VoxelShape NORTH = VoxelShapes.cuboid(0f, 0.5f, 0f, 1f, 1f, 0.5f); - public static final VoxelShape SOUTH = VoxelShapes.cuboid(0f, 0.5f, 0.5f, 1f, 1f, 1f); - public static final VoxelShape EAST = VoxelShapes.cuboid(0.5f, 0.5f, 0f, 1f, 1f, 1f); - public static final VoxelShape WEST = VoxelShapes.cuboid(0f, 0.5f, 0f, 0.5f, 1f, 1f); + private static final VoxelShape[] shapes = new VoxelShape[8]; + private static int shapeIndex(Direction dir, BlockHalf half) { + return dir.getHorizontal() + (half == BlockHalf.TOP ? 4 : 0); + } + static { + for(BlockHalf half : BlockHalf.values()) { + for(Direction d : Direction.values()) { + if(d.getHorizontal() == -1) continue; + shapes[shapeIndex(d, half)] = StairShapeMaker.createHorizontal(d, half, 8, 0.125d, 0.125d); + } + } + } public TemplateSlopeBlock(Settings settings) { super(settings); - setDefaultState(getDefaultState().with(FACING, Direction.NORTH)); + setDefaultState(getDefaultState().with(FACING, Direction.NORTH).with(HALF, BlockHalf.BOTTOM)); } @Override protected void appendProperties(StateManager.Builder builder) { - super.appendProperties(builder.add(FACING)); + super.appendProperties(builder.add(FACING, HALF)); } @Override @@ -44,24 +54,20 @@ public class TemplateSlopeBlock extends TemplateBlock { @Nullable @Override public BlockState getPlacementState(ItemPlacementContext ctx) { - return getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing()); + BlockHalf half = switch(ctx.getSide()) { + case UP -> BlockHalf.BOTTOM; + case DOWN -> BlockHalf.TOP; + default -> (ctx.getHitPos().getY() - (double) ctx.getBlockPos().getY() < 0.5) ? BlockHalf.BOTTOM : BlockHalf.TOP; + }; + + return getDefaultState() + .with(FACING, ctx.getHorizontalPlayerFacing()) + .with(HALF, half); } @Override public VoxelShape getCollisionShape(BlockState state, BlockView view, BlockPos pos, ShapeContext ctx) { - Direction dir = state.get(FACING); - switch(dir) { - case NORTH: - return VoxelShapes.union(BASE, NORTH); - case SOUTH: - return VoxelShapes.union(BASE, SOUTH); - case EAST: - return VoxelShapes.union(BASE, EAST); - case WEST: - return VoxelShapes.union(BASE, WEST); - default: - return VoxelShapes.fullCube(); - } + return shapes[shapeIndex(state.get(FACING), state.get(HALF))]; } @Override diff --git a/src/main/java/io/github/cottonmc/templates/util/StairShapeMaker.java b/src/main/java/io/github/cottonmc/templates/util/StairShapeMaker.java new file mode 100644 index 0000000..02abc2d --- /dev/null +++ b/src/main/java/io/github/cottonmc/templates/util/StairShapeMaker.java @@ -0,0 +1,64 @@ +package io.github.cottonmc.templates.util; + +import net.minecraft.block.enums.BlockHalf; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; + +public class StairShapeMaker { + public static VoxelShape createHorizontal(Direction shortSide, BlockHalf half, int steps, double rise, double run) { + VoxelShape shape = VoxelShapes.empty(); + + Vec3d a, b, march; + switch(shortSide) { + case SOUTH -> { + a = new Vec3d(0, 0, 1); + b = new Vec3d(1, rise, 0); + march = new Vec3d(0, rise, run); + } + case NORTH -> { + a = new Vec3d(0, 0, 0); + b = new Vec3d(1, rise, 1); + march = new Vec3d(0, rise, -run); + } + case EAST -> { + a = new Vec3d(1, 0, 0); + b = new Vec3d(0, rise, 1); + march = new Vec3d(run, rise, 0); + } + case WEST -> { + a = new Vec3d(0, 0, 0); + b = new Vec3d(1, rise, 1); + march = new Vec3d(-run, rise, 0); + } + default -> { + return VoxelShapes.fullCube(); //TODO + } + } + + if(half == BlockHalf.TOP) { + a = new Vec3d(a.x, 1 - a.y, a.z); + b = new Vec3d(b.x, 1 - b.y, b.z); + march = march.multiply(1, -1, 1); + } + + for(int i = 0; i < steps; i++) { + VoxelShape newShape = agh(a.x, a.y, a.z, b.x, b.y, b.z); + shape = VoxelShapes.union(shape, newShape); + b = b.add(march); + } + + return shape.simplify(); + } + + private static VoxelShape agh(double x1, double y1, double z1, double x2, double y2, double z2) { + double minX = Math.min(x1, x2); + double maxX = Math.max(x1, x2); + double minY = Math.min(y1, y2); + double maxY = Math.max(y1, y2); + double minZ = Math.min(z1, z2); + double maxZ = Math.max(z1, z2); + return VoxelShapes.cuboid(minX, minY, minZ, maxX, maxY, maxZ); + } +} diff --git a/src/main/resources/assets/templates/blockstates/slope.json b/src/main/resources/assets/templates/blockstates/slope.json index 4e51b33..544a4b9 100644 --- a/src/main/resources/assets/templates/blockstates/slope.json +++ b/src/main/resources/assets/templates/blockstates/slope.json @@ -1,19 +1,38 @@ { "variants": { - "facing=east": { + "facing=east,half=bottom": { "model": "templates:slope_special", "y": 270 }, - "facing=north": { + "facing=north,half=bottom": { "model": "templates:slope_special", "y": 180 }, - "facing=south": { + "facing=south,half=bottom": { "model": "templates:slope_special" }, - "facing=west": { + "facing=west,half=bottom": { "model": "templates:slope_special", "y": 90 + }, + "facing=east,half=top": { + "model": "templates:slope_special", + "x": 180, + "y": 90 + }, + "facing=north,half=top": { + "model": "templates:slope_special", + "x": 180 + }, + "facing=south,half=top": { + "model": "templates:slope_special", + "x": 180, + "y": 180 + }, + "facing=west,half=top": { + "model": "templates:slope_special", + "x": 180, + "y": 270 } } } \ No newline at end of file