diff --git a/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java index b3494074..44dd6f8e 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/FancyBedBlock.java @@ -1,14 +1,18 @@ package com.minelittlepony.unicopia.block; +import java.util.List; import java.util.Locale; +import java.util.function.Function; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.item.BedsheetsItem; +import com.minelittlepony.unicopia.util.VoxelShapeUtil; import net.minecraft.block.BedBlock; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; import net.minecraft.block.entity.BedBlockEntity; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; @@ -19,9 +23,26 @@ import net.minecraft.util.DyeColor; import net.minecraft.util.StringIdentifiable; 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 net.minecraft.world.World; public class FancyBedBlock extends BedBlock { + private static final List> SHAPES = List.of( + VoxelShapeUtil.rotator(VoxelShapes.union( + createCuboidShape(0, 3, 1, 16, 9, 16), + createCuboidShape(-0.5, 0, 1, 1.5, 13, 4), + createCuboidShape(14.5, 0, 1, 16.5, 13, 4), + createCuboidShape(1.5, 1, 0, 14.5, 16, 3) + )), + VoxelShapeUtil.rotator(VoxelShapes.union( + createCuboidShape(0, 3, 0, 16, 9, 16), + createCuboidShape(-0.5, 0, -1, 2.5, 10, 2), + createCuboidShape(13.5, 0, -1, 16.5, 10, 2), + createCuboidShape(1.5, 1, -2, 14.5, 12, 1) + )) + ); private final String base; @@ -30,6 +51,11 @@ public class FancyBedBlock extends BedBlock { this.base = base; } + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return SHAPES.get(state.get(PART).ordinal()).apply(BedBlock.getOppositePartDirection(state)); + } + @Override public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return new Tile(pos, state); diff --git a/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java b/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java new file mode 100644 index 00000000..adff046a --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/util/VoxelShapeUtil.java @@ -0,0 +1,52 @@ +package com.minelittlepony.unicopia.util; + +import net.minecraft.util.math.Box; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Direction.Axis; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; + +import java.util.function.Function; + +public interface VoxelShapeUtil { + Vec3d CENTER = new Vec3d(0.5, 0, 0.5); + + static Function rotator(VoxelShape base) { + return d -> rotate(base, d); + } + + static VoxelShape rotate(VoxelShape shape, Direction direction) { + if (direction.asRotation() == 0) { + return shape; + } + if (direction.getAxis() == Axis.X) { + direction = direction.getOpposite(); + } + float angle = direction.asRotation() * MathHelper.RADIANS_PER_DEGREE; + return VoxelShapes.union(VoxelShapes.empty(), shape.getBoundingBoxes().stream() + .map(box -> { + //These first two are enough for orthogonal rotations + Vec3d a = rotate(box.minX, box.minZ, angle); + Vec3d b = rotate(box.maxX, box.maxZ, angle); + //These cover odd angles + Vec3d c = rotate(box.minX, box.maxZ, angle); + Vec3d d = rotate(box.maxX, box.minZ, angle); + + return VoxelShapes.cuboid(new Box( + Math.min(Math.min(a.x, b.x), Math.min(c.x, d.x)), + box.minY, + Math.min(Math.min(a.z, b.z), Math.min(c.z, d.z)), + Math.max(Math.max(a.x, b.x), Math.max(c.x, d.x)), + box.maxY, + Math.max(Math.max(a.z, b.z), Math.max(c.z, d.z)) + )); + }) + .toArray(VoxelShape[]::new)); + } + + static Vec3d rotate(double x, double z, float angle) { + return new Vec3d(x, 0, z).subtract(CENTER).rotateY(angle).add(CENTER); + } +}