/* * Decompiled with CFR 0.152. * * Could not load the following classes: * com.google.common.collect.ImmutableMap * com.google.common.collect.Maps * com.mojang.serialization.MapCodec */ package net.minecraft.world.level.block; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.mojang.serialization.MapCodec; import java.util.Map; import java.util.function.Function; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.tags.BlockTags; import net.minecraft.util.RandomSource; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.FenceGateBlock; import net.minecraft.world.level.block.IronBarsBlock; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.SimpleWaterloggedBlock; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; import net.minecraft.world.level.block.state.properties.EnumProperty; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.properties.WallSide; import net.minecraft.world.level.material.FluidState; import net.minecraft.world.level.material.Fluids; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.BooleanOp; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.VoxelShape; public class WallBlock extends Block implements SimpleWaterloggedBlock { public static final MapCodec CODEC = WallBlock.simpleCodec(WallBlock::new); public static final BooleanProperty UP = BlockStateProperties.UP; public static final EnumProperty EAST = BlockStateProperties.EAST_WALL; public static final EnumProperty NORTH = BlockStateProperties.NORTH_WALL; public static final EnumProperty SOUTH = BlockStateProperties.SOUTH_WALL; public static final EnumProperty WEST = BlockStateProperties.WEST_WALL; public static final Map> PROPERTY_BY_DIRECTION = ImmutableMap.copyOf((Map)Maps.newEnumMap(Map.of(Direction.NORTH, NORTH, Direction.EAST, EAST, Direction.SOUTH, SOUTH, Direction.WEST, WEST))); public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED; private final Function shapes; private final Function collisionShapes; private static final VoxelShape TEST_SHAPE_POST = Block.column(2.0, 0.0, 16.0); private static final Map TEST_SHAPES_WALL = Shapes.rotateHorizontal(Block.boxZ(2.0, 16.0, 0.0, 9.0)); public MapCodec codec() { return CODEC; } public WallBlock(BlockBehaviour.Properties properties) { super(properties); this.registerDefaultState((BlockState)((BlockState)((BlockState)((BlockState)((BlockState)((BlockState)((BlockState)this.stateDefinition.any()).setValue(UP, true)).setValue(NORTH, WallSide.NONE)).setValue(EAST, WallSide.NONE)).setValue(SOUTH, WallSide.NONE)).setValue(WEST, WallSide.NONE)).setValue(WATERLOGGED, false)); this.shapes = this.makeShapes(16.0f, 14.0f); this.collisionShapes = this.makeShapes(24.0f, 24.0f); } private Function makeShapes(float postHeight, float wallTop) { VoxelShape post = Block.column(8.0, 0.0, postHeight); int width = 6; Map low = Shapes.rotateHorizontal(Block.boxZ(6.0, 0.0, wallTop, 0.0, 11.0)); Map tall = Shapes.rotateHorizontal(Block.boxZ(6.0, 0.0, postHeight, 0.0, 11.0)); return this.getShapeForEachState(state -> { VoxelShape shape = state.getValue(UP) != false ? post : Shapes.empty(); for (Map.Entry> entry : PROPERTY_BY_DIRECTION.entrySet()) { shape = Shapes.or(shape, switch ((WallSide)state.getValue(entry.getValue())) { default -> throw new MatchException(null, null); case WallSide.NONE -> Shapes.empty(); case WallSide.LOW -> (VoxelShape)low.get(entry.getKey()); case WallSide.TALL -> (VoxelShape)tall.get(entry.getKey()); }); } return shape; }, WATERLOGGED); } @Override protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { return this.shapes.apply(state); } @Override protected VoxelShape getCollisionShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) { return this.collisionShapes.apply(state); } @Override protected boolean isPathfindable(BlockState state, PathComputationType type) { return false; } private boolean connectsTo(BlockState state, boolean faceSolid, Direction direction) { Block block = state.getBlock(); boolean connectedFenceGate = block instanceof FenceGateBlock && FenceGateBlock.connectsToDirection(state, direction); return state.is(BlockTags.WALLS) || !WallBlock.isExceptionForConnection(state) && faceSolid || block instanceof IronBarsBlock || connectedFenceGate; } @Override public BlockState getStateForPlacement(BlockPlaceContext context) { Level level = context.getLevel(); BlockPos pos = context.getClickedPos(); FluidState replacedFluidState = context.getLevel().getFluidState(context.getClickedPos()); BlockPos northPos = pos.north(); BlockPos eastPos = pos.east(); BlockPos southPos = pos.south(); BlockPos westPos = pos.west(); BlockPos topPos = pos.above(); BlockState northState = level.getBlockState(northPos); BlockState eastState = level.getBlockState(eastPos); BlockState southState = level.getBlockState(southPos); BlockState westState = level.getBlockState(westPos); BlockState topState = level.getBlockState(topPos); boolean north = this.connectsTo(northState, northState.isFaceSturdy(level, northPos, Direction.SOUTH), Direction.SOUTH); boolean east = this.connectsTo(eastState, eastState.isFaceSturdy(level, eastPos, Direction.WEST), Direction.WEST); boolean south = this.connectsTo(southState, southState.isFaceSturdy(level, southPos, Direction.NORTH), Direction.NORTH); boolean west = this.connectsTo(westState, westState.isFaceSturdy(level, westPos, Direction.EAST), Direction.EAST); BlockState state = (BlockState)this.defaultBlockState().setValue(WATERLOGGED, replacedFluidState.getType() == Fluids.WATER); return this.updateShape(level, state, topPos, topState, north, east, south, west); } @Override protected BlockState updateShape(BlockState state, LevelReader level, ScheduledTickAccess ticks, BlockPos pos, Direction directionToNeighbour, BlockPos neighbourPos, BlockState neighbourState, RandomSource random) { if (state.getValue(WATERLOGGED).booleanValue()) { ticks.scheduleTick(pos, Fluids.WATER, Fluids.WATER.getTickDelay(level)); } if (directionToNeighbour == Direction.DOWN) { return super.updateShape(state, level, ticks, pos, directionToNeighbour, neighbourPos, neighbourState, random); } if (directionToNeighbour == Direction.UP) { return this.topUpdate(level, state, neighbourPos, neighbourState); } return this.sideUpdate(level, pos, state, neighbourPos, neighbourState, directionToNeighbour); } private static boolean isConnected(BlockState state, Property northWall) { return state.getValue(northWall) != WallSide.NONE; } private static boolean isCovered(VoxelShape aboveShape, VoxelShape testShape) { return !Shapes.joinIsNotEmpty(testShape, aboveShape, BooleanOp.ONLY_FIRST); } private BlockState topUpdate(LevelReader level, BlockState state, BlockPos topPos, BlockState topNeighbour) { boolean north = WallBlock.isConnected(state, NORTH); boolean east = WallBlock.isConnected(state, EAST); boolean south = WallBlock.isConnected(state, SOUTH); boolean west = WallBlock.isConnected(state, WEST); return this.updateShape(level, state, topPos, topNeighbour, north, east, south, west); } private BlockState sideUpdate(LevelReader level, BlockPos pos, BlockState state, BlockPos neighbourPos, BlockState neighbour, Direction direction) { Direction opposite = direction.getOpposite(); boolean isNorthConnected = direction == Direction.NORTH ? this.connectsTo(neighbour, neighbour.isFaceSturdy(level, neighbourPos, opposite), opposite) : WallBlock.isConnected(state, NORTH); boolean isEastConnected = direction == Direction.EAST ? this.connectsTo(neighbour, neighbour.isFaceSturdy(level, neighbourPos, opposite), opposite) : WallBlock.isConnected(state, EAST); boolean isSouthConnected = direction == Direction.SOUTH ? this.connectsTo(neighbour, neighbour.isFaceSturdy(level, neighbourPos, opposite), opposite) : WallBlock.isConnected(state, SOUTH); boolean isWestConnected = direction == Direction.WEST ? this.connectsTo(neighbour, neighbour.isFaceSturdy(level, neighbourPos, opposite), opposite) : WallBlock.isConnected(state, WEST); BlockPos above = pos.above(); BlockState aboveState = level.getBlockState(above); return this.updateShape(level, state, above, aboveState, isNorthConnected, isEastConnected, isSouthConnected, isWestConnected); } private BlockState updateShape(LevelReader level, BlockState state, BlockPos topPos, BlockState topNeighbour, boolean north, boolean east, boolean south, boolean west) { VoxelShape aboveShape = topNeighbour.getCollisionShape(level, topPos).getFaceShape(Direction.DOWN); BlockState sidesUpdatedState = this.updateSides(state, north, east, south, west, aboveShape); return (BlockState)sidesUpdatedState.setValue(UP, this.shouldRaisePost(sidesUpdatedState, topNeighbour, aboveShape)); } private boolean shouldRaisePost(BlockState state, BlockState topNeighbour, VoxelShape aboveShape) { boolean hasHighWall; boolean hasCorner; boolean topNeighbourHasPost; boolean bl = topNeighbourHasPost = topNeighbour.getBlock() instanceof WallBlock && topNeighbour.getValue(UP) != false; if (topNeighbourHasPost) { return true; } WallSide northWall = state.getValue(NORTH); WallSide southWall = state.getValue(SOUTH); WallSide eastWall = state.getValue(EAST); WallSide westWall = state.getValue(WEST); boolean southNone = southWall == WallSide.NONE; boolean westNone = westWall == WallSide.NONE; boolean eastNone = eastWall == WallSide.NONE; boolean northNone = northWall == WallSide.NONE; boolean bl2 = hasCorner = northNone && southNone && westNone && eastNone || northNone != southNone || westNone != eastNone; if (hasCorner) { return true; } boolean bl3 = hasHighWall = northWall == WallSide.TALL && southWall == WallSide.TALL || eastWall == WallSide.TALL && westWall == WallSide.TALL; if (hasHighWall) { return false; } return topNeighbour.is(BlockTags.WALL_POST_OVERRIDE) || WallBlock.isCovered(aboveShape, TEST_SHAPE_POST); } private BlockState updateSides(BlockState state, boolean northConnection, boolean eastConnection, boolean southConnection, boolean westConnection, VoxelShape aboveShape) { return (BlockState)((BlockState)((BlockState)((BlockState)state.setValue(NORTH, this.makeWallState(northConnection, aboveShape, TEST_SHAPES_WALL.get(Direction.NORTH)))).setValue(EAST, this.makeWallState(eastConnection, aboveShape, TEST_SHAPES_WALL.get(Direction.EAST)))).setValue(SOUTH, this.makeWallState(southConnection, aboveShape, TEST_SHAPES_WALL.get(Direction.SOUTH)))).setValue(WEST, this.makeWallState(westConnection, aboveShape, TEST_SHAPES_WALL.get(Direction.WEST))); } private WallSide makeWallState(boolean connectsToSide, VoxelShape aboveShape, VoxelShape testShape) { if (connectsToSide) { if (WallBlock.isCovered(aboveShape, testShape)) { return WallSide.TALL; } return WallSide.LOW; } return WallSide.NONE; } @Override protected FluidState getFluidState(BlockState state) { if (state.getValue(WATERLOGGED).booleanValue()) { return Fluids.WATER.getSource(false); } return super.getFluidState(state); } @Override protected boolean propagatesSkylightDown(BlockState state) { return state.getValue(WATERLOGGED) == false; } @Override protected void createBlockStateDefinition(StateDefinition.Builder builder) { builder.add(UP, NORTH, EAST, WEST, SOUTH, WATERLOGGED); } @Override protected BlockState rotate(BlockState state, Rotation rotation) { switch (rotation) { case CLOCKWISE_180: { return (BlockState)((BlockState)((BlockState)((BlockState)state.setValue(NORTH, state.getValue(SOUTH))).setValue(EAST, state.getValue(WEST))).setValue(SOUTH, state.getValue(NORTH))).setValue(WEST, state.getValue(EAST)); } case COUNTERCLOCKWISE_90: { return (BlockState)((BlockState)((BlockState)((BlockState)state.setValue(NORTH, state.getValue(EAST))).setValue(EAST, state.getValue(SOUTH))).setValue(SOUTH, state.getValue(WEST))).setValue(WEST, state.getValue(NORTH)); } case CLOCKWISE_90: { return (BlockState)((BlockState)((BlockState)((BlockState)state.setValue(NORTH, state.getValue(WEST))).setValue(EAST, state.getValue(NORTH))).setValue(SOUTH, state.getValue(EAST))).setValue(WEST, state.getValue(SOUTH)); } } return state; } @Override protected BlockState mirror(BlockState state, Mirror mirror) { switch (mirror) { case LEFT_RIGHT: { return (BlockState)((BlockState)state.setValue(NORTH, state.getValue(SOUTH))).setValue(SOUTH, state.getValue(NORTH)); } case FRONT_BACK: { return (BlockState)((BlockState)state.setValue(EAST, state.getValue(WEST))).setValue(WEST, state.getValue(EAST)); } } return super.mirror(state, mirror); } }