minecraft-source/src/net/minecraft/world/level/block/VineBlock.java

340 lines
17 KiB
Java

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<Direction, BooleanProperty> 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<O, BlockState>)this.stateDefinition.any()).setValue((Property<Comparable>)VineBlock.UP, false)).setValue((Property<Comparable>)VineBlock.NORTH, false)).setValue((Property<Comparable>)VineBlock.EAST, false)).setValue((Property<Comparable>)VineBlock.SOUTH, false)).<Comparable, Boolean>setValue((Property<Comparable>)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.<Boolean>getValue((Property<Boolean>)VineBlock.UP)) {
cwc6 = Shapes.or(cwc6, VineBlock.UP_AABB);
}
if (byg.<Boolean>getValue((Property<Boolean>)VineBlock.NORTH)) {
cwc6 = Shapes.or(cwc6, VineBlock.SOUTH_AABB);
}
if (byg.<Boolean>getValue((Property<Boolean>)VineBlock.EAST)) {
cwc6 = Shapes.or(cwc6, VineBlock.WEST_AABB);
}
if (byg.<Boolean>getValue((Property<Boolean>)VineBlock.SOUTH)) {
cwc6 = Shapes.or(cwc6, VineBlock.NORTH_AABB);
}
if (byg.<Boolean>getValue((Property<Boolean>)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.<Boolean>getValue((Property<Boolean>)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.<Boolean>getValue((Property<Boolean>)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.<Boolean>getValue((Property<Boolean>)VineBlock.UP)) {
byg = ((AbstractStateHolder<O, BlockState>)byg).<Comparable, Boolean>setValue((Property<Comparable>)VineBlock.UP, isAcceptableNeighbour(bjd, fk2, Direction.DOWN));
}
BlockState byg2 = null;
for (final Direction fp8 : Direction.Plane.HORIZONTAL) {
final BooleanProperty byy9 = getPropertyForFace(fp8);
if (byg.<Boolean>getValue((Property<Boolean>)byy9)) {
boolean boolean10 = this.canSupportAtFace(bjd, fk, fp8);
if (!boolean10) {
if (byg2 == null) {
byg2 = bjd.getBlockState(fk2);
}
boolean10 = (byg2.getBlock() == this && byg2.<Boolean>getValue((Property<Boolean>)byy9));
}
byg = ((AbstractStateHolder<O, BlockState>)byg).<Comparable, Boolean>setValue((Property<Comparable>)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.<Boolean>getValue((Property<Boolean>)getPropertyForFace(fp7))) {
if (fp7 == Direction.UP && fk.getY() < 255) {
if (this.canSupportAtFace(xd, fk, fp7)) {
xd.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byg).<Comparable, Boolean>setValue((Property<Comparable>)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<O, BlockState>)byg3).<Comparable, Boolean>setValue((Property<Comparable>)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.<Boolean>getValue((Property<Boolean>)getPropertyForFace(fp8));
final boolean boolean14 = byg.<Boolean>getValue((Property<Boolean>)getPropertyForFace(fp9));
final BlockPos fk4 = fk3.relative(fp8);
final BlockPos fk5 = fk3.relative(fp9);
if (boolean13 && isAcceptableNeighbour(xd, fk4, fp8)) {
xd.setBlock(fk3, ((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Boolean>setValue((Property<Comparable>)getPropertyForFace(fp8), true), 2);
}
else if (boolean14 && isAcceptableNeighbour(xd, fk5, fp9)) {
xd.setBlock(fk3, ((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Boolean>setValue((Property<Comparable>)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<O, BlockState>)this.defaultBlockState()).<Comparable, Boolean>setValue((Property<Comparable>)getPropertyForFace(fp10), true), 2);
}
else if (boolean14 && xd.isEmptyBlock(fk5) && isAcceptableNeighbour(xd, fk.relative(fp9), fp10)) {
xd.setBlock(fk5, ((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Boolean>setValue((Property<Comparable>)getPropertyForFace(fp10), true), 2);
}
else if (xd.random.nextFloat() < 0.05 && isAcceptableNeighbour(xd, fk3.above(), Direction.UP)) {
xd.setBlock(fk3, ((AbstractStateHolder<O, BlockState>)this.defaultBlockState()).<Comparable, Boolean>setValue((Property<Comparable>)VineBlock.UP, true), 2);
}
}
}
else if (isAcceptableNeighbour(xd, fk3, fp7)) {
xd.setBlock(fk, ((AbstractStateHolder<O, BlockState>)byg).<Comparable, Boolean>setValue((Property<Comparable>)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.<Boolean>getValue((Property<Boolean>)byy7)) {
continue;
}
byg2 = ((AbstractStateHolder<O, BlockState>)byg2).<Comparable, Boolean>setValue((Property<Comparable>)byy7, true);
}
}
return byg2;
}
private boolean hasHorizontalConnection(final BlockState byg) {
return byg.<Boolean>getValue((Property<Boolean>)VineBlock.NORTH) || byg.<Boolean>getValue((Property<Boolean>)VineBlock.EAST) || byg.<Boolean>getValue((Property<Boolean>)VineBlock.SOUTH) || byg.<Boolean>getValue((Property<Boolean>)VineBlock.WEST);
}
private boolean canSpread(final BlockGetter bjd, final BlockPos fk) {
final int integer4 = 4;
final Iterable<BlockPos> 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.<Boolean>getValue((Property<Boolean>)byy10);
if (!boolean5 && this.canSupportAtFace(bcn.getLevel(), bcn.getClickedPos(), fp9)) {
return ((AbstractStateHolder<O, BlockState>)byg4).<Comparable, Boolean>setValue((Property<Comparable>)byy10, true);
}
}
}
return boolean4 ? byg4 : null;
}
@Override
protected void createBlockStateDefinition(final StateDefinition.Builder<Block, BlockState> 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<O, BlockState>)byg).setValue((Property<Comparable>)VineBlock.NORTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.SOUTH))).setValue((Property<Comparable>)VineBlock.EAST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.WEST))).setValue((Property<Comparable>)VineBlock.SOUTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.NORTH))).<Comparable, Comparable>setValue((Property<Comparable>)VineBlock.WEST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.EAST));
}
case COUNTERCLOCKWISE_90: {
return (((((AbstractStateHolder<O, BlockState>)byg).setValue((Property<Comparable>)VineBlock.NORTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.EAST))).setValue((Property<Comparable>)VineBlock.EAST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.SOUTH))).setValue((Property<Comparable>)VineBlock.SOUTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.WEST))).<Comparable, Comparable>setValue((Property<Comparable>)VineBlock.WEST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.NORTH));
}
case CLOCKWISE_90: {
return (((((AbstractStateHolder<O, BlockState>)byg).setValue((Property<Comparable>)VineBlock.NORTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.WEST))).setValue((Property<Comparable>)VineBlock.EAST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.NORTH))).setValue((Property<Comparable>)VineBlock.SOUTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.EAST))).<Comparable, Comparable>setValue((Property<Comparable>)VineBlock.WEST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.SOUTH));
}
default: {
return byg;
}
}
}
@Override
public BlockState mirror(final BlockState byg, final Mirror bsr) {
switch (bsr) {
case LEFT_RIGHT: {
return (((AbstractStateHolder<O, BlockState>)byg).setValue((Property<Comparable>)VineBlock.NORTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.SOUTH))).<Comparable, Comparable>setValue((Property<Comparable>)VineBlock.SOUTH, (Comparable)byg.<V>getValue((Property<V>)VineBlock.NORTH));
}
case FRONT_BACK: {
return (((AbstractStateHolder<O, BlockState>)byg).setValue((Property<Comparable>)VineBlock.EAST, (Comparable)byg.<V>getValue((Property<V>)VineBlock.WEST))).<Comparable, Comparable>setValue((Property<Comparable>)VineBlock.WEST, (Comparable)byg.<V>getValue((Property<V>)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.<Direction, BooleanProperty>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);
}
}