106 lines
3.9 KiB
Java
106 lines
3.9 KiB
Java
package net.minecraft.world.level.block;
|
|
|
|
import com.mojang.serialization.MapCodec;
|
|
import java.util.function.BiConsumer;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.particles.ParticleTypes;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.tags.BlockTags;
|
|
import net.minecraft.util.RandomSource;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.entity.projectile.Projectile;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.Explosion;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.level.block.state.BlockBehaviour;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
|
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
|
import net.minecraft.world.level.gameevent.GameEvent;
|
|
import net.minecraft.world.phys.BlockHitResult;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public abstract class AbstractCandleBlock extends Block {
|
|
public static final int LIGHT_PER_CANDLE = 3;
|
|
public static final BooleanProperty LIT = BlockStateProperties.LIT;
|
|
|
|
@Override
|
|
protected abstract MapCodec<? extends AbstractCandleBlock> codec();
|
|
|
|
protected AbstractCandleBlock(BlockBehaviour.Properties properties) {
|
|
super(properties);
|
|
}
|
|
|
|
protected abstract Iterable<Vec3> getParticleOffsets(BlockState state);
|
|
|
|
public static boolean isLit(BlockState state) {
|
|
return state.hasProperty(LIT) && (state.is(BlockTags.CANDLES) || state.is(BlockTags.CANDLE_CAKES)) && (Boolean)state.getValue(LIT);
|
|
}
|
|
|
|
@Override
|
|
protected void onProjectileHit(Level level, BlockState state, BlockHitResult hit, Projectile projectile) {
|
|
if (!level.isClientSide && projectile.isOnFire() && this.canBeLit(state)) {
|
|
setLit(level, state, hit.getBlockPos(), true);
|
|
}
|
|
}
|
|
|
|
protected boolean canBeLit(BlockState state) {
|
|
return !(Boolean)state.getValue(LIT);
|
|
}
|
|
|
|
@Override
|
|
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
|
|
if ((Boolean)state.getValue(LIT)) {
|
|
this.getParticleOffsets(state).forEach(vec3 -> addParticlesAndSound(level, vec3.add(pos.getX(), pos.getY(), pos.getZ()), random));
|
|
}
|
|
}
|
|
|
|
private static void addParticlesAndSound(Level level, Vec3 offset, RandomSource random) {
|
|
float f = random.nextFloat();
|
|
if (f < 0.3F) {
|
|
level.addParticle(ParticleTypes.SMOKE, offset.x, offset.y, offset.z, 0.0, 0.0, 0.0);
|
|
if (f < 0.17F) {
|
|
level.playLocalSound(
|
|
offset.x + 0.5,
|
|
offset.y + 0.5,
|
|
offset.z + 0.5,
|
|
SoundEvents.CANDLE_AMBIENT,
|
|
SoundSource.BLOCKS,
|
|
1.0F + random.nextFloat(),
|
|
random.nextFloat() * 0.7F + 0.3F,
|
|
false
|
|
);
|
|
}
|
|
}
|
|
|
|
level.addParticle(ParticleTypes.SMALL_FLAME, offset.x, offset.y, offset.z, 0.0, 0.0, 0.0);
|
|
}
|
|
|
|
public static void extinguish(@Nullable Player player, BlockState state, LevelAccessor level, BlockPos pos) {
|
|
setLit(level, state, pos, false);
|
|
if (state.getBlock() instanceof AbstractCandleBlock) {
|
|
((AbstractCandleBlock)state.getBlock())
|
|
.getParticleOffsets(state)
|
|
.forEach(vec3 -> level.addParticle(ParticleTypes.SMOKE, pos.getX() + vec3.x(), pos.getY() + vec3.y(), pos.getZ() + vec3.z(), 0.0, 0.1F, 0.0));
|
|
}
|
|
|
|
level.playSound(null, pos, SoundEvents.CANDLE_EXTINGUISH, SoundSource.BLOCKS, 1.0F, 1.0F);
|
|
level.gameEvent(player, GameEvent.BLOCK_CHANGE, pos);
|
|
}
|
|
|
|
private static void setLit(LevelAccessor level, BlockState state, BlockPos pos, boolean lit) {
|
|
level.setBlock(pos, state.setValue(LIT, lit), 11);
|
|
}
|
|
|
|
@Override
|
|
protected void onExplosionHit(BlockState state, Level level, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> dropConsumer) {
|
|
if (explosion.canTriggerBlocks() && (Boolean)state.getValue(LIT)) {
|
|
extinguish(null, state, level, pos);
|
|
}
|
|
|
|
super.onExplosionHit(state, level, pos, explosion, dropConsumer);
|
|
}
|
|
}
|