2025-11-24 22:52:51 +03:00

273 lines
15 KiB
Java

/*
* 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<WallBlock> CODEC = WallBlock.simpleCodec(WallBlock::new);
public static final BooleanProperty UP = BlockStateProperties.UP;
public static final EnumProperty<WallSide> EAST = BlockStateProperties.EAST_WALL;
public static final EnumProperty<WallSide> NORTH = BlockStateProperties.NORTH_WALL;
public static final EnumProperty<WallSide> SOUTH = BlockStateProperties.SOUTH_WALL;
public static final EnumProperty<WallSide> WEST = BlockStateProperties.WEST_WALL;
public static final Map<Direction, EnumProperty<WallSide>> 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<BlockState, VoxelShape> shapes;
private final Function<BlockState, VoxelShape> collisionShapes;
private static final VoxelShape TEST_SHAPE_POST = Block.column(2.0, 0.0, 16.0);
private static final Map<Direction, VoxelShape> TEST_SHAPES_WALL = Shapes.rotateHorizontal(Block.boxZ(2.0, 16.0, 0.0, 9.0));
public MapCodec<WallBlock> 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<BlockState, VoxelShape> makeShapes(float postHeight, float wallTop) {
VoxelShape post = Block.column(8.0, 0.0, postHeight);
int width = 6;
Map<Direction, VoxelShape> low = Shapes.rotateHorizontal(Block.boxZ(6.0, 0.0, wallTop, 0.0, 11.0));
Map<Direction, VoxelShape> 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<Direction, EnumProperty<WallSide>> 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<WallSide> 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<Block, BlockState> 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);
}
}