package net.minecraft.world.level.material; import java.util.Optional; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.particles.ParticleOptions; import net.minecraft.core.particles.ParticleTypes; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.tags.FluidTags; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.InsideBlockEffectApplier; import net.minecraft.world.entity.InsideBlockEffectType; import net.minecraft.world.item.Item; import net.minecraft.world.item.Items; import net.minecraft.world.level.BlockGetter; import net.minecraft.world.level.GameRules; import net.minecraft.world.level.Level; import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.LevelReader; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.LiquidBlock; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition.Builder; import org.jetbrains.annotations.Nullable; public abstract class WaterFluid extends FlowingFluid { @Override public Fluid getFlowing() { return Fluids.FLOWING_WATER; } @Override public Fluid getSource() { return Fluids.WATER; } @Override public Item getBucket() { return Items.WATER_BUCKET; } @Override public void animateTick(Level level, BlockPos pos, FluidState state, RandomSource random) { if (!state.isSource() && !(Boolean)state.getValue(FALLING)) { if (random.nextInt(64) == 0) { level.playLocalSound( pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, SoundEvents.WATER_AMBIENT, SoundSource.AMBIENT, random.nextFloat() * 0.25F + 0.75F, random.nextFloat() + 0.5F, false ); } } else if (random.nextInt(10) == 0) { level.addParticle( ParticleTypes.UNDERWATER, pos.getX() + random.nextDouble(), pos.getY() + random.nextDouble(), pos.getZ() + random.nextDouble(), 0.0, 0.0, 0.0 ); } } @Nullable @Override public ParticleOptions getDripParticle() { return ParticleTypes.DRIPPING_WATER; } @Override protected boolean canConvertToSource(ServerLevel level) { return level.getGameRules().getBoolean(GameRules.RULE_WATER_SOURCE_CONVERSION); } @Override protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state) { BlockEntity blockEntity = state.hasBlockEntity() ? level.getBlockEntity(pos) : null; Block.dropResources(state, level, pos, blockEntity); } @Override protected void entityInside(Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) { effectApplier.apply(InsideBlockEffectType.EXTINGUISH); } @Override public int getSlopeFindDistance(LevelReader level) { return 4; } @Override public BlockState createLegacyBlock(FluidState state) { return Blocks.WATER.defaultBlockState().setValue(LiquidBlock.LEVEL, getLegacyLevel(state)); } @Override public boolean isSame(Fluid fluid) { return fluid == Fluids.WATER || fluid == Fluids.FLOWING_WATER; } @Override public int getDropOff(LevelReader level) { return 1; } @Override public int getTickDelay(LevelReader level) { return 5; } @Override public boolean canBeReplacedWith(FluidState state, BlockGetter level, BlockPos pos, Fluid fluid, Direction direction) { return direction == Direction.DOWN && !fluid.is(FluidTags.WATER); } @Override protected float getExplosionResistance() { return 100.0F; } @Override public Optional getPickupSound() { return Optional.of(SoundEvents.BUCKET_FILL); } public static class Flowing extends WaterFluid { @Override protected void createFluidStateDefinition(Builder builder) { super.createFluidStateDefinition(builder); builder.add(LEVEL); } @Override public int getAmount(FluidState state) { return (Integer)state.getValue(LEVEL); } @Override public boolean isSource(FluidState state) { return false; } } public static class Source extends WaterFluid { @Override public int getAmount(FluidState state) { return 8; } @Override public boolean isSource(FluidState state) { return true; } } }