Code/net/minecraft/world/level/block/BambooStalkBlock.java

230 lines
9.7 KiB
Java
Raw Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.world.level.block;
import com.mojang.serialization.MapCodec;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.server.level.ServerLevel;
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.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.BambooLeaves;
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraft.world.level.block.state.properties.IntegerProperty;
import net.minecraft.world.level.material.FluidState;
import net.minecraft.world.level.pathfinder.PathComputationType;
import net.minecraft.world.phys.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class BambooStalkBlock extends Block implements BonemealableBlock {
public static final MapCodec<BambooStalkBlock> CODEC = simpleCodec(BambooStalkBlock::new);
private static final VoxelShape SHAPE_SMALL = Block.column(6.0, 0.0, 16.0);
private static final VoxelShape SHAPE_LARGE = Block.column(10.0, 0.0, 16.0);
private static final VoxelShape SHAPE_COLLISION = Block.column(3.0, 0.0, 16.0);
public static final IntegerProperty AGE = BlockStateProperties.AGE_1;
public static final EnumProperty<BambooLeaves> LEAVES = BlockStateProperties.BAMBOO_LEAVES;
public static final IntegerProperty STAGE = BlockStateProperties.STAGE;
public static final int MAX_HEIGHT = 16;
public static final int STAGE_GROWING = 0;
public static final int STAGE_DONE_GROWING = 1;
public static final int AGE_THIN_BAMBOO = 0;
public static final int AGE_THICK_BAMBOO = 1;
@Override
public MapCodec<BambooStalkBlock> codec() {
return CODEC;
}
public BambooStalkBlock(BlockBehaviour.Properties p_261753_) {
super(p_261753_);
this.registerDefaultState(this.stateDefinition.any().setValue(AGE, 0).setValue(LEAVES, BambooLeaves.NONE).setValue(STAGE, 0));
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_261641_) {
p_261641_.add(AGE, LEAVES, STAGE);
}
@Override
protected boolean propagatesSkylightDown(BlockState p_261479_) {
return true;
}
@Override
protected VoxelShape getShape(BlockState p_261515_, BlockGetter p_261586_, BlockPos p_261526_, CollisionContext p_261930_) {
VoxelShape voxelshape = p_261515_.getValue(LEAVES) == BambooLeaves.LARGE ? SHAPE_LARGE : SHAPE_SMALL;
return voxelshape.move(p_261515_.getOffset(p_261526_));
}
@Override
protected boolean isPathfindable(BlockState p_262166_, PathComputationType p_261513_) {
return false;
}
@Override
protected VoxelShape getCollisionShape(BlockState p_261560_, BlockGetter p_261965_, BlockPos p_261950_, CollisionContext p_261571_) {
return SHAPE_COLLISION.move(p_261560_.getOffset(p_261950_));
}
@Override
protected boolean isCollisionShapeFullBlock(BlockState p_262062_, BlockGetter p_261848_, BlockPos p_261466_) {
return false;
}
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext p_261764_) {
FluidState fluidstate = p_261764_.getLevel().getFluidState(p_261764_.getClickedPos());
if (!fluidstate.isEmpty()) {
return null;
} else {
BlockState blockstate = p_261764_.getLevel().getBlockState(p_261764_.getClickedPos().below());
if (blockstate.is(BlockTags.BAMBOO_PLANTABLE_ON)) {
if (blockstate.is(Blocks.BAMBOO_SAPLING)) {
return this.defaultBlockState().setValue(AGE, 0);
} else if (blockstate.is(Blocks.BAMBOO)) {
int i = blockstate.getValue(AGE) > 0 ? 1 : 0;
return this.defaultBlockState().setValue(AGE, i);
} else {
BlockState blockstate1 = p_261764_.getLevel().getBlockState(p_261764_.getClickedPos().above());
return blockstate1.is(Blocks.BAMBOO)
? this.defaultBlockState().setValue(AGE, blockstate1.getValue(AGE))
: Blocks.BAMBOO_SAPLING.defaultBlockState();
}
} else {
return null;
}
}
}
@Override
protected void tick(BlockState p_261612_, ServerLevel p_261527_, BlockPos p_261846_, RandomSource p_261638_) {
if (!p_261612_.canSurvive(p_261527_, p_261846_)) {
p_261527_.destroyBlock(p_261846_, true);
}
}
@Override
protected boolean isRandomlyTicking(BlockState p_262083_) {
return p_262083_.getValue(STAGE) == 0;
}
@Override
protected void randomTick(BlockState p_261931_, ServerLevel p_261751_, BlockPos p_261616_, RandomSource p_261766_) {
if (p_261931_.getValue(STAGE) == 0) {
if (p_261766_.nextInt(3) == 0 && p_261751_.isEmptyBlock(p_261616_.above()) && p_261751_.getRawBrightness(p_261616_.above(), 0) >= 9) {
int i = this.getHeightBelowUpToMax(p_261751_, p_261616_) + 1;
if (i < 16) {
this.growBamboo(p_261931_, p_261751_, p_261616_, p_261766_, i);
}
}
}
}
@Override
protected boolean canSurvive(BlockState p_261860_, LevelReader p_262154_, BlockPos p_261493_) {
return p_262154_.getBlockState(p_261493_.below()).is(BlockTags.BAMBOO_PLANTABLE_ON);
}
@Override
protected BlockState updateShape(
BlockState p_261476_,
LevelReader p_362157_,
ScheduledTickAccess p_366749_,
BlockPos p_261876_,
Direction p_261512_,
BlockPos p_262140_,
BlockState p_262167_,
RandomSource p_364105_
) {
if (!p_261476_.canSurvive(p_362157_, p_261876_)) {
p_366749_.scheduleTick(p_261876_, this, 1);
}
return p_261512_ == Direction.UP && p_262167_.is(Blocks.BAMBOO) && p_262167_.getValue(AGE) > p_261476_.getValue(AGE)
? p_261476_.cycle(AGE)
: super.updateShape(p_261476_, p_362157_, p_366749_, p_261876_, p_261512_, p_262140_, p_262167_, p_364105_);
}
@Override
public boolean isValidBonemealTarget(LevelReader p_262065_, BlockPos p_262033_, BlockState p_261700_) {
int i = this.getHeightAboveUpToMax(p_262065_, p_262033_);
int j = this.getHeightBelowUpToMax(p_262065_, p_262033_);
return i + j + 1 < 16 && p_262065_.getBlockState(p_262033_.above(i)).getValue(STAGE) != 1;
}
@Override
public boolean isBonemealSuccess(Level p_261870_, RandomSource p_261802_, BlockPos p_262123_, BlockState p_261972_) {
return true;
}
@Override
public void performBonemeal(ServerLevel p_261845_, RandomSource p_262034_, BlockPos p_261955_, BlockState p_261685_) {
int i = this.getHeightAboveUpToMax(p_261845_, p_261955_);
int j = this.getHeightBelowUpToMax(p_261845_, p_261955_);
int k = i + j + 1;
int l = 1 + p_262034_.nextInt(2);
for (int i1 = 0; i1 < l; i1++) {
BlockPos blockpos = p_261955_.above(i);
BlockState blockstate = p_261845_.getBlockState(blockpos);
if (k >= 16 || blockstate.getValue(STAGE) == 1 || !p_261845_.isEmptyBlock(blockpos.above())) {
return;
}
this.growBamboo(blockstate, p_261845_, blockpos, p_262034_, k);
i++;
k++;
}
}
protected void growBamboo(BlockState p_261855_, Level p_262076_, BlockPos p_262109_, RandomSource p_261633_, int p_261759_) {
BlockState blockstate = p_262076_.getBlockState(p_262109_.below());
BlockPos blockpos = p_262109_.below(2);
BlockState blockstate1 = p_262076_.getBlockState(blockpos);
BambooLeaves bambooleaves = BambooLeaves.NONE;
if (p_261759_ >= 1) {
if (!blockstate.is(Blocks.BAMBOO) || blockstate.getValue(LEAVES) == BambooLeaves.NONE) {
bambooleaves = BambooLeaves.SMALL;
} else if (blockstate.is(Blocks.BAMBOO) && blockstate.getValue(LEAVES) != BambooLeaves.NONE) {
bambooleaves = BambooLeaves.LARGE;
if (blockstate1.is(Blocks.BAMBOO)) {
p_262076_.setBlock(p_262109_.below(), blockstate.setValue(LEAVES, BambooLeaves.SMALL), 3);
p_262076_.setBlock(blockpos, blockstate1.setValue(LEAVES, BambooLeaves.NONE), 3);
}
}
}
int i = p_261855_.getValue(AGE) != 1 && !blockstate1.is(Blocks.BAMBOO) ? 0 : 1;
int j = (p_261759_ < 11 || !(p_261633_.nextFloat() < 0.25F)) && p_261759_ != 15 ? 0 : 1;
p_262076_.setBlock(p_262109_.above(), this.defaultBlockState().setValue(AGE, i).setValue(LEAVES, bambooleaves).setValue(STAGE, j), 3);
}
protected int getHeightAboveUpToMax(BlockGetter p_261541_, BlockPos p_261593_) {
int i = 0;
while (i < 16 && p_261541_.getBlockState(p_261593_.above(i + 1)).is(Blocks.BAMBOO)) {
i++;
}
return i;
}
protected int getHeightBelowUpToMax(BlockGetter p_261927_, BlockPos p_261481_) {
int i = 0;
while (i < 16 && p_261927_.getBlockState(p_261481_.below(i + 1)).is(Blocks.BAMBOO)) {
i++;
}
return i;
}
}