package tech.nevets.vplus.blocks; import net.minecraft.block.*; import net.minecraft.block.enums.SlabType; import net.minecraft.entity.ai.pathing.NavigationType; import net.minecraft.fluid.Fluid; import net.minecraft.fluid.FluidState; import net.minecraft.fluid.Fluids; import net.minecraft.item.ItemPlacementContext; import net.minecraft.state.StateManager; import net.minecraft.state.property.BooleanProperty; import net.minecraft.state.property.DirectionProperty; import net.minecraft.state.property.EnumProperty; import net.minecraft.state.property.Properties; import net.minecraft.tag.FluidTags; 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.WorldAccess; import org.jetbrains.annotations.Nullable; import tech.nevets.vplus.VPProperties; import tech.nevets.vplus.blocks.enums.VerticalSlabType; public class VerticalSlabBlock extends HorizontalFacingBlock implements Waterloggable { public static final EnumProperty TYPE; public static final BooleanProperty WATERLOGGED; private static final VoxelShape NORTH; private static final VoxelShape EAST; private static final VoxelShape SOUTH; private static final VoxelShape WEST; public VerticalSlabBlock(Settings settings) { super(settings); setDefaultState(this.stateManager.getDefaultState().with(Properties.HORIZONTAL_FACING, Direction.NORTH).with(WATERLOGGED, false)); } // @Override // public boolean hasSidedTransparency(BlockState state) { // return state.get(TYPE) != VerticalSlabType.DOUBLE; // } @Override protected void appendProperties(StateManager.Builder stateManager) { stateManager.add(Properties.HORIZONTAL_FACING, WATERLOGGED); } @Override public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { VerticalSlabType verticalSlabType = state.get(TYPE); Direction dir = state.get(FACING); switch (dir) { case NORTH -> {return NORTH;} case SOUTH -> {return SOUTH;} case EAST -> {return EAST;} case WEST -> {return WEST;} default -> {return VoxelShapes.fullCube();} } } @Nullable public BlockState getPlacementState(ItemPlacementContext ctx) { BlockPos blockPos = ctx.getBlockPos(); BlockState blockState = ctx.getWorld().getBlockState(blockPos); if (blockState.isOf(this)) { return blockState.with(TYPE, VerticalSlabType.DOUBLE).with(WATERLOGGED, false); } else { return this.getDefaultState().with(Properties.HORIZONTAL_FACING, ctx.getPlayerFacing().getOpposite()).with(WATERLOGGED, ctx.getWorld().getFluidState(ctx.getBlockPos()).getFluid() == Fluids.WATER); } } @Override public FluidState getFluidState(BlockState state) { return state.get(WATERLOGGED) ? Fluids.WATER.getStill(false) : super.getFluidState(state); } @Override public BlockState getStateForNeighborUpdate(BlockState state, Direction direction, BlockState neighborState, WorldAccess world, BlockPos pos, BlockPos neighborPos) { if (state.get(WATERLOGGED)) { world.createAndScheduleFluidTick(pos, Fluids.WATER, Fluids.WATER.getTickRate(world)); } return super.getStateForNeighborUpdate(state, direction, neighborState, world, pos, neighborPos); } @Override public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { switch (type) { case WATER -> {return world.getFluidState(pos).isIn(FluidTags.WATER);} default -> {return false;} } } @Override public boolean tryFillWithFluid(WorldAccess world, BlockPos pos, BlockState state, FluidState fluidState) { Direction dir = state.get(FACING); switch(dir) { case NORTH, SOUTH, EAST, WEST -> {return Waterloggable.super.tryFillWithFluid(world, pos, state, fluidState);} default -> {return false;} } } @Override public boolean canFillWithFluid(BlockView world, BlockPos pos, BlockState state, Fluid fluid) { Direction dir = state.get(FACING); switch(dir) { case NORTH, SOUTH, EAST, WEST -> {return Waterloggable.super.canFillWithFluid(world, pos, state, fluid);} default -> {return false;} } } @Override public BlockRenderType getRenderType(BlockState blockState_1) { return BlockRenderType.MODEL; } private static VoxelShape rotate(Direction from, Direction to, VoxelShape shape) { VoxelShape[] buffer = new VoxelShape[]{ shape, VoxelShapes.empty() }; int times = (to.getHorizontal() - from.getHorizontal() + 4) % 4; for (int i = 0; i < times; i++) { buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> buffer[1] = VoxelShapes.union(buffer[1], VoxelShapes.cuboid(1-maxZ, minY, minX, 1-minZ, maxY, maxX))); buffer[0] = buffer[1]; buffer[1] = VoxelShapes.empty(); } return buffer[0]; } static { TYPE = VPProperties.VERTICAL_SLAB_TYPE; WATERLOGGED = Properties.WATERLOGGED; VoxelShape shape = createCuboidShape(0.0D, 0.0D, 0.0D, 8.0D, 16.0D, 16.0D); EAST = shape; NORTH = rotate(Direction.EAST, Direction.NORTH, shape); SOUTH = rotate(Direction.EAST, Direction.SOUTH, shape); WEST = rotate(Direction.EAST, Direction.WEST, shape); } }