262 lines
		
	
	
	
		
			7.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			262 lines
		
	
	
	
		
			7.5 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| 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.BaseFireBlock;
 | |
| import net.minecraft.world.level.block.Blocks;
 | |
| import net.minecraft.world.level.block.LiquidBlock;
 | |
| import net.minecraft.world.level.block.state.BlockState;
 | |
| import net.minecraft.world.level.block.state.StateDefinition;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| public abstract class LavaFluid extends FlowingFluid {
 | |
| 	public static final float MIN_LEVEL_CUTOFF = 0.44444445F;
 | |
| 
 | |
| 	@Override
 | |
| 	public Fluid getFlowing() {
 | |
| 		return Fluids.FLOWING_LAVA;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public Fluid getSource() {
 | |
| 		return Fluids.LAVA;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public Item getBucket() {
 | |
| 		return Items.LAVA_BUCKET;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void animateTick(Level level, BlockPos pos, FluidState state, RandomSource random) {
 | |
| 		BlockPos blockPos = pos.above();
 | |
| 		if (level.getBlockState(blockPos).isAir() && !level.getBlockState(blockPos).isSolidRender()) {
 | |
| 			if (random.nextInt(100) == 0) {
 | |
| 				double d = pos.getX() + random.nextDouble();
 | |
| 				double e = pos.getY() + 1.0;
 | |
| 				double f = pos.getZ() + random.nextDouble();
 | |
| 				level.addParticle(ParticleTypes.LAVA, d, e, f, 0.0, 0.0, 0.0);
 | |
| 				level.playLocalSound(d, e, f, SoundEvents.LAVA_POP, SoundSource.AMBIENT, 0.2F + random.nextFloat() * 0.2F, 0.9F + random.nextFloat() * 0.15F, false);
 | |
| 			}
 | |
| 
 | |
| 			if (random.nextInt(200) == 0) {
 | |
| 				level.playLocalSound(
 | |
| 					pos.getX(),
 | |
| 					pos.getY(),
 | |
| 					pos.getZ(),
 | |
| 					SoundEvents.LAVA_AMBIENT,
 | |
| 					SoundSource.AMBIENT,
 | |
| 					0.2F + random.nextFloat() * 0.2F,
 | |
| 					0.9F + random.nextFloat() * 0.15F,
 | |
| 					false
 | |
| 				);
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void randomTick(ServerLevel level, BlockPos pos, FluidState state, RandomSource random) {
 | |
| 		if (level.getGameRules().getBoolean(GameRules.RULE_DOFIRETICK)) {
 | |
| 			if (level.getGameRules().getBoolean(GameRules.RULE_ALLOWFIRETICKAWAYFROMPLAYERS) || level.anyPlayerCloseEnoughForSpawning(pos)) {
 | |
| 				int i = random.nextInt(3);
 | |
| 				if (i > 0) {
 | |
| 					BlockPos blockPos = pos;
 | |
| 
 | |
| 					for (int j = 0; j < i; j++) {
 | |
| 						blockPos = blockPos.offset(random.nextInt(3) - 1, 1, random.nextInt(3) - 1);
 | |
| 						if (!level.isLoaded(blockPos)) {
 | |
| 							return;
 | |
| 						}
 | |
| 
 | |
| 						BlockState blockState = level.getBlockState(blockPos);
 | |
| 						if (blockState.isAir()) {
 | |
| 							if (this.hasFlammableNeighbours(level, blockPos)) {
 | |
| 								level.setBlockAndUpdate(blockPos, BaseFireBlock.getState(level, blockPos));
 | |
| 								return;
 | |
| 							}
 | |
| 						} else if (blockState.blocksMotion()) {
 | |
| 							return;
 | |
| 						}
 | |
| 					}
 | |
| 				} else {
 | |
| 					for (int k = 0; k < 3; k++) {
 | |
| 						BlockPos blockPos2 = pos.offset(random.nextInt(3) - 1, 0, random.nextInt(3) - 1);
 | |
| 						if (!level.isLoaded(blockPos2)) {
 | |
| 							return;
 | |
| 						}
 | |
| 
 | |
| 						if (level.isEmptyBlock(blockPos2.above()) && this.isFlammable(level, blockPos2)) {
 | |
| 							level.setBlockAndUpdate(blockPos2.above(), BaseFireBlock.getState(level, blockPos2));
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void entityInside(Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
 | |
| 		effectApplier.apply(InsideBlockEffectType.LAVA_IGNITE);
 | |
| 		effectApplier.runAfter(InsideBlockEffectType.LAVA_IGNITE, Entity::lavaHurt);
 | |
| 	}
 | |
| 
 | |
| 	private boolean hasFlammableNeighbours(LevelReader level, BlockPos pos) {
 | |
| 		for (Direction direction : Direction.values()) {
 | |
| 			if (this.isFlammable(level, pos.relative(direction))) {
 | |
| 				return true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	private boolean isFlammable(LevelReader level, BlockPos pos) {
 | |
| 		return level.isInsideBuildHeight(pos.getY()) && !level.hasChunkAt(pos) ? false : level.getBlockState(pos).ignitedByLava();
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	@Override
 | |
| 	public ParticleOptions getDripParticle() {
 | |
| 		return ParticleTypes.DRIPPING_LAVA;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void beforeDestroyingBlock(LevelAccessor level, BlockPos pos, BlockState state) {
 | |
| 		this.fizz(level, pos);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getSlopeFindDistance(LevelReader level) {
 | |
| 		return level.dimensionType().ultraWarm() ? 4 : 2;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public BlockState createLegacyBlock(FluidState state) {
 | |
| 		return Blocks.LAVA.defaultBlockState().setValue(LiquidBlock.LEVEL, getLegacyLevel(state));
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean isSame(Fluid fluid) {
 | |
| 		return fluid == Fluids.LAVA || fluid == Fluids.FLOWING_LAVA;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getDropOff(LevelReader level) {
 | |
| 		return level.dimensionType().ultraWarm() ? 1 : 2;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public boolean canBeReplacedWith(FluidState state, BlockGetter level, BlockPos pos, Fluid fluid, Direction direction) {
 | |
| 		return state.getHeight(level, pos) >= 0.44444445F && fluid.is(FluidTags.WATER);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getTickDelay(LevelReader level) {
 | |
| 		return level.dimensionType().ultraWarm() ? 10 : 30;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public int getSpreadDelay(Level level, BlockPos pos, FluidState currentState, FluidState newState) {
 | |
| 		int i = this.getTickDelay(level);
 | |
| 		if (!currentState.isEmpty()
 | |
| 			&& !newState.isEmpty()
 | |
| 			&& !(Boolean)currentState.getValue(FALLING)
 | |
| 			&& !(Boolean)newState.getValue(FALLING)
 | |
| 			&& newState.getHeight(level, pos) > currentState.getHeight(level, pos)
 | |
| 			&& level.getRandom().nextInt(4) != 0) {
 | |
| 			i *= 4;
 | |
| 		}
 | |
| 
 | |
| 		return i;
 | |
| 	}
 | |
| 
 | |
| 	private void fizz(LevelAccessor level, BlockPos pos) {
 | |
| 		level.levelEvent(1501, pos, 0);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected boolean canConvertToSource(ServerLevel level) {
 | |
| 		return level.getGameRules().getBoolean(GameRules.RULE_LAVA_SOURCE_CONVERSION);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void spreadTo(LevelAccessor level, BlockPos pos, BlockState blockState, Direction direction, FluidState fluidState) {
 | |
| 		if (direction == Direction.DOWN) {
 | |
| 			FluidState fluidState2 = level.getFluidState(pos);
 | |
| 			if (this.is(FluidTags.LAVA) && fluidState2.is(FluidTags.WATER)) {
 | |
| 				if (blockState.getBlock() instanceof LiquidBlock) {
 | |
| 					level.setBlock(pos, Blocks.STONE.defaultBlockState(), 3);
 | |
| 				}
 | |
| 
 | |
| 				this.fizz(level, pos);
 | |
| 				return;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		super.spreadTo(level, pos, blockState, direction, fluidState);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected boolean isRandomlyTicking() {
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected float getExplosionResistance() {
 | |
| 		return 100.0F;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public Optional<SoundEvent> getPickupSound() {
 | |
| 		return Optional.of(SoundEvents.BUCKET_FILL_LAVA);
 | |
| 	}
 | |
| 
 | |
| 	public static class Flowing extends LavaFluid {
 | |
| 		@Override
 | |
| 		protected void createFluidStateDefinition(StateDefinition.Builder<Fluid, FluidState> 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 LavaFluid {
 | |
| 		@Override
 | |
| 		public int getAmount(FluidState state) {
 | |
| 			return 8;
 | |
| 		}
 | |
| 
 | |
| 		@Override
 | |
| 		public boolean isSource(FluidState state) {
 | |
| 			return true;
 | |
| 		}
 | |
| 	}
 | |
| }
 |