minecraft-src/net/minecraft/world/level/block/EyeblossomBlock.java
2025-07-04 03:45:38 +03:00

178 lines
6.4 KiB
Java

package net.minecraft.world.level.block;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Holder;
import net.minecraft.core.particles.TrailParticleOption;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.RandomSource;
import net.minecraft.world.Difficulty;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.effect.MobEffectInstance;
import net.minecraft.world.effect.MobEffects;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.InsideBlockEffectApplier;
import net.minecraft.world.entity.animal.Bee;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.level.gameevent.GameEvent.Context;
import net.minecraft.world.phys.Vec3;
public class EyeblossomBlock extends FlowerBlock {
public static final MapCodec<EyeblossomBlock> CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(Codec.BOOL.fieldOf("open").forGetter(eyeblossomBlock -> eyeblossomBlock.type.open), propertiesCodec())
.apply(instance, EyeblossomBlock::new)
);
private static final int EYEBLOSSOM_XZ_RANGE = 3;
private static final int EYEBLOSSOM_Y_RANGE = 2;
private final EyeblossomBlock.Type type;
@Override
public MapCodec<? extends EyeblossomBlock> codec() {
return CODEC;
}
public EyeblossomBlock(EyeblossomBlock.Type type, BlockBehaviour.Properties properties) {
super(type.effect, type.effectDuration, properties);
this.type = type;
}
public EyeblossomBlock(boolean open, BlockBehaviour.Properties properties) {
super(EyeblossomBlock.Type.fromBoolean(open).effect, EyeblossomBlock.Type.fromBoolean(open).effectDuration, properties);
this.type = EyeblossomBlock.Type.fromBoolean(open);
}
@Override
public void animateTick(BlockState state, Level level, BlockPos pos, RandomSource random) {
if (this.type.emitSounds() && random.nextInt(700) == 0) {
BlockState blockState = level.getBlockState(pos.below());
if (blockState.is(Blocks.PALE_MOSS_BLOCK)) {
level.playLocalSound(pos.getX(), pos.getY(), pos.getZ(), SoundEvents.EYEBLOSSOM_IDLE, SoundSource.AMBIENT, 1.0F, 1.0F, false);
}
}
}
@Override
protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (this.tryChangingState(state, level, pos, random)) {
level.playSound(null, pos, this.type.transform().longSwitchSound, SoundSource.BLOCKS, 1.0F, 1.0F);
}
super.randomTick(state, level, pos, random);
}
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (this.tryChangingState(state, level, pos, random)) {
level.playSound(null, pos, this.type.transform().shortSwitchSound, SoundSource.BLOCKS, 1.0F, 1.0F);
}
super.tick(state, level, pos, random);
}
private boolean tryChangingState(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (!level.dimensionType().natural()) {
return false;
} else if (CreakingHeartBlock.isNaturalNight(level) == this.type.open) {
return false;
} else {
EyeblossomBlock.Type type = this.type.transform();
level.setBlock(pos, type.state(), 3);
level.gameEvent(GameEvent.BLOCK_CHANGE, pos, Context.of(state));
type.spawnTransformParticle(level, pos, random);
BlockPos.betweenClosed(pos.offset(-3, -2, -3), pos.offset(3, 2, 3)).forEach(blockPos2 -> {
BlockState blockState2 = level.getBlockState(blockPos2);
if (blockState2 == state) {
double d = Math.sqrt(pos.distSqr(blockPos2));
int i = random.nextIntBetweenInclusive((int)(d * 5.0), (int)(d * 10.0));
level.scheduleTick(blockPos2, state.getBlock(), i);
}
});
return true;
}
}
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
if (!level.isClientSide()
&& level.getDifficulty() != Difficulty.PEACEFUL
&& entity instanceof Bee bee
&& Bee.attractsBees(state)
&& !bee.hasEffect(MobEffects.POISON)) {
bee.addEffect(this.getBeeInteractionEffect());
}
}
@Override
public MobEffectInstance getBeeInteractionEffect() {
return new MobEffectInstance(MobEffects.POISON, 25);
}
public static enum Type {
OPEN(true, MobEffects.BLINDNESS, 11.0F, SoundEvents.EYEBLOSSOM_OPEN_LONG, SoundEvents.EYEBLOSSOM_OPEN, 16545810),
CLOSED(false, MobEffects.NAUSEA, 7.0F, SoundEvents.EYEBLOSSOM_CLOSE_LONG, SoundEvents.EYEBLOSSOM_CLOSE, 6250335);
final boolean open;
final Holder<MobEffect> effect;
final float effectDuration;
final SoundEvent longSwitchSound;
final SoundEvent shortSwitchSound;
private final int particleColor;
private Type(
final boolean open,
final Holder<MobEffect> effect,
final float effectDuration,
final SoundEvent longSwitchSound,
final SoundEvent shortSwitchSound,
final int particleColor
) {
this.open = open;
this.effect = effect;
this.effectDuration = effectDuration;
this.longSwitchSound = longSwitchSound;
this.shortSwitchSound = shortSwitchSound;
this.particleColor = particleColor;
}
public Block block() {
return this.open ? Blocks.OPEN_EYEBLOSSOM : Blocks.CLOSED_EYEBLOSSOM;
}
public BlockState state() {
return this.block().defaultBlockState();
}
public EyeblossomBlock.Type transform() {
return fromBoolean(!this.open);
}
public boolean emitSounds() {
return this.open;
}
public static EyeblossomBlock.Type fromBoolean(boolean open) {
return open ? OPEN : CLOSED;
}
public void spawnTransformParticle(ServerLevel level, BlockPos pos, RandomSource random) {
Vec3 vec3 = pos.getCenter();
double d = 0.5 + random.nextDouble();
Vec3 vec32 = new Vec3(random.nextDouble() - 0.5, random.nextDouble() + 1.0, random.nextDouble() - 0.5);
Vec3 vec33 = vec3.add(vec32.scale(d));
TrailParticleOption trailParticleOption = new TrailParticleOption(vec33, this.particleColor, (int)(20.0 * d));
level.sendParticles(trailParticleOption, vec3.x, vec3.y, vec3.z, 1, 0.0, 0.0, 0.0, 0.0);
}
public SoundEvent longSwitchSound() {
return this.longSwitchSound;
}
}
}