174 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			174 lines
		
	
	
	
		
			6.8 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
| package net.minecraft.world.level.block;
 | |
| 
 | |
| import com.mojang.serialization.MapCodec;
 | |
| 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;
 | |
| import org.jetbrains.annotations.Nullable;
 | |
| 
 | |
| 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 properties) {
 | |
| 		super(properties);
 | |
| 		this.registerDefaultState(this.stateDefinition.any().setValue(HATCH, 0).setValue(EGGS, 1));
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void stepOn(Level level, BlockPos pos, BlockState state, Entity entity) {
 | |
| 		if (!entity.isSteppingCarefully()) {
 | |
| 			this.destroyEgg(level, state, pos, entity, 100);
 | |
| 		}
 | |
| 
 | |
| 		super.stepOn(level, pos, state, entity);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void fallOn(Level level, BlockState state, BlockPos pos, Entity entity, double fallDistance) {
 | |
| 		if (!(entity instanceof Zombie)) {
 | |
| 			this.destroyEgg(level, state, pos, entity, 3);
 | |
| 		}
 | |
| 
 | |
| 		super.fallOn(level, state, pos, entity, fallDistance);
 | |
| 	}
 | |
| 
 | |
| 	private void destroyEgg(Level level, BlockState state, BlockPos pos, Entity entity, int chance) {
 | |
| 		if (state.is(Blocks.TURTLE_EGG) && level instanceof ServerLevel serverLevel && this.canDestroyEgg(serverLevel, entity) && level.random.nextInt(chance) == 0) {
 | |
| 			this.decreaseEggs(serverLevel, pos, state);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private void decreaseEggs(Level level, BlockPos pos, BlockState state) {
 | |
| 		level.playSound(null, pos, SoundEvents.TURTLE_EGG_BREAK, SoundSource.BLOCKS, 0.7F, 0.9F + level.random.nextFloat() * 0.2F);
 | |
| 		int i = (Integer)state.getValue(EGGS);
 | |
| 		if (i <= 1) {
 | |
| 			level.destroyBlock(pos, false);
 | |
| 		} else {
 | |
| 			level.setBlock(pos, state.setValue(EGGS, i - 1), 2);
 | |
| 			level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state));
 | |
| 			level.levelEvent(2001, pos, Block.getId(state));
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void randomTick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
 | |
| 		if (this.shouldUpdateHatchLevel(level) && onSand(level, pos)) {
 | |
| 			int i = (Integer)state.getValue(HATCH);
 | |
| 			if (i < 2) {
 | |
| 				level.playSound(null, pos, SoundEvents.TURTLE_EGG_CRACK, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
 | |
| 				level.setBlock(pos, state.setValue(HATCH, i + 1), 2);
 | |
| 				level.gameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Context.of(state));
 | |
| 			} else {
 | |
| 				level.playSound(null, pos, SoundEvents.TURTLE_EGG_HATCH, SoundSource.BLOCKS, 0.7F, 0.9F + random.nextFloat() * 0.2F);
 | |
| 				level.removeBlock(pos, false);
 | |
| 				level.gameEvent(GameEvent.BLOCK_DESTROY, pos, GameEvent.Context.of(state));
 | |
| 
 | |
| 				for (int j = 0; j < state.getValue(EGGS); j++) {
 | |
| 					level.levelEvent(2001, pos, Block.getId(state));
 | |
| 					Turtle turtle = EntityType.TURTLE.create(level, EntitySpawnReason.BREEDING);
 | |
| 					if (turtle != null) {
 | |
| 						turtle.setAge(-24000);
 | |
| 						turtle.setHomePos(pos);
 | |
| 						turtle.snapTo(pos.getX() + 0.3 + j * 0.2, pos.getY(), pos.getZ() + 0.3, 0.0F, 0.0F);
 | |
| 						level.addFreshEntity(turtle);
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public static boolean onSand(BlockGetter level, BlockPos pos) {
 | |
| 		return isSand(level, pos.below());
 | |
| 	}
 | |
| 
 | |
| 	public static boolean isSand(BlockGetter reader, BlockPos pos) {
 | |
| 		return reader.getBlockState(pos).is(BlockTags.SAND);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void onPlace(BlockState state, Level level, BlockPos pos, BlockState oldState, boolean movedByPiston) {
 | |
| 		if (onSand(level, pos) && !level.isClientSide) {
 | |
| 			level.levelEvent(2012, pos, 15);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	private boolean shouldUpdateHatchLevel(Level level) {
 | |
| 		float f = level.getTimeOfDay(1.0F);
 | |
| 		return f < 0.69 && f > 0.65 ? true : level.random.nextInt(500) == 0;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	public void playerDestroy(Level level, Player player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack tool) {
 | |
| 		super.playerDestroy(level, player, pos, state, blockEntity, tool);
 | |
| 		this.decreaseEggs(level, pos, state);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected boolean canBeReplaced(BlockState state, BlockPlaceContext useContext) {
 | |
| 		return !useContext.isSecondaryUseActive() && useContext.getItemInHand().is(this.asItem()) && state.getValue(EGGS) < 4
 | |
| 			? true
 | |
| 			: super.canBeReplaced(state, useContext);
 | |
| 	}
 | |
| 
 | |
| 	@Nullable
 | |
| 	@Override
 | |
| 	public BlockState getStateForPlacement(BlockPlaceContext context) {
 | |
| 		BlockState blockState = context.getLevel().getBlockState(context.getClickedPos());
 | |
| 		return blockState.is(this) ? blockState.setValue(EGGS, Math.min(4, (Integer)blockState.getValue(EGGS) + 1)) : super.getStateForPlacement(context);
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected VoxelShape getShape(BlockState state, BlockGetter level, BlockPos pos, CollisionContext context) {
 | |
| 		return state.getValue(EGGS) == 1 ? SHAPE_SINGLE : SHAPE_MULTIPLE;
 | |
| 	}
 | |
| 
 | |
| 	@Override
 | |
| 	protected void createBlockStateDefinition(StateDefinition.Builder<Block, BlockState> builder) {
 | |
| 		builder.add(HATCH, EGGS);
 | |
| 	}
 | |
| 
 | |
| 	private boolean canDestroyEgg(ServerLevel level, Entity entity) {
 | |
| 		if (entity instanceof Turtle || entity instanceof Bat) {
 | |
| 			return false;
 | |
| 		} else {
 | |
| 			return !(entity instanceof LivingEntity) ? false : entity instanceof Player || level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
 | |
| 		}
 | |
| 	}
 | |
| }
 |