package net.minecraft.world.level.block; import com.mojang.serialization.MapCodec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.BlockParticleOption; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.ScheduledTickAccess; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BrushableBlockEntity; import net.minecraft.world.level.block.state.BlockBehaviour; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition.Builder; 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.phys.Vec3; import org.jetbrains.annotations.Nullable; public class BrushableBlock extends BaseEntityBlock implements Fallable { public static final MapCodec CODEC = RecordCodecBuilder.mapCodec( instance -> instance.group( BuiltInRegistries.BLOCK.byNameCodec().fieldOf("turns_into").forGetter(BrushableBlock::getTurnsInto), BuiltInRegistries.SOUND_EVENT.byNameCodec().fieldOf("brush_sound").forGetter(BrushableBlock::getBrushSound), BuiltInRegistries.SOUND_EVENT.byNameCodec().fieldOf("brush_completed_sound").forGetter(BrushableBlock::getBrushCompletedSound), propertiesCodec() ) .apply(instance, BrushableBlock::new) ); private static final IntegerProperty DUSTED = BlockStateProperties.DUSTED; public static final int TICK_DELAY = 2; private final Block turnsInto; private final SoundEvent brushSound; private final SoundEvent brushCompletedSound; @Override public MapCodec codec() { return CODEC; } public BrushableBlock(Block turnsInto, SoundEvent brushSound, SoundEvent brushCompletedSound, BlockBehaviour.Properties properties) { super(properties); this.turnsInto = turnsInto; this.brushSound = brushSound; this.brushCompletedSound = brushCompletedSound; this.registerDefaultState(this.stateDefinition.any().setValue(DUSTED, 0)); } @Override protected void createBlockStateDefinition(Builder builder) { builder.add(DUSTED); } @Override public void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) { level.scheduleTick(pos, this, 2); } @Override public BlockState updateShape( BlockState state, LevelReader level, ScheduledTickAccess scheduledTickAccess, BlockPos pos, Direction direction, BlockPos neighborPos, BlockState neighborState, RandomSource random ) { scheduledTickAccess.scheduleTick(pos, this, 2); return super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random); } @Override public void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) { if (level.getBlockEntity(pos) instanceof BrushableBlockEntity brushableBlockEntity) { brushableBlockEntity.checkReset(level); } if (FallingBlock.isFree(level.getBlockState(pos.below())) && pos.getY() >= level.getMinY()) { FallingBlockEntity fallingBlockEntity = FallingBlockEntity.fall(level, pos, state); fallingBlockEntity.disableDrop(); } } @Override public void onBrokenAfterFall(Level level, BlockPos pos, FallingBlockEntity fallingBlock) { Vec3 vec3 = fallingBlock.getBoundingBox().getCenter(); level.levelEvent(2001, BlockPos.containing(vec3), Block.getId(fallingBlock.getBlockState())); level.gameEvent(fallingBlock, GameEvent.BLOCK_DESTROY, vec3); } @Override public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) { if (random.nextInt(16) == 0) { BlockPos blockPos = pos.below(); if (FallingBlock.isFree(level.getBlockState(blockPos))) { double d = pos.getX() + random.nextDouble(); double e = pos.getY() - 0.05; double f = pos.getZ() + random.nextDouble(); level.addParticle(new BlockParticleOption(ParticleTypes.FALLING_DUST, state), d, e, f, 0.0, 0.0, 0.0); } } } @Nullable @Override public BlockEntity newBlockEntity(BlockPos pos, BlockState state) { return new BrushableBlockEntity(pos, state); } public Block getTurnsInto() { return this.turnsInto; } public SoundEvent getBrushSound() { return this.brushSound; } public SoundEvent getBrushCompletedSound() { return this.brushCompletedSound; } }