579 lines
21 KiB
Java
579 lines
21 KiB
Java
package net.minecraft.world.entity.animal;
|
|
|
|
import net.minecraft.world.level.block.state.AbstractStateHolder;
|
|
import net.minecraft.world.entity.ai.goal.MeleeAttackGoal;
|
|
import net.minecraft.world.entity.ai.goal.PanicGoal;
|
|
import net.minecraft.world.level.LevelReader;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
import net.minecraft.world.level.block.CarrotBlock;
|
|
import net.minecraft.world.level.GameRules;
|
|
import net.minecraft.world.entity.ai.goal.MoveToBlockGoal;
|
|
import net.minecraft.world.entity.ai.goal.AvoidEntityGoal;
|
|
import net.minecraft.world.entity.ai.control.MoveControl;
|
|
import net.minecraft.network.syncher.SynchedEntityData;
|
|
import net.minecraft.network.syncher.EntityDataSerializers;
|
|
import net.minecraft.world.entity.ai.control.JumpControl;
|
|
import net.minecraft.world.level.block.Block;
|
|
import java.util.Random;
|
|
import net.minecraft.world.level.biome.Biome;
|
|
import net.minecraft.core.BlockPos;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.world.entity.SpawnGroupData;
|
|
import net.minecraft.world.entity.MobSpawnType;
|
|
import net.minecraft.world.DifficultyInstance;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.TranslatableComponent;
|
|
import net.minecraft.Util;
|
|
import net.minecraft.world.entity.ai.goal.target.NearestAttackableTargetGoal;
|
|
import net.minecraft.world.entity.ai.goal.target.HurtByTargetGoal;
|
|
import net.minecraft.world.item.ItemStack;
|
|
import net.minecraft.world.level.LevelAccessor;
|
|
import net.minecraft.world.entity.AgableMob;
|
|
import net.minecraft.world.item.Item;
|
|
import net.minecraft.sounds.SoundSource;
|
|
import net.minecraft.world.damagesource.DamageSource;
|
|
import net.minecraft.sounds.SoundEvents;
|
|
import net.minecraft.sounds.SoundEvent;
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.world.entity.monster.SharedMonsterAttributes;
|
|
import net.minecraft.util.Mth;
|
|
import net.minecraft.world.phys.Vec3;
|
|
import net.minecraft.world.level.pathfinder.Path;
|
|
import net.minecraft.world.entity.Entity;
|
|
import net.minecraft.world.entity.LivingEntity;
|
|
import net.minecraft.world.entity.ai.goal.LookAtPlayerGoal;
|
|
import net.minecraft.world.entity.ai.goal.WaterAvoidingRandomStrollGoal;
|
|
import net.minecraft.world.entity.monster.Monster;
|
|
import net.minecraft.world.entity.player.Player;
|
|
import net.minecraft.world.entity.PathfinderMob;
|
|
import net.minecraft.world.entity.ai.goal.TemptGoal;
|
|
import net.minecraft.world.item.crafting.Ingredient;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import net.minecraft.world.item.Items;
|
|
import net.minecraft.world.level.ItemLike;
|
|
import net.minecraft.world.entity.ai.goal.BreedGoal;
|
|
import net.minecraft.world.entity.ai.goal.Goal;
|
|
import net.minecraft.world.entity.Mob;
|
|
import net.minecraft.world.entity.ai.goal.FloatGoal;
|
|
import net.minecraft.world.level.Level;
|
|
import net.minecraft.world.entity.EntityType;
|
|
import net.minecraft.resources.ResourceLocation;
|
|
import net.minecraft.network.syncher.EntityDataAccessor;
|
|
|
|
public class Rabbit extends Animal {
|
|
private static final EntityDataAccessor<Integer> DATA_TYPE_ID;
|
|
private static final ResourceLocation KILLER_BUNNY;
|
|
private int jumpTicks;
|
|
private int jumpDuration;
|
|
private boolean wasOnGround;
|
|
private int jumpDelayTicks;
|
|
private int moreCarrotTicks;
|
|
|
|
public Rabbit(final EntityType<? extends Rabbit> akr, final Level bjt) {
|
|
super(akr, bjt);
|
|
this.jumpControl = new RabbitJumpControl(this);
|
|
this.moveControl = new RabbitMoveControl(this);
|
|
this.setSpeedModifier(0.0);
|
|
}
|
|
|
|
@Override
|
|
protected void registerGoals() {
|
|
this.goalSelector.addGoal(1, new FloatGoal(this));
|
|
this.goalSelector.addGoal(1, new RabbitPanicGoal(this, 2.2));
|
|
this.goalSelector.addGoal(2, new BreedGoal(this, 0.8));
|
|
this.goalSelector.addGoal(3, new TemptGoal(this, 1.0, Ingredient.of(Items.CARROT, Items.GOLDEN_CARROT, Blocks.DANDELION), false));
|
|
this.goalSelector.addGoal(4, new RabbitAvoidEntityGoal<>(this, Player.class, 8.0f, 2.2, 2.2));
|
|
this.goalSelector.addGoal(4, new RabbitAvoidEntityGoal<>(this, Wolf.class, 10.0f, 2.2, 2.2));
|
|
this.goalSelector.addGoal(4, new RabbitAvoidEntityGoal<>(this, Monster.class, 4.0f, 2.2, 2.2));
|
|
this.goalSelector.addGoal(5, new RaidGardenGoal(this));
|
|
this.goalSelector.addGoal(6, new WaterAvoidingRandomStrollGoal(this, 0.6));
|
|
this.goalSelector.addGoal(11, new LookAtPlayerGoal(this, Player.class, 10.0f));
|
|
}
|
|
|
|
@Override
|
|
protected float getJumpPower() {
|
|
if (this.horizontalCollision || (this.moveControl.hasWanted() && this.moveControl.getWantedY() > this.getY() + 0.5)) {
|
|
return 0.5f;
|
|
}
|
|
final Path cqn2 = this.navigation.getPath();
|
|
if (cqn2 != null && cqn2.getIndex() < cqn2.getSize()) {
|
|
final Vec3 cvi3 = cqn2.currentPos(this);
|
|
if (cvi3.y > this.getY() + 0.5) {
|
|
return 0.5f;
|
|
}
|
|
}
|
|
if (this.moveControl.getSpeedModifier() <= 0.6) {
|
|
return 0.2f;
|
|
}
|
|
return 0.3f;
|
|
}
|
|
|
|
@Override
|
|
protected void jumpFromGround() {
|
|
super.jumpFromGround();
|
|
final double double2 = this.moveControl.getSpeedModifier();
|
|
if (double2 > 0.0) {
|
|
final double double3 = Entity.getHorizontalDistanceSqr(this.getDeltaMovement());
|
|
if (double3 < 0.01) {
|
|
this.moveRelative(0.1f, new Vec3(0.0, 0.0, 1.0));
|
|
}
|
|
}
|
|
if (!this.level.isClientSide) {
|
|
this.level.broadcastEntityEvent(this, (byte)1);
|
|
}
|
|
}
|
|
|
|
public float getJumpCompletion(final float float1) {
|
|
if (this.jumpDuration == 0) {
|
|
return 0.0f;
|
|
}
|
|
return (this.jumpTicks + float1) / this.jumpDuration;
|
|
}
|
|
|
|
public void setSpeedModifier(final double double1) {
|
|
this.getNavigation().setSpeedModifier(double1);
|
|
this.moveControl.setWantedPosition(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ(), double1);
|
|
}
|
|
|
|
@Override
|
|
public void setJumping(final boolean boolean1) {
|
|
super.setJumping(boolean1);
|
|
if (boolean1) {
|
|
this.playSound(this.getJumpSound(), this.getSoundVolume(), ((this.random.nextFloat() - this.random.nextFloat()) * 0.2f + 1.0f) * 0.8f);
|
|
}
|
|
}
|
|
|
|
public void startJumping() {
|
|
this.setJumping(true);
|
|
this.jumpDuration = 10;
|
|
this.jumpTicks = 0;
|
|
}
|
|
|
|
@Override
|
|
protected void defineSynchedData() {
|
|
super.defineSynchedData();
|
|
this.entityData.<Integer>define(Rabbit.DATA_TYPE_ID, 0);
|
|
}
|
|
|
|
public void customServerAiStep() {
|
|
if (this.jumpDelayTicks > 0) {
|
|
--this.jumpDelayTicks;
|
|
}
|
|
if (this.moreCarrotTicks > 0) {
|
|
this.moreCarrotTicks -= this.random.nextInt(3);
|
|
if (this.moreCarrotTicks < 0) {
|
|
this.moreCarrotTicks = 0;
|
|
}
|
|
}
|
|
if (this.onGround) {
|
|
if (!this.wasOnGround) {
|
|
this.setJumping(false);
|
|
this.checkLandingDelay();
|
|
}
|
|
if (this.getRabbitType() == 99 && this.jumpDelayTicks == 0) {
|
|
final LivingEntity akw2 = this.getTarget();
|
|
if (akw2 != null && this.distanceToSqr(akw2) < 16.0) {
|
|
this.facePoint(akw2.getX(), akw2.getZ());
|
|
this.moveControl.setWantedPosition(akw2.getX(), akw2.getY(), akw2.getZ(), this.moveControl.getSpeedModifier());
|
|
this.startJumping();
|
|
this.wasOnGround = true;
|
|
}
|
|
}
|
|
final RabbitJumpControl d2 = (RabbitJumpControl)this.jumpControl;
|
|
if (!d2.wantJump()) {
|
|
if (this.moveControl.hasWanted() && this.jumpDelayTicks == 0) {
|
|
final Path cqn3 = this.navigation.getPath();
|
|
Vec3 cvi4 = new Vec3(this.moveControl.getWantedX(), this.moveControl.getWantedY(), this.moveControl.getWantedZ());
|
|
if (cqn3 != null && cqn3.getIndex() < cqn3.getSize()) {
|
|
cvi4 = cqn3.currentPos(this);
|
|
}
|
|
this.facePoint(cvi4.x, cvi4.z);
|
|
this.startJumping();
|
|
}
|
|
}
|
|
else if (!d2.canJump()) {
|
|
this.enableJumpControl();
|
|
}
|
|
}
|
|
this.wasOnGround = this.onGround;
|
|
}
|
|
|
|
@Override
|
|
public void updateSprintingState() {
|
|
}
|
|
|
|
private void facePoint(final double double1, final double double2) {
|
|
this.yRot = (float)(Mth.atan2(double2 - this.getZ(), double1 - this.getX()) * 57.2957763671875) - 90.0f;
|
|
}
|
|
|
|
private void enableJumpControl() {
|
|
((RabbitJumpControl)this.jumpControl).setCanJump(true);
|
|
}
|
|
|
|
private void disableJumpControl() {
|
|
((RabbitJumpControl)this.jumpControl).setCanJump(false);
|
|
}
|
|
|
|
private void setLandingDelay() {
|
|
if (this.moveControl.getSpeedModifier() < 2.2) {
|
|
this.jumpDelayTicks = 10;
|
|
}
|
|
else {
|
|
this.jumpDelayTicks = 1;
|
|
}
|
|
}
|
|
|
|
private void checkLandingDelay() {
|
|
this.setLandingDelay();
|
|
this.disableJumpControl();
|
|
}
|
|
|
|
@Override
|
|
public void aiStep() {
|
|
super.aiStep();
|
|
if (this.jumpTicks != this.jumpDuration) {
|
|
++this.jumpTicks;
|
|
}
|
|
else if (this.jumpDuration != 0) {
|
|
this.jumpTicks = 0;
|
|
this.jumpDuration = 0;
|
|
this.setJumping(false);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected void registerAttributes() {
|
|
super.registerAttributes();
|
|
this.getAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(3.0);
|
|
this.getAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896);
|
|
}
|
|
|
|
@Override
|
|
public void addAdditionalSaveData(final CompoundTag jt) {
|
|
super.addAdditionalSaveData(jt);
|
|
jt.putInt("RabbitType", this.getRabbitType());
|
|
jt.putInt("MoreCarrotTicks", this.moreCarrotTicks);
|
|
}
|
|
|
|
@Override
|
|
public void readAdditionalSaveData(final CompoundTag jt) {
|
|
super.readAdditionalSaveData(jt);
|
|
this.setRabbitType(jt.getInt("RabbitType"));
|
|
this.moreCarrotTicks = jt.getInt("MoreCarrotTicks");
|
|
}
|
|
|
|
protected SoundEvent getJumpSound() {
|
|
return SoundEvents.RABBIT_JUMP;
|
|
}
|
|
|
|
@Override
|
|
protected SoundEvent getAmbientSound() {
|
|
return SoundEvents.RABBIT_AMBIENT;
|
|
}
|
|
|
|
@Override
|
|
protected SoundEvent getHurtSound(final DamageSource ajw) {
|
|
return SoundEvents.RABBIT_HURT;
|
|
}
|
|
|
|
@Override
|
|
protected SoundEvent getDeathSound() {
|
|
return SoundEvents.RABBIT_DEATH;
|
|
}
|
|
|
|
@Override
|
|
public boolean doHurtTarget(final Entity akn) {
|
|
if (this.getRabbitType() == 99) {
|
|
this.playSound(SoundEvents.RABBIT_ATTACK, 1.0f, (this.random.nextFloat() - this.random.nextFloat()) * 0.2f + 1.0f);
|
|
return akn.hurt(DamageSource.mobAttack(this), 8.0f);
|
|
}
|
|
return akn.hurt(DamageSource.mobAttack(this), 3.0f);
|
|
}
|
|
|
|
@Override
|
|
public SoundSource getSoundSource() {
|
|
return (this.getRabbitType() == 99) ? SoundSource.HOSTILE : SoundSource.NEUTRAL;
|
|
}
|
|
|
|
@Override
|
|
public boolean hurt(final DamageSource ajw, final float float2) {
|
|
return !this.isInvulnerableTo(ajw) && super.hurt(ajw, float2);
|
|
}
|
|
|
|
private boolean isTemptingItem(final Item bef) {
|
|
return bef == Items.CARROT || bef == Items.GOLDEN_CARROT || bef == Blocks.DANDELION.asItem();
|
|
}
|
|
|
|
@Override
|
|
public Rabbit getBreedOffspring(final AgableMob akl) {
|
|
final Rabbit atq3 = EntityType.RABBIT.create(this.level);
|
|
int integer4 = this.getRandomRabbitType(this.level);
|
|
if (this.random.nextInt(20) != 0) {
|
|
if (akl instanceof Rabbit && this.random.nextBoolean()) {
|
|
integer4 = ((Rabbit)akl).getRabbitType();
|
|
}
|
|
else {
|
|
integer4 = this.getRabbitType();
|
|
}
|
|
}
|
|
atq3.setRabbitType(integer4);
|
|
return atq3;
|
|
}
|
|
|
|
@Override
|
|
public boolean isFood(final ItemStack bek) {
|
|
return this.isTemptingItem(bek.getItem());
|
|
}
|
|
|
|
public int getRabbitType() {
|
|
return this.entityData.<Integer>get(Rabbit.DATA_TYPE_ID);
|
|
}
|
|
|
|
public void setRabbitType(final int integer) {
|
|
if (integer == 99) {
|
|
this.getAttribute(SharedMonsterAttributes.ARMOR).setBaseValue(8.0);
|
|
this.goalSelector.addGoal(4, new EvilRabbitAttackGoal(this));
|
|
this.targetSelector.addGoal(1, new HurtByTargetGoal(this, new Class[0]).setAlertOthers(new Class[0]));
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Player.class, true));
|
|
this.targetSelector.addGoal(2, new NearestAttackableTargetGoal<>(this, Wolf.class, true));
|
|
if (!this.hasCustomName()) {
|
|
this.setCustomName(new TranslatableComponent(Util.makeDescriptionId("entity", Rabbit.KILLER_BUNNY), new Object[0]));
|
|
}
|
|
}
|
|
this.entityData.<Integer>set(Rabbit.DATA_TYPE_ID, integer);
|
|
}
|
|
|
|
@Nullable
|
|
@Override
|
|
public SpawnGroupData finalizeSpawn(final LevelAccessor bju, final DifficultyInstance ajg, final MobSpawnType akz, @Nullable SpawnGroupData alj, @Nullable final CompoundTag jt) {
|
|
int integer7 = this.getRandomRabbitType(bju);
|
|
if (alj instanceof RabbitGroupData) {
|
|
integer7 = ((RabbitGroupData)alj).rabbitType;
|
|
}
|
|
else {
|
|
alj = new RabbitGroupData(integer7);
|
|
}
|
|
this.setRabbitType(integer7);
|
|
return super.finalizeSpawn(bju, ajg, akz, alj, jt);
|
|
}
|
|
|
|
private int getRandomRabbitType(final LevelAccessor bju) {
|
|
final Biome bkq3 = bju.getBiome(new BlockPos(this));
|
|
final int integer4 = this.random.nextInt(100);
|
|
if (bkq3.getPrecipitation() == Biome.Precipitation.SNOW) {
|
|
return (integer4 < 80) ? 1 : 3;
|
|
}
|
|
if (bkq3.getBiomeCategory() == Biome.BiomeCategory.DESERT) {
|
|
return 4;
|
|
}
|
|
return (integer4 < 50) ? 0 : ((integer4 < 90) ? 5 : 2);
|
|
}
|
|
|
|
public static boolean checkRabbitSpawnRules(final EntityType<Rabbit> akr, final LevelAccessor bju, final MobSpawnType akz, final BlockPos fk, final Random random) {
|
|
final Block bpe6 = bju.getBlockState(fk.below()).getBlock();
|
|
return (bpe6 == Blocks.GRASS_BLOCK || bpe6 == Blocks.SNOW || bpe6 == Blocks.SAND) && bju.getRawBrightness(fk, 0) > 8;
|
|
}
|
|
|
|
private boolean wantsMoreFood() {
|
|
return this.moreCarrotTicks == 0;
|
|
}
|
|
|
|
@Override
|
|
public void handleEntityEvent(final byte byte1) {
|
|
if (byte1 == 1) {
|
|
this.doSprintParticleEffect();
|
|
this.jumpDuration = 10;
|
|
this.jumpTicks = 0;
|
|
}
|
|
else {
|
|
super.handleEntityEvent(byte1);
|
|
}
|
|
}
|
|
|
|
static {
|
|
DATA_TYPE_ID = SynchedEntityData.<Integer>defineId(Rabbit.class, EntityDataSerializers.INT);
|
|
KILLER_BUNNY = new ResourceLocation("killer_bunny");
|
|
}
|
|
|
|
public static class RabbitGroupData extends AgableMobGroupData {
|
|
public final int rabbitType;
|
|
|
|
public RabbitGroupData(final int integer) {
|
|
this.rabbitType = integer;
|
|
this.setBabySpawnChance(1.0f);
|
|
}
|
|
}
|
|
|
|
public class RabbitJumpControl extends JumpControl {
|
|
private final Rabbit rabbit;
|
|
private boolean canJump;
|
|
|
|
public RabbitJumpControl(final Rabbit atq2) {
|
|
super(atq2);
|
|
this.rabbit = atq2;
|
|
}
|
|
|
|
public boolean wantJump() {
|
|
return this.jump;
|
|
}
|
|
|
|
public boolean canJump() {
|
|
return this.canJump;
|
|
}
|
|
|
|
public void setCanJump(final boolean boolean1) {
|
|
this.canJump = boolean1;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
if (this.jump) {
|
|
this.rabbit.startJumping();
|
|
this.jump = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
static class RabbitMoveControl extends MoveControl {
|
|
private final Rabbit rabbit;
|
|
private double nextJumpSpeed;
|
|
|
|
public RabbitMoveControl(final Rabbit atq) {
|
|
super(atq);
|
|
this.rabbit = atq;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
if (this.rabbit.onGround && !this.rabbit.jumping && !((RabbitJumpControl)this.rabbit.jumpControl).wantJump()) {
|
|
this.rabbit.setSpeedModifier(0.0);
|
|
}
|
|
else if (this.hasWanted()) {
|
|
this.rabbit.setSpeedModifier(this.nextJumpSpeed);
|
|
}
|
|
super.tick();
|
|
}
|
|
|
|
@Override
|
|
public void setWantedPosition(final double double1, final double double2, final double double3, double double4) {
|
|
if (this.rabbit.isInWater()) {
|
|
double4 = 1.5;
|
|
}
|
|
super.setWantedPosition(double1, double2, double3, double4);
|
|
if (double4 > 0.0) {
|
|
this.nextJumpSpeed = double4;
|
|
}
|
|
}
|
|
}
|
|
|
|
static class RabbitAvoidEntityGoal<T extends LivingEntity> extends AvoidEntityGoal<T> {
|
|
private final Rabbit rabbit;
|
|
|
|
public RabbitAvoidEntityGoal(final Rabbit atq, final Class<T> class2, final float float3, final double double4, final double double5) {
|
|
super(atq, class2, float3, double4, double5);
|
|
this.rabbit = atq;
|
|
}
|
|
|
|
@Override
|
|
public boolean canUse() {
|
|
return this.rabbit.getRabbitType() != 99 && super.canUse();
|
|
}
|
|
}
|
|
|
|
static class RaidGardenGoal extends MoveToBlockGoal {
|
|
private final Rabbit rabbit;
|
|
private boolean wantsToRaid;
|
|
private boolean canRaid;
|
|
|
|
public RaidGardenGoal(final Rabbit atq) {
|
|
super(atq, 0.699999988079071, 16);
|
|
this.rabbit = atq;
|
|
}
|
|
|
|
@Override
|
|
public boolean canUse() {
|
|
if (this.nextStartTick <= 0) {
|
|
if (!this.rabbit.level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING)) {
|
|
return false;
|
|
}
|
|
this.canRaid = false;
|
|
this.wantsToRaid = this.rabbit.wantsMoreFood();
|
|
this.wantsToRaid = true;
|
|
}
|
|
return super.canUse();
|
|
}
|
|
|
|
@Override
|
|
public boolean canContinueToUse() {
|
|
return this.canRaid && super.canContinueToUse();
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
this.rabbit.getLookControl().setLookAt(this.blockPos.getX() + 0.5, this.blockPos.getY() + 1, this.blockPos.getZ() + 0.5, 10.0f, (float)this.rabbit.getMaxHeadXRot());
|
|
if (this.isReachedTarget()) {
|
|
final Level bjt2 = this.rabbit.level;
|
|
final BlockPos fk3 = this.blockPos.above();
|
|
final BlockState byg4 = bjt2.getBlockState(fk3);
|
|
final Block bpe5 = byg4.getBlock();
|
|
if (this.canRaid && bpe5 instanceof CarrotBlock) {
|
|
final Integer integer6 = byg4.<Integer>getValue((Property<Integer>)CarrotBlock.AGE);
|
|
if (integer6 == 0) {
|
|
bjt2.setBlock(fk3, Blocks.AIR.defaultBlockState(), 2);
|
|
bjt2.destroyBlock(fk3, true, this.rabbit);
|
|
}
|
|
else {
|
|
bjt2.setBlock(fk3, ((AbstractStateHolder<O, BlockState>)byg4).<Comparable, Integer>setValue((Property<Comparable>)CarrotBlock.AGE, integer6 - 1), 2);
|
|
bjt2.levelEvent(2001, fk3, Block.getId(byg4));
|
|
}
|
|
this.rabbit.moreCarrotTicks = 40;
|
|
}
|
|
this.canRaid = false;
|
|
this.nextStartTick = 10;
|
|
}
|
|
}
|
|
|
|
@Override
|
|
protected boolean isValidTarget(final LevelReader bjw, BlockPos fk) {
|
|
Block bpe4 = bjw.getBlockState(fk).getBlock();
|
|
if (bpe4 == Blocks.FARMLAND && this.wantsToRaid && !this.canRaid) {
|
|
fk = fk.above();
|
|
final BlockState byg5 = bjw.getBlockState(fk);
|
|
bpe4 = byg5.getBlock();
|
|
if (bpe4 instanceof CarrotBlock && ((CarrotBlock)bpe4).isMaxAge(byg5)) {
|
|
return this.canRaid = true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static class RabbitPanicGoal extends PanicGoal {
|
|
private final Rabbit rabbit;
|
|
|
|
public RabbitPanicGoal(final Rabbit atq, final double double2) {
|
|
super(atq, double2);
|
|
this.rabbit = atq;
|
|
}
|
|
|
|
@Override
|
|
public void tick() {
|
|
super.tick();
|
|
this.rabbit.setSpeedModifier(this.speedModifier);
|
|
}
|
|
}
|
|
|
|
static class EvilRabbitAttackGoal extends MeleeAttackGoal {
|
|
public EvilRabbitAttackGoal(final Rabbit atq) {
|
|
super(atq, 1.4, true);
|
|
}
|
|
|
|
@Override
|
|
protected double getAttackReachSqr(final LivingEntity akw) {
|
|
return 4.0f + akw.getBbWidth();
|
|
}
|
|
}
|
|
}
|