initial commit
This commit is contained in:
parent
3c9ee26b06
commit
22186c33b9
1458 changed files with 282792 additions and 0 deletions
324
java/src/game/entity/animal/EntityBat.java
Executable file
324
java/src/game/entity/animal/EntityBat.java
Executable file
|
@ -0,0 +1,324 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.block.Block;
|
||||
import game.entity.DamageSource;
|
||||
import game.entity.Entity;
|
||||
import game.entity.npc.Alignment;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.SoundEvent;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.world.BlockPos;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityBat extends EntityLiving
|
||||
{
|
||||
/** Coordinates of where the bat spawned. */
|
||||
private BlockPos spawnPosition;
|
||||
|
||||
public EntityBat(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.5F, 0.9F);
|
||||
this.setIsBatHanging(true);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(16, (byte)0);
|
||||
}
|
||||
|
||||
public boolean allowLeashing()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the volume for the sounds this mob makes.
|
||||
*/
|
||||
protected float getSoundVolume()
|
||||
{
|
||||
return 0.1F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the pitch of living sounds in living entities.
|
||||
*/
|
||||
protected float getSoundPitch()
|
||||
{
|
||||
return super.getSoundPitch() * 0.95F;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return this.getIsBatHanging() && this.rand.rarity(4) ? null : SoundEvent.BAT_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.BAT_HIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.BAT_DEATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this entity should push and be pushed by other entities when colliding.
|
||||
*/
|
||||
public boolean canBePushed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
protected void collideWithEntity(Entity entityIn)
|
||||
{
|
||||
}
|
||||
|
||||
protected void collideWithNearbyEntities()
|
||||
{
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(6);
|
||||
}
|
||||
|
||||
public boolean getIsBatHanging()
|
||||
{
|
||||
return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
|
||||
}
|
||||
|
||||
public void setIsBatHanging(boolean isHanging)
|
||||
{
|
||||
byte b0 = this.dataWatcher.getWatchableObjectByte(16);
|
||||
|
||||
if (isHanging)
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 1)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -2)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
|
||||
if (this.getIsBatHanging())
|
||||
{
|
||||
this.motionX = this.motionY = this.motionZ = 0.0D;
|
||||
this.posY = (double)ExtMath.floord(this.posY) + 1.0D - (double)this.height;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.motionY *= 0.6000000238418579D;
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateAITasks()
|
||||
{
|
||||
super.updateAITasks();
|
||||
BlockPos blockpos = new BlockPos(this);
|
||||
BlockPos blockpos1 = blockpos.up();
|
||||
|
||||
if (this.getIsBatHanging())
|
||||
{
|
||||
if (!this.worldObj.getState(blockpos1).getBlock().isNormalCube())
|
||||
{
|
||||
this.setIsBatHanging(false);
|
||||
this.worldObj.playAuxSFX(1015, blockpos, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.rand.chance(200))
|
||||
{
|
||||
this.headYaw = (float)this.rand.zrange(360);
|
||||
}
|
||||
|
||||
if (this.worldObj.getClosestPlayerToEntity(this, 4.0D) != null)
|
||||
{
|
||||
this.setIsBatHanging(false);
|
||||
this.worldObj.playAuxSFX(1015, blockpos, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.spawnPosition != null && (!this.worldObj.isAirBlock(this.spawnPosition) || this.spawnPosition.getY() < 1))
|
||||
{
|
||||
this.spawnPosition = null;
|
||||
}
|
||||
|
||||
if (this.spawnPosition == null || this.rand.chance(30) || this.spawnPosition.distanceSq((double)((int)this.posX), (double)((int)this.posY), (double)((int)this.posZ)) < 4.0D)
|
||||
{
|
||||
this.spawnPosition = new BlockPos((int)this.posX + this.rand.zrange(7) - this.rand.zrange(7), (int)this.posY + this.rand.range(-2, 3), (int)this.posZ + this.rand.zrange(7) - this.rand.zrange(7));
|
||||
}
|
||||
|
||||
double d0 = (double)this.spawnPosition.getX() + 0.5D - this.posX;
|
||||
double d1 = (double)this.spawnPosition.getY() + 0.1D - this.posY;
|
||||
double d2 = (double)this.spawnPosition.getZ() + 0.5D - this.posZ;
|
||||
this.motionX += (Math.signum(d0) * 0.5D - this.motionX) * 0.10000000149011612D;
|
||||
this.motionY += (Math.signum(d1) * 0.699999988079071D - this.motionY) * 0.10000000149011612D;
|
||||
this.motionZ += (Math.signum(d2) * 0.5D - this.motionZ) * 0.10000000149011612D;
|
||||
float f = (float)(ExtMath.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) - 90.0F;
|
||||
float f1 = ExtMath.wrapf(f - this.rotYaw);
|
||||
this.moveForward = 0.5F;
|
||||
this.rotYaw += f1;
|
||||
|
||||
if (this.rand.chance(100) && this.worldObj.getState(blockpos1).getBlock().isNormalCube())
|
||||
{
|
||||
this.setIsBatHanging(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
|
||||
* prevent them from trampling crops
|
||||
*/
|
||||
protected boolean canTriggerWalking()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void fall(float distance, float damageMultiplier)
|
||||
{
|
||||
}
|
||||
|
||||
protected void updateFallState(double y, boolean onGroundIn, Block blockIn, BlockPos pos)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether this entity should NOT trigger a pressure plate or a tripwire.
|
||||
*/
|
||||
public boolean doesEntityNotTriggerPressurePlate()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, int amount)
|
||||
{
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.worldObj.client && this.getIsBatHanging())
|
||||
{
|
||||
this.setIsBatHanging(false);
|
||||
}
|
||||
|
||||
return super.attackEntityFrom(source, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf(tagCompund.getByte("BatFlags")));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setByte("BatFlags", this.dataWatcher.getWatchableObjectByte(16));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity's current position is a valid location to spawn this entity.
|
||||
*/
|
||||
public boolean getCanSpawnHere()
|
||||
{
|
||||
BlockPos blockpos = new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ);
|
||||
|
||||
if (blockpos.getY() >= this.worldObj.getSeaLevel())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
int i = this.worldObj.getLightFromNeighbors(blockpos);
|
||||
int j = 4;
|
||||
|
||||
// if (Config.useHalloween && isDateAroundHalloween(World.getCurrentDate()))
|
||||
// {
|
||||
// j = 7;
|
||||
// }
|
||||
// else
|
||||
if (this.rand.chance())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return i <= this.rand.zrange(j); // ? false : super.getCanSpawnHere();
|
||||
}
|
||||
}
|
||||
|
||||
// private static boolean isDateAroundHalloween(Calendar calendar)
|
||||
// {
|
||||
// return calendar.get(2) + 1 == 10 && calendar.get(5) >= 20 || calendar.get(2) + 1 == 11 && calendar.get(5) <= 3;
|
||||
// }
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return this.height / 2.0F;
|
||||
}
|
||||
|
||||
public int getTrackingRange() {
|
||||
return 80;
|
||||
}
|
||||
|
||||
public int getUpdateFrequency() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
public boolean isSendingVeloUpdates() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0x5c5c8a;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return Alignment.NEUTRAL;
|
||||
}
|
||||
}
|
249
java/src/game/entity/animal/EntityChicken.java
Executable file
249
java/src/game/entity/animal/EntityChicken.java
Executable file
|
@ -0,0 +1,249 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.ai.EntityAIFollowParent;
|
||||
import game.ai.EntityAILookIdle;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIPanic;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.Config;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityChicken extends EntityAnimal
|
||||
{
|
||||
public float wingRotation;
|
||||
public float destPos;
|
||||
public float field_70884_g;
|
||||
public float field_70888_h;
|
||||
public float wingRotDelta = 1.0F;
|
||||
|
||||
/** The time until the next egg is spawned. */
|
||||
public int timeUntilNextEgg;
|
||||
public boolean chickenJockey;
|
||||
|
||||
public EntityChicken(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.4F, 0.7F);
|
||||
this.timeUntilNextEgg = worldIn.client || Config.eggTimer <= 0 ? 1000 : this.rand.excl(Config.eggTimer, Config.eggTimer * 2);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 1.4D));
|
||||
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(3, new EntityAITempt(this, 1.0D, Items.wheat, false));
|
||||
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
|
||||
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(7, new EntityAILookIdle(this));
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return this.height;
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(4);
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.25D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
|
||||
* use this to react to sunlight and start to burn.
|
||||
*/
|
||||
public void onLivingUpdate()
|
||||
{
|
||||
super.onLivingUpdate();
|
||||
this.field_70888_h = this.wingRotation;
|
||||
this.field_70884_g = this.destPos;
|
||||
this.destPos = (float)((double)this.destPos + (double)(this.onGround ? -1 : 4) * 0.3D);
|
||||
this.destPos = ExtMath.clampf(this.destPos, 0.0F, 1.0F);
|
||||
|
||||
if (!this.onGround && this.wingRotDelta < 1.0F)
|
||||
{
|
||||
this.wingRotDelta = 1.0F;
|
||||
}
|
||||
|
||||
this.wingRotDelta = (float)((double)this.wingRotDelta * 0.9D);
|
||||
|
||||
if (!this.onGround && this.motionY < 0.0D)
|
||||
{
|
||||
this.motionY *= 0.6D;
|
||||
}
|
||||
|
||||
this.wingRotation += this.wingRotDelta * 2.0F;
|
||||
|
||||
if (!this.worldObj.client && Config.eggTimer > 0 && !this.isChild() && !this.isChickenJockey() && --this.timeUntilNextEgg <= 0)
|
||||
{
|
||||
this.playSound(SoundEvent.PLOP, 1.0F, (this.rand.floatv() - this.rand.floatv()) * 0.2F + 1.0F);
|
||||
this.dropItem(Items.egg, 1);
|
||||
this.timeUntilNextEgg = this.rand.excl(Config.eggTimer, Config.eggTimer * 2);
|
||||
}
|
||||
}
|
||||
|
||||
public void fall(float distance, float damageMultiplier)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return SoundEvent.CHICKEN_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.CHICKEN_HIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.CHICKEN_HIT;
|
||||
}
|
||||
|
||||
// protected void playStepSound(BlockPos pos, Block blockIn)
|
||||
// {
|
||||
// this.playSound("mob.chicken.step", 0.15F, 1.0F);
|
||||
// }
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return Items.feather;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
int i = this.rand.zrange(3) + this.rand.zrange(1 + lootingModifier);
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
this.dropItem(Items.feather, 1);
|
||||
}
|
||||
|
||||
if (this.isBurning())
|
||||
{
|
||||
this.dropItem(Items.cooked_chicken, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dropItem(Items.chicken, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityChicken createChild(EntityLiving ageable)
|
||||
{
|
||||
return new EntityChicken(this.worldObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
|
||||
* the animal type)
|
||||
*/
|
||||
public boolean isBreedingItem(ItemStack stack)
|
||||
{
|
||||
return stack != null && stack.getItem() == Items.wheat;
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.chickenJockey = tagCompund.getBoolean("IsChickenJockey");
|
||||
|
||||
if (tagCompund.hasKey("EggLayTime"))
|
||||
{
|
||||
this.timeUntilNextEgg = tagCompund.getInteger("EggLayTime");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the experience points the entity currently has.
|
||||
*/
|
||||
protected int getExperiencePoints(EntityNPC player)
|
||||
{
|
||||
return this.isChickenJockey() ? 10 : super.getExperiencePoints(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setBoolean("IsChickenJockey", this.chickenJockey);
|
||||
tagCompound.setInteger("EggLayTime", this.timeUntilNextEgg);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Determines if an entity can be despawned, used on idle far away entities
|
||||
// */
|
||||
// protected boolean canDespawn()
|
||||
// {
|
||||
// return this.isChickenJockey() && this.passenger == null;
|
||||
// }
|
||||
|
||||
public void updateRiderPosition()
|
||||
{
|
||||
super.updateRiderPosition();
|
||||
float f = ExtMath.sin(this.yawOffset * (float)Math.PI / 180.0F);
|
||||
float f1 = ExtMath.cos(this.yawOffset * (float)Math.PI / 180.0F);
|
||||
float f2 = 0.1F;
|
||||
float f3 = 0.0F;
|
||||
this.passenger.setPosition(this.posX + (double)(f2 * f), this.posY + (double)(this.height * 0.5F) + this.passenger.getYOffset() + (double)f3, this.posZ - (double)(f2 * f1));
|
||||
|
||||
if (this.passenger instanceof EntityLiving)
|
||||
{
|
||||
((EntityLiving)this.passenger).yawOffset = this.yawOffset;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if this chicken is a jokey with a zombie riding it.
|
||||
*/
|
||||
public boolean isChickenJockey()
|
||||
{
|
||||
return this.chickenJockey;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this chicken is a jockey or not.
|
||||
*/
|
||||
public void setChickenJockey(boolean jockey)
|
||||
{
|
||||
this.chickenJockey = jockey;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0xdb5152;
|
||||
}
|
||||
}
|
158
java/src/game/entity/animal/EntityCow.java
Executable file
158
java/src/game/entity/animal/EntityCow.java
Executable file
|
@ -0,0 +1,158 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.ai.EntityAIFollowParent;
|
||||
import game.ai.EntityAILookIdle;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIPanic;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemStack;
|
||||
import game.pathfinding.PathNavigateGround;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityCow extends EntityAnimal
|
||||
{
|
||||
public EntityCow(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.9F, 1.3F);
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 2.0D));
|
||||
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(3, new EntityAITempt(this, 1.25D, Items.wheats, false));
|
||||
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.25D));
|
||||
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(7, new EntityAILookIdle(this));
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(10);
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.20000000298023224D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return SoundEvent.COW_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.COW_HIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.COW_HIT;
|
||||
}
|
||||
|
||||
// protected void playStepSound(BlockPos pos, Block blockIn)
|
||||
// {
|
||||
// this.playSound("mob.cow.step", 0.15F, 1.0F);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns the volume for the sounds this mob makes.
|
||||
*/
|
||||
protected float getSoundVolume()
|
||||
{
|
||||
return 0.4F;
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return Items.leather;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
int i = this.rand.zrange(3) + this.rand.zrange(1 + lootingModifier);
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
this.dropItem(Items.leather, 1);
|
||||
}
|
||||
|
||||
i = this.rand.roll(3) + this.rand.zrange(1 + lootingModifier);
|
||||
|
||||
for (int k = 0; k < i; ++k)
|
||||
{
|
||||
if (this.isBurning())
|
||||
{
|
||||
this.dropItem(Items.cooked_beef, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dropItem(Items.beef, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
ItemStack itemstack = player.inventory.getCurrentItem();
|
||||
|
||||
if (itemstack != null && itemstack.getItem() == Items.bucket /* && !player.creative */ && !this.isChild())
|
||||
{
|
||||
if (itemstack.stackSize-- == 1)
|
||||
{
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, new ItemStack(Items.milk_bucket));
|
||||
}
|
||||
else if (!player.inventory.addItemStackToInventory(new ItemStack(Items.milk_bucket)))
|
||||
{
|
||||
player.dropPlayerItemWithRandomChoice(new ItemStack(Items.milk_bucket, 1, 0), false);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.interact(player);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityCow createChild(EntityLiving ageable)
|
||||
{
|
||||
return new EntityCow(this.worldObj);
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return this.height;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0x8f4f21;
|
||||
}
|
||||
}
|
619
java/src/game/entity/animal/EntityDragon.java
Executable file
619
java/src/game/entity/animal/EntityDragon.java
Executable file
|
@ -0,0 +1,619 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.collect.Lists;
|
||||
import game.entity.DamageSource;
|
||||
import game.entity.Entity;
|
||||
import game.entity.npc.Alignment;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.entity.types.IEntityMultiPart;
|
||||
import game.init.Config;
|
||||
import game.init.SoundEvent;
|
||||
import game.renderer.particle.ParticleType;
|
||||
import game.world.Vec3;
|
||||
import game.world.World;
|
||||
import game.world.WorldClient;
|
||||
|
||||
public class EntityDragon extends EntityLiving implements IEntityMultiPart
|
||||
{
|
||||
public double targetX;
|
||||
public double targetY;
|
||||
public double targetZ;
|
||||
public double[][] ringBuffer = new double[64][3];
|
||||
public int ringBufferIndex = -1;
|
||||
public EntityDragonPart[] dragonPartArray;
|
||||
public EntityDragonPart dragonPartHead;
|
||||
public EntityDragonPart dragonPartBody;
|
||||
public EntityDragonPart dragonPartTail1;
|
||||
public EntityDragonPart dragonPartTail2;
|
||||
public EntityDragonPart dragonPartTail3;
|
||||
public EntityDragonPart dragonPartWing1;
|
||||
public EntityDragonPart dragonPartWing2;
|
||||
public float prevAnimTime;
|
||||
public float animTime;
|
||||
public boolean forceNewTarget;
|
||||
private Entity target;
|
||||
|
||||
public EntityDragon(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.dragonPartArray = new EntityDragonPart[] {this.dragonPartHead = new EntityDragonPart(this, "head", 6.0F, 6.0F), this.dragonPartBody = new EntityDragonPart(this, "body", 8.0F, 8.0F), this.dragonPartTail1 = new EntityDragonPart(this, "tail", 4.0F, 4.0F), this.dragonPartTail2 = new EntityDragonPart(this, "tail", 4.0F, 4.0F), this.dragonPartTail3 = new EntityDragonPart(this, "tail", 4.0F, 4.0F), this.dragonPartWing1 = new EntityDragonPart(this, "wing", 4.0F, 4.0F), this.dragonPartWing2 = new EntityDragonPart(this, "wing", 4.0F, 4.0F)};
|
||||
this.setHealth(this.getMaxHealth());
|
||||
this.setSize(16.0F, 8.0F);
|
||||
this.noClip = true;
|
||||
// this.fireImmune = true;
|
||||
this.targetY = 100.0D;
|
||||
this.noFrustumCheck = true;
|
||||
this.xpValue = 12000;
|
||||
}
|
||||
|
||||
public boolean isImmuneToFire()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(200);
|
||||
}
|
||||
|
||||
// protected void entityInit()
|
||||
// {
|
||||
// super.entityInit();
|
||||
// }
|
||||
|
||||
public boolean allowLeashing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a double[3] array with movement offsets, used to calculate trailing tail/neck positions. [0] = yaw
|
||||
* offset, [1] = y offset, [2] = unused, always 0. Parameters: buffer index offset, partial ticks.
|
||||
*/
|
||||
public double[] getMovementOffsets(int p_70974_1_, float p_70974_2_)
|
||||
{
|
||||
if (this.getHealth() <= 0)
|
||||
{
|
||||
p_70974_2_ = 0.0F;
|
||||
}
|
||||
|
||||
p_70974_2_ = 1.0F - p_70974_2_;
|
||||
int i = this.ringBufferIndex - p_70974_1_ * 1 & 63;
|
||||
int j = this.ringBufferIndex - p_70974_1_ * 1 - 1 & 63;
|
||||
double[] adouble = new double[3];
|
||||
double d0 = this.ringBuffer[i][0];
|
||||
double d1 = ExtMath.wrapd(this.ringBuffer[j][0] - d0);
|
||||
adouble[0] = d0 + d1 * (double)p_70974_2_;
|
||||
d0 = this.ringBuffer[i][1];
|
||||
d1 = this.ringBuffer[j][1] - d0;
|
||||
adouble[1] = d0 + d1 * (double)p_70974_2_;
|
||||
adouble[2] = this.ringBuffer[i][2] + (this.ringBuffer[j][2] - this.ringBuffer[i][2]) * (double)p_70974_2_;
|
||||
return adouble;
|
||||
}
|
||||
|
||||
public void onLivingUpdate()
|
||||
{
|
||||
if (this.worldObj.client)
|
||||
{
|
||||
float f = ExtMath.cos(this.animTime * (float)Math.PI * 2.0F);
|
||||
float f1 = ExtMath.cos(this.prevAnimTime * (float)Math.PI * 2.0F);
|
||||
|
||||
if (f1 <= -0.3F && f >= -0.3F) // && !this.isSilent())
|
||||
{
|
||||
((WorldClient)this.worldObj).playSound(this.posX, this.posY, this.posZ, SoundEvent.DRAGON_WINGS, 5.0F, 0.8F + this.rand.floatv() * 0.3F);
|
||||
}
|
||||
}
|
||||
|
||||
this.prevAnimTime = this.animTime;
|
||||
|
||||
if (this.getHealth() <= 0)
|
||||
{
|
||||
float f11 = (this.rand.floatv() - 0.5F) * 8.0F;
|
||||
float f13 = (this.rand.floatv() - 0.5F) * 4.0F;
|
||||
float f14 = (this.rand.floatv() - 0.5F) * 8.0F;
|
||||
this.worldObj.spawnParticle(ParticleType.EXPLOSION_LARGE, this.posX + (double)f11, this.posY + 2.0D + (double)f13, this.posZ + (double)f14, 0.0D, 0.0D, 0.0D);
|
||||
}
|
||||
else
|
||||
{
|
||||
// this.updateDragonEnderCrystal();
|
||||
float f10 = 0.2F / (ExtMath.sqrtd(this.motionX * this.motionX + this.motionZ * this.motionZ) * 10.0F + 1.0F);
|
||||
f10 = f10 * (float)Math.pow(2.0D, this.motionY);
|
||||
|
||||
this.animTime += f10;
|
||||
|
||||
this.rotYaw = ExtMath.wrapf(this.rotYaw);
|
||||
|
||||
// if (this.isAIDisabled() ||
|
||||
if(!this.worldObj.client && !Config.mobTick) // )
|
||||
{
|
||||
this.animTime = 0.5F;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (this.ringBufferIndex < 0)
|
||||
{
|
||||
for (int i = 0; i < this.ringBuffer.length; ++i)
|
||||
{
|
||||
this.ringBuffer[i][0] = (double)this.rotYaw;
|
||||
this.ringBuffer[i][1] = this.posY;
|
||||
}
|
||||
}
|
||||
|
||||
if (++this.ringBufferIndex == this.ringBuffer.length)
|
||||
{
|
||||
this.ringBufferIndex = 0;
|
||||
}
|
||||
|
||||
this.ringBuffer[this.ringBufferIndex][0] = (double)this.rotYaw;
|
||||
this.ringBuffer[this.ringBufferIndex][1] = this.posY;
|
||||
|
||||
if (this.worldObj.client)
|
||||
{
|
||||
if (this.moveIncrements > 0)
|
||||
{
|
||||
double d10 = this.posX + (this.newX - this.posX) / (double)this.moveIncrements;
|
||||
double d0 = this.posY + (this.newY - this.posY) / (double)this.moveIncrements;
|
||||
double d1 = this.posZ + (this.newZ - this.posZ) / (double)this.moveIncrements;
|
||||
double d2 = ExtMath.wrapd(this.newYaw - (double)this.rotYaw);
|
||||
this.rotYaw = (float)((double)this.rotYaw + d2 / (double)this.moveIncrements);
|
||||
this.rotPitch = (float)((double)this.rotPitch + (this.newPitch - (double)this.rotPitch) / (double)this.moveIncrements);
|
||||
--this.moveIncrements;
|
||||
this.setPosition(d10, d0, d1);
|
||||
this.setRotation(this.rotYaw, this.rotPitch);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
double d11 = this.targetX - this.posX;
|
||||
double d12 = this.targetY - this.posY;
|
||||
double d13 = this.targetZ - this.posZ;
|
||||
double d14 = d11 * d11 + d12 * d12 + d13 * d13;
|
||||
|
||||
if (this.target != null)
|
||||
{
|
||||
this.targetX = this.target.posX;
|
||||
this.targetZ = this.target.posZ;
|
||||
double d3 = this.targetX - this.posX;
|
||||
double d5 = this.targetZ - this.posZ;
|
||||
double d7 = Math.sqrt(d3 * d3 + d5 * d5);
|
||||
double d8 = 0.4000000059604645D + d7 / 80.0D - 1.0D;
|
||||
|
||||
if (d8 > 10.0D)
|
||||
{
|
||||
d8 = 10.0D;
|
||||
}
|
||||
|
||||
this.targetY = this.target.getEntityBoundingBox().minY + d8;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.targetX += this.rand.gaussian() * 2.0D;
|
||||
this.targetZ += this.rand.gaussian() * 2.0D;
|
||||
}
|
||||
|
||||
if (this.forceNewTarget || d14 < 100.0D || d14 > 22500.0D || this.collidedHorizontally || this.collidedVertically)
|
||||
{
|
||||
this.setNewTarget();
|
||||
}
|
||||
|
||||
d12 = d12 / (double)ExtMath.sqrtd(d11 * d11 + d13 * d13);
|
||||
float f17 = 0.6F;
|
||||
d12 = ExtMath.clampd(d12, (double)(-f17), (double)f17);
|
||||
this.motionY += d12 * 0.10000000149011612D;
|
||||
this.rotYaw = ExtMath.wrapf(this.rotYaw);
|
||||
double d4 = 180.0D - ExtMath.atan2(d11, d13) * 180.0D / Math.PI;
|
||||
double d6 = ExtMath.wrapd(d4 - (double)this.rotYaw);
|
||||
|
||||
if (d6 > 50.0D)
|
||||
{
|
||||
d6 = 50.0D;
|
||||
}
|
||||
|
||||
if (d6 < -50.0D)
|
||||
{
|
||||
d6 = -50.0D;
|
||||
}
|
||||
|
||||
Vec3 vec3 = (new Vec3(this.targetX - this.posX, this.targetY - this.posY, this.targetZ - this.posZ)).normalize();
|
||||
double d15 = (double)(-ExtMath.cos(this.rotYaw * (float)Math.PI / 180.0F));
|
||||
Vec3 vec31 = (new Vec3((double)ExtMath.sin(this.rotYaw * (float)Math.PI / 180.0F), this.motionY, d15)).normalize();
|
||||
float f5 = ((float)vec31.dotProduct(vec3) + 0.5F) / 1.5F;
|
||||
|
||||
if (f5 < 0.0F)
|
||||
{
|
||||
f5 = 0.0F;
|
||||
}
|
||||
|
||||
this.randomYawVelo *= 0.8F;
|
||||
float f6 = ExtMath.sqrtd(this.motionX * this.motionX + this.motionZ * this.motionZ) * 1.0F + 1.0F;
|
||||
double d9 = Math.sqrt(this.motionX * this.motionX + this.motionZ * this.motionZ) * 1.0D + 1.0D;
|
||||
|
||||
if (d9 > 40.0D)
|
||||
{
|
||||
d9 = 40.0D;
|
||||
}
|
||||
|
||||
this.randomYawVelo = (float)((double)this.randomYawVelo + d6 * (0.699999988079071D / d9 / (double)f6));
|
||||
this.rotYaw += this.randomYawVelo * 0.1F;
|
||||
float f7 = (float)(2.0D / (d9 + 1.0D));
|
||||
float f8 = 0.06F;
|
||||
this.moveFlying(0.0F, -1.0F, f8 * (f5 * f7 + (1.0F - f7)));
|
||||
|
||||
this.moveEntity(this.motionX, this.motionY, this.motionZ);
|
||||
|
||||
Vec3 vec32 = (new Vec3(this.motionX, this.motionY, this.motionZ)).normalize();
|
||||
float f9 = ((float)vec32.dotProduct(vec31) + 1.0F) / 2.0F;
|
||||
f9 = 0.8F + 0.15F * f9;
|
||||
this.motionX *= (double)f9;
|
||||
this.motionZ *= (double)f9;
|
||||
this.motionY *= 0.9100000262260437D;
|
||||
}
|
||||
|
||||
this.yawOffset = this.rotYaw;
|
||||
this.dragonPartHead.width = this.dragonPartHead.height = 3.0F;
|
||||
this.dragonPartTail1.width = this.dragonPartTail1.height = 2.0F;
|
||||
this.dragonPartTail2.width = this.dragonPartTail2.height = 2.0F;
|
||||
this.dragonPartTail3.width = this.dragonPartTail3.height = 2.0F;
|
||||
this.dragonPartBody.height = 3.0F;
|
||||
this.dragonPartBody.width = 5.0F;
|
||||
this.dragonPartWing1.height = 2.0F;
|
||||
this.dragonPartWing1.width = 4.0F;
|
||||
this.dragonPartWing2.height = 3.0F;
|
||||
this.dragonPartWing2.width = 4.0F;
|
||||
float f12 = (float)(this.getMovementOffsets(5, 1.0F)[1] - this.getMovementOffsets(10, 1.0F)[1]) * 10.0F / 180.0F * (float)Math.PI;
|
||||
float f2 = ExtMath.cos(f12);
|
||||
float f15 = -ExtMath.sin(f12);
|
||||
float f3 = this.rotYaw * (float)Math.PI / 180.0F;
|
||||
float f16 = ExtMath.sin(f3);
|
||||
float f4 = ExtMath.cos(f3);
|
||||
this.dragonPartBody.onUpdate();
|
||||
this.dragonPartBody.setLocationAndAngles(this.posX + (double)(f16 * 0.5F), this.posY, this.posZ - (double)(f4 * 0.5F), 0.0F, 0.0F);
|
||||
this.dragonPartWing1.onUpdate();
|
||||
this.dragonPartWing1.setLocationAndAngles(this.posX + (double)(f4 * 4.5F), this.posY + 2.0D, this.posZ + (double)(f16 * 4.5F), 0.0F, 0.0F);
|
||||
this.dragonPartWing2.onUpdate();
|
||||
this.dragonPartWing2.setLocationAndAngles(this.posX - (double)(f4 * 4.5F), this.posY + 2.0D, this.posZ - (double)(f16 * 4.5F), 0.0F, 0.0F);
|
||||
|
||||
if (!this.worldObj.client && this.hurtTime == 0)
|
||||
{
|
||||
this.collideWithEntities(this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.dragonPartWing1.getEntityBoundingBox().expand(4.0D, 2.0D, 4.0D).offset(0.0D, -2.0D, 0.0D)));
|
||||
this.collideWithEntities(this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.dragonPartWing2.getEntityBoundingBox().expand(4.0D, 2.0D, 4.0D).offset(0.0D, -2.0D, 0.0D)));
|
||||
if(Config.damageMobs)
|
||||
this.attackEntitiesInList(this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.dragonPartHead.getEntityBoundingBox().expand(1.0D, 1.0D, 1.0D)));
|
||||
}
|
||||
|
||||
double[] adouble1 = this.getMovementOffsets(5, 1.0F);
|
||||
double[] adouble = this.getMovementOffsets(0, 1.0F);
|
||||
float f18 = ExtMath.sin(this.rotYaw * (float)Math.PI / 180.0F - this.randomYawVelo * 0.01F);
|
||||
float f19 = ExtMath.cos(this.rotYaw * (float)Math.PI / 180.0F - this.randomYawVelo * 0.01F);
|
||||
this.dragonPartHead.onUpdate();
|
||||
this.dragonPartHead.setLocationAndAngles(this.posX + (double)(f18 * 5.5F * f2), this.posY + (adouble[1] - adouble1[1]) * 1.0D + (double)(f15 * 5.5F), this.posZ - (double)(f19 * 5.5F * f2), 0.0F, 0.0F);
|
||||
|
||||
for (int j = 0; j < 3; ++j)
|
||||
{
|
||||
EntityDragonPart entitydragonpart = null;
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
entitydragonpart = this.dragonPartTail1;
|
||||
}
|
||||
|
||||
if (j == 1)
|
||||
{
|
||||
entitydragonpart = this.dragonPartTail2;
|
||||
}
|
||||
|
||||
if (j == 2)
|
||||
{
|
||||
entitydragonpart = this.dragonPartTail3;
|
||||
}
|
||||
|
||||
double[] adouble2 = this.getMovementOffsets(12 + j * 2, 1.0F);
|
||||
float f20 = this.rotYaw * (float)Math.PI / 180.0F + this.simplifyAngle(adouble2[0] - adouble1[0]) * (float)Math.PI / 180.0F * 1.0F;
|
||||
float f21 = ExtMath.sin(f20);
|
||||
float f22 = ExtMath.cos(f20);
|
||||
float f23 = 1.5F;
|
||||
float f24 = (float)(j + 1) * 2.0F;
|
||||
entitydragonpart.onUpdate();
|
||||
entitydragonpart.setLocationAndAngles(this.posX - (double)((f16 * f23 + f21 * f24) * f2), this.posY + (adouble2[1] - adouble1[1]) * 1.0D - (double)((f24 + f23) * f15) + 1.5D, this.posZ + (double)((f4 * f23 + f22 * f24) * f2), 0.0F, 0.0F);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// private void updateDragonEnderCrystal()
|
||||
// {
|
||||
// if (this.healingEnderCrystal != null)
|
||||
// {
|
||||
// if (this.healingEnderCrystal.dead)
|
||||
// {
|
||||
// if (!this.worldObj.client)
|
||||
// {
|
||||
// this.attackEntityFromPart(this.dragonPartHead, DamageSource.setExplosionSource((Explosion)null), 10);
|
||||
// }
|
||||
//
|
||||
// this.healingEnderCrystal = null;
|
||||
// }
|
||||
// else if (this.ticksExisted % 10 == 0 && this.getHealth() < this.getMaxHealth())
|
||||
// {
|
||||
// this.setHealth(this.getHealth() + 1);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (this.rand.chance(10))
|
||||
// {
|
||||
// float f = 32.0F;
|
||||
// List<EntityCrystal> list = this.worldObj.<EntityCrystal>getEntitiesWithinAABB(EntityCrystal.class, this.getEntityBoundingBox().expand((double)f, (double)f, (double)f));
|
||||
// EntityCrystal entityendercrystal = null;
|
||||
// double d0 = Double.MAX_VALUE;
|
||||
//
|
||||
// for (EntityCrystal entityendercrystal1 : list)
|
||||
// {
|
||||
// double d1 = entityendercrystal1.getDistanceSqToEntity(this);
|
||||
//
|
||||
// if (d1 < d0)
|
||||
// {
|
||||
// d0 = d1;
|
||||
// entityendercrystal = entityendercrystal1;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// this.healingEnderCrystal = entityendercrystal;
|
||||
// }
|
||||
// }
|
||||
|
||||
private void collideWithEntities(List<Entity> p_70970_1_)
|
||||
{
|
||||
double d0 = (this.dragonPartBody.getEntityBoundingBox().minX + this.dragonPartBody.getEntityBoundingBox().maxX) / 2.0D;
|
||||
double d1 = (this.dragonPartBody.getEntityBoundingBox().minZ + this.dragonPartBody.getEntityBoundingBox().maxZ) / 2.0D;
|
||||
|
||||
for (Entity entity : p_70970_1_)
|
||||
{
|
||||
if (entity instanceof EntityLiving)
|
||||
{
|
||||
double d2 = entity.posX - d0;
|
||||
double d3 = entity.posZ - d1;
|
||||
double d4 = d2 * d2 + d3 * d3;
|
||||
entity.addKnockback(d2 / d4 * 4.0D, 0.20000000298023224D, d3 / d4 * 4.0D);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void attackEntitiesInList(List<Entity> p_70971_1_)
|
||||
{
|
||||
for (int i = 0; i < p_70971_1_.size(); ++i)
|
||||
{
|
||||
Entity entity = (Entity)p_70971_1_.get(i);
|
||||
|
||||
if (entity instanceof EntityLiving)
|
||||
{
|
||||
entity.attackEntityFrom(DamageSource.causeMobDamage(this), 10);
|
||||
this.applyEnchantments(this, entity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a new target for the flight AI. It can be a random coordinate or a nearby player.
|
||||
*/
|
||||
private void setNewTarget()
|
||||
{
|
||||
this.forceNewTarget = false;
|
||||
List<EntityNPC> list = Lists.newArrayList(this.worldObj.players);
|
||||
// Iterator<EntityNPC> iterator = list.iterator();
|
||||
//
|
||||
// while (iterator.hasNext())
|
||||
// {
|
||||
// if (((EntityNPC)iterator.next()).isSpectator())
|
||||
// {
|
||||
// iterator.remove();
|
||||
// }
|
||||
// }
|
||||
|
||||
if (this.rand.chance(2) && !list.isEmpty())
|
||||
{
|
||||
this.target = this.rand.pick(list);
|
||||
}
|
||||
else
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
this.targetX = 0.0D;
|
||||
this.targetY = (double)(70.0F + this.rand.floatv() * 50.0F);
|
||||
this.targetZ = 0.0D;
|
||||
this.targetX += (double)(this.rand.floatv() * 120.0F - 60.0F);
|
||||
this.targetZ += (double)(this.rand.floatv() * 120.0F - 60.0F);
|
||||
double d0 = this.posX - this.targetX;
|
||||
double d1 = this.posY - this.targetY;
|
||||
double d2 = this.posZ - this.targetZ;
|
||||
boolean flag = d0 * d0 + d1 * d1 + d2 * d2 > 100.0D;
|
||||
|
||||
if (flag)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
this.target = null;
|
||||
}
|
||||
}
|
||||
|
||||
private float simplifyAngle(double p_70973_1_)
|
||||
{
|
||||
return (float)ExtMath.wrapd(p_70973_1_);
|
||||
}
|
||||
|
||||
public boolean attackEntityFromPart(EntityDragonPart dragonPart, DamageSource source, int amount)
|
||||
{
|
||||
if (dragonPart != this.dragonPartHead)
|
||||
{
|
||||
amount = amount / 4 + 1;
|
||||
}
|
||||
|
||||
float f = this.rotYaw * (float)Math.PI / 180.0F;
|
||||
float f1 = ExtMath.sin(f);
|
||||
float f2 = ExtMath.cos(f);
|
||||
this.targetX = this.posX + (double)(f1 * 5.0F) + (double)((this.rand.floatv() - 0.5F) * 2.0F);
|
||||
this.targetY = this.posY + (double)(this.rand.floatv() * 3.0F) + 1.0D;
|
||||
this.targetZ = this.posZ - (double)(f2 * 5.0F) + (double)((this.rand.floatv() - 0.5F) * 2.0F);
|
||||
this.target = null;
|
||||
|
||||
// if ((source.getEntity() != null && source.getEntity().isPlayer()) || source.isExplosion())
|
||||
// {
|
||||
this.attackEntityFrom(source, amount);
|
||||
// }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// public boolean attackEntityFrom(DamageSource source, int amount)
|
||||
// {
|
||||
// if (source instanceof EntityDamageSource && ((EntityDamageSource)source).getIsThornsDamage())
|
||||
// {
|
||||
// this.attackDragonFrom(source, amount);
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// protected boolean attackDragonFrom(DamageSource source, int amount)
|
||||
// {
|
||||
// return super.attackEntityFrom(source, amount);
|
||||
// }
|
||||
|
||||
// protected void onDeathUpdate()
|
||||
// {
|
||||
// super.onDeathUpdate();
|
||||
// if (this.deathTime == 20)
|
||||
// {
|
||||
// float f = (this.rand.floatv() - 0.5F) * 8.0F;
|
||||
// float f1 = (this.rand.floatv() - 0.5F) * 4.0F;
|
||||
// float f2 = (this.rand.floatv() - 0.5F) * 8.0F;
|
||||
// this.worldObj.spawnParticle(EnumParticleTypes.EXPLOSION_HUGE, this.posX + (double)f, this.posY + 2.0D + (double)f1, this.posZ + (double)f2, 0.0D, 0.0D, 0.0D);
|
||||
// }
|
||||
// }
|
||||
|
||||
// private void generatePortal(BlockPos pos)
|
||||
// {
|
||||
// int i = 4;
|
||||
// double d0 = 12.25D;
|
||||
// double d1 = 6.25D;
|
||||
//
|
||||
// for (int j = -1; j <= 32; ++j)
|
||||
// {
|
||||
// for (int k = -4; k <= 4; ++k)
|
||||
// {
|
||||
// for (int l = -4; l <= 4; ++l)
|
||||
// {
|
||||
// double d2 = (double)(k * k + l * l);
|
||||
//
|
||||
// if (d2 <= 12.25D)
|
||||
// {
|
||||
// BlockPos blockpos = pos.add(k, j, l);
|
||||
//
|
||||
// if (j < 0)
|
||||
// {
|
||||
// if (d2 <= 6.25D)
|
||||
// {
|
||||
// this.worldObj.setBlockState(blockpos, Blocks.obsidian.getDefaultState());
|
||||
// }
|
||||
// }
|
||||
// else if (j > 0)
|
||||
// {
|
||||
// this.worldObj.setBlockState(blockpos, Blocks.air.getDefaultState());
|
||||
// }
|
||||
// else if (d2 > 6.25D)
|
||||
// {
|
||||
// this.worldObj.setBlockState(blockpos, Blocks.obsidian.getDefaultState());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// this.worldObj.setBlockState(blockpos, Blocks.end_portal.getDefaultState());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// this.worldObj.setBlockState(pos, Blocks.obsidian.getDefaultState());
|
||||
// this.worldObj.setBlockState(pos.up(), Blocks.obsidian.getDefaultState());
|
||||
// BlockPos blockpos1 = pos.up(2);
|
||||
// this.worldObj.setBlockState(blockpos1, Blocks.obsidian.getDefaultState());
|
||||
// this.worldObj.setBlockState(blockpos1.west(), Blocks.torch.getDefaultState().withProperty(BlockTorch.FACING, EnumFacing.EAST));
|
||||
// this.worldObj.setBlockState(blockpos1.east(), Blocks.torch.getDefaultState().withProperty(BlockTorch.FACING, EnumFacing.WEST));
|
||||
// this.worldObj.setBlockState(blockpos1.north(), Blocks.torch.getDefaultState().withProperty(BlockTorch.FACING, EnumFacing.SOUTH));
|
||||
// this.worldObj.setBlockState(blockpos1.south(), Blocks.torch.getDefaultState().withProperty(BlockTorch.FACING, EnumFacing.NORTH));
|
||||
// this.worldObj.setBlockState(pos.up(3), Blocks.obsidian.getDefaultState());
|
||||
// this.worldObj.setBlockState(pos.up(4), Blocks.dragon_egg.getDefaultState());
|
||||
// }
|
||||
|
||||
// protected void despawnEntity()
|
||||
// {
|
||||
// }
|
||||
|
||||
public Entity[] getParts()
|
||||
{
|
||||
return this.dragonPartArray;
|
||||
}
|
||||
|
||||
public boolean canBeCollidedWith()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public World getWorld()
|
||||
{
|
||||
return this.worldObj;
|
||||
}
|
||||
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return SoundEvent.DRAGON_IDLE;
|
||||
}
|
||||
|
||||
// protected Sounds getHurtSound()
|
||||
// {
|
||||
// return Sounds.MOB_DRAGON_HIT;
|
||||
// }
|
||||
//
|
||||
// protected Sounds getDeathSound()
|
||||
// {
|
||||
// return Sounds.MOB_DRAGON_HIT;
|
||||
// }
|
||||
|
||||
protected float getSoundVolume()
|
||||
{
|
||||
return 5.0F;
|
||||
}
|
||||
|
||||
public int getTrackingRange() {
|
||||
return 160;
|
||||
}
|
||||
|
||||
public int getUpdateFrequency() {
|
||||
return 3;
|
||||
}
|
||||
|
||||
public boolean isSendingVeloUpdates() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0xb900ff;
|
||||
}
|
||||
|
||||
public boolean isBoss() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean getCanSpawnHere() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return Alignment.LAWFUL_EVIL;
|
||||
}
|
||||
}
|
75
java/src/game/entity/animal/EntityDragonPart.java
Executable file
75
java/src/game/entity/animal/EntityDragonPart.java
Executable file
|
@ -0,0 +1,75 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.entity.DamageSource;
|
||||
import game.entity.Entity;
|
||||
import game.entity.types.IEntityMultiPart;
|
||||
import game.nbt.NBTTagCompound;
|
||||
|
||||
public class EntityDragonPart extends Entity
|
||||
{
|
||||
/** The dragon entity this dragon part belongs to */
|
||||
public final IEntityMultiPart entityDragonObj;
|
||||
public final String partName;
|
||||
|
||||
public EntityDragonPart(IEntityMultiPart parent, String partName, float base, float sizeHeight)
|
||||
{
|
||||
super(parent.getWorld());
|
||||
this.setSize(base, sizeHeight);
|
||||
this.entityDragonObj = parent;
|
||||
this.partName = partName;
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
protected void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
protected void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if other Entities should be prevented from moving through this Entity.
|
||||
*/
|
||||
public boolean canBeCollidedWith()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, int amount)
|
||||
{
|
||||
return this.isEntityInvulnerable(source) ? false : this.entityDragonObj.attackEntityFromPart(this, source, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Entity argument is equal to this Entity
|
||||
*/
|
||||
public boolean isEntityEqual(Entity entityIn)
|
||||
{
|
||||
return this == entityIn || this.entityDragonObj == entityIn;
|
||||
}
|
||||
|
||||
public int getTrackingRange() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getUpdateFrequency() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isSendingVeloUpdates() {
|
||||
return false;
|
||||
}
|
||||
}
|
1886
java/src/game/entity/animal/EntityHorse.java
Executable file
1886
java/src/game/entity/animal/EntityHorse.java
Executable file
File diff suppressed because it is too large
Load diff
90
java/src/game/entity/animal/EntityMooshroom.java
Executable file
90
java/src/game/entity/animal/EntityMooshroom.java
Executable file
|
@ -0,0 +1,90 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.entity.item.EntityItem;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.Blocks;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.ItemShears;
|
||||
import game.item.ItemStack;
|
||||
import game.renderer.particle.ParticleType;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityMooshroom extends EntityCow
|
||||
{
|
||||
public EntityMooshroom(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.9F, 1.3F);
|
||||
this.spawnableBlocks.clear();
|
||||
this.spawnableBlocks.add(Blocks.mycelium);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
ItemStack itemstack = player.inventory.getCurrentItem();
|
||||
|
||||
if (itemstack != null && itemstack.getItem() == Items.bowl && !this.isChild())
|
||||
{
|
||||
if (itemstack.stackSize == 1)
|
||||
{
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, new ItemStack(Items.mushroom_stew));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (player.inventory.addItemStackToInventory(new ItemStack(Items.mushroom_stew))) // && !player.creative)
|
||||
{
|
||||
player.inventory.decrStackSize(player.inventory.currentItem, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (itemstack != null && itemstack.getItem() instanceof ItemShears && !this.isChild())
|
||||
{
|
||||
this.setDead();
|
||||
this.worldObj.spawnParticle(ParticleType.EXPLOSION_LARGE, this.posX, this.posY + (double)(this.height / 2.0F), this.posZ, 0.0D, 0.0D, 0.0D);
|
||||
|
||||
if (!this.worldObj.client)
|
||||
{
|
||||
EntityCow entitycow = new EntityCow(this.worldObj);
|
||||
entitycow.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotYaw, this.rotPitch);
|
||||
entitycow.setHealth(this.getHealth());
|
||||
entitycow.yawOffset = this.yawOffset;
|
||||
|
||||
if (this.hasCustomName())
|
||||
{
|
||||
entitycow.setCustomNameTag(this.getCustomNameTag());
|
||||
}
|
||||
|
||||
this.worldObj.spawnEntityInWorld(entitycow);
|
||||
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
this.worldObj.spawnEntityInWorld(new EntityItem(this.worldObj, this.posX, this.posY + (double)this.height, this.posZ, new ItemStack(Blocks.red_mushroom)));
|
||||
}
|
||||
|
||||
itemstack.damageItem(1, player);
|
||||
this.playSound(SoundEvent.CUT, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.interact(player);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityMooshroom createChild(EntityLiving ageable)
|
||||
{
|
||||
return new EntityMooshroom(this.worldObj);
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0x7c4c83;
|
||||
}
|
||||
}
|
132
java/src/game/entity/animal/EntityMouse.java
Executable file
132
java/src/game/entity/animal/EntityMouse.java
Executable file
|
@ -0,0 +1,132 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
import game.ai.EntityAIFollowParent;
|
||||
import game.ai.EntityAILookIdle;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIPanic;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.block.Block;
|
||||
import game.entity.attributes.AttributeInstance;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.Blocks;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.ItemStack;
|
||||
import game.world.BlockPos;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityMouse extends EntityAnimal {
|
||||
public EntityMouse(World world) {
|
||||
super(world);
|
||||
this.setSize(0.3F, 0.2F);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 1.4D));
|
||||
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(3, new EntityAITempt(this, 1.0D, Items.sugar, false));
|
||||
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
|
||||
this.tasks.addTask(5, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(6, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(7, new EntityAILookIdle(this));
|
||||
this.spawnableBlocks.clear();
|
||||
Collections.addAll(this.spawnableBlocks, Blocks.stone, Blocks.tian);
|
||||
}
|
||||
|
||||
public float getEyeHeight() {
|
||||
return this.height;
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes() {
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(1);
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.25D);
|
||||
}
|
||||
|
||||
// protected String getLivingSound() {
|
||||
// return "mob.mouse.idle";
|
||||
// }
|
||||
|
||||
protected SoundEvent getHurtSound() {
|
||||
return SoundEvent.RABBIT_HIT;
|
||||
}
|
||||
|
||||
protected SoundEvent getDeathSound() {
|
||||
return SoundEvent.RABBIT_HIT;
|
||||
}
|
||||
|
||||
protected void playStepSound(BlockPos pos, Block block) {
|
||||
}
|
||||
|
||||
protected float getSoundVolume() {
|
||||
return 0.3F;
|
||||
}
|
||||
|
||||
protected float getSoundPitch() {
|
||||
return (this.rand.floatv() - this.rand.floatv()) * 0.2F + (this.isChild() ? 1.8F : 1.6F);
|
||||
}
|
||||
|
||||
protected void dropFewItems(boolean hit, int looting) {
|
||||
int amt = this.rand.zrange(2);
|
||||
if(looting > 0) {
|
||||
amt += this.rand.zrange(looting + 1);
|
||||
}
|
||||
for(int z = 0; z < amt; z++) {
|
||||
this.dropItem(Items.string, 1);
|
||||
}
|
||||
}
|
||||
|
||||
public EntityMouse createChild(EntityLiving parent) {
|
||||
return new EntityMouse(this.worldObj);
|
||||
}
|
||||
|
||||
public boolean isBreedingItem(ItemStack stack) {
|
||||
return stack != null && stack.getItem() == Items.sugar;
|
||||
}
|
||||
|
||||
protected int getExperiencePoints(EntityNPC player) {
|
||||
return this.worldObj.rand.range(0, 1);
|
||||
}
|
||||
|
||||
public boolean getCanSpawnHere()
|
||||
{
|
||||
if (((int)this.getEntityBoundingBox().minY) >= this.worldObj.getSeaLevel())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return super.getCanSpawnHere();
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isValidLightLevel(int level)
|
||||
{
|
||||
return level < 6;
|
||||
}
|
||||
|
||||
public float getBlockPathWeight(BlockPos pos)
|
||||
{
|
||||
return 0.5F - this.worldObj.getLightBrightness(pos);
|
||||
}
|
||||
|
||||
public void setCustomNameTag(String name) {
|
||||
super.setCustomNameTag(name);
|
||||
if(this.worldObj != null && !this.worldObj.client) {
|
||||
AttributeInstance speed = this.getEntityAttribute(Attributes.MOVEMENT_SPEED);
|
||||
speed.removeModifier(Attributes.MOUSE_SPEEDY_MOD);
|
||||
if(name.equals("Gonzales") || name.equals("Gonzalez"))
|
||||
speed.applyModifier(Attributes.MOUSE_SPEEDY_MOD);
|
||||
}
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0x888888;
|
||||
}
|
||||
}
|
419
java/src/game/entity/animal/EntityOcelot.java
Executable file
419
java/src/game/entity/animal/EntityOcelot.java
Executable file
|
@ -0,0 +1,419 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import game.ai.EntityAIAvoidEntity;
|
||||
import game.ai.EntityAIFollowOwner;
|
||||
import game.ai.EntityAILeapAtTarget;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIOcelotAttack;
|
||||
import game.ai.EntityAIOcelotSit;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITargetNonTamed;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.entity.DamageSource;
|
||||
import game.entity.Entity;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.Alignment;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.entity.types.EntityTameable;
|
||||
import game.init.Config;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.pathfinding.PathNavigateGround;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityOcelot extends EntityTameable
|
||||
{
|
||||
private EntityAIAvoidEntity<EntityNPC> avoidEntity;
|
||||
|
||||
/**
|
||||
* The tempt AI task for this mob, used to prevent taming while it is fleeing.
|
||||
*/
|
||||
private EntityAITempt aiTempt;
|
||||
private boolean wasTempted;
|
||||
|
||||
public EntityOcelot(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.6F, 0.7F);
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
this.tasks.addTask(1, new EntityAISwimming(this));
|
||||
this.tasks.addTask(2, this.aiSit);
|
||||
this.tasks.addTask(3, this.aiTempt = new EntityAITempt(this, 0.6D, Items.fish, true));
|
||||
this.tasks.addTask(5, new EntityAIFollowOwner(this, 1.0D, 10.0F, 5.0F));
|
||||
this.tasks.addTask(6, new EntityAIOcelotSit(this, 0.8D));
|
||||
this.tasks.addTask(7, new EntityAILeapAtTarget(this, 0.3F));
|
||||
this.tasks.addTask(8, new EntityAIOcelotAttack(this));
|
||||
this.tasks.addTask(9, new EntityAIMate(this, 0.8D));
|
||||
this.tasks.addTask(10, new EntityAIWander(this, 0.8D));
|
||||
this.tasks.addTask(11, new EntityAIWatchClosest(this, null, 10.0F));
|
||||
this.targets.addTask(1, new EntityAITargetNonTamed(this, EntityAnimal.class, false, new Predicate<EntityAnimal>() {
|
||||
public boolean test(EntityAnimal entity) {
|
||||
return entity instanceof EntityChicken || entity instanceof EntityMouse;
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(18, Byte.valueOf((byte)0));
|
||||
}
|
||||
|
||||
public void updateAITasks()
|
||||
{
|
||||
if (this.getMoveHelper().isUpdating())
|
||||
{
|
||||
double d0 = this.getMoveHelper().getSpeed();
|
||||
|
||||
if (d0 == 0.6D)
|
||||
{
|
||||
this.setSneaking(this.wasTempted);
|
||||
this.setSprinting(false);
|
||||
this.wasTempted = true;
|
||||
}
|
||||
else if (d0 == 1.33D)
|
||||
{
|
||||
this.setSneaking(false);
|
||||
this.setSprinting(true);
|
||||
this.wasTempted = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setSneaking(false);
|
||||
this.setSprinting(false);
|
||||
this.wasTempted = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setSneaking(false);
|
||||
this.setSprinting(false);
|
||||
this.wasTempted = false;
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Determines if an entity can be despawned, used on idle far away entities
|
||||
// */
|
||||
// protected boolean canDespawn()
|
||||
// {
|
||||
// return !this.isTamed() && this.ticksExisted > 2400;
|
||||
// }
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(10);
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
|
||||
}
|
||||
|
||||
public void fall(float distance, float damageMultiplier)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setInteger("CatType", this.getTameSkin());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.setTameSkin(tagCompund.getInteger("CatType"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return this.isTamed() ? (this.isInLove() ? SoundEvent.CAT_PURREOW : (this.rand.chance(4) ? SoundEvent.CAT_PURREOW : SoundEvent.CAT_MEOW)) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.CAT_HIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.CAT_HIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the volume for the sounds this mob makes.
|
||||
*/
|
||||
protected float getSoundVolume()
|
||||
{
|
||||
return 0.4F;
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return Items.leather;
|
||||
}
|
||||
|
||||
public boolean attackEntityAsMob(Entity entityIn)
|
||||
{
|
||||
if(!this.worldObj.client && !Config.damageMobs)
|
||||
return false;
|
||||
return entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), 3);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, int amount)
|
||||
{
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.aiSit.setSitting(false);
|
||||
return super.attackEntityFrom(source, amount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
ItemStack itemstack = player.inventory.getCurrentItem();
|
||||
|
||||
if (this.isTamed())
|
||||
{
|
||||
if (this.isOwner(player) && !this.worldObj.client && !this.isBreedingItem(itemstack))
|
||||
{
|
||||
this.aiSit.setSitting(!this.isSitting());
|
||||
}
|
||||
}
|
||||
else if (this.aiTempt.isRunning() && itemstack != null && itemstack.getItem() == Items.fish && player.getDistanceSqToEntity(this) < 9.0D)
|
||||
{
|
||||
// if (!player.creative)
|
||||
// {
|
||||
--itemstack.stackSize;
|
||||
// }
|
||||
|
||||
if (itemstack.stackSize <= 0)
|
||||
{
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
|
||||
}
|
||||
|
||||
if (!this.worldObj.client)
|
||||
{
|
||||
if (this.rand.chance(3))
|
||||
{
|
||||
this.setTamed(true);
|
||||
this.setTameSkin(this.worldObj.rand.roll(3));
|
||||
// this.setOwnerId(player.getUser());
|
||||
this.playTameEffect(true);
|
||||
this.aiSit.setSitting(true);
|
||||
this.worldObj.setEntityState(this, (byte)7);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.playTameEffect(false);
|
||||
this.worldObj.setEntityState(this, (byte)6);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.interact(player);
|
||||
}
|
||||
|
||||
public EntityOcelot createChild(EntityLiving ageable)
|
||||
{
|
||||
EntityOcelot entityocelot = new EntityOcelot(this.worldObj);
|
||||
|
||||
if (this.isTamed())
|
||||
{
|
||||
// entityocelot.setOwnerId(this.getOwnerId());
|
||||
entityocelot.setTamed(true);
|
||||
entityocelot.setTameSkin(this.getTameSkin());
|
||||
}
|
||||
|
||||
return entityocelot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
|
||||
* the animal type)
|
||||
*/
|
||||
public boolean isBreedingItem(ItemStack stack)
|
||||
{
|
||||
return stack != null && stack.getItem() == Items.fish;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the mob is currently able to mate with the specified mob.
|
||||
*/
|
||||
public boolean canMateWith(EntityAnimal otherAnimal)
|
||||
{
|
||||
if (otherAnimal == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
// else if (!this.isTamed())
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
else if (!(otherAnimal instanceof EntityOcelot))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityOcelot entityocelot = (EntityOcelot)otherAnimal;
|
||||
return (entityocelot.isTamed() != this.isTamed()) ? false : this.isInLove() && entityocelot.isInLove();
|
||||
}
|
||||
}
|
||||
|
||||
public int getTameSkin()
|
||||
{
|
||||
return this.dataWatcher.getWatchableObjectByte(18);
|
||||
}
|
||||
|
||||
public void setTameSkin(int skinId)
|
||||
{
|
||||
this.dataWatcher.updateObject(18, Byte.valueOf((byte)skinId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the entity's current position is a valid location to spawn this entity.
|
||||
*/
|
||||
public boolean getCanSpawnHere()
|
||||
{
|
||||
return this.worldObj.rand.rarity(3);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Checks that the entity is not colliding with any blocks / liquids
|
||||
// */
|
||||
// public boolean isNotColliding()
|
||||
// {
|
||||
// if (this.worldObj.checkNoEntityCollision(this.getEntityBoundingBox(), this) && this.worldObj.getCollidingBoundingBoxes(this, this.getEntityBoundingBox()).isEmpty() && !this.worldObj.isAnyLiquid(this.getEntityBoundingBox()))
|
||||
// {
|
||||
// BlockPos blockpos = new BlockPos(this.posX, this.getEntityBoundingBox().minY, this.posZ);
|
||||
//
|
||||
// if (blockpos.getY() < this.worldObj.getSeaLevel())
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Block block = this.worldObj.getBlockState(blockpos.down()).getBlock();
|
||||
//
|
||||
// if (block == Blocks.grass || block.getMaterial() == Material.leaves)
|
||||
// {
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return false;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Get the name of this object. For players this returns their username
|
||||
*/
|
||||
public String getTypeName()
|
||||
{
|
||||
return this.hasCustomName() ? this.getCustomNameTag() : (this.isTamed() ? "Katze" : super.getTypeName());
|
||||
}
|
||||
|
||||
public void setTamed(boolean tamed)
|
||||
{
|
||||
super.setTamed(tamed);
|
||||
}
|
||||
|
||||
protected void setupTamedAI()
|
||||
{
|
||||
if (this.avoidEntity == null)
|
||||
{
|
||||
this.avoidEntity = new EntityAIAvoidEntity(this, EntityNPC.class,
|
||||
// new Predicate<EntityNPC>() {
|
||||
// public boolean apply(EntityNPC entity) {
|
||||
// return !entity.capabilities.disableTarget;
|
||||
// }
|
||||
// } ,
|
||||
16.0F, 0.8D, 1.33D);
|
||||
}
|
||||
|
||||
this.tasks.removeTask(this.avoidEntity);
|
||||
|
||||
if (!this.isTamed())
|
||||
{
|
||||
this.tasks.addTask(4, this.avoidEntity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
|
||||
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
|
||||
*/
|
||||
public Object onInitialSpawn(Object livingdata)
|
||||
{
|
||||
livingdata = super.onInitialSpawn(livingdata);
|
||||
|
||||
if (this.worldObj.rand.chance(7))
|
||||
{
|
||||
for (int i = 0; i < 2; ++i)
|
||||
{
|
||||
EntityOcelot entityocelot = new EntityOcelot(this.worldObj);
|
||||
entityocelot.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotYaw, 0.0F);
|
||||
entityocelot.setGrowingAge(-24000);
|
||||
this.worldObj.spawnEntityInWorld(entityocelot);
|
||||
}
|
||||
}
|
||||
|
||||
return livingdata;
|
||||
}
|
||||
|
||||
public int getLeashColor() {
|
||||
return this.isTamed() ? 0xf02020 : super.getLeashColor();
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return this.isTamed() ? 0xdeb059 : 0xffe15b;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return this.isTamed() ? Alignment.CHAOTIC_GOOD : Alignment.CHAOTIC;
|
||||
}
|
||||
}
|
251
java/src/game/entity/animal/EntityPig.java
Executable file
251
java/src/game/entity/animal/EntityPig.java
Executable file
|
@ -0,0 +1,251 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.ai.EntityAIControlledByPlayer;
|
||||
import game.ai.EntityAIFollowParent;
|
||||
import game.ai.EntityAILookIdle;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIPanic;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.pathfinding.PathNavigateGround;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityPig extends EntityAnimal
|
||||
{
|
||||
/** AI task for player control. */
|
||||
private final EntityAIControlledByPlayer aiControlledByPlayer;
|
||||
|
||||
public EntityPig(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.9F, 0.9F);
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 1.25D));
|
||||
this.tasks.addTask(2, this.aiControlledByPlayer = new EntityAIControlledByPlayer(this, 0.3F));
|
||||
this.tasks.addTask(3, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(4, new EntityAITempt(this, 1.2D, Items.carrot_on_a_stick, false));
|
||||
this.tasks.addTask(4, new EntityAITempt(this, 1.2D, Items.carrot, false));
|
||||
this.tasks.addTask(5, new EntityAIFollowParent(this, 1.1D));
|
||||
this.tasks.addTask(6, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(7, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(8, new EntityAILookIdle(this));
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(10);
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.25D);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if all the conditions for steering the entity are met. For pigs, this is true if it is being ridden
|
||||
* by a player and the player is holding a carrot-on-a-stick
|
||||
*/
|
||||
public boolean canBeSteered()
|
||||
{
|
||||
ItemStack itemstack = ((EntityNPC)this.passenger).getHeldItem();
|
||||
return itemstack != null && itemstack.getItem() == Items.carrot_on_a_stick;
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setBoolean("Saddle", this.getSaddled());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.setSaddled(tagCompund.getBoolean("Saddle"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return SoundEvent.PIG_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.PIG_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.PIG_DEATH;
|
||||
}
|
||||
|
||||
// protected void playStepSound(BlockPos pos, Block blockIn)
|
||||
// {
|
||||
// this.playSound("mob.pig.step", 0.15F, 1.0F);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
if (super.interact(player))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (!this.getSaddled() || this.worldObj.client || this.passenger != null && this.passenger != player)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
player.mountEntity(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return this.isBurning() ? Items.cooked_porkchop : Items.porkchop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
int i = this.rand.roll(3) + this.rand.zrange(1 + lootingModifier);
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
if (this.isBurning())
|
||||
{
|
||||
this.dropItem(Items.cooked_porkchop, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dropItem(Items.porkchop, 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.getSaddled())
|
||||
{
|
||||
this.dropItem(Items.saddle, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the pig is saddled.
|
||||
*/
|
||||
public boolean getSaddled()
|
||||
{
|
||||
return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set or remove the saddle of the pig.
|
||||
*/
|
||||
public void setSaddled(boolean saddled)
|
||||
{
|
||||
if (saddled)
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)1));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)0));
|
||||
}
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Called when a lightning bolt hits the entity.
|
||||
// */
|
||||
// public void onStruckByLightning(EntityLightning lightningBolt)
|
||||
// {
|
||||
// if (!this.worldObj.client && !this.dead && Config.convertPigman)
|
||||
// {
|
||||
// EntityMobNPC entitypigzombie = new EntityMobNPC(this.worldObj);
|
||||
// entitypigzombie.setItem(0, new ItemStack(Items.golden_sword));
|
||||
// entitypigzombie.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotYaw, this.rotPitch);
|
||||
// entitypigzombie.setNoAI(this.isAIDisabled());
|
||||
//
|
||||
// if (this.hasCustomName())
|
||||
// {
|
||||
// entitypigzombie.setCustomNameTag(this.getCustomNameTag());
|
||||
// entitypigzombie.setAlwaysRenderNameTag(this.getAlwaysRenderNameTag());
|
||||
// }
|
||||
//
|
||||
// this.worldObj.spawnEntityInWorld(entitypigzombie);
|
||||
// this.setDead();
|
||||
// }
|
||||
// }
|
||||
|
||||
// public void fall(float distance, float damageMultiplier)
|
||||
// {
|
||||
// super.fall(distance, damageMultiplier);
|
||||
//
|
||||
// if (distance > 5.0F && this.passenger.isPlayer())
|
||||
// {
|
||||
// ((EntityNPC)this.passenger).triggerAchievement(AchievementList.flyPig);
|
||||
// }
|
||||
// }
|
||||
|
||||
public EntityPig createChild(EntityLiving ageable)
|
||||
{
|
||||
return new EntityPig(this.worldObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
|
||||
* the animal type)
|
||||
*/
|
||||
public boolean isBreedingItem(ItemStack stack)
|
||||
{
|
||||
return stack != null && stack.getItem() == Items.carrot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the AI task for player control.
|
||||
*/
|
||||
public EntityAIControlledByPlayer getAIControlledByPlayer()
|
||||
{
|
||||
return this.aiControlledByPlayer;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0xe78e8e;
|
||||
}
|
||||
}
|
581
java/src/game/entity/animal/EntityRabbit.java
Executable file
581
java/src/game/entity/animal/EntityRabbit.java
Executable file
|
@ -0,0 +1,581 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.ai.EntityAIAttackOnCollide;
|
||||
import game.ai.EntityAIAvoidEntity;
|
||||
import game.ai.EntityAIHurtByTarget;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIMoveToBlock;
|
||||
import game.ai.EntityAINearestAttackableTarget;
|
||||
import game.ai.EntityAIPanic;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.ai.EntityJumpHelper;
|
||||
import game.ai.EntityMoveHelper;
|
||||
import game.block.Block;
|
||||
import game.block.BlockTallGrass;
|
||||
import game.entity.DamageSource;
|
||||
import game.entity.Entity;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.Alignment;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.BlockRegistry;
|
||||
import game.init.Blocks;
|
||||
import game.init.Config;
|
||||
import game.init.ItemRegistry;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.pathfinding.PathEntity;
|
||||
import game.pathfinding.PathNavigateGround;
|
||||
import game.potion.Potion;
|
||||
import game.potion.PotionEffect;
|
||||
import game.renderer.particle.ParticleType;
|
||||
import game.world.BlockPos;
|
||||
import game.world.State;
|
||||
import game.world.Vec3;
|
||||
import game.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.rand.floatv() - this.rand.floatv()) * 0.2F + 1.0F) * 0.8F);
|
||||
}
|
||||
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(Attributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
|
||||
}
|
||||
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound) {
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setInteger("RabbitType", this.getRabbitType());
|
||||
tagCompound.setInteger("MoreCarrotTicks", this.foodCooldown);
|
||||
}
|
||||
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund) {
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.setRabbitType(tagCompund.getInteger("RabbitType"));
|
||||
this.foodCooldown = tagCompund.getInteger("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 && !Config.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 = Config.killerBunnyChance > 0 && this.rand.chance(Config.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(Config.rabbitMateChance > 0 && this.rand.chance(Config.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.moveSpeed.id, 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(!Config.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 = Config.rabidRabbits ? this.destinationBlock : this.destinationBlock.up();
|
||||
State state = world.getState(pos);
|
||||
// Block block = iblockstate.getBlock();
|
||||
if(this.foodFound && canEat(state) && Config.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(Config.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;
|
||||
}
|
||||
}
|
||||
}
|
406
java/src/game/entity/animal/EntitySheep.java
Executable file
406
java/src/game/entity/animal/EntitySheep.java
Executable file
|
@ -0,0 +1,406 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.ai.EntityAIEatGrass;
|
||||
import game.ai.EntityAIFollowParent;
|
||||
import game.ai.EntityAILookIdle;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIPanic;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITempt;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.biome.Biome;
|
||||
import game.collect.Maps;
|
||||
import game.color.DyeColor;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.item.EntityItem;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.init.Blocks;
|
||||
import game.init.CraftingRegistry;
|
||||
import game.init.ItemRegistry;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.inventory.Container;
|
||||
import game.inventory.InventoryCrafting;
|
||||
import game.item.Item;
|
||||
import game.item.ItemShears;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.pathfinding.PathNavigateGround;
|
||||
import game.rng.Random;
|
||||
import game.world.World;
|
||||
|
||||
public class EntitySheep extends EntityAnimal
|
||||
{
|
||||
/**
|
||||
* Internal crafting inventory used to check the result of mixing dyes corresponding to the fleece color when
|
||||
* breeding sheep.
|
||||
*/
|
||||
private final InventoryCrafting inventoryCrafting = new InventoryCrafting(new Container()
|
||||
{
|
||||
public boolean canInteractWith(EntityNPC playerIn)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}, 2, 1);
|
||||
private static final Map<DyeColor, float[]> DYE_TO_RGB = Maps.newEnumMap(DyeColor.class);
|
||||
|
||||
/**
|
||||
* Used to control movement as well as wool regrowth. Set to 40 on handleHealthUpdate and counts down with each
|
||||
* tick.
|
||||
*/
|
||||
private int sheepTimer;
|
||||
private EntityAIEatGrass entityAIEatGrass = new EntityAIEatGrass(this);
|
||||
|
||||
public static float[] getDyeRgb(DyeColor dyeColor)
|
||||
{
|
||||
return (float[])DYE_TO_RGB.get(dyeColor);
|
||||
}
|
||||
|
||||
public EntitySheep(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.9F, 1.3F);
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
this.tasks.addTask(0, new EntityAISwimming(this));
|
||||
this.tasks.addTask(1, new EntityAIPanic(this, 1.25D));
|
||||
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(3, new EntityAITempt(this, 1.1D, Items.wheats, false));
|
||||
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.1D));
|
||||
this.tasks.addTask(5, this.entityAIEatGrass);
|
||||
this.tasks.addTask(6, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(7, new EntityAIWatchClosest(this, null, 6.0F));
|
||||
this.tasks.addTask(8, new EntityAILookIdle(this));
|
||||
this.inventoryCrafting.setInventorySlotContents(0, new ItemStack(Items.dye, 1, 0));
|
||||
this.inventoryCrafting.setInventorySlotContents(1, new ItemStack(Items.dye, 1, 0));
|
||||
}
|
||||
|
||||
protected void updateAITasks()
|
||||
{
|
||||
this.sheepTimer = this.entityAIEatGrass.getEatingGrassTimer();
|
||||
super.updateAITasks();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
|
||||
* use this to react to sunlight and start to burn.
|
||||
*/
|
||||
public void onLivingUpdate()
|
||||
{
|
||||
if (this.worldObj.client)
|
||||
{
|
||||
this.sheepTimer = Math.max(0, this.sheepTimer - 1);
|
||||
}
|
||||
|
||||
super.onLivingUpdate();
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(8);
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.23000000417232513D);
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(16, (byte)0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
if (!this.getSheared())
|
||||
{
|
||||
this.entityDropItem(new ItemStack(ItemRegistry.getItemFromBlock(Blocks.wool), 1, this.getFleeceColor().getMetadata()), 0.0F);
|
||||
}
|
||||
|
||||
// int i = this.rand.roll(2) + this.rand.zrange(1 + lootingModifier);
|
||||
//
|
||||
// for (int j = 0; j < i; ++j)
|
||||
// {
|
||||
// if (this.isBurning())
|
||||
// {
|
||||
// this.dropItem(Items.cooked_mutton, 1);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// this.dropItem(Items.mutton, 1);
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return ItemRegistry.getItemFromBlock(Blocks.wool);
|
||||
}
|
||||
|
||||
public void handleStatusUpdate(byte id)
|
||||
{
|
||||
if (id == 10)
|
||||
{
|
||||
this.sheepTimer = 40;
|
||||
}
|
||||
else
|
||||
{
|
||||
super.handleStatusUpdate(id);
|
||||
}
|
||||
}
|
||||
|
||||
public float getHeadRotationPointY(float p_70894_1_)
|
||||
{
|
||||
return this.sheepTimer <= 0 ? 0.0F : (this.sheepTimer >= 4 && this.sheepTimer <= 36 ? 1.0F : (this.sheepTimer < 4 ? ((float)this.sheepTimer - p_70894_1_) / 4.0F : -((float)(this.sheepTimer - 40) - p_70894_1_) / 4.0F));
|
||||
}
|
||||
|
||||
public float getHeadRotationAngleX(float p_70890_1_)
|
||||
{
|
||||
if (this.sheepTimer > 4 && this.sheepTimer <= 36)
|
||||
{
|
||||
float f = ((float)(this.sheepTimer - 4) - p_70890_1_) / 32.0F;
|
||||
return ((float)Math.PI / 5F) + ((float)Math.PI * 7F / 100F) * ExtMath.sin(f * 28.7F);
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.sheepTimer > 0 ? ((float)Math.PI / 5F) : this.rotPitch / (180F / (float)Math.PI);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
ItemStack itemstack = player.inventory.getCurrentItem();
|
||||
|
||||
if (itemstack != null && itemstack.getItem() instanceof ItemShears /* && this.worldObj.dimension.getDimensionId() != 2 */ && !this.getSheared() && !this.isChild())
|
||||
{
|
||||
if (!this.worldObj.client)
|
||||
{
|
||||
this.setSheared(true);
|
||||
int i = this.rand.roll(3);
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
EntityItem entityitem = this.entityDropItem(new ItemStack(ItemRegistry.getItemFromBlock(Blocks.wool), 1, this.getFleeceColor().getMetadata()), 1.0F);
|
||||
entityitem.motionY += (double)(this.rand.floatv() * 0.05F);
|
||||
entityitem.motionX += (double)((this.rand.floatv() - this.rand.floatv()) * 0.1F);
|
||||
entityitem.motionZ += (double)((this.rand.floatv() - this.rand.floatv()) * 0.1F);
|
||||
}
|
||||
}
|
||||
|
||||
itemstack.damageItem(1, player);
|
||||
this.playSound(SoundEvent.CUT, 1.0F, 1.0F);
|
||||
}
|
||||
|
||||
return super.interact(player);
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setBoolean("Sheared", this.getSheared());
|
||||
tagCompound.setByte("Color", (byte)this.getFleeceColor().getMetadata());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.setSheared(tagCompund.getBoolean("Sheared"));
|
||||
this.setFleeceColor(DyeColor.byMetadata(tagCompund.getByte("Color")));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return SoundEvent.SHEEP_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.SHEEP_IDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.SHEEP_IDLE;
|
||||
}
|
||||
|
||||
// protected void playStepSound(BlockPos pos, Block blockIn)
|
||||
// {
|
||||
// this.playSound("mob.sheep.step", 0.15F, 1.0F);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Gets the wool color of this sheep.
|
||||
*/
|
||||
public DyeColor getFleeceColor()
|
||||
{
|
||||
return DyeColor.byMetadata(this.dataWatcher.getWatchableObjectByte(16) & 15);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the wool color of this sheep
|
||||
*/
|
||||
public void setFleeceColor(DyeColor color)
|
||||
{
|
||||
byte b0 = this.dataWatcher.getWatchableObjectByte(16);
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & 240 | color.getMetadata() & 15)));
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if a sheeps wool has been sheared
|
||||
*/
|
||||
public boolean getSheared()
|
||||
{
|
||||
return (this.dataWatcher.getWatchableObjectByte(16) & 16) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* make a sheep sheared if set to true
|
||||
*/
|
||||
public void setSheared(boolean sheared)
|
||||
{
|
||||
byte b0 = this.dataWatcher.getWatchableObjectByte(16);
|
||||
|
||||
if (sheared)
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 16)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -17)));
|
||||
}
|
||||
}
|
||||
|
||||
private static final DyeColor[] RARE_COLORS = {
|
||||
DyeColor.BLUE, DyeColor.CYAN, DyeColor.GREEN, DyeColor.LIGHT_BLUE, DyeColor.LIME,
|
||||
DyeColor.MAGENTA, DyeColor.ORANGE, DyeColor.PINK, DyeColor.PURPLE, DyeColor.RED
|
||||
};
|
||||
|
||||
public static DyeColor getRandomSheepColor(Random random, Biome biome)
|
||||
{
|
||||
if(biome == Biome.snowLand)
|
||||
return DyeColor.WHITE;
|
||||
int i = random.zrange(140);
|
||||
return i < 20 ? DyeColor.BLACK :
|
||||
(i < 30 ? DyeColor.GRAY :
|
||||
(i < 40 ? DyeColor.SILVER :
|
||||
(i < 70 ? DyeColor.BROWN :
|
||||
(i < 120 ? DyeColor.WHITE :
|
||||
(i < 130 ? (random.chance(10) ? RARE_COLORS[i - 120] : DyeColor.WHITE) :
|
||||
(random.chance(500) ? DyeColor.YELLOW : DyeColor.WHITE)
|
||||
)))));
|
||||
}
|
||||
|
||||
public EntitySheep createChild(EntityLiving ageable)
|
||||
{
|
||||
EntitySheep entitysheep = (EntitySheep)ageable;
|
||||
EntitySheep entitysheep1 = new EntitySheep(this.worldObj);
|
||||
entitysheep1.setFleeceColor(this.getDyeColorMixFromParents(this, entitysheep));
|
||||
return entitysheep1;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function applies the benefits of growing back wool and faster growing up to the acting entity. (This
|
||||
* function is used in the AIEatGrass)
|
||||
*/
|
||||
public void eatGrassBonus()
|
||||
{
|
||||
this.setSheared(false);
|
||||
|
||||
if (this.isChild() && !this.worldObj.client)
|
||||
{
|
||||
this.grow(60);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called only once on an entity when first time spawned, via egg, mob spawner, natural spawning etc, but not called
|
||||
* when entity is reloaded from nbt. Mainly used for initializing attributes and inventory
|
||||
*/
|
||||
public Object onInitialSpawn(Object livingdata)
|
||||
{
|
||||
livingdata = super.onInitialSpawn(livingdata);
|
||||
this.setFleeceColor(getRandomSheepColor(this.worldObj.rand, this.worldObj.getBiomeGenForCoords(this.getPosition())));
|
||||
return livingdata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to mix both parent sheep to come up with a mixed dye color.
|
||||
*/
|
||||
private DyeColor getDyeColorMixFromParents(EntityAnimal father, EntityAnimal mother)
|
||||
{
|
||||
int i = ((EntitySheep)father).getFleeceColor().getDyeDamage();
|
||||
int j = ((EntitySheep)mother).getFleeceColor().getDyeDamage();
|
||||
this.inventoryCrafting.getStackInSlot(0).setItemDamage(i);
|
||||
this.inventoryCrafting.getStackInSlot(1).setItemDamage(j);
|
||||
ItemStack itemstack = CraftingRegistry.getMatching(this.inventoryCrafting, ((EntitySheep)father).worldObj);
|
||||
int k;
|
||||
|
||||
if (itemstack != null && itemstack.getItem() == Items.dye)
|
||||
{
|
||||
k = itemstack.getMetadata();
|
||||
}
|
||||
else
|
||||
{
|
||||
k = this.worldObj.rand.chance() ? i : j;
|
||||
}
|
||||
|
||||
return DyeColor.byDyeDamage(k);
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return 0.95F * this.height;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0xd9d9d9;
|
||||
}
|
||||
|
||||
static
|
||||
{
|
||||
DYE_TO_RGB.put(DyeColor.WHITE, new float[] {1.0F, 1.0F, 1.0F});
|
||||
DYE_TO_RGB.put(DyeColor.ORANGE, new float[] {0.85F, 0.5F, 0.2F});
|
||||
DYE_TO_RGB.put(DyeColor.MAGENTA, new float[] {0.7F, 0.3F, 0.85F});
|
||||
DYE_TO_RGB.put(DyeColor.LIGHT_BLUE, new float[] {0.4F, 0.6F, 0.85F});
|
||||
DYE_TO_RGB.put(DyeColor.YELLOW, new float[] {0.9F, 0.9F, 0.2F});
|
||||
DYE_TO_RGB.put(DyeColor.LIME, new float[] {0.5F, 0.8F, 0.1F});
|
||||
DYE_TO_RGB.put(DyeColor.PINK, new float[] {0.95F, 0.5F, 0.65F});
|
||||
DYE_TO_RGB.put(DyeColor.GRAY, new float[] {0.3F, 0.3F, 0.3F});
|
||||
DYE_TO_RGB.put(DyeColor.SILVER, new float[] {0.6F, 0.6F, 0.6F});
|
||||
DYE_TO_RGB.put(DyeColor.CYAN, new float[] {0.3F, 0.5F, 0.6F});
|
||||
DYE_TO_RGB.put(DyeColor.PURPLE, new float[] {0.5F, 0.25F, 0.7F});
|
||||
DYE_TO_RGB.put(DyeColor.BLUE, new float[] {0.2F, 0.3F, 0.7F});
|
||||
DYE_TO_RGB.put(DyeColor.BROWN, new float[] {0.4F, 0.3F, 0.2F});
|
||||
DYE_TO_RGB.put(DyeColor.GREEN, new float[] {0.4F, 0.5F, 0.2F});
|
||||
DYE_TO_RGB.put(DyeColor.RED, new float[] {0.6F, 0.2F, 0.2F});
|
||||
DYE_TO_RGB.put(DyeColor.BLACK, new float[] {0.1F, 0.1F, 0.1F});
|
||||
}
|
||||
}
|
293
java/src/game/entity/animal/EntitySquid.java
Executable file
293
java/src/game/entity/animal/EntitySquid.java
Executable file
|
@ -0,0 +1,293 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.ai.EntityAIBase;
|
||||
import game.color.DyeColor;
|
||||
import game.entity.npc.Alignment;
|
||||
import game.entity.types.EntityWaterMob;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemStack;
|
||||
import game.world.World;
|
||||
|
||||
public class EntitySquid extends EntityWaterMob
|
||||
{
|
||||
public float squidPitch;
|
||||
public float prevSquidPitch;
|
||||
public float squidYaw;
|
||||
public float prevSquidYaw;
|
||||
|
||||
/**
|
||||
* appears to be rotation in radians; we already have pitch & yaw, so this completes the triumvirate.
|
||||
*/
|
||||
public float squidRotation;
|
||||
|
||||
/** previous squidRotation in radians */
|
||||
public float prevSquidRotation;
|
||||
|
||||
/** angle of the tentacles in radians */
|
||||
public float tentacleAngle;
|
||||
|
||||
/** the last calculated angle of the tentacles in radians */
|
||||
public float lastTentacleAngle;
|
||||
private float randomMotionSpeed;
|
||||
|
||||
/** change in squidRotation in radians. */
|
||||
private float rotationVelocity;
|
||||
private float field_70871_bB;
|
||||
private float randomMotionVecX;
|
||||
private float randomMotionVecY;
|
||||
private float randomMotionVecZ;
|
||||
|
||||
public EntitySquid(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.95F, 0.95F);
|
||||
this.rand.setSeed((long)(1 + this.getId()));
|
||||
this.rotationVelocity = 1.0F / (this.rand.floatv() + 1.0F) * 0.2F;
|
||||
this.tasks.addTask(0, new EntitySquid.AIMoveRandom(this));
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.setMaxHealth(10);
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return this.height * 0.5F;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Returns the sound this mob makes while it's alive.
|
||||
// */
|
||||
// protected String getLivingSound()
|
||||
// {
|
||||
// return null;
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the volume for the sounds this mob makes.
|
||||
*/
|
||||
protected float getSoundVolume()
|
||||
{
|
||||
return 0.4F;
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
|
||||
* prevent them from trampling crops
|
||||
*/
|
||||
protected boolean canTriggerWalking()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Drop 0-2 items of this living's type
|
||||
*
|
||||
* @param wasRecentlyHit true if this this entity was recently hit by appropriate entity (generally only if player
|
||||
* or tameable)
|
||||
* @param lootingModifier level of enchanment to be applied to this drop
|
||||
*/
|
||||
protected void dropFewItems(boolean wasRecentlyHit, int lootingModifier)
|
||||
{
|
||||
int i = this.rand.roll(3 + lootingModifier);
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
this.entityDropItem(new ItemStack(Items.dye, 1, DyeColor.BLACK.getDyeDamage()), 0.0F);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this entity is inside water (if inWater field is true as a result of handleWaterMovement() returning
|
||||
* true)
|
||||
*/
|
||||
public boolean isInLiquid()
|
||||
{
|
||||
return this.worldObj.handleLiquidAcceleration(this.getEntityBoundingBox().expand(0.0D, -0.6000000238418579D, 0.0D), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
|
||||
* use this to react to sunlight and start to burn.
|
||||
*/
|
||||
public void onLivingUpdate()
|
||||
{
|
||||
super.onLivingUpdate();
|
||||
this.prevSquidPitch = this.squidPitch;
|
||||
this.prevSquidYaw = this.squidYaw;
|
||||
this.prevSquidRotation = this.squidRotation;
|
||||
this.lastTentacleAngle = this.tentacleAngle;
|
||||
this.squidRotation += this.rotationVelocity;
|
||||
|
||||
if ((double)this.squidRotation > (Math.PI * 2D))
|
||||
{
|
||||
if (this.worldObj.client)
|
||||
{
|
||||
this.squidRotation = ((float)Math.PI * 2F);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.squidRotation = (float)((double)this.squidRotation - (Math.PI * 2D));
|
||||
|
||||
if (this.rand.chance(10))
|
||||
{
|
||||
this.rotationVelocity = 1.0F / (this.rand.floatv() + 1.0F) * 0.2F;
|
||||
}
|
||||
|
||||
this.worldObj.setEntityState(this, (byte)19);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.inLiquid)
|
||||
{
|
||||
if (this.squidRotation < (float)Math.PI)
|
||||
{
|
||||
float f = this.squidRotation / (float)Math.PI;
|
||||
this.tentacleAngle = ExtMath.sin(f * f * (float)Math.PI) * (float)Math.PI * 0.25F;
|
||||
|
||||
if ((double)f > 0.75D)
|
||||
{
|
||||
this.randomMotionSpeed = 1.0F;
|
||||
this.field_70871_bB = 1.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.field_70871_bB *= 0.8F;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tentacleAngle = 0.0F;
|
||||
this.randomMotionSpeed *= 0.9F;
|
||||
this.field_70871_bB *= 0.99F;
|
||||
}
|
||||
|
||||
if (!this.worldObj.client)
|
||||
{
|
||||
this.motionX = (double)(this.randomMotionVecX * this.randomMotionSpeed);
|
||||
this.motionY = (double)(this.randomMotionVecY * this.randomMotionSpeed);
|
||||
this.motionZ = (double)(this.randomMotionVecZ * this.randomMotionSpeed);
|
||||
}
|
||||
|
||||
float f1 = ExtMath.sqrtd(this.motionX * this.motionX + this.motionZ * this.motionZ);
|
||||
this.yawOffset += (-((float)ExtMath.atan2(this.motionX, this.motionZ)) * 180.0F / (float)Math.PI - this.yawOffset) * 0.1F;
|
||||
this.rotYaw = this.yawOffset;
|
||||
this.squidYaw = (float)((double)this.squidYaw + Math.PI * (double)this.field_70871_bB * 1.5D);
|
||||
this.squidPitch += (-((float)ExtMath.atan2((double)f1, this.motionY)) * 180.0F / (float)Math.PI - this.squidPitch) * 0.1F;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.tentacleAngle = ExtMath.absf(ExtMath.sin(this.squidRotation)) * (float)Math.PI * 0.25F;
|
||||
|
||||
if (!this.worldObj.client)
|
||||
{
|
||||
this.motionX = 0.0D;
|
||||
this.motionY -= 0.08D;
|
||||
this.motionY *= 0.9800000190734863D;
|
||||
this.motionZ = 0.0D;
|
||||
}
|
||||
|
||||
this.squidPitch = (float)((double)this.squidPitch + (double)(-90.0F - this.squidPitch) * 0.02D);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves the entity based on the specified heading. Args: strafe, forward
|
||||
*/
|
||||
public void moveEntityWithHeading(float strafe, float forward)
|
||||
{
|
||||
this.moveEntity(this.motionX, this.motionY, this.motionZ);
|
||||
}
|
||||
|
||||
public void handleStatusUpdate(byte id)
|
||||
{
|
||||
if (id == 19)
|
||||
{
|
||||
this.squidRotation = 0.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
super.handleStatusUpdate(id);
|
||||
}
|
||||
}
|
||||
|
||||
public void func_175568_b(float randomMotionVecXIn, float randomMotionVecYIn, float randomMotionVecZIn)
|
||||
{
|
||||
this.randomMotionVecX = randomMotionVecXIn;
|
||||
this.randomMotionVecY = randomMotionVecYIn;
|
||||
this.randomMotionVecZ = randomMotionVecZIn;
|
||||
}
|
||||
|
||||
public boolean func_175567_n()
|
||||
{
|
||||
return this.randomMotionVecX != 0.0F || this.randomMotionVecY != 0.0F || this.randomMotionVecZ != 0.0F;
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return 0x0000ff;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return Alignment.CHAOTIC_GOOD;
|
||||
}
|
||||
|
||||
static class AIMoveRandom extends EntityAIBase
|
||||
{
|
||||
private EntitySquid squid;
|
||||
|
||||
public AIMoveRandom(EntitySquid p_i45859_1_)
|
||||
{
|
||||
this.squid = p_i45859_1_;
|
||||
}
|
||||
|
||||
public boolean shouldExecute()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateTask()
|
||||
{
|
||||
// int i = this.squid.getAge();
|
||||
//
|
||||
// if (i > 100)
|
||||
// {
|
||||
// this.squid.func_175568_b(0.0F, 0.0F, 0.0F);
|
||||
// }
|
||||
// else
|
||||
if (this.squid.getRNG().chance(50) || !this.squid.inLiquid || !this.squid.func_175567_n())
|
||||
{
|
||||
float f = this.squid.getRNG().floatv() * (float)Math.PI * 2.0F;
|
||||
float f1 = ExtMath.cos(f) * 0.2F;
|
||||
float f2 = -0.1F + this.squid.getRNG().floatv() * 0.2F;
|
||||
float f3 = ExtMath.sin(f) * 0.2F;
|
||||
this.squid.func_175568_b(f1, f2, f3);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
656
java/src/game/entity/animal/EntityWolf.java
Executable file
656
java/src/game/entity/animal/EntityWolf.java
Executable file
|
@ -0,0 +1,656 @@
|
|||
package game.entity.animal;
|
||||
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import game.ExtMath;
|
||||
import game.ai.EntityAIAttackOnCollide;
|
||||
import game.ai.EntityAIBeg;
|
||||
import game.ai.EntityAIFollowOwner;
|
||||
import game.ai.EntityAIHurtByTarget;
|
||||
import game.ai.EntityAILeapAtTarget;
|
||||
import game.ai.EntityAILookIdle;
|
||||
import game.ai.EntityAIMate;
|
||||
import game.ai.EntityAIOwnerHurtByTarget;
|
||||
import game.ai.EntityAIOwnerHurtTarget;
|
||||
import game.ai.EntityAISwimming;
|
||||
import game.ai.EntityAITargetNonTamed;
|
||||
import game.ai.EntityAIWander;
|
||||
import game.ai.EntityAIWatchClosest;
|
||||
import game.color.DyeColor;
|
||||
import game.entity.DamageSource;
|
||||
import game.entity.Entity;
|
||||
import game.entity.attributes.Attributes;
|
||||
import game.entity.npc.Alignment;
|
||||
import game.entity.npc.EntityNPC;
|
||||
import game.entity.types.EntityAnimal;
|
||||
import game.entity.types.EntityLiving;
|
||||
import game.entity.types.EntityTameable;
|
||||
import game.init.Config;
|
||||
import game.init.Items;
|
||||
import game.init.SoundEvent;
|
||||
import game.item.Item;
|
||||
import game.item.ItemFood;
|
||||
import game.item.ItemStack;
|
||||
import game.nbt.NBTTagCompound;
|
||||
import game.pathfinding.PathNavigateGround;
|
||||
import game.renderer.particle.ParticleType;
|
||||
import game.world.World;
|
||||
|
||||
public class EntityWolf extends EntityTameable
|
||||
{
|
||||
/** Float used to smooth the rotation of the wolf head */
|
||||
private float headRotationCourse;
|
||||
private float headRotationCourseOld;
|
||||
|
||||
/** true is the wolf is wet else false */
|
||||
private boolean isWet;
|
||||
|
||||
/** True if the wolf is shaking else False */
|
||||
private boolean isShaking;
|
||||
|
||||
/**
|
||||
* This time increases while wolf is shaking and emitting water particles.
|
||||
*/
|
||||
private float timeWolfIsShaking;
|
||||
private float prevTimeWolfIsShaking;
|
||||
|
||||
public EntityWolf(World worldIn)
|
||||
{
|
||||
super(worldIn);
|
||||
this.setSize(0.6F, 0.8F);
|
||||
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
||||
this.tasks.addTask(1, new EntityAISwimming(this));
|
||||
this.tasks.addTask(2, this.aiSit);
|
||||
this.tasks.addTask(3, new EntityAILeapAtTarget(this, 0.4F));
|
||||
this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 1.0D, true));
|
||||
this.tasks.addTask(5, new EntityAIFollowOwner(this, 1.0D, 10.0F, 2.0F));
|
||||
this.tasks.addTask(6, new EntityAIMate(this, 1.0D));
|
||||
this.tasks.addTask(7, new EntityAIWander(this, 1.0D));
|
||||
this.tasks.addTask(8, new EntityAIBeg(this, 8.0F));
|
||||
this.tasks.addTask(9, new EntityAIWatchClosest(this, null, 8.0F));
|
||||
this.tasks.addTask(9, new EntityAILookIdle(this));
|
||||
this.targets.addTask(1, new EntityAIOwnerHurtByTarget(this));
|
||||
this.targets.addTask(2, new EntityAIOwnerHurtTarget(this));
|
||||
this.targets.addTask(3, new EntityAIHurtByTarget(this, true));
|
||||
this.targets.addTask(4, new EntityAITargetNonTamed(this, EntityAnimal.class, false, new Predicate<Entity>()
|
||||
{
|
||||
public boolean test(Entity p_apply_1_)
|
||||
{
|
||||
return p_apply_1_ instanceof EntitySheep || p_apply_1_ instanceof EntityRabbit;
|
||||
}
|
||||
}));
|
||||
// this.targets.addTask(5, new EntityAINearestAttackableTarget(this, EntityUndead.class, false));
|
||||
this.setTamed(false);
|
||||
}
|
||||
|
||||
protected void applyEntityAttributes()
|
||||
{
|
||||
super.applyEntityAttributes();
|
||||
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.30000001192092896D);
|
||||
|
||||
if (this.isTamed())
|
||||
{
|
||||
this.setMaxHealth(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setMaxHealth(8);
|
||||
}
|
||||
|
||||
this.getAttributeMap().registerAttribute(Attributes.ATTACK_DAMAGE);
|
||||
this.getEntityAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(2.0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the active target the Task system uses for tracking
|
||||
*/
|
||||
public void setAttackTarget(EntityLiving entitylivingbaseIn)
|
||||
{
|
||||
super.setAttackTarget(entitylivingbaseIn);
|
||||
|
||||
if (entitylivingbaseIn == null)
|
||||
{
|
||||
this.setAngry(false);
|
||||
}
|
||||
else if (!this.isTamed())
|
||||
{
|
||||
this.setAngry(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateAITasks()
|
||||
{
|
||||
this.dataWatcher.updateObject(18, Integer.valueOf(this.getHealth()));
|
||||
}
|
||||
|
||||
protected void entityInit()
|
||||
{
|
||||
super.entityInit();
|
||||
this.dataWatcher.addObject(18, this.getHealth());
|
||||
this.dataWatcher.addObject(19, (byte)0);
|
||||
this.dataWatcher.addObject(20, (byte)DyeColor.RED.getMetadata());
|
||||
}
|
||||
|
||||
// protected void playStepSound(BlockPos pos, Block blockIn)
|
||||
// {
|
||||
// this.playSound("mob.wolf.step", 0.15F, 1.0F);
|
||||
// }
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to write subclass entity data to NBT.
|
||||
*/
|
||||
public void writeEntityToNBT(NBTTagCompound tagCompound)
|
||||
{
|
||||
super.writeEntityToNBT(tagCompound);
|
||||
tagCompound.setBoolean("Angry", this.isAngry());
|
||||
tagCompound.setByte("CollarColor", (byte)this.getCollarColor().getDyeDamage());
|
||||
}
|
||||
|
||||
/**
|
||||
* (abstract) Protected helper method to read subclass entity data from NBT.
|
||||
*/
|
||||
public void readEntityFromNBT(NBTTagCompound tagCompund)
|
||||
{
|
||||
super.readEntityFromNBT(tagCompund);
|
||||
this.setAngry(tagCompund.getBoolean("Angry"));
|
||||
|
||||
if (tagCompund.hasKey("CollarColor", 99))
|
||||
{
|
||||
this.setCollarColor(DyeColor.byDyeDamage(tagCompund.getByte("CollarColor")));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes while it's alive.
|
||||
*/
|
||||
protected SoundEvent getLivingSound()
|
||||
{
|
||||
return this.isAngry() ? SoundEvent.WOLF_GROWL : (this.rand.chance(3) ? (this.isTamed() && this.dataWatcher.getWatchableObjectInt(18) < 10 ? SoundEvent.WOLF_WHINE : SoundEvent.WOLF_PANTING) : SoundEvent.WOLF_BARK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes when it is hurt.
|
||||
*/
|
||||
protected SoundEvent getHurtSound()
|
||||
{
|
||||
return SoundEvent.WOLF_HURT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sound this mob makes on death.
|
||||
*/
|
||||
protected SoundEvent getDeathSound()
|
||||
{
|
||||
return SoundEvent.WOLF_DEATH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the volume for the sounds this mob makes.
|
||||
*/
|
||||
protected float getSoundVolume()
|
||||
{
|
||||
return 0.4F;
|
||||
}
|
||||
|
||||
protected Item getDropItem()
|
||||
{
|
||||
return null; // ItemRegistry.getItemById(-1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
|
||||
* use this to react to sunlight and start to burn.
|
||||
*/
|
||||
public void onLivingUpdate()
|
||||
{
|
||||
super.onLivingUpdate();
|
||||
|
||||
if (!this.worldObj.client && this.isWet && !this.isShaking && !this.hasPath() && this.onGround)
|
||||
{
|
||||
this.isShaking = true;
|
||||
this.timeWolfIsShaking = 0.0F;
|
||||
this.prevTimeWolfIsShaking = 0.0F;
|
||||
this.worldObj.setEntityState(this, (byte)8);
|
||||
}
|
||||
|
||||
if (!this.worldObj.client && this.getAttackTarget() == null && this.isAngry())
|
||||
{
|
||||
this.setAngry(false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to update the entity's position/logic.
|
||||
*/
|
||||
public void onUpdate()
|
||||
{
|
||||
super.onUpdate();
|
||||
this.headRotationCourseOld = this.headRotationCourse;
|
||||
|
||||
if (this.isBegging())
|
||||
{
|
||||
this.headRotationCourse += (1.0F - this.headRotationCourse) * 0.4F;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.headRotationCourse += (0.0F - this.headRotationCourse) * 0.4F;
|
||||
}
|
||||
|
||||
if (this.isWet())
|
||||
{
|
||||
this.isWet = true;
|
||||
this.isShaking = false;
|
||||
this.timeWolfIsShaking = 0.0F;
|
||||
this.prevTimeWolfIsShaking = 0.0F;
|
||||
}
|
||||
else if ((this.isWet || this.isShaking) && this.isShaking)
|
||||
{
|
||||
if (this.timeWolfIsShaking == 0.0F)
|
||||
{
|
||||
this.playSound(SoundEvent.WOLF_SHAKE, this.getSoundVolume(), (this.rand.floatv() - this.rand.floatv()) * 0.2F + 1.0F);
|
||||
}
|
||||
|
||||
this.prevTimeWolfIsShaking = this.timeWolfIsShaking;
|
||||
this.timeWolfIsShaking += 0.05F;
|
||||
|
||||
if (this.prevTimeWolfIsShaking >= 2.0F)
|
||||
{
|
||||
this.isWet = false;
|
||||
this.isShaking = false;
|
||||
this.prevTimeWolfIsShaking = 0.0F;
|
||||
this.timeWolfIsShaking = 0.0F;
|
||||
}
|
||||
|
||||
if (this.timeWolfIsShaking > 0.4F)
|
||||
{
|
||||
float f = (float)this.getEntityBoundingBox().minY;
|
||||
int i = (int)(ExtMath.sin((this.timeWolfIsShaking - 0.4F) * (float)Math.PI) * 7.0F);
|
||||
|
||||
for (int j = 0; j < i; ++j)
|
||||
{
|
||||
float f1 = (this.rand.floatv() * 2.0F - 1.0F) * this.width * 0.5F;
|
||||
float f2 = (this.rand.floatv() * 2.0F - 1.0F) * this.width * 0.5F;
|
||||
this.worldObj.spawnParticle(ParticleType.WATER_SPLASH, this.posX + (double)f1, (double)(f + 0.8F), this.posZ + (double)f2, this.motionX, this.motionY, this.motionZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* True if the wolf is wet
|
||||
*/
|
||||
public boolean isWolfWet()
|
||||
{
|
||||
return this.isWet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used when calculating the amount of shading to apply while the wolf is wet.
|
||||
*/
|
||||
public float getShadingWhileWet(float p_70915_1_)
|
||||
{
|
||||
return 0.75F + (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * p_70915_1_) / 2.0F * 0.25F;
|
||||
}
|
||||
|
||||
public float getShakeAngle(float p_70923_1_, float p_70923_2_)
|
||||
{
|
||||
float f = (this.prevTimeWolfIsShaking + (this.timeWolfIsShaking - this.prevTimeWolfIsShaking) * p_70923_1_ + p_70923_2_) / 1.8F;
|
||||
|
||||
if (f < 0.0F)
|
||||
{
|
||||
f = 0.0F;
|
||||
}
|
||||
else if (f > 1.0F)
|
||||
{
|
||||
f = 1.0F;
|
||||
}
|
||||
|
||||
return ExtMath.sin(f * (float)Math.PI) * ExtMath.sin(f * (float)Math.PI * 11.0F) * 0.15F * (float)Math.PI;
|
||||
}
|
||||
|
||||
public float getInterestedAngle(float p_70917_1_)
|
||||
{
|
||||
return (this.headRotationCourseOld + (this.headRotationCourse - this.headRotationCourseOld) * p_70917_1_) * 0.15F * (float)Math.PI;
|
||||
}
|
||||
|
||||
public float getEyeHeight()
|
||||
{
|
||||
return this.height * 0.8F;
|
||||
}
|
||||
|
||||
/**
|
||||
* The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
|
||||
* use in wolves.
|
||||
*/
|
||||
public int getVerticalFaceSpeed()
|
||||
{
|
||||
return this.isSitting() ? 20 : super.getVerticalFaceSpeed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the entity is attacked.
|
||||
*/
|
||||
public boolean attackEntityFrom(DamageSource source, int amount)
|
||||
{
|
||||
if (this.isEntityInvulnerable(source))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Entity entity = source.getEntity();
|
||||
this.aiSit.setSitting(false);
|
||||
|
||||
// if (entity != null && !(entity.isPlayer()) && !(entity instanceof EntityArrow))
|
||||
// {
|
||||
// amount = (amount + 1) / 2;
|
||||
// }
|
||||
|
||||
return super.attackEntityFrom(source, amount);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean attackEntityAsMob(Entity entityIn)
|
||||
{
|
||||
if(!this.worldObj.client && !Config.damageMobs)
|
||||
return false;
|
||||
boolean flag = entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), ((int)this.getEntityAttribute(Attributes.ATTACK_DAMAGE).getAttributeValue()));
|
||||
|
||||
if (flag)
|
||||
{
|
||||
this.applyEnchantments(this, entityIn);
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
public void setTamed(boolean tamed)
|
||||
{
|
||||
super.setTamed(tamed);
|
||||
|
||||
if (tamed)
|
||||
{
|
||||
this.setMaxHealth(20);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.setMaxHealth(8);
|
||||
}
|
||||
|
||||
this.getEntityAttribute(Attributes.ATTACK_DAMAGE).setBaseValue(4.0D);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
|
||||
*/
|
||||
public boolean interact(EntityNPC player)
|
||||
{
|
||||
ItemStack itemstack = player.inventory.getCurrentItem();
|
||||
|
||||
if (this.isTamed())
|
||||
{
|
||||
if (itemstack != null)
|
||||
{
|
||||
if (itemstack.getItem() instanceof ItemFood)
|
||||
{
|
||||
ItemFood itemfood = (ItemFood)itemstack.getItem();
|
||||
|
||||
if (itemfood.isWolfsFavoriteMeat() && this.dataWatcher.getWatchableObjectInt(18) < 20)
|
||||
{
|
||||
// if (!player.creative)
|
||||
// {
|
||||
--itemstack.stackSize;
|
||||
// }
|
||||
|
||||
this.heal(itemfood.getHealAmount(itemstack));
|
||||
|
||||
if (itemstack.stackSize <= 0)
|
||||
{
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (itemstack.getItem() == Items.dye)
|
||||
{
|
||||
DyeColor enumdyecolor = DyeColor.byDyeDamage(itemstack.getMetadata());
|
||||
|
||||
if (enumdyecolor != this.getCollarColor())
|
||||
{
|
||||
this.setCollarColor(enumdyecolor);
|
||||
|
||||
if (/* !player.creative && */ --itemstack.stackSize <= 0)
|
||||
{
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isOwner(player) && !this.worldObj.client && !this.isBreedingItem(itemstack))
|
||||
{
|
||||
this.aiSit.setSitting(!this.isSitting());
|
||||
this.jumping = false;
|
||||
this.navigator.clearPathEntity();
|
||||
this.setAttackTarget((EntityLiving)null);
|
||||
}
|
||||
}
|
||||
else if (itemstack != null && itemstack.getItem() == Items.bone && !this.isAngry())
|
||||
{
|
||||
// if (!player.creative)
|
||||
// {
|
||||
--itemstack.stackSize;
|
||||
// }
|
||||
|
||||
if (itemstack.stackSize <= 0)
|
||||
{
|
||||
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
|
||||
}
|
||||
|
||||
if (!this.worldObj.client)
|
||||
{
|
||||
if (this.rand.chance(3))
|
||||
{
|
||||
this.setTamed(true);
|
||||
this.navigator.clearPathEntity();
|
||||
this.setAttackTarget((EntityLiving)null);
|
||||
this.aiSit.setSitting(true);
|
||||
this.setHealth(20);
|
||||
// this.setOwnerId(player.getUser());
|
||||
this.playTameEffect(true);
|
||||
this.worldObj.setEntityState(this, (byte)7);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.playTameEffect(false);
|
||||
this.worldObj.setEntityState(this, (byte)6);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return super.interact(player);
|
||||
}
|
||||
|
||||
public void handleStatusUpdate(byte id)
|
||||
{
|
||||
if (id == 8)
|
||||
{
|
||||
this.isShaking = true;
|
||||
this.timeWolfIsShaking = 0.0F;
|
||||
this.prevTimeWolfIsShaking = 0.0F;
|
||||
}
|
||||
else
|
||||
{
|
||||
super.handleStatusUpdate(id);
|
||||
}
|
||||
}
|
||||
|
||||
public float getTailRotation()
|
||||
{
|
||||
return this.isAngry() ? 1.5393804F : (this.isTamed() ? (0.55F - (20.0F - (float)this.dataWatcher.getWatchableObjectInt(18)) * 0.02F) * (float)Math.PI : ((float)Math.PI / 5F));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the parameter is an item which this animal can be fed to breed it (wheat, carrots or seeds depending on
|
||||
* the animal type)
|
||||
*/
|
||||
public boolean isBreedingItem(ItemStack stack)
|
||||
{
|
||||
return stack == null ? false : (!(stack.getItem() instanceof ItemFood) ? false : ((ItemFood)stack.getItem()).isWolfsFavoriteMeat());
|
||||
}
|
||||
|
||||
/**
|
||||
* Will return how many at most can spawn in a chunk at once.
|
||||
*/
|
||||
public int getMaxChunkSpawns()
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether this wolf is angry or not.
|
||||
*/
|
||||
public boolean isAngry()
|
||||
{
|
||||
return (this.dataWatcher.getWatchableObjectByte(16) & 2) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this wolf is angry or not.
|
||||
*/
|
||||
public void setAngry(boolean angry)
|
||||
{
|
||||
byte b0 = this.dataWatcher.getWatchableObjectByte(16);
|
||||
|
||||
if (angry)
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 2)));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -3)));
|
||||
}
|
||||
}
|
||||
|
||||
public DyeColor getCollarColor()
|
||||
{
|
||||
return DyeColor.byDyeDamage(this.dataWatcher.getWatchableObjectByte(20) & 15);
|
||||
}
|
||||
|
||||
public void setCollarColor(DyeColor collarcolor)
|
||||
{
|
||||
this.dataWatcher.updateObject(20, Byte.valueOf((byte)(collarcolor.getDyeDamage() & 15)));
|
||||
}
|
||||
|
||||
public EntityWolf createChild(EntityLiving ageable)
|
||||
{
|
||||
EntityWolf entitywolf = new EntityWolf(this.worldObj);
|
||||
// String s = this.getOwnerId();
|
||||
//
|
||||
// if (s != null && s.trim().length() > 0)
|
||||
// {
|
||||
// entitywolf.setOwnerId(s);
|
||||
entitywolf.setTamed(this.isTamed());
|
||||
// }
|
||||
|
||||
return entitywolf;
|
||||
}
|
||||
|
||||
public void setBegging(boolean beg)
|
||||
{
|
||||
if (beg)
|
||||
{
|
||||
this.dataWatcher.updateObject(19, Byte.valueOf((byte)1));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.dataWatcher.updateObject(19, Byte.valueOf((byte)0));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the mob is currently able to mate with the specified mob.
|
||||
*/
|
||||
public boolean canMateWith(EntityAnimal otherAnimal)
|
||||
{
|
||||
if (otherAnimal == this)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!this.isTamed())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (!(otherAnimal instanceof EntityWolf))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
EntityWolf entitywolf = (EntityWolf)otherAnimal;
|
||||
return !entitywolf.isTamed() ? false : (entitywolf.isSitting() ? false : this.isInLove() && entitywolf.isInLove());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isBegging()
|
||||
{
|
||||
return this.dataWatcher.getWatchableObjectByte(19) == 1;
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Determines if an entity can be despawned, used on idle far away entities
|
||||
// */
|
||||
// protected boolean canDespawn()
|
||||
// {
|
||||
// return !this.isTamed() && this.ticksExisted > 2400;
|
||||
// }
|
||||
|
||||
public boolean shouldAttackEntity(EntityLiving p_142018_1_, EntityLiving p_142018_2_)
|
||||
{
|
||||
// if (!(p_142018_1_ instanceof EntityHaunter)) // && !(p_142018_1_ instanceof EntityFireDemon))
|
||||
// {
|
||||
// if (p_142018_1_ instanceof EntityWolf)
|
||||
// {
|
||||
// EntityWolf entitywolf = (EntityWolf)p_142018_1_;
|
||||
//
|
||||
// if (entitywolf.isTamed() && entitywolf.getOwner() == p_142018_2_)
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
return /* p_142018_1_.isPlayer() && p_142018_2_.isPlayer() && !((EntityNPC)p_142018_2_).canAttackPlayer((EntityNPC)p_142018_1_) ? false : */ !(p_142018_1_ instanceof EntityHorse) || !((EntityHorse)p_142018_1_).isTame();
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return false;
|
||||
// }
|
||||
}
|
||||
|
||||
public boolean allowLeashing()
|
||||
{
|
||||
return !this.isAngry() && super.allowLeashing();
|
||||
}
|
||||
|
||||
public int getLeashColor() {
|
||||
if(this.isTamed()) {
|
||||
DyeColor color = DyeColor.byMetadata(this.getCollarColor().getMetadata());
|
||||
float[] rgb = EntitySheep.getDyeRgb(color);
|
||||
return (((int)(rgb[0] * 255.0f)) << 16) | (((int)(rgb[1] * 255.0f)) << 8) | ((int)(rgb[2] * 255.0f));
|
||||
}
|
||||
return super.getLeashColor();
|
||||
}
|
||||
|
||||
public int getColor() {
|
||||
return this.isTamed() ? 0x00ff7a : 0x59de9e;
|
||||
}
|
||||
|
||||
public Alignment getAlignment() {
|
||||
return this.isTamed() ? Alignment.LAWFUL_GOOD : Alignment.NEUTRAL;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue