tcr/common/src/main/java/common/entity/animal/EntityRabbit.java

581 lines
18 KiB
Java
Executable file

package common.entity.animal;
import java.util.function.Predicate;
import common.ai.EntityAIAttackOnCollide;
import common.ai.EntityAIAvoidEntity;
import common.ai.EntityAIHurtByTarget;
import common.ai.EntityAIMate;
import common.ai.EntityAIMoveToBlock;
import common.ai.EntityAINearestAttackableTarget;
import common.ai.EntityAIPanic;
import common.ai.EntityAISwimming;
import common.ai.EntityAITempt;
import common.ai.EntityAIWander;
import common.ai.EntityAIWatchClosest;
import common.ai.EntityJumpHelper;
import common.ai.EntityMoveHelper;
import common.attributes.Attribute;
import common.block.Block;
import common.block.foliage.BlockTallGrass;
import common.entity.DamageSource;
import common.entity.Entity;
import common.entity.npc.Alignment;
import common.entity.npc.EntityNPC;
import common.entity.types.EntityAnimal;
import common.entity.types.EntityLiving;
import common.init.BlockRegistry;
import common.init.Blocks;
import common.init.ItemRegistry;
import common.init.Items;
import common.init.SoundEvent;
import common.item.Item;
import common.item.ItemStack;
import common.model.ParticleType;
import common.pathfinding.PathEntity;
import common.pathfinding.PathNavigateGround;
import common.potion.Potion;
import common.potion.PotionEffect;
import common.tags.TagObject;
import common.util.BlockPos;
import common.util.ExtMath;
import common.util.Vec3;
import common.vars.Vars;
import common.world.State;
import common.world.World;
public class EntityRabbit extends EntityAnimal {
private static final int TYPES = 10;
private EntityRabbit.AIAvoidEntity<EntityWolf> aiAvoidWolves;
private int jumpRotTimer = 0;
private int jumpRotFactor = 0;
private boolean jumped = false;
private boolean attacking = false;
private int moveDuration = 0;
private EntityRabbit.EnumMoveType moveType = EntityRabbit.EnumMoveType.HOP;
private int foodCooldown = 0;
public EntityRabbit(World world) {
super(world);
this.setSize(0.6F, 0.7F);
this.jumpHelper = new EntityRabbit.RabbitJumpHelper(this);
this.moveHelper = new EntityRabbit.RabbitMoveHelper(this);
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
this.navigator.setHeightRequirement(2.5F);
this.tasks.addTask(1, new EntityAISwimming(this));
this.tasks.addTask(1, new EntityRabbit.AIPanic(this, 1.33D));
this.tasks.addTask(2, new EntityAITempt(this, 1.0D, Items.carrot, false));
this.tasks.addTask(2, new EntityAITempt(this, 1.0D, Items.golden_carrot, false));
this.tasks.addTask(2, new EntityAITempt(this, 1.0D, ItemRegistry.getItemFromBlock(Blocks.flower), false));
this.tasks.addTask(3, new EntityAIMate(this, 0.8D) {
protected int getMatingCooldown() {
return EntityRabbit.this.rand.excl(50, 200);
}
});
this.tasks.addTask(4, new EntityRabbit.AIRaidFarm(this));
this.tasks.addTask(5, new EntityAIWander(this, 0.6D));
this.tasks.addTask(11, new EntityAIWatchClosest(this, null, 10.0F));
this.aiAvoidWolves = new EntityRabbit.AIAvoidEntity(this, EntityWolf.class, 16.0F, 1.33D, 1.33D);
this.tasks.addTask(4, this.aiAvoidWolves);
this.setMovementSpeed(0.0D);
}
protected float getJumpUpwardsMotion() {
return this.moveHelper.isUpdating() && this.moveHelper.getY() > this.posY + 0.5D ? 0.5F : this.moveType.getUpwardsMotion();
}
public void setMoveType(EntityRabbit.EnumMoveType type) {
this.moveType = type;
}
public float getJumpRotation(float delta) {
return this.jumpRotFactor == 0 ? 0.0F : ((float)this.jumpRotTimer + delta) / (float)this.jumpRotFactor;
}
public void setMovementSpeed(double newSpeed) {
this.getNavigator().setSpeed(newSpeed);
this.moveHelper.setMoveTo(this.moveHelper.getX(), this.moveHelper.getY(), this.moveHelper.getZ(), newSpeed);
}
public void setJumping(boolean jump, EntityRabbit.EnumMoveType moveTypeIn) {
super.setJumping(jump);
if(!jump) {
if(this.moveType == EntityRabbit.EnumMoveType.ATTACK)
this.moveType = EntityRabbit.EnumMoveType.HOP;
}
else {
this.setMovementSpeed(1.5D * (double)moveTypeIn.getSpeed());
this.playSound(SoundEvent.RABBIT_JUMP, this.getSoundVolume());
}
this.jumped = jump;
}
public void doMovementAction(EntityRabbit.EnumMoveType movetype) {
this.setJumping(true, movetype);
this.jumpRotFactor = movetype.getRotationFactor();
this.jumpRotTimer = 0;
}
public boolean hasJumped() {
return this.jumped;
}
protected void entityInit() {
super.entityInit();
this.dataWatcher.addObject(18, Byte.valueOf((byte)0));
}
public void updateAITasks() {
if(this.moveHelper.getSpeed() > 0.8D)
this.setMoveType(EntityRabbit.EnumMoveType.SPRINT);
else if(this.moveType != EntityRabbit.EnumMoveType.ATTACK)
this.setMoveType(EntityRabbit.EnumMoveType.HOP);
if(this.moveDuration > 0)
--this.moveDuration;
if(this.foodCooldown > 0) {
this.foodCooldown -= this.rand.zrange(3);
if(this.foodCooldown < 0)
this.foodCooldown = 0;
}
if(this.onGround) {
if(!this.attacking) {
this.setJumping(false, EntityRabbit.EnumMoveType.NONE);
this.moveDuration = this.getMoveTypeDuration();
((EntityRabbit.RabbitJumpHelper)this.jumpHelper).setWasJumping(false);
}
if(this.getRabbitType() == 99 && this.moveDuration == 0) {
EntityLiving target = this.getAttackTarget();
if(target != null && this.getDistanceSqToEntity(target) < 16.0D) {
this.calculateRotationYaw(target.posX, target.posZ);
this.moveHelper.setMoveTo(target.posX, target.posY, target.posZ, this.moveHelper.getSpeed());
this.doMovementAction(EntityRabbit.EnumMoveType.ATTACK);
this.attacking = true;
}
}
EntityRabbit.RabbitJumpHelper jumpHelper = (EntityRabbit.RabbitJumpHelper)this.jumpHelper;
if(!jumpHelper.getIsJumping()) {
if(this.moveHelper.isUpdating() && this.moveDuration == 0) {
PathEntity pathentity = this.navigator.getPath();
Vec3 vec3 = new Vec3(this.moveHelper.getX(), this.moveHelper.getY(), this.moveHelper.getZ());
if(pathentity != null && pathentity.getCurrentPathIndex() < pathentity.getCurrentPathLength()) {
vec3 = pathentity.getPosition(this);
}
this.calculateRotationYaw(vec3.xCoord, vec3.zCoord);
this.doMovementAction(this.moveType);
}
}
else if(!jumpHelper.getWasJumping()) {
((EntityRabbit.RabbitJumpHelper)this.jumpHelper).setWasJumping(true);
}
}
this.attacking = this.onGround;
}
public void spawnRunningParticles() {
}
private void calculateRotationYaw(double x, double z) {
this.rotYaw = (float)(ExtMath.atan2(z - this.posZ, x - this.posX) * 180.0D / Math.PI) - 90.0F;
}
public void onLivingUpdate() {
super.onLivingUpdate();
if(this.jumpRotTimer != this.jumpRotFactor) {
if(this.jumpRotTimer == 0 && !this.worldObj.client)
this.worldObj.setEntityState(this, (byte)1);
++this.jumpRotTimer;
}
else if(this.jumpRotFactor != 0) {
this.jumpRotTimer = 0;
this.jumpRotFactor = 0;
}
}
protected void applyEntityAttributes() {
super.applyEntityAttributes();
this.setMaxHealth(5);
this.getEntityAttribute(Attribute.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
}
public void writeEntity(TagObject tagCompound) {
super.writeEntity(tagCompound);
tagCompound.setInt("RabbitType", this.getRabbitType());
tagCompound.setInt("MoreCarrotTicks", this.foodCooldown);
}
public void readEntity(TagObject tagCompund) {
super.readEntity(tagCompund);
this.setRabbitType(tagCompund.getInt("RabbitType"));
this.foodCooldown = tagCompund.getInt("MoreCarrotTicks");
}
// protected String getJumpingSound() {
// return "mob.rabbit.hop";
// }
protected SoundEvent getLivingSound() {
return SoundEvent.RABBIT_IDLE;
}
protected SoundEvent getHurtSound() {
return SoundEvent.RABBIT_HIT;
}
protected SoundEvent getDeathSound() {
return SoundEvent.RABBIT_DEATH;
}
public boolean attackEntityAsMob(Entity entityIn) {
if(!this.worldObj.client && !Vars.damageMobs)
return false;
if(this.getRabbitType() == 99) {
// this.playSound("mob.attack", 1.0F, (this.rand.floatv() - this.rand.floatv()) * 0.2F + 1.0F);
return entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), 8);
}
else {
return entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), 3);
}
}
public int getTotalArmorValue() {
return this.getRabbitType() == 99 ? 8 : super.getTotalArmorValue();
}
// public boolean attackEntityFrom(DamageSource source, int amount) {
// return this.isEntityInvulnerable(source) ? false : super.attackEntityFrom(source, amount);
// }
// protected void addRandomDrop() {
// this.entityDropItem(new ItemStack(Items.rabbit_foot, 1), 0.0F);
// }
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier) {
int amt = this.rand.zrange(2) + this.rand.zrange(1 + lootingModifier);
for(int j = 0; j < amt; ++j) {
this.dropItem(Items.carrot, 1);
}
// amt = this.rand.zrange(2);
// for(int k = 0; k < amt; ++k) {
// if(this.isBurning())
// this.dropItem(Items.cooked_rabbit, 1);
// else
// this.dropItem(Items.rabbit, 1);
// }
}
private boolean isRabbitBreedingItem(Item itemIn) {
return itemIn == Items.carrot || itemIn == Items.golden_carrot || itemIn == ItemRegistry.getItemFromBlock(Blocks.flower);
}
public EntityRabbit createChild(EntityLiving ageable) {
EntityRabbit rabbit = new EntityRabbit(this.worldObj);
if(ageable instanceof EntityRabbit)
rabbit.setRabbitType(this.rand.chance() ? this.getRabbitType() : ((EntityRabbit)ageable).getRabbitType());
return rabbit;
}
public boolean isBreedingItem(ItemStack stack) {
return stack != null && this.isRabbitBreedingItem(stack.getItem());
}
public int getRabbitType() {
return this.dataWatcher.getWatchableObjectByte(18);
}
public void setRabbitType(int type) {
if(type == 99) {
this.tasks.removeTask(this.aiAvoidWolves);
this.tasks.addTask(4, new EntityRabbit.AIEvilAttack(this));
this.targets.addTask(1, new EntityAIHurtByTarget(this, false));
this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityNPC.class, true));
this.targets.addTask(2, new EntityAINearestAttackableTarget(this, EntityWolf.class, true));
// if(!this.hasCustomName())
// this.setCustomNameTag(I18n.formatKey("entity.KillerBunny.name"));
}
this.dataWatcher.updateObject(18, Byte.valueOf((byte)type));
}
public String getTypeName() {
return !this.hasCustomName() && this.getRabbitType() == 99 ? "Killer-Kaninchen" : super.getTypeName();
}
public Object onInitialSpawn(Object livingdata) {
livingdata = super.onInitialSpawn(livingdata);
int type = Vars.killerBunnyChance > 0 && this.rand.chance(Vars.killerBunnyChance) ? 99 : this.rand.zrange(TYPES);
boolean typeSet = false;
if(livingdata instanceof EntityRabbit.RabbitTypeData) {
type = ((EntityRabbit.RabbitTypeData)livingdata).typeData;
typeSet = true;
}
else {
livingdata = new EntityRabbit.RabbitTypeData(type);
}
this.setRabbitType(type);
if(type == 99) {
this.setMaxHealth(15);
this.setHealth(this.getMaxHealth());
}
if(typeSet && this.rand.chance())
this.setGrowingAge(-24000);
return livingdata;
}
private boolean canEatMore() {
return this.foodCooldown == 0;
}
protected int getMoveTypeDuration() {
return this.moveType.getDuration();
}
protected void consumeBlock(BlockPos pos, State state) {
this.worldObj.setEntityState(this, (byte)19);
this.foodCooldown = this.rand.excl(10, this.isChild() ? 20 : 50);
if(this.isChild())
this.grow(this.rand.range(250, 350));
if(Vars.rabbitMateChance > 0 && this.rand.chance(Vars.rabbitMateChance) && this.getGrowingAge() == 0 && !this.isInLove() &&
!this.worldObj.getEntitiesWithinAABB(EntityRabbit.class, this.getEntityBoundingBox().expand(15.0f, 15.0f, 15.0f), new Predicate<EntityRabbit>() {
public boolean test(EntityRabbit entity) {
return entity != EntityRabbit.this && entity.getGrowingAge() == 0;
}
}).isEmpty())
this.setInLove(null);
if(state.getBlock() == Blocks.blue_mushroom)
this.addEffect(new PotionEffect(Potion.SPEED, this.rand.range(400, 2600), this.rand.chance(0, 1, 5)));
this.worldObj.destroyBlock(pos, false);
this.worldObj.setState(pos, Blocks.air.getState(), 2);
}
public void handleStatusUpdate(byte id) {
if(id == 1) {
this.createRunningParticles();
this.jumpRotFactor = 10;
this.jumpRotTimer = 0;
}
else if(id == 19) {
this.worldObj.spawnParticle(ParticleType.BLOCK_DUST,
this.posX + (double)(this.rand.floatv() * this.width * 2.0F) - (double)this.width,
this.posY + 0.5D + (double)(this.rand.floatv() * this.height),
this.posZ + (double)(this.rand.floatv() * this.width * 2.0F) - (double)this.width, 0.0D, 0.0D, 0.0D,
BlockRegistry.getStateId(this.worldObj.getState(this.getPosition())));
}
else {
super.handleStatusUpdate(id);
}
}
public int getColor() {
return 0xd4d499;
}
public Alignment getAlignment() {
return this.getRabbitType() == 99 ? Alignment.CHAOTIC_EVIL : super.getAlignment();
}
static class AIAvoidEntity<T extends Entity> extends EntityAIAvoidEntity<T> {
private EntityRabbit entity;
public AIAvoidEntity(EntityRabbit rabbit, Class<T> toAvoid, float distance, double farSpeed, double nearSpeed) {
super(rabbit, toAvoid, distance, farSpeed, nearSpeed);
this.entity = rabbit;
}
// public void updateTask() {
// super.updateTask();
// }
}
static class AIEvilAttack extends EntityAIAttackOnCollide {
public AIEvilAttack(EntityRabbit rabbit) {
super(rabbit, EntityLiving.class, 1.4D, true);
}
protected double getAttackRange(EntityLiving attackTarget) {
return (double)(4.0F + attackTarget.width);
}
}
static class AIPanic extends EntityAIPanic {
private EntityRabbit entity;
public AIPanic(EntityRabbit rabbit, double speedIn) {
super(rabbit, speedIn);
this.entity = rabbit;
}
public void updateTask() {
super.updateTask();
this.entity.setMovementSpeed(this.speed);
}
}
static class AIRaidFarm extends EntityAIMoveToBlock {
private final EntityRabbit entity;
private boolean isHungry;
private boolean foodFound = false;
public AIRaidFarm(EntityRabbit rabbitIn) {
super(rabbitIn, 0.699999988079071D, 16);
this.entity = rabbitIn;
this.runDelay = this.entity.getRNG().excl(10, 40);
}
public boolean shouldExecute() {
if(this.runDelay <= 0) {
if(!Vars.mobGrief)
return false;
this.foodFound = false;
this.isHungry = this.entity.canEatMore();
}
if(this.runDelay > 0) {
--this.runDelay;
return false;
}
else {
this.runDelay = this.entity.getRNG().excl(10, 40);
return this.searchForDestination();
}
}
public boolean continueExecuting() {
return this.foodFound && super.continueExecuting();
}
public void startExecuting() {
super.startExecuting();
}
public void resetTask() {
super.resetTask();
}
public void updateTask() {
super.updateTask();
this.entity.getLookHelper().setLookPosition((double)this.destinationBlock.getX() + 0.5D, (double)(this.destinationBlock.getY() + 1),
(double)this.destinationBlock.getZ() + 0.5D, 10.0F, (float)this.entity.getVerticalFaceSpeed());
if(this.getIsAboveDestination()) {
World world = this.entity.worldObj;
BlockPos pos = Vars.rabidRabbits ? this.destinationBlock : this.destinationBlock.up();
State state = world.getState(pos);
// Block block = iblockstate.getBlock();
if(this.foodFound && canEat(state) && Vars.mobGrief) // block instanceof BlockCarrot && ((Integer)iblockstate.getValue(BlockCarrot.AGE)).intValue() == 7) {
this.entity.consumeBlock(pos, state);
this.foodFound = false;
this.runDelay = 10;
}
}
protected boolean shouldMoveTo(World worldIn, BlockPos pos) {
// Block block = worldIn.getBlockState(pos).getBlock();
// if(block == Blocks.farmland) {
pos = pos.up();
State state = worldIn.getState(pos);
// block = state.getBlock();
if(/* block instanceof BlockCarrot && ((Integer)state.getValue(BlockCarrot.AGE)).intValue() == 7
*/ canEat(state) && this.isHungry && !this.foodFound) {
this.foodFound = true;
return true;
}
// }
return false;
}
private static boolean canEat(State state) {
Block block = state.getBlock();
if(Vars.rabidRabbits)
return block != Blocks.bedrock;
return block == Blocks.carrot || block == Blocks.potato || block == Blocks.wheat || block == Blocks.brown_mushroom ||
block == Blocks.flower || block == Blocks.blue_mushroom ||
(block == Blocks.tallgrass && state.getValue(BlockTallGrass.TYPE) == BlockTallGrass.EnumType.GRASS);
}
}
static enum EnumMoveType {
NONE(0.0F, 0.0F, 30, 1),
HOP(0.8F, 0.2F, 20, 10),
STEP(1.0F, 0.45F, 14, 14),
SPRINT(1.75F, 0.4F, 1, 8),
ATTACK(2.0F, 0.7F, 7, 8);
private final float speed;
private final float upMotion;
private final int duration;
private final int rotFactor;
private EnumMoveType(float typeSpeed, float upwardsMotion, int typeDuration, int rotationFactor) {
this.speed = typeSpeed;
this.upMotion = upwardsMotion;
this.duration = typeDuration;
this.rotFactor = rotationFactor;
}
public float getSpeed() {
return this.speed;
}
public float getUpwardsMotion() {
return this.upMotion;
}
public int getDuration() {
return this.duration;
}
public int getRotationFactor() {
return this.rotFactor;
}
}
public class RabbitJumpHelper extends EntityJumpHelper {
private EntityRabbit entity;
private boolean wasJumping = false;
public RabbitJumpHelper(EntityRabbit rabbit) {
super(rabbit);
this.entity = rabbit;
}
public boolean getIsJumping() {
return this.isJumping;
}
public boolean getWasJumping() {
return this.wasJumping;
}
public void setWasJumping(boolean jumped) {
this.wasJumping = jumped;
}
public void doJump() {
if(this.isJumping) {
this.entity.doMovementAction(EntityRabbit.EnumMoveType.STEP);
this.isJumping = false;
}
}
}
static class RabbitMoveHelper extends EntityMoveHelper {
private EntityRabbit entity;
public RabbitMoveHelper(EntityRabbit rabbit) {
super(rabbit);
this.entity = rabbit;
}
public void onUpdateMoveHelper() {
if(this.entity.onGround && !this.entity.hasJumped())
this.entity.setMovementSpeed(0.0D);
super.onUpdateMoveHelper();
}
}
public static class RabbitTypeData {
public int typeData;
public RabbitTypeData(int type) {
this.typeData = type;
}
}
}