181 lines
7.5 KiB
Java
181 lines
7.5 KiB
Java
|
package net.minecraft.world.level.block;
|
||
|
|
||
|
import com.mojang.serialization.MapCodec;
|
||
|
import net.minecraft.core.BlockPos;
|
||
|
import net.minecraft.core.Direction;
|
||
|
import net.minecraft.server.level.ServerLevel;
|
||
|
import net.minecraft.util.RandomSource;
|
||
|
import net.minecraft.world.entity.item.FallingBlockEntity;
|
||
|
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.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.IntegerProperty;
|
||
|
import net.minecraft.world.level.material.FluidState;
|
||
|
import net.minecraft.world.level.material.Fluids;
|
||
|
import net.minecraft.world.phys.shapes.CollisionContext;
|
||
|
import net.minecraft.world.phys.shapes.Shapes;
|
||
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
||
|
|
||
|
public class ScaffoldingBlock extends Block implements SimpleWaterloggedBlock {
|
||
|
public static final MapCodec<ScaffoldingBlock> CODEC = simpleCodec(ScaffoldingBlock::new);
|
||
|
private static final int TICK_DELAY = 1;
|
||
|
private static final VoxelShape SHAPE_STABLE = Shapes.or(
|
||
|
Block.column(16.0, 14.0, 16.0),
|
||
|
Shapes.rotateHorizontal(Block.box(0.0, 0.0, 0.0, 2.0, 16.0, 2.0)).values().stream().reduce(Shapes.empty(), Shapes::or)
|
||
|
);
|
||
|
private static final VoxelShape SHAPE_UNSTABLE_BOTTOM = Block.column(16.0, 0.0, 2.0);
|
||
|
private static final VoxelShape SHAPE_UNSTABLE = Shapes.or(
|
||
|
SHAPE_STABLE, SHAPE_UNSTABLE_BOTTOM, Shapes.rotateHorizontal(Block.boxZ(16.0, 0.0, 2.0, 0.0, 2.0)).values().stream().reduce(Shapes.empty(), Shapes::or)
|
||
|
);
|
||
|
private static final VoxelShape SHAPE_BELOW_BLOCK = Shapes.block().move(0.0, -1.0, 0.0).optimize();
|
||
|
public static final int STABILITY_MAX_DISTANCE = 7;
|
||
|
public static final IntegerProperty DISTANCE = BlockStateProperties.STABILITY_DISTANCE;
|
||
|
public static final BooleanProperty WATERLOGGED = BlockStateProperties.WATERLOGGED;
|
||
|
public static final BooleanProperty BOTTOM = BlockStateProperties.BOTTOM;
|
||
|
|
||
|
@Override
|
||
|
public MapCodec<ScaffoldingBlock> codec() {
|
||
|
return CODEC;
|
||
|
}
|
||
|
|
||
|
protected ScaffoldingBlock(BlockBehaviour.Properties p_56021_) {
|
||
|
super(p_56021_);
|
||
|
this.registerDefaultState(this.stateDefinition.any().setValue(DISTANCE, 7).setValue(WATERLOGGED, false).setValue(BOTTOM, false));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_56051_) {
|
||
|
p_56051_.add(DISTANCE, WATERLOGGED, BOTTOM);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected VoxelShape getShape(BlockState p_56057_, BlockGetter p_56058_, BlockPos p_56059_, CollisionContext p_56060_) {
|
||
|
if (!p_56060_.isHoldingItem(p_56057_.getBlock().asItem())) {
|
||
|
return p_56057_.getValue(BOTTOM) ? SHAPE_UNSTABLE : SHAPE_STABLE;
|
||
|
} else {
|
||
|
return Shapes.block();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected VoxelShape getInteractionShape(BlockState p_56053_, BlockGetter p_56054_, BlockPos p_56055_) {
|
||
|
return Shapes.block();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected boolean canBeReplaced(BlockState p_56037_, BlockPlaceContext p_56038_) {
|
||
|
return p_56038_.getItemInHand().is(this.asItem());
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public BlockState getStateForPlacement(BlockPlaceContext p_56023_) {
|
||
|
BlockPos blockpos = p_56023_.getClickedPos();
|
||
|
Level level = p_56023_.getLevel();
|
||
|
int i = getDistance(level, blockpos);
|
||
|
return this.defaultBlockState()
|
||
|
.setValue(WATERLOGGED, level.getFluidState(blockpos).getType() == Fluids.WATER)
|
||
|
.setValue(DISTANCE, i)
|
||
|
.setValue(BOTTOM, this.isBottom(level, blockpos, i));
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void onPlace(BlockState p_56062_, Level p_56063_, BlockPos p_56064_, BlockState p_56065_, boolean p_56066_) {
|
||
|
if (!p_56063_.isClientSide) {
|
||
|
p_56063_.scheduleTick(p_56064_, this, 1);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected BlockState updateShape(
|
||
|
BlockState p_56044_,
|
||
|
LevelReader p_365588_,
|
||
|
ScheduledTickAccess p_361394_,
|
||
|
BlockPos p_56048_,
|
||
|
Direction p_56045_,
|
||
|
BlockPos p_56049_,
|
||
|
BlockState p_56046_,
|
||
|
RandomSource p_369734_
|
||
|
) {
|
||
|
if (p_56044_.getValue(WATERLOGGED)) {
|
||
|
p_361394_.scheduleTick(p_56048_, Fluids.WATER, Fluids.WATER.getTickDelay(p_365588_));
|
||
|
}
|
||
|
|
||
|
if (!p_365588_.isClientSide()) {
|
||
|
p_361394_.scheduleTick(p_56048_, this, 1);
|
||
|
}
|
||
|
|
||
|
return p_56044_;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected void tick(BlockState p_222019_, ServerLevel p_222020_, BlockPos p_222021_, RandomSource p_222022_) {
|
||
|
int i = getDistance(p_222020_, p_222021_);
|
||
|
BlockState blockstate = p_222019_.setValue(DISTANCE, i).setValue(BOTTOM, this.isBottom(p_222020_, p_222021_, i));
|
||
|
if (blockstate.getValue(DISTANCE) == 7) {
|
||
|
if (p_222019_.getValue(DISTANCE) == 7) {
|
||
|
FallingBlockEntity.fall(p_222020_, p_222021_, blockstate);
|
||
|
} else {
|
||
|
p_222020_.destroyBlock(p_222021_, true);
|
||
|
}
|
||
|
} else if (p_222019_ != blockstate) {
|
||
|
p_222020_.setBlock(p_222021_, blockstate, 3);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected boolean canSurvive(BlockState p_56040_, LevelReader p_56041_, BlockPos p_56042_) {
|
||
|
return getDistance(p_56041_, p_56042_) < 7;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected VoxelShape getCollisionShape(BlockState p_56068_, BlockGetter p_56069_, BlockPos p_56070_, CollisionContext p_56071_) {
|
||
|
if (p_56071_.isPlacement()) {
|
||
|
return Shapes.empty();
|
||
|
} else if (p_56071_.isAbove(Shapes.block(), p_56070_, true) && !p_56071_.isDescending()) {
|
||
|
return SHAPE_STABLE;
|
||
|
} else {
|
||
|
return p_56068_.getValue(DISTANCE) != 0 && p_56068_.getValue(BOTTOM) && p_56071_.isAbove(SHAPE_BELOW_BLOCK, p_56070_, true)
|
||
|
? SHAPE_UNSTABLE_BOTTOM
|
||
|
: Shapes.empty();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
protected FluidState getFluidState(BlockState p_56073_) {
|
||
|
return p_56073_.getValue(WATERLOGGED) ? Fluids.WATER.getSource(false) : super.getFluidState(p_56073_);
|
||
|
}
|
||
|
|
||
|
private boolean isBottom(BlockGetter p_56028_, BlockPos p_56029_, int p_56030_) {
|
||
|
return p_56030_ > 0 && !p_56028_.getBlockState(p_56029_.below()).is(this);
|
||
|
}
|
||
|
|
||
|
public static int getDistance(BlockGetter p_56025_, BlockPos p_56026_) {
|
||
|
BlockPos.MutableBlockPos blockpos$mutableblockpos = p_56026_.mutable().move(Direction.DOWN);
|
||
|
BlockState blockstate = p_56025_.getBlockState(blockpos$mutableblockpos);
|
||
|
int i = 7;
|
||
|
if (blockstate.is(Blocks.SCAFFOLDING)) {
|
||
|
i = blockstate.getValue(DISTANCE);
|
||
|
} else if (blockstate.isFaceSturdy(p_56025_, blockpos$mutableblockpos, Direction.UP)) {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
for (Direction direction : Direction.Plane.HORIZONTAL) {
|
||
|
BlockState blockstate1 = p_56025_.getBlockState(blockpos$mutableblockpos.setWithOffset(p_56026_, direction));
|
||
|
if (blockstate1.is(Blocks.SCAFFOLDING)) {
|
||
|
i = Math.min(i, blockstate1.getValue(DISTANCE) + 1);
|
||
|
if (i == 1) {
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return i;
|
||
|
}
|
||
|
}
|