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.tags.FluidTags; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.piston.MovingPistonBlock; 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.IntegerProperty; import net.minecraft.world.level.gameevent.GameEvent; import net.minecraft.world.level.pathfinder.PathComputationType; import net.minecraft.world.phys.shapes.CollisionContext; import net.minecraft.world.phys.shapes.VoxelShape; public class FarmBlock extends Block { public static final MapCodec CODEC = simpleCodec(FarmBlock::new); public static final IntegerProperty MOISTURE = BlockStateProperties.MOISTURE; private static final VoxelShape SHAPE = Block.column(16.0, 0.0, 15.0); public static final int MAX_MOISTURE = 7; @Override public MapCodec codec() { return CODEC; } protected FarmBlock(BlockBehaviour.Properties p_53247_) { super(p_53247_); this.registerDefaultState(this.stateDefinition.any().setValue(MOISTURE, 0)); } @Override protected BlockState updateShape( BlockState p_53276_, LevelReader p_365387_, ScheduledTickAccess p_368906_, BlockPos p_53280_, Direction p_53277_, BlockPos p_53281_, BlockState p_53278_, RandomSource p_363271_ ) { if (p_53277_ == Direction.UP && !p_53276_.canSurvive(p_365387_, p_53280_)) { p_368906_.scheduleTick(p_53280_, this, 1); } return super.updateShape(p_53276_, p_365387_, p_368906_, p_53280_, p_53277_, p_53281_, p_53278_, p_363271_); } @Override protected boolean canSurvive(BlockState p_53272_, LevelReader p_53273_, BlockPos p_53274_) { BlockState blockstate = p_53273_.getBlockState(p_53274_.above()); return !blockstate.isSolid() || blockstate.getBlock() instanceof FenceGateBlock || blockstate.getBlock() instanceof MovingPistonBlock; } @Override public BlockState getStateForPlacement(BlockPlaceContext p_53249_) { return !this.defaultBlockState().canSurvive(p_53249_.getLevel(), p_53249_.getClickedPos()) ? Blocks.DIRT.defaultBlockState() : super.getStateForPlacement(p_53249_); } @Override protected boolean useShapeForLightOcclusion(BlockState p_53295_) { return true; } @Override protected VoxelShape getShape(BlockState p_53290_, BlockGetter p_53291_, BlockPos p_53292_, CollisionContext p_53293_) { return SHAPE; } @Override protected void tick(BlockState p_221134_, ServerLevel p_221135_, BlockPos p_221136_, RandomSource p_221137_) { if (!p_221134_.canSurvive(p_221135_, p_221136_)) { turnToDirt(null, p_221134_, p_221135_, p_221136_); } } @Override protected void randomTick(BlockState p_221139_, ServerLevel p_221140_, BlockPos p_221141_, RandomSource p_221142_) { int i = p_221139_.getValue(MOISTURE); if (!isNearWater(p_221140_, p_221141_) && !p_221140_.isRainingAt(p_221141_.above())) { if (i > 0) { p_221140_.setBlock(p_221141_, p_221139_.setValue(MOISTURE, i - 1), 2); } else if (!shouldMaintainFarmland(p_221140_, p_221141_)) { turnToDirt(null, p_221139_, p_221140_, p_221141_); } } else if (i < 7) { p_221140_.setBlock(p_221141_, p_221139_.setValue(MOISTURE, 7), 2); } } @Override public void fallOn(Level p_153227_, BlockState p_153228_, BlockPos p_153229_, Entity p_153230_, double p_394537_) { if (p_153227_ instanceof ServerLevel serverlevel && p_153227_.random.nextFloat() < p_394537_ - 0.5 && p_153230_ instanceof LivingEntity && (p_153230_ instanceof Player || serverlevel.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) && p_153230_.getBbWidth() * p_153230_.getBbWidth() * p_153230_.getBbHeight() > 0.512F) { turnToDirt(p_153230_, p_153228_, p_153227_, p_153229_); } super.fallOn(p_153227_, p_153228_, p_153229_, p_153230_, p_394537_); } public static void turnToDirt(@Nullable Entity p_270981_, BlockState p_270402_, Level p_270568_, BlockPos p_270551_) { BlockState blockstate = pushEntitiesUp(p_270402_, Blocks.DIRT.defaultBlockState(), p_270568_, p_270551_); p_270568_.setBlockAndUpdate(p_270551_, blockstate); p_270568_.gameEvent(GameEvent.BLOCK_CHANGE, p_270551_, GameEvent.Context.of(p_270981_, blockstate)); } private static boolean shouldMaintainFarmland(BlockGetter p_279219_, BlockPos p_279209_) { return p_279219_.getBlockState(p_279209_.above()).is(BlockTags.MAINTAINS_FARMLAND); } private static boolean isNearWater(LevelReader p_53259_, BlockPos p_53260_) { for (BlockPos blockpos : BlockPos.betweenClosed(p_53260_.offset(-4, 0, -4), p_53260_.offset(4, 1, 4))) { if (p_53259_.getFluidState(blockpos).is(FluidTags.WATER)) { return true; } } return false; } @Override protected void createBlockStateDefinition(StateDefinition.Builder p_53283_) { p_53283_.add(MOISTURE); } @Override protected boolean isPathfindable(BlockState p_53267_, PathComputationType p_53270_) { return false; } }