package net.minecraft.world.level.block; import net.minecraft.world.level.block.state.AbstractStateHolder; import java.util.stream.Collector; import net.minecraft.Util; import net.minecraft.world.level.block.state.StateDefinition; import javax.annotation.Nullable; import net.minecraft.world.item.BlockPlaceContext; import net.minecraft.world.level.Level; import java.util.Random; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.LevelAccessor; import java.util.Iterator; import net.minecraft.world.level.LevelReader; import net.minecraft.world.phys.shapes.Shapes; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.core.BlockPos; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.block.state.properties.Property; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.shapes.VoxelShape; import net.minecraft.core.Direction; import java.util.Map; import net.minecraft.world.level.block.state.properties.BooleanProperty; public class VineBlock extends Block { public static final BooleanProperty UP; public static final BooleanProperty NORTH; public static final BooleanProperty EAST; public static final BooleanProperty SOUTH; public static final BooleanProperty WEST; public static final Map PROPERTY_BY_DIRECTION; protected static final VoxelShape UP_AABB; protected static final VoxelShape EAST_AABB; protected static final VoxelShape WEST_AABB; protected static final VoxelShape SOUTH_AABB; protected static final VoxelShape NORTH_AABB; public VineBlock(final Properties c) { super(c); this.registerDefaultState(((((((AbstractStateHolder)this.stateDefinition.any()).setValue((Property)VineBlock.UP, false)).setValue((Property)VineBlock.NORTH, false)).setValue((Property)VineBlock.EAST, false)).setValue((Property)VineBlock.SOUTH, false)).setValue((Property)VineBlock.WEST, false)); } @Override public VoxelShape getShape(final BlockState byg, final BlockGetter bjd, final BlockPos fk, final CollisionContext cvn) { VoxelShape cwc6 = Shapes.empty(); if (byg.getValue((Property)VineBlock.UP)) { cwc6 = Shapes.or(cwc6, VineBlock.UP_AABB); } if (byg.getValue((Property)VineBlock.NORTH)) { cwc6 = Shapes.or(cwc6, VineBlock.SOUTH_AABB); } if (byg.getValue((Property)VineBlock.EAST)) { cwc6 = Shapes.or(cwc6, VineBlock.WEST_AABB); } if (byg.getValue((Property)VineBlock.SOUTH)) { cwc6 = Shapes.or(cwc6, VineBlock.NORTH_AABB); } if (byg.getValue((Property)VineBlock.WEST)) { cwc6 = Shapes.or(cwc6, VineBlock.EAST_AABB); } return cwc6; } @Override public boolean canSurvive(final BlockState byg, final LevelReader bjw, final BlockPos fk) { return this.hasFaces(this.getUpdatedState(byg, bjw, fk)); } private boolean hasFaces(final BlockState byg) { return this.countFaces(byg) > 0; } private int countFaces(final BlockState byg) { int integer3 = 0; for (final BooleanProperty byy5 : VineBlock.PROPERTY_BY_DIRECTION.values()) { if (byg.getValue((Property)byy5)) { ++integer3; } } return integer3; } private boolean canSupportAtFace(final BlockGetter bjd, final BlockPos fk, final Direction fp) { if (fp == Direction.DOWN) { return false; } final BlockPos fk2 = fk.relative(fp); if (isAcceptableNeighbour(bjd, fk2, fp)) { return true; } if (fp.getAxis() != Direction.Axis.Y) { final BooleanProperty byy6 = VineBlock.PROPERTY_BY_DIRECTION.get(fp); final BlockState byg7 = bjd.getBlockState(fk.above()); return byg7.getBlock() == this && byg7.getValue((Property)byy6); } return false; } public static boolean isAcceptableNeighbour(final BlockGetter bjd, final BlockPos fk, final Direction fp) { final BlockState byg4 = bjd.getBlockState(fk); return Block.isFaceFull(byg4.getCollisionShape(bjd, fk), fp.getOpposite()); } private BlockState getUpdatedState(BlockState byg, final BlockGetter bjd, final BlockPos fk) { final BlockPos fk2 = fk.above(); if (byg.getValue((Property)VineBlock.UP)) { byg = ((AbstractStateHolder)byg).setValue((Property)VineBlock.UP, isAcceptableNeighbour(bjd, fk2, Direction.DOWN)); } BlockState byg2 = null; for (final Direction fp8 : Direction.Plane.HORIZONTAL) { final BooleanProperty byy9 = getPropertyForFace(fp8); if (byg.getValue((Property)byy9)) { boolean boolean10 = this.canSupportAtFace(bjd, fk, fp8); if (!boolean10) { if (byg2 == null) { byg2 = bjd.getBlockState(fk2); } boolean10 = (byg2.getBlock() == this && byg2.getValue((Property)byy9)); } byg = ((AbstractStateHolder)byg).setValue((Property)byy9, boolean10); } } return byg; } @Override public BlockState updateShape(final BlockState byg1, final Direction fp, final BlockState byg3, final LevelAccessor bju, final BlockPos fk5, final BlockPos fk6) { if (fp == Direction.DOWN) { return super.updateShape(byg1, fp, byg3, bju, fk5, fk6); } final BlockState byg4 = this.getUpdatedState(byg1, bju, fk5); if (!this.hasFaces(byg4)) { return Blocks.AIR.defaultBlockState(); } return byg4; } @Override public void tick(final BlockState byg, final ServerLevel xd, final BlockPos fk, final Random random) { final BlockState byg2 = this.getUpdatedState(byg, xd, fk); if (byg2 != byg) { if (this.hasFaces(byg2)) { xd.setBlock(fk, byg2, 2); } else { Block.dropResources(byg, xd, fk); xd.removeBlock(fk, false); } return; } if (xd.random.nextInt(4) != 0) { return; } final Direction fp7 = Direction.getRandomFace(random); final BlockPos fk2 = fk.above(); if (!fp7.getAxis().isHorizontal() || byg.getValue((Property)getPropertyForFace(fp7))) { if (fp7 == Direction.UP && fk.getY() < 255) { if (this.canSupportAtFace(xd, fk, fp7)) { xd.setBlock(fk, ((AbstractStateHolder)byg).setValue((Property)VineBlock.UP, true), 2); return; } if (xd.isEmptyBlock(fk2)) { if (!this.canSpread(xd, fk)) { return; } BlockState byg3 = byg; for (final Direction fp8 : Direction.Plane.HORIZONTAL) { if (random.nextBoolean() || !isAcceptableNeighbour(xd, fk2.relative(fp8), Direction.UP)) { byg3 = ((AbstractStateHolder)byg3).setValue((Property)getPropertyForFace(fp8), false); } } if (this.hasHorizontalConnection(byg3)) { xd.setBlock(fk2, byg3, 2); } return; } } if (fk.getY() > 0) { final BlockPos fk3 = fk.below(); final BlockState byg4 = xd.getBlockState(fk3); if (byg4.isAir() || byg4.getBlock() == this) { final BlockState byg5 = byg4.isAir() ? this.defaultBlockState() : byg4; final BlockState byg6 = this.copyRandomFaces(byg, byg5, random); if (byg5 != byg6 && this.hasHorizontalConnection(byg6)) { xd.setBlock(fk3, byg6, 2); } } } return; } if (!this.canSpread(xd, fk)) { return; } final BlockPos fk3 = fk.relative(fp7); final BlockState byg4 = xd.getBlockState(fk3); if (byg4.isAir()) { final Direction fp8 = fp7.getClockWise(); final Direction fp9 = fp7.getCounterClockWise(); final boolean boolean13 = byg.getValue((Property)getPropertyForFace(fp8)); final boolean boolean14 = byg.getValue((Property)getPropertyForFace(fp9)); final BlockPos fk4 = fk3.relative(fp8); final BlockPos fk5 = fk3.relative(fp9); if (boolean13 && isAcceptableNeighbour(xd, fk4, fp8)) { xd.setBlock(fk3, ((AbstractStateHolder)this.defaultBlockState()).setValue((Property)getPropertyForFace(fp8), true), 2); } else if (boolean14 && isAcceptableNeighbour(xd, fk5, fp9)) { xd.setBlock(fk3, ((AbstractStateHolder)this.defaultBlockState()).setValue((Property)getPropertyForFace(fp9), true), 2); } else { final Direction fp10 = fp7.getOpposite(); if (boolean13 && xd.isEmptyBlock(fk4) && isAcceptableNeighbour(xd, fk.relative(fp8), fp10)) { xd.setBlock(fk4, ((AbstractStateHolder)this.defaultBlockState()).setValue((Property)getPropertyForFace(fp10), true), 2); } else if (boolean14 && xd.isEmptyBlock(fk5) && isAcceptableNeighbour(xd, fk.relative(fp9), fp10)) { xd.setBlock(fk5, ((AbstractStateHolder)this.defaultBlockState()).setValue((Property)getPropertyForFace(fp10), true), 2); } else if (xd.random.nextFloat() < 0.05 && isAcceptableNeighbour(xd, fk3.above(), Direction.UP)) { xd.setBlock(fk3, ((AbstractStateHolder)this.defaultBlockState()).setValue((Property)VineBlock.UP, true), 2); } } } else if (isAcceptableNeighbour(xd, fk3, fp7)) { xd.setBlock(fk, ((AbstractStateHolder)byg).setValue((Property)getPropertyForFace(fp7), true), 2); } } private BlockState copyRandomFaces(final BlockState byg1, BlockState byg2, final Random random) { for (final Direction fp6 : Direction.Plane.HORIZONTAL) { if (random.nextBoolean()) { final BooleanProperty byy7 = getPropertyForFace(fp6); if (!byg1.getValue((Property)byy7)) { continue; } byg2 = ((AbstractStateHolder)byg2).setValue((Property)byy7, true); } } return byg2; } private boolean hasHorizontalConnection(final BlockState byg) { return byg.getValue((Property)VineBlock.NORTH) || byg.getValue((Property)VineBlock.EAST) || byg.getValue((Property)VineBlock.SOUTH) || byg.getValue((Property)VineBlock.WEST); } private boolean canSpread(final BlockGetter bjd, final BlockPos fk) { final int integer4 = 4; final Iterable iterable5 = BlockPos.betweenClosed(fk.getX() - 4, fk.getY() - 1, fk.getZ() - 4, fk.getX() + 4, fk.getY() + 1, fk.getZ() + 4); int integer5 = 5; for (final BlockPos fk2 : iterable5) { if (bjd.getBlockState(fk2).getBlock() == this && --integer5 <= 0) { return false; } } return true; } @Override public boolean canBeReplaced(final BlockState byg, final BlockPlaceContext bcn) { final BlockState byg2 = bcn.getLevel().getBlockState(bcn.getClickedPos()); if (byg2.getBlock() == this) { return this.countFaces(byg2) < VineBlock.PROPERTY_BY_DIRECTION.size(); } return super.canBeReplaced(byg, bcn); } @Nullable @Override public BlockState getStateForPlacement(final BlockPlaceContext bcn) { final BlockState byg3 = bcn.getLevel().getBlockState(bcn.getClickedPos()); final boolean boolean4 = byg3.getBlock() == this; final BlockState byg4 = boolean4 ? byg3 : this.defaultBlockState(); for (final Direction fp9 : bcn.getNearestLookingDirections()) { if (fp9 != Direction.DOWN) { final BooleanProperty byy10 = getPropertyForFace(fp9); final boolean boolean5 = boolean4 && byg3.getValue((Property)byy10); if (!boolean5 && this.canSupportAtFace(bcn.getLevel(), bcn.getClickedPos(), fp9)) { return ((AbstractStateHolder)byg4).setValue((Property)byy10, true); } } } return boolean4 ? byg4 : null; } @Override protected void createBlockStateDefinition(final StateDefinition.Builder a) { a.add(VineBlock.UP, VineBlock.NORTH, VineBlock.EAST, VineBlock.SOUTH, VineBlock.WEST); } @Override public BlockState rotate(final BlockState byg, final Rotation btr) { switch (btr) { case CLOCKWISE_180: { return (((((AbstractStateHolder)byg).setValue((Property)VineBlock.NORTH, (Comparable)byg.getValue((Property)VineBlock.SOUTH))).setValue((Property)VineBlock.EAST, (Comparable)byg.getValue((Property)VineBlock.WEST))).setValue((Property)VineBlock.SOUTH, (Comparable)byg.getValue((Property)VineBlock.NORTH))).setValue((Property)VineBlock.WEST, (Comparable)byg.getValue((Property)VineBlock.EAST)); } case COUNTERCLOCKWISE_90: { return (((((AbstractStateHolder)byg).setValue((Property)VineBlock.NORTH, (Comparable)byg.getValue((Property)VineBlock.EAST))).setValue((Property)VineBlock.EAST, (Comparable)byg.getValue((Property)VineBlock.SOUTH))).setValue((Property)VineBlock.SOUTH, (Comparable)byg.getValue((Property)VineBlock.WEST))).setValue((Property)VineBlock.WEST, (Comparable)byg.getValue((Property)VineBlock.NORTH)); } case CLOCKWISE_90: { return (((((AbstractStateHolder)byg).setValue((Property)VineBlock.NORTH, (Comparable)byg.getValue((Property)VineBlock.WEST))).setValue((Property)VineBlock.EAST, (Comparable)byg.getValue((Property)VineBlock.NORTH))).setValue((Property)VineBlock.SOUTH, (Comparable)byg.getValue((Property)VineBlock.EAST))).setValue((Property)VineBlock.WEST, (Comparable)byg.getValue((Property)VineBlock.SOUTH)); } default: { return byg; } } } @Override public BlockState mirror(final BlockState byg, final Mirror bsr) { switch (bsr) { case LEFT_RIGHT: { return (((AbstractStateHolder)byg).setValue((Property)VineBlock.NORTH, (Comparable)byg.getValue((Property)VineBlock.SOUTH))).setValue((Property)VineBlock.SOUTH, (Comparable)byg.getValue((Property)VineBlock.NORTH)); } case FRONT_BACK: { return (((AbstractStateHolder)byg).setValue((Property)VineBlock.EAST, (Comparable)byg.getValue((Property)VineBlock.WEST))).setValue((Property)VineBlock.WEST, (Comparable)byg.getValue((Property)VineBlock.EAST)); } default: { return super.mirror(byg, bsr); } } } public static BooleanProperty getPropertyForFace(final Direction fp) { return VineBlock.PROPERTY_BY_DIRECTION.get(fp); } static { UP = PipeBlock.UP; NORTH = PipeBlock.NORTH; EAST = PipeBlock.EAST; SOUTH = PipeBlock.SOUTH; WEST = PipeBlock.WEST; PROPERTY_BY_DIRECTION = PipeBlock.PROPERTY_BY_DIRECTION.entrySet().stream().filter(entry -> entry.getKey() != Direction.DOWN).collect(Util.toMap()); UP_AABB = Block.box(0.0, 15.0, 0.0, 16.0, 16.0, 16.0); EAST_AABB = Block.box(0.0, 0.0, 0.0, 1.0, 16.0, 16.0); WEST_AABB = Block.box(15.0, 0.0, 0.0, 16.0, 16.0, 16.0); SOUTH_AABB = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 1.0); NORTH_AABB = Block.box(0.0, 0.0, 15.0, 16.0, 16.0, 16.0); } }