Code/net/minecraft/world/level/block/TurtleEggBlock.java

177 lines
8.0 KiB
Java
Raw Normal View History

2025-07-01 06:20:03 +00:00
package net.minecraft.world.level.block;
import com.mojang.serialization.MapCodec;
import javax.annotation.Nullable;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
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.Entity;
import net.minecraft.world.entity.EntitySpawnReason;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ambient.Bat;
import net.minecraft.world.entity.animal.Turtle;
import net.minecraft.world.entity.monster.Zombie;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.context.BlockPlaceContext;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.GameRules;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.StateDefinition;
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.shapes.CollisionContext;
import net.minecraft.world.phys.shapes.VoxelShape;
public class TurtleEggBlock extends Block {
public static final MapCodec<TurtleEggBlock> CODEC = simpleCodec(TurtleEggBlock::new);
public static final IntegerProperty HATCH = BlockStateProperties.HATCH;
public static final IntegerProperty EGGS = BlockStateProperties.EGGS;
public static final int MAX_HATCH_LEVEL = 2;
public static final int MIN_EGGS = 1;
public static final int MAX_EGGS = 4;
private static final VoxelShape SHAPE_SINGLE = Block.box(3.0, 0.0, 3.0, 12.0, 7.0, 12.0);
private static final VoxelShape SHAPE_MULTIPLE = Block.column(14.0, 0.0, 7.0);
@Override
public MapCodec<TurtleEggBlock> codec() {
return CODEC;
}
public TurtleEggBlock(BlockBehaviour.Properties p_57759_) {
super(p_57759_);
this.registerDefaultState(this.stateDefinition.any().setValue(HATCH, 0).setValue(EGGS, 1));
}
@Override
public void stepOn(Level p_154857_, BlockPos p_154858_, BlockState p_154859_, Entity p_154860_) {
if (!p_154860_.isSteppingCarefully()) {
this.destroyEgg(p_154857_, p_154859_, p_154858_, p_154860_, 100);
}
super.stepOn(p_154857_, p_154858_, p_154859_, p_154860_);
}
@Override
public void fallOn(Level p_154845_, BlockState p_154846_, BlockPos p_154847_, Entity p_154848_, double p_392306_) {
if (!(p_154848_ instanceof Zombie)) {
this.destroyEgg(p_154845_, p_154846_, p_154847_, p_154848_, 3);
}
super.fallOn(p_154845_, p_154846_, p_154847_, p_154848_, p_392306_);
}
private void destroyEgg(Level p_154851_, BlockState p_154852_, BlockPos p_154853_, Entity p_154854_, int p_154855_) {
if (p_154852_.is(Blocks.TURTLE_EGG)
&& p_154851_ instanceof ServerLevel serverlevel
&& this.canDestroyEgg(serverlevel, p_154854_)
&& p_154851_.random.nextInt(p_154855_) == 0) {
this.decreaseEggs(serverlevel, p_154853_, p_154852_);
}
}
private void decreaseEggs(Level p_57792_, BlockPos p_57793_, BlockState p_57794_) {
p_57792_.playSound(null, p_57793_, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + p_57792_.random.nextFloat() * 0.2F);
int i = p_57794_.getValue(EGGS);
if (i <= 1) {
p_57792_.destroyBlock(p_57793_, false);
} else {
p_57792_.setBlock(p_57793_, p_57794_.setValue(EGGS, i - 1), 2);
p_57792_.gameEvent(GameEvent.BLOCK_DESTROY, p_57793_, GameEvent.Context.of(p_57794_));
p_57792_.levelEvent(2001, p_57793_, Block.getId(p_57794_));
}
}
@Override
protected void randomTick(BlockState p_222644_, ServerLevel p_222645_, BlockPos p_222646_, RandomSource p_222647_) {
if (this.shouldUpdateHatchLevel(p_222645_) && onSand(p_222645_, p_222646_)) {
int i = p_222644_.getValue(HATCH);
if (i < 2) {
p_222645_.playSound(null, p_222646_, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + p_222647_.nextFloat() * 0.2F);
p_222645_.setBlock(p_222646_, p_222644_.setValue(HATCH, i + 1), 2);
p_222645_.gameEvent(GameEvent.BLOCK_CHANGE, p_222646_, GameEvent.Context.of(p_222644_));
} else {
p_222645_.playSound(null, p_222646_, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + p_222647_.nextFloat() * 0.2F);
p_222645_.removeBlock(p_222646_, false);
p_222645_.gameEvent(GameEvent.BLOCK_DESTROY, p_222646_, GameEvent.Context.of(p_222644_));
for (int j = 0; j < p_222644_.getValue(EGGS); j++) {
p_222645_.levelEvent(2001, p_222646_, Block.getId(p_222644_));
Turtle turtle = EntityType.TURTLE.create(p_222645_, EntitySpawnReason.BREEDING);
if (turtle != null) {
turtle.setAge(-24000);
turtle.setHomePos(p_222646_);
turtle.snapTo(p_222646_.getX() + 0.3 + j * 0.2, p_222646_.getY(), p_222646_.getZ() + 0.3, 0.0F, 0.0F);
p_222645_.addFreshEntity(turtle);
}
}
}
}
}
public static boolean onSand(BlockGetter p_57763_, BlockPos p_57764_) {
return isSand(p_57763_, p_57764_.below());
}
public static boolean isSand(BlockGetter p_57801_, BlockPos p_57802_) {
return p_57801_.getBlockState(p_57802_).is(BlockTags.SAND);
}
@Override
protected void onPlace(BlockState p_57814_, Level p_57815_, BlockPos p_57816_, BlockState p_57817_, boolean p_57818_) {
if (onSand(p_57815_, p_57816_) && !p_57815_.isClientSide) {
p_57815_.levelEvent(2012, p_57816_, 15);
}
}
private boolean shouldUpdateHatchLevel(Level p_57766_) {
float f = p_57766_.getTimeOfDay(1.0F);
return f < 0.69 && f > 0.65 ? true : p_57766_.random.nextInt(500) == 0;
}
@Override
public void playerDestroy(Level p_57771_, Player p_57772_, BlockPos p_57773_, BlockState p_57774_, @Nullable BlockEntity p_57775_, ItemStack p_57776_) {
super.playerDestroy(p_57771_, p_57772_, p_57773_, p_57774_, p_57775_, p_57776_);
this.decreaseEggs(p_57771_, p_57773_, p_57774_);
}
@Override
protected boolean canBeReplaced(BlockState p_57796_, BlockPlaceContext p_57797_) {
return !p_57797_.isSecondaryUseActive() && p_57797_.getItemInHand().is(this.asItem()) && p_57796_.getValue(EGGS) < 4
? true
: super.canBeReplaced(p_57796_, p_57797_);
}
@Nullable
@Override
public BlockState getStateForPlacement(BlockPlaceContext p_57761_) {
BlockState blockstate = p_57761_.getLevel().getBlockState(p_57761_.getClickedPos());
return blockstate.is(this) ? blockstate.setValue(EGGS, Math.min(4, blockstate.getValue(EGGS) + 1)) : super.getStateForPlacement(p_57761_);
}
@Override
protected VoxelShape getShape(BlockState p_57809_, BlockGetter p_57810_, BlockPos p_57811_, CollisionContext p_57812_) {
return p_57809_.getValue(EGGS) == 1 ? SHAPE_SINGLE : SHAPE_MULTIPLE;
}
@Override
protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> p_57799_) {
p_57799_.add(HATCH, EGGS);
}
private boolean canDestroyEgg(ServerLevel p_366354_, Entity p_57769_) {
if (p_57769_ instanceof Turtle || p_57769_ instanceof Bat) {
return false;
} else {
return !(p_57769_ instanceof LivingEntity) ? false : p_57769_ instanceof Player || p_366354_.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
}
}
}