1885 lines
54 KiB
Java
Executable file
1885 lines
54 KiB
Java
Executable file
package common.entity.animal;
|
|
|
|
import java.util.function.Predicate;
|
|
|
|
import common.ai.EntityAIFollowParent;
|
|
import common.ai.EntityAILookIdle;
|
|
import common.ai.EntityAIMate;
|
|
import common.ai.EntityAIPanic;
|
|
import common.ai.EntityAIRunAroundLikeCrazy;
|
|
import common.ai.EntityAISwimming;
|
|
import common.ai.EntityAIWander;
|
|
import common.ai.EntityAIWatchClosest;
|
|
import common.attributes.AttributeInstance;
|
|
import common.attributes.Attributes;
|
|
import common.block.Block;
|
|
import common.block.SoundType;
|
|
import common.entity.DamageSource;
|
|
import common.entity.Entity;
|
|
import common.entity.npc.EntityNPC;
|
|
import common.entity.types.EntityAnimal;
|
|
import common.entity.types.EntityLiving;
|
|
import common.init.Blocks;
|
|
import common.init.Config;
|
|
import common.init.ItemRegistry;
|
|
import common.init.Items;
|
|
import common.init.SoundEvent;
|
|
import common.inventory.AnimalChest;
|
|
import common.inventory.IInvBasic;
|
|
import common.inventory.InventoryBasic;
|
|
import common.item.Item;
|
|
import common.item.ItemMonsterPlacer;
|
|
import common.item.ItemStack;
|
|
import common.model.ParticleType;
|
|
import common.nbt.TagObject;
|
|
import common.nbt.TagObjectList;
|
|
import common.pathfinding.PathNavigateGround;
|
|
import common.potion.Potion;
|
|
import common.util.BlockPos;
|
|
import common.util.ExtMath;
|
|
import common.world.World;
|
|
|
|
public class EntityHorse extends EntityAnimal implements IInvBasic
|
|
{
|
|
private static final Predicate<Entity> horseBreedingSelector = new Predicate<Entity>()
|
|
{
|
|
public boolean test(Entity p_apply_1_)
|
|
{
|
|
return p_apply_1_ instanceof EntityHorse && ((EntityHorse)p_apply_1_).isBreeding();
|
|
}
|
|
};
|
|
private static final String[] horseArmorTextures = new String[] {null, "textures/armor/horse_armor_iron.png", "textures/armor/horse_armor_gold.png", "textures/armor/horse_armor_diamond.png"};
|
|
private static final String[] HORSE_ARMOR_TEXTURES_ABBR = new String[] {"", "meo", "goo", "dio"};
|
|
private static final int[] armorValues = new int[] {0, 5, 7, 11};
|
|
private static final String[] horseTextures = new String[] {"textures/entity/horse_white.png", "textures/entity/horse_creamy.png", "textures/entity/horse_chestnut.png", "textures/entity/horse_brown.png", "textures/entity/horse_black.png", "textures/entity/horse_gray.png", "textures/entity/horse_darkbrown.png"};
|
|
private static final String[] HORSE_TEXTURES_ABBR = new String[] {"hwh", "hcr", "hch", "hbr", "hbl", "hgr", "hdb"};
|
|
private static final String[] horseMarkingTextures = new String[] {null, "textures/entity/horse_markings_white.png", "textures/entity/horse_markings_whitefield.png", "textures/entity/horse_markings_whitedots.png", "textures/entity/horse_markings_blackdots.png"};
|
|
private static final String[] HORSE_MARKING_TEXTURES_ABBR = new String[] {"", "wo_", "wmo", "wdo", "bdo"};
|
|
private int eatingHaystackCounter;
|
|
private int openMouthCounter;
|
|
private int jumpRearingCounter;
|
|
public int field_110278_bp;
|
|
public int field_110279_bq;
|
|
protected boolean horseJumping;
|
|
private AnimalChest horseChest;
|
|
private boolean hasReproduced;
|
|
|
|
/**
|
|
* "The higher this value, the more likely the horse is to be tamed next time a player rides it."
|
|
*/
|
|
protected int temper;
|
|
protected float jumpPower;
|
|
private boolean field_110294_bI;
|
|
private float headLean;
|
|
private float prevHeadLean;
|
|
private float rearingAmount;
|
|
private float prevRearingAmount;
|
|
private float mouthOpenness;
|
|
private float prevMouthOpenness;
|
|
|
|
/** Used to determine the sound that the horse should make when it steps */
|
|
private int gallopTime;
|
|
private String texturePrefix;
|
|
private String[] horseTexturesArray = new String[3];
|
|
private boolean field_175508_bO = false;
|
|
|
|
public EntityHorse(World worldIn)
|
|
{
|
|
super(worldIn);
|
|
this.setSize(1.4F, 1.6F);
|
|
// this.fireImmune = false;
|
|
this.setChested(false);
|
|
((PathNavigateGround)this.getNavigator()).setAvoidsWater(true);
|
|
this.tasks.addTask(0, new EntityAISwimming(this));
|
|
this.tasks.addTask(1, new EntityAIPanic(this, 1.2D));
|
|
this.tasks.addTask(1, new EntityAIRunAroundLikeCrazy(this, 1.2D));
|
|
this.tasks.addTask(2, new EntityAIMate(this, 1.0D));
|
|
this.tasks.addTask(4, new EntityAIFollowParent(this, 1.0D));
|
|
this.tasks.addTask(6, new EntityAIWander(this, 0.7D));
|
|
this.tasks.addTask(7, new EntityAIWatchClosest(this, null, 6.0F));
|
|
this.tasks.addTask(8, new EntityAILookIdle(this));
|
|
this.initHorseChest();
|
|
}
|
|
|
|
protected void entityInit()
|
|
{
|
|
super.entityInit();
|
|
this.dataWatcher.addObject(16, Integer.valueOf(0));
|
|
this.dataWatcher.addObject(19, Byte.valueOf((byte)0));
|
|
this.dataWatcher.addObject(20, Integer.valueOf(0));
|
|
// this.dataWatcher.addObject(21, String.valueOf((Object)""));
|
|
this.dataWatcher.addObject(22, Integer.valueOf(0));
|
|
}
|
|
|
|
public void setHorseType(int type)
|
|
{
|
|
this.dataWatcher.updateObject(19, Byte.valueOf((byte)type));
|
|
this.resetTexturePrefix();
|
|
}
|
|
|
|
/**
|
|
* Returns the horse type. 0 = Normal, 1 = Donkey, 2 = Mule, 3 = Undead Horse, 4 = Skeleton Horse
|
|
*/
|
|
public int getHorseType()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectByte(19);
|
|
}
|
|
|
|
public void setHorseVariant(int variant)
|
|
{
|
|
this.dataWatcher.updateObject(20, Integer.valueOf(variant));
|
|
this.resetTexturePrefix();
|
|
}
|
|
|
|
public int getHorseVariant()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectInt(20);
|
|
}
|
|
|
|
/**
|
|
* Get the name of this object. For players this returns their username
|
|
*/
|
|
public String getTypeName()
|
|
{
|
|
if (this.hasCustomName())
|
|
{
|
|
return this.getCustomNameTag();
|
|
}
|
|
else
|
|
{
|
|
int i = this.getHorseType();
|
|
|
|
switch (i)
|
|
{
|
|
case 0:
|
|
default:
|
|
return "Pferd";
|
|
|
|
case 1:
|
|
return "Esel";
|
|
|
|
case 2:
|
|
return "Maultier";
|
|
|
|
case 3:
|
|
return "Zombiepferd";
|
|
|
|
case 4:
|
|
return "Skelettpferd";
|
|
}
|
|
}
|
|
}
|
|
|
|
private boolean getHorseWatchableBoolean(int p_110233_1_)
|
|
{
|
|
return (this.dataWatcher.getWatchableObjectInt(16) & p_110233_1_) != 0;
|
|
}
|
|
|
|
private void setHorseWatchableBoolean(int p_110208_1_, boolean p_110208_2_)
|
|
{
|
|
int i = this.dataWatcher.getWatchableObjectInt(16);
|
|
|
|
if (p_110208_2_)
|
|
{
|
|
this.dataWatcher.updateObject(16, Integer.valueOf(i | p_110208_1_));
|
|
}
|
|
else
|
|
{
|
|
this.dataWatcher.updateObject(16, Integer.valueOf(i & ~p_110208_1_));
|
|
}
|
|
}
|
|
|
|
public boolean isAdultHorse()
|
|
{
|
|
return !this.isChild();
|
|
}
|
|
|
|
public boolean isTame()
|
|
{
|
|
return this.getHorseWatchableBoolean(2);
|
|
}
|
|
|
|
public boolean func_110253_bW()
|
|
{
|
|
return this.isAdultHorse();
|
|
}
|
|
|
|
// /**
|
|
// * Gets the horse's owner
|
|
// */
|
|
// public String getOwnerId()
|
|
// {
|
|
// return this.dataWatcher.getWatchableObjectString(21);
|
|
// }
|
|
//
|
|
// public void setOwnerId(String id)
|
|
// {
|
|
// this.dataWatcher.updateObject(21, id);
|
|
// }
|
|
|
|
public float getHorseSize()
|
|
{
|
|
return 0.5F;
|
|
}
|
|
|
|
/**
|
|
* "Sets the scale for an ageable entity according to the boolean parameter, which says if it's a child."
|
|
*/
|
|
public void setScaleForAge()
|
|
{
|
|
if (this.isChild())
|
|
{
|
|
this.setScale(this.getHorseSize());
|
|
}
|
|
else
|
|
{
|
|
this.setScale(1.0F);
|
|
}
|
|
}
|
|
|
|
public boolean isHorseJumping()
|
|
{
|
|
return this.horseJumping;
|
|
}
|
|
|
|
public void setHorseTamed(boolean tamed)
|
|
{
|
|
this.setHorseWatchableBoolean(2, tamed);
|
|
}
|
|
|
|
public void setHorseJumping(boolean jumping)
|
|
{
|
|
this.horseJumping = jumping;
|
|
}
|
|
|
|
public boolean allowLeashing()
|
|
{
|
|
return !this.isUndead() && super.allowLeashing();
|
|
}
|
|
|
|
protected void onUpdateLeashed(float distance)
|
|
{
|
|
if (distance > 6.0F && this.isEatingHaystack())
|
|
{
|
|
this.setEatingHaystack(false);
|
|
}
|
|
}
|
|
|
|
public boolean isChested()
|
|
{
|
|
return this.getHorseWatchableBoolean(8);
|
|
}
|
|
|
|
/**
|
|
* Returns type of armor from DataWatcher (0 = iron, 1 = gold, 2 = diamond)
|
|
*/
|
|
public int getHorseArmorIndexSynced()
|
|
{
|
|
return this.dataWatcher.getWatchableObjectInt(22);
|
|
}
|
|
|
|
/**
|
|
* 0 = iron, 1 = gold, 2 = diamond
|
|
*/
|
|
private int getHorseArmorIndex(ItemStack itemStackIn)
|
|
{
|
|
if (itemStackIn == null)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
Item item = itemStackIn.getItem();
|
|
return item == Items.iron_horse_armor ? 1 : (item == Items.gold_horse_armor ? 2 : (item == Items.diamond_horse_armor ? 3 : 0));
|
|
}
|
|
}
|
|
|
|
public boolean isEatingHaystack()
|
|
{
|
|
return this.getHorseWatchableBoolean(32);
|
|
}
|
|
|
|
public boolean isRearing()
|
|
{
|
|
return this.getHorseWatchableBoolean(64);
|
|
}
|
|
|
|
public boolean isBreeding()
|
|
{
|
|
return this.getHorseWatchableBoolean(16);
|
|
}
|
|
|
|
public boolean getHasReproduced()
|
|
{
|
|
return this.hasReproduced;
|
|
}
|
|
|
|
/**
|
|
* Set horse armor stack (for example: new ItemStack(Items.iron_horse_armor))
|
|
*/
|
|
public void setHorseArmorStack(ItemStack itemStackIn)
|
|
{
|
|
this.dataWatcher.updateObject(22, Integer.valueOf(this.getHorseArmorIndex(itemStackIn)));
|
|
this.resetTexturePrefix();
|
|
}
|
|
|
|
public void setBreeding(boolean breeding)
|
|
{
|
|
this.setHorseWatchableBoolean(16, breeding);
|
|
}
|
|
|
|
public void setChested(boolean chested)
|
|
{
|
|
this.setHorseWatchableBoolean(8, chested);
|
|
}
|
|
|
|
public void setHasReproduced(boolean hasReproducedIn)
|
|
{
|
|
this.hasReproduced = hasReproducedIn;
|
|
}
|
|
|
|
public void setHorseSaddled(boolean saddled)
|
|
{
|
|
this.setHorseWatchableBoolean(4, saddled);
|
|
}
|
|
|
|
public int getTemper()
|
|
{
|
|
return this.temper;
|
|
}
|
|
|
|
public void setTemper(int temperIn)
|
|
{
|
|
this.temper = temperIn;
|
|
}
|
|
|
|
public int increaseTemper(int p_110198_1_)
|
|
{
|
|
int i = ExtMath.clampi(this.getTemper() + p_110198_1_, 0, this.getMaxTemper());
|
|
this.setTemper(i);
|
|
return i;
|
|
}
|
|
|
|
/**
|
|
* Called when the entity is attacked.
|
|
*/
|
|
public boolean attackEntityFrom(DamageSource source, int amount)
|
|
{
|
|
Entity entity = source.getEntity();
|
|
return this.passenger != null && this.passenger.equals(entity) ? false : super.attackEntityFrom(source, amount);
|
|
}
|
|
|
|
/**
|
|
* Returns the current armor value as determined by a call to InventoryPlayer.getTotalArmorValue
|
|
*/
|
|
public int getTotalArmorValue()
|
|
{
|
|
return armorValues[this.getHorseArmorIndexSynced()];
|
|
}
|
|
|
|
/**
|
|
* Returns true if this entity should push and be pushed by other entities when colliding.
|
|
*/
|
|
public boolean canBePushed()
|
|
{
|
|
return this.passenger == null;
|
|
}
|
|
|
|
public boolean prepareChunkForSpawn()
|
|
{
|
|
int i = ExtMath.floord(this.posX);
|
|
int j = ExtMath.floord(this.posZ);
|
|
this.worldObj.getBiomeGenForCoords(new BlockPos(i, 0, j));
|
|
return true;
|
|
}
|
|
|
|
public void dropChests()
|
|
{
|
|
if (!this.worldObj.client && this.isChested())
|
|
{
|
|
this.dropItem(ItemRegistry.getItemFromBlock(Blocks.chest), 1);
|
|
this.setChested(false);
|
|
}
|
|
}
|
|
|
|
private void func_110266_cB()
|
|
{
|
|
this.openHorseMouth();
|
|
|
|
// if (!this.isSilent())
|
|
// {
|
|
// this.worldObj.playSoundAtEntity(this, "eating", 1.0F, 1.0F + (this.rand.floatv() - this.rand.floatv()) * 0.2F);
|
|
// }
|
|
}
|
|
|
|
public void fall(float distance, float damageMultiplier)
|
|
{
|
|
damageMultiplier = Math.max(0.0f, damageMultiplier - (1.65f - (float)this.worldObj.gravity * 1.65f));
|
|
if (distance > 1.0F)
|
|
{
|
|
this.playSound(SoundEvent.HORSE_LAND, 0.4F);
|
|
}
|
|
|
|
int i = ExtMath.ceilf((distance * 0.5F - 3.0F) * damageMultiplier);
|
|
|
|
if (i > 0)
|
|
{
|
|
if(Config.damageFall) {
|
|
this.attackEntityFrom(DamageSource.fall, i);
|
|
|
|
if (this.passenger != null)
|
|
{
|
|
this.passenger.attackEntityFrom(DamageSource.fall, i);
|
|
}
|
|
}
|
|
|
|
Block block = this.worldObj.getState(new BlockPos(this.posX, this.posY - 0.2D - (double)this.prevYaw, this.posZ)).getBlock();
|
|
|
|
if (block != Blocks.air) // && !this.isSilent())
|
|
{
|
|
SoundType block$soundtype = block.sound;
|
|
if(block$soundtype.getStepSound() != null)
|
|
this.worldObj.playSoundAtEntity(this, block$soundtype.getStepSound(), 0.5F);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns number of slots depending horse type
|
|
*/
|
|
private int getChestSize()
|
|
{
|
|
int i = this.getHorseType();
|
|
return !this.isChested() || i != 1 && i != 2 ? 2 : 17;
|
|
}
|
|
|
|
private void initHorseChest()
|
|
{
|
|
AnimalChest animalchest = this.horseChest;
|
|
this.horseChest = new AnimalChest("HorseChest", this.getChestSize());
|
|
this.horseChest.setCustomName(this.getName());
|
|
|
|
if (animalchest != null)
|
|
{
|
|
animalchest.removeInventoryChangeListener(this);
|
|
int i = Math.min(animalchest.getSizeInventory(), this.horseChest.getSizeInventory());
|
|
|
|
for (int j = 0; j < i; ++j)
|
|
{
|
|
ItemStack itemstack = animalchest.getStackInSlot(j);
|
|
|
|
if (itemstack != null)
|
|
{
|
|
this.horseChest.setInventorySlotContents(j, itemstack.copy());
|
|
}
|
|
}
|
|
}
|
|
|
|
this.horseChest.addInventoryChangeListener(this);
|
|
this.updateHorseSlots();
|
|
}
|
|
|
|
/**
|
|
* Updates the items in the saddle and armor slots of the horse's inventory.
|
|
*/
|
|
private void updateHorseSlots()
|
|
{
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.setHorseSaddled(this.horseChest.getStackInSlot(0) != null);
|
|
|
|
if (this.canWearArmor())
|
|
{
|
|
this.setHorseArmorStack(this.horseChest.getStackInSlot(1));
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called by InventoryBasic.onInventoryChanged() on a array that is never filled.
|
|
*/
|
|
public void onInventoryChanged(InventoryBasic p_76316_1_)
|
|
{
|
|
// int i = this.getHorseArmorIndexSynced();
|
|
// boolean flag = this.isHorseSaddled();
|
|
this.updateHorseSlots();
|
|
|
|
// if (this.ticksExisted > 20)
|
|
// {
|
|
// if (i == 0 && i != this.getHorseArmorIndexSynced())
|
|
// {
|
|
// this.playSound("mob.horse.armor", 0.5F, 1.0F);
|
|
// }
|
|
// else if (i != this.getHorseArmorIndexSynced())
|
|
// {
|
|
// this.playSound("mob.horse.armor", 0.5F, 1.0F);
|
|
// }
|
|
//
|
|
// if (!flag && this.isHorseSaddled())
|
|
// {
|
|
// this.playSound("mob.horse.leather", 0.5F, 1.0F);
|
|
// }
|
|
// }
|
|
}
|
|
|
|
/**
|
|
* Checks if the entity's current position is a valid location to spawn this entity.
|
|
*/
|
|
public boolean getCanSpawnHere()
|
|
{
|
|
this.prepareChunkForSpawn();
|
|
return super.getCanSpawnHere();
|
|
}
|
|
|
|
protected EntityHorse getClosestHorse(Entity entityIn, double distance)
|
|
{
|
|
double d0 = Double.MAX_VALUE;
|
|
Entity entity = null;
|
|
|
|
for (Entity entity1 : this.worldObj.getEntitiesInAABBexcluding(entityIn, entityIn.getEntityBoundingBox().addCoord(distance, distance, distance), horseBreedingSelector))
|
|
{
|
|
double d1 = entity1.getDistanceSq(entityIn.posX, entityIn.posY, entityIn.posZ);
|
|
|
|
if (d1 < d0)
|
|
{
|
|
entity = entity1;
|
|
d0 = d1;
|
|
}
|
|
}
|
|
|
|
return (EntityHorse)entity;
|
|
}
|
|
|
|
public double getHorseJumpStrength()
|
|
{
|
|
return this.getEntityAttribute(Attributes.HORSE_JUMP_STRENGTH).getAttributeValue();
|
|
}
|
|
|
|
/**
|
|
* Returns the sound this mob makes on death.
|
|
*/
|
|
protected SoundEvent getDeathSound()
|
|
{
|
|
this.openHorseMouth();
|
|
// int i = this.getHorseType();
|
|
return SoundEvent.HORSE_DEATH;
|
|
}
|
|
|
|
protected Item getDropItem()
|
|
{
|
|
boolean flag = this.rand.chance(4);
|
|
int i = this.getHorseType();
|
|
return i == 4 ? Items.bone : (i == 3 ? (flag ? null : Items.rotten_flesh) : Items.leather);
|
|
}
|
|
|
|
/**
|
|
* Returns the sound this mob makes when it is hurt.
|
|
*/
|
|
protected SoundEvent getHurtSound()
|
|
{
|
|
this.openHorseMouth();
|
|
|
|
if (this.rand.chance(3))
|
|
{
|
|
this.makeHorseRear();
|
|
}
|
|
|
|
// int i = this.getHorseType();
|
|
return SoundEvent.HORSE_HIT;
|
|
}
|
|
|
|
public boolean isHorseSaddled()
|
|
{
|
|
return this.getHorseWatchableBoolean(4);
|
|
}
|
|
|
|
/**
|
|
* Returns the sound this mob makes while it's alive.
|
|
*/
|
|
protected SoundEvent getLivingSound()
|
|
{
|
|
this.openHorseMouth();
|
|
|
|
if (this.rand.chance(10) && !this.isMovementBlocked())
|
|
{
|
|
this.makeHorseRear();
|
|
}
|
|
|
|
// int i = this.getHorseType();
|
|
return SoundEvent.HORSE_IDLE;
|
|
}
|
|
|
|
// protected void getAngrySoundName()
|
|
// {
|
|
// this.openHorseMouth();
|
|
// this.makeHorseRear();
|
|
//// int i = this.getHorseType();
|
|
//// return "mob.horse.angry";
|
|
// }
|
|
|
|
protected void playStepSound(BlockPos pos, Block blockIn)
|
|
{
|
|
SoundType block$soundtype = blockIn.sound;
|
|
|
|
if (this.worldObj.getState(pos.up()).getBlock() == Blocks.snow_layer)
|
|
{
|
|
block$soundtype = Blocks.snow_layer.sound;
|
|
}
|
|
|
|
if (!blockIn.getMaterial().isLiquid())
|
|
{
|
|
int i = this.getHorseType();
|
|
|
|
if (this.passenger != null && i != 1 && i != 2)
|
|
{
|
|
++this.gallopTime;
|
|
|
|
if (this.gallopTime > 5 && this.gallopTime % 3 == 0)
|
|
{
|
|
this.playSound(SoundEvent.HORSE_GALLOP, 0.15F);
|
|
|
|
if (i == 0 && this.rand.chance(10))
|
|
{
|
|
this.playSound(SoundEvent.HORSE_BREATHE, 0.6F);
|
|
}
|
|
}
|
|
else if (this.gallopTime <= 5)
|
|
{
|
|
this.playSound(SoundEvent.HORSE_WOOD, 0.15F);
|
|
}
|
|
}
|
|
else if (block$soundtype == SoundType.WOOD)
|
|
{
|
|
this.playSound(SoundEvent.HORSE_WOOD, 0.15F);
|
|
}
|
|
else
|
|
{
|
|
this.playSound(SoundEvent.HORSE_SOFT, 0.15F);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected void applyEntityAttributes()
|
|
{
|
|
super.applyEntityAttributes();
|
|
this.getAttributeMap().registerAttribute(Attributes.HORSE_JUMP_STRENGTH);
|
|
this.setMaxHealth(53);
|
|
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.22499999403953552D);
|
|
}
|
|
|
|
/**
|
|
* Will return how many at most can spawn in a chunk at once.
|
|
*/
|
|
public int getMaxChunkSpawns()
|
|
{
|
|
return 6;
|
|
}
|
|
|
|
public int getMaxTemper()
|
|
{
|
|
return 100;
|
|
}
|
|
|
|
/**
|
|
* Returns the volume for the sounds this mob makes.
|
|
*/
|
|
protected float getSoundVolume()
|
|
{
|
|
return 0.8F;
|
|
}
|
|
|
|
/**
|
|
* Get number of ticks, at least during which the living entity will be silent.
|
|
*/
|
|
public int getTalkInterval()
|
|
{
|
|
return 400;
|
|
}
|
|
|
|
public boolean func_110239_cn()
|
|
{
|
|
return this.getHorseType() == 0 || this.getHorseArmorIndexSynced() > 0;
|
|
}
|
|
|
|
private void resetTexturePrefix()
|
|
{
|
|
this.texturePrefix = null;
|
|
}
|
|
|
|
public boolean func_175507_cI()
|
|
{
|
|
return this.field_175508_bO;
|
|
}
|
|
|
|
private void setHorseTexturePaths()
|
|
{
|
|
this.texturePrefix = "horse/";
|
|
this.horseTexturesArray[0] = null;
|
|
this.horseTexturesArray[1] = null;
|
|
this.horseTexturesArray[2] = null;
|
|
int i = this.getHorseType();
|
|
int j = this.getHorseVariant();
|
|
|
|
if (i == 0)
|
|
{
|
|
int k = j & 255;
|
|
int l = (j & 65280) >> 8;
|
|
|
|
if (k >= horseTextures.length)
|
|
{
|
|
this.field_175508_bO = false;
|
|
return;
|
|
}
|
|
|
|
this.horseTexturesArray[0] = horseTextures[k];
|
|
this.texturePrefix = this.texturePrefix + HORSE_TEXTURES_ABBR[k];
|
|
|
|
if (l >= horseMarkingTextures.length)
|
|
{
|
|
this.field_175508_bO = false;
|
|
return;
|
|
}
|
|
|
|
this.horseTexturesArray[1] = horseMarkingTextures[l];
|
|
this.texturePrefix = this.texturePrefix + HORSE_MARKING_TEXTURES_ABBR[l];
|
|
}
|
|
else
|
|
{
|
|
this.horseTexturesArray[0] = "";
|
|
this.texturePrefix = this.texturePrefix + "_" + i + "_";
|
|
}
|
|
|
|
int i1 = this.getHorseArmorIndexSynced();
|
|
|
|
if (i1 >= horseArmorTextures.length)
|
|
{
|
|
this.field_175508_bO = false;
|
|
}
|
|
else
|
|
{
|
|
this.horseTexturesArray[2] = horseArmorTextures[i1];
|
|
this.texturePrefix = this.texturePrefix + HORSE_ARMOR_TEXTURES_ABBR[i1];
|
|
this.field_175508_bO = true;
|
|
}
|
|
}
|
|
|
|
public String getHorseTexture()
|
|
{
|
|
if (this.texturePrefix == null)
|
|
{
|
|
this.setHorseTexturePaths();
|
|
}
|
|
|
|
return this.texturePrefix;
|
|
}
|
|
|
|
public String[] getVariantTexturePaths()
|
|
{
|
|
if (this.texturePrefix == null)
|
|
{
|
|
this.setHorseTexturePaths();
|
|
}
|
|
|
|
return this.horseTexturesArray;
|
|
}
|
|
|
|
public void openGUI(EntityNPC playerEntity)
|
|
{
|
|
if (!this.worldObj.client && (this.passenger == null || this.passenger == playerEntity) && this.isTame())
|
|
{
|
|
this.horseChest.setCustomName(this.getName());
|
|
playerEntity.displayGUIHorse(this, this.horseChest);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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 ItemMonsterPlacer)
|
|
{
|
|
return super.interact(player);
|
|
}
|
|
else if (!this.isTame() && this.isUndead())
|
|
{
|
|
return false;
|
|
}
|
|
else if (this.isTame() && this.isAdultHorse() && player.isSneaking())
|
|
{
|
|
this.openGUI(player);
|
|
return true;
|
|
}
|
|
else if (this.func_110253_bW() && this.passenger != null)
|
|
{
|
|
return super.interact(player);
|
|
}
|
|
else
|
|
{
|
|
if (itemstack != null)
|
|
{
|
|
boolean flag = false;
|
|
|
|
if (this.canWearArmor())
|
|
{
|
|
int i = -1;
|
|
|
|
if (itemstack.getItem() == Items.iron_horse_armor)
|
|
{
|
|
i = 1;
|
|
}
|
|
else if (itemstack.getItem() == Items.gold_horse_armor)
|
|
{
|
|
i = 2;
|
|
}
|
|
else if (itemstack.getItem() == Items.diamond_horse_armor)
|
|
{
|
|
i = 3;
|
|
}
|
|
|
|
if (i >= 0)
|
|
{
|
|
if (!this.isTame())
|
|
{
|
|
this.makeHorseRearWithSound();
|
|
return true;
|
|
}
|
|
|
|
this.openGUI(player);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (!flag && !this.isUndead())
|
|
{
|
|
int hp = 0;
|
|
int j = 0;
|
|
int k = 0;
|
|
|
|
if (itemstack.getItem() == Items.wheats)
|
|
{
|
|
hp = 2;
|
|
j = 20;
|
|
k = 3;
|
|
}
|
|
else if (itemstack.getItem() == Items.sugar)
|
|
{
|
|
hp = 1;
|
|
j = 30;
|
|
k = 3;
|
|
}
|
|
else if (itemstack.getItem().getBlock() == Blocks.hay_block)
|
|
{
|
|
hp = 20;
|
|
j = 180;
|
|
}
|
|
else if (itemstack.getItem() == Items.apple)
|
|
{
|
|
hp = 3;
|
|
j = 60;
|
|
k = 3;
|
|
}
|
|
else if (itemstack.getItem() == Items.golden_carrot)
|
|
{
|
|
hp = 4;
|
|
j = 60;
|
|
k = 5;
|
|
|
|
if (this.isTame() && this.getGrowingAge() == 0)
|
|
{
|
|
flag = true;
|
|
this.setInLove(player);
|
|
}
|
|
}
|
|
else if (itemstack.getItem() == Items.golden_apple)
|
|
{
|
|
hp = 10;
|
|
j = 240;
|
|
k = 10;
|
|
|
|
if (this.isTame() && this.getGrowingAge() == 0)
|
|
{
|
|
flag = true;
|
|
this.setInLove(player);
|
|
}
|
|
}
|
|
|
|
if (this.getHealth() < this.getMaxHealth() && hp > 0)
|
|
{
|
|
this.heal(hp);
|
|
flag = true;
|
|
}
|
|
|
|
if (!this.isAdultHorse() && j > 0)
|
|
{
|
|
if(!this.worldObj.client)
|
|
this.grow(j);
|
|
flag = true;
|
|
}
|
|
|
|
if (k > 0 && (flag || !this.isTame()) && k < this.getMaxTemper())
|
|
{
|
|
flag = true;
|
|
this.increaseTemper(k);
|
|
}
|
|
|
|
if (flag)
|
|
{
|
|
this.func_110266_cB();
|
|
}
|
|
}
|
|
|
|
if (!this.isTame() && !flag)
|
|
{
|
|
if (itemstack != null && itemstack.interactWithEntity(player, this))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
this.makeHorseRearWithSound();
|
|
return true;
|
|
}
|
|
|
|
if (!flag && this.canCarryChest() && !this.isChested() && itemstack.getItem() == ItemRegistry.getItemFromBlock(Blocks.chest))
|
|
{
|
|
this.setChested(true);
|
|
this.playSound(SoundEvent.PLOP, 1.0F);
|
|
flag = true;
|
|
this.initHorseChest();
|
|
}
|
|
|
|
if (!flag && this.func_110253_bW() && !this.isHorseSaddled() && itemstack.getItem() == Items.saddle)
|
|
{
|
|
this.openGUI(player);
|
|
return true;
|
|
}
|
|
|
|
if (flag)
|
|
{
|
|
if (/* !player.creative && */ --itemstack.stackSize == 0)
|
|
{
|
|
player.inventory.setInventorySlotContents(player.inventory.currentItem, (ItemStack)null);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (this.func_110253_bW() && this.passenger == null)
|
|
{
|
|
if (itemstack != null && itemstack.interactWithEntity(player, this))
|
|
{
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
this.mountTo(player);
|
|
return true;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return super.interact(player);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void mountTo(EntityNPC player)
|
|
{
|
|
player.rotYaw = this.rotYaw;
|
|
player.rotPitch = this.rotPitch;
|
|
this.setEatingHaystack(false);
|
|
this.setRearing(false);
|
|
|
|
if (!this.worldObj.client)
|
|
{
|
|
player.mountEntity(this);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if the horse entity can wear an armor
|
|
*/
|
|
public boolean canWearArmor()
|
|
{
|
|
return this.getHorseType() == 0;
|
|
}
|
|
|
|
/**
|
|
* Return true if the horse entity can carry a chest.
|
|
*/
|
|
public boolean canCarryChest()
|
|
{
|
|
int i = this.getHorseType();
|
|
return i == 2 || i == 1;
|
|
}
|
|
|
|
/**
|
|
* Dead and sleeping entities cannot move
|
|
*/
|
|
protected boolean isMovementBlocked()
|
|
{
|
|
return this.passenger != null && this.isHorseSaddled() ? true : this.isEatingHaystack() || this.isRearing();
|
|
}
|
|
|
|
/**
|
|
* Used to know if the horse can be leashed, if he can mate, or if we can interact with him
|
|
*/
|
|
public boolean isUndead()
|
|
{
|
|
int i = this.getHorseType();
|
|
return i == 3 || i == 4;
|
|
}
|
|
|
|
/**
|
|
* Return true if the horse entity is sterile (Undead || Mule)
|
|
*/
|
|
public boolean isSterile()
|
|
{
|
|
return this.isUndead() || this.getHorseType() == 2;
|
|
}
|
|
|
|
/**
|
|
* 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 false;
|
|
}
|
|
|
|
private void func_110210_cH()
|
|
{
|
|
this.field_110278_bp = 1;
|
|
}
|
|
|
|
/**
|
|
* Called when the mob's health reaches 0.
|
|
*/
|
|
public void onDeath(DamageSource cause)
|
|
{
|
|
super.onDeath(cause);
|
|
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.dropChestItems();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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.rand.chance(200))
|
|
{
|
|
this.func_110210_cH();
|
|
}
|
|
|
|
super.onLivingUpdate();
|
|
|
|
if (!this.worldObj.client)
|
|
{
|
|
if (this.rand.chance(900) && this.deathTime == 0)
|
|
{
|
|
this.heal(1);
|
|
}
|
|
|
|
if (!this.isEatingHaystack() && this.passenger == null && this.rand.chance(300) && this.worldObj.getState(new BlockPos(ExtMath.floord(this.posX), ExtMath.floord(this.posY) - 1, ExtMath.floord(this.posZ))).getBlock() == Blocks.grass)
|
|
{
|
|
this.setEatingHaystack(true);
|
|
}
|
|
|
|
if (this.isEatingHaystack() && ++this.eatingHaystackCounter > 50)
|
|
{
|
|
this.eatingHaystackCounter = 0;
|
|
this.setEatingHaystack(false);
|
|
}
|
|
|
|
if (this.isBreeding() && !this.isAdultHorse() && !this.isEatingHaystack())
|
|
{
|
|
EntityHorse entityhorse = this.getClosestHorse(this, 16.0D);
|
|
|
|
if (entityhorse != null && this.getDistanceSqToEntity(entityhorse) > 4.0D)
|
|
{
|
|
this.navigator.getPathToEntityLiving(entityhorse);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to update the entity's position/logic.
|
|
*/
|
|
public void onUpdate()
|
|
{
|
|
super.onUpdate();
|
|
|
|
if (this.worldObj.client && this.dataWatcher.hasObjectChanged())
|
|
{
|
|
this.dataWatcher.markUnchanged();
|
|
this.resetTexturePrefix();
|
|
}
|
|
|
|
if (this.openMouthCounter > 0 && ++this.openMouthCounter > 30)
|
|
{
|
|
this.openMouthCounter = 0;
|
|
this.setHorseWatchableBoolean(128, false);
|
|
}
|
|
|
|
if (!this.worldObj.client && this.jumpRearingCounter > 0 && ++this.jumpRearingCounter > 20)
|
|
{
|
|
this.jumpRearingCounter = 0;
|
|
this.setRearing(false);
|
|
}
|
|
|
|
if (this.field_110278_bp > 0 && ++this.field_110278_bp > 8)
|
|
{
|
|
this.field_110278_bp = 0;
|
|
}
|
|
|
|
if (this.field_110279_bq > 0)
|
|
{
|
|
++this.field_110279_bq;
|
|
|
|
if (this.field_110279_bq > 300)
|
|
{
|
|
this.field_110279_bq = 0;
|
|
}
|
|
}
|
|
|
|
this.prevHeadLean = this.headLean;
|
|
|
|
if (this.isEatingHaystack())
|
|
{
|
|
this.headLean += (1.0F - this.headLean) * 0.4F + 0.05F;
|
|
|
|
if (this.headLean > 1.0F)
|
|
{
|
|
this.headLean = 1.0F;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.headLean += (0.0F - this.headLean) * 0.4F - 0.05F;
|
|
|
|
if (this.headLean < 0.0F)
|
|
{
|
|
this.headLean = 0.0F;
|
|
}
|
|
}
|
|
|
|
this.prevRearingAmount = this.rearingAmount;
|
|
|
|
if (this.isRearing())
|
|
{
|
|
this.prevHeadLean = this.headLean = 0.0F;
|
|
this.rearingAmount += (1.0F - this.rearingAmount) * 0.4F + 0.05F;
|
|
|
|
if (this.rearingAmount > 1.0F)
|
|
{
|
|
this.rearingAmount = 1.0F;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.field_110294_bI = false;
|
|
this.rearingAmount += (0.8F * this.rearingAmount * this.rearingAmount * this.rearingAmount - this.rearingAmount) * 0.6F - 0.05F;
|
|
|
|
if (this.rearingAmount < 0.0F)
|
|
{
|
|
this.rearingAmount = 0.0F;
|
|
}
|
|
}
|
|
|
|
this.prevMouthOpenness = this.mouthOpenness;
|
|
|
|
if (this.getHorseWatchableBoolean(128))
|
|
{
|
|
this.mouthOpenness += (1.0F - this.mouthOpenness) * 0.7F + 0.05F;
|
|
|
|
if (this.mouthOpenness > 1.0F)
|
|
{
|
|
this.mouthOpenness = 1.0F;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.mouthOpenness += (0.0F - this.mouthOpenness) * 0.7F - 0.05F;
|
|
|
|
if (this.mouthOpenness < 0.0F)
|
|
{
|
|
this.mouthOpenness = 0.0F;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void openHorseMouth()
|
|
{
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.openMouthCounter = 1;
|
|
this.setHorseWatchableBoolean(128, true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Return true if the horse entity ready to mate. (no rider, not riding, tame, adult, not steril...)
|
|
*/
|
|
private boolean canMate()
|
|
{
|
|
return this.passenger == null && this.vehicle == null && this.isTame() && this.isAdultHorse() && !this.isSterile() && this.getHealth() >= this.getMaxHealth() && this.isInLove();
|
|
}
|
|
|
|
public void setUsing(boolean eating)
|
|
{
|
|
this.setHorseWatchableBoolean(32, eating);
|
|
}
|
|
|
|
public void setEatingHaystack(boolean p_110227_1_)
|
|
{
|
|
this.setUsing(p_110227_1_);
|
|
}
|
|
|
|
public void setRearing(boolean rearing)
|
|
{
|
|
if (rearing)
|
|
{
|
|
this.setEatingHaystack(false);
|
|
}
|
|
|
|
this.setHorseWatchableBoolean(64, rearing);
|
|
}
|
|
|
|
private void makeHorseRear()
|
|
{
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.jumpRearingCounter = 1;
|
|
this.setRearing(true);
|
|
}
|
|
}
|
|
|
|
public void makeHorseRearWithSound()
|
|
{
|
|
this.openHorseMouth();
|
|
this.makeHorseRear();
|
|
// String s =
|
|
// this.getAngrySoundName();
|
|
|
|
// if (s != null)
|
|
// {
|
|
this.playSound(SoundEvent.HORSE_ANGRY, this.getSoundVolume());
|
|
// }
|
|
}
|
|
|
|
public void dropChestItems()
|
|
{
|
|
this.dropItemsInChest(this, this.horseChest);
|
|
this.dropChests();
|
|
}
|
|
|
|
private void dropItemsInChest(Entity entityIn, AnimalChest animalChestIn)
|
|
{
|
|
if (animalChestIn != null && !this.worldObj.client)
|
|
{
|
|
for (int i = 0; i < animalChestIn.getSizeInventory(); ++i)
|
|
{
|
|
ItemStack itemstack = animalChestIn.getStackInSlot(i);
|
|
|
|
if (itemstack != null)
|
|
{
|
|
this.entityDropItem(itemstack, 0.0F);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Moves the entity based on the specified heading. Args: strafe, forward
|
|
*/
|
|
public void moveEntityWithHeading(float strafe, float forward)
|
|
{
|
|
if (this.passenger != null && this.passenger instanceof EntityLiving && this.isHorseSaddled())
|
|
{
|
|
this.prevYaw = this.rotYaw = this.passenger.rotYaw;
|
|
this.rotPitch = this.passenger.rotPitch * 0.5F;
|
|
this.setRotation(this.rotYaw, this.rotPitch);
|
|
this.headYaw = this.yawOffset = this.rotYaw;
|
|
strafe = ((EntityLiving)this.passenger).moveStrafe * 0.5F;
|
|
forward = ((EntityLiving)this.passenger).moveForward;
|
|
|
|
if (forward <= 0.0F)
|
|
{
|
|
forward *= 0.25F;
|
|
this.gallopTime = 0;
|
|
}
|
|
|
|
if (this.onGround && this.jumpPower == 0.0F && this.isRearing() && !this.field_110294_bI)
|
|
{
|
|
strafe = 0.0F;
|
|
forward = 0.0F;
|
|
}
|
|
|
|
if (this.jumpPower > 0.0F && !this.isHorseJumping() && this.onGround)
|
|
{
|
|
this.motionY = this.getHorseJumpStrength() * (double)this.jumpPower;
|
|
|
|
if (this.hasEffect(Potion.JUMP))
|
|
{
|
|
this.motionY += (double)((float)(this.getEffect(Potion.JUMP).getAmplifier() + 1) * 0.1F);
|
|
}
|
|
|
|
this.setHorseJumping(true);
|
|
this.isAirBorne = true;
|
|
|
|
if (forward > 0.0F)
|
|
{
|
|
float f = ExtMath.sin(this.rotYaw * (float)Math.PI / 180.0F);
|
|
float f1 = ExtMath.cos(this.rotYaw * (float)Math.PI / 180.0F);
|
|
this.motionX += (double)(-0.4F * f * this.jumpPower);
|
|
this.motionZ += (double)(0.4F * f1 * this.jumpPower);
|
|
this.playSound(SoundEvent.HORSE_JUMP, 0.4F);
|
|
}
|
|
|
|
this.jumpPower = 0.0F;
|
|
}
|
|
|
|
this.stepHeight = 1.0F;
|
|
this.jumpMovement = this.getAIMoveSpeed() * 0.1F;
|
|
|
|
if (!this.worldObj.client)
|
|
{
|
|
this.setAIMoveSpeed((float)this.getEntityAttribute(Attributes.MOVEMENT_SPEED).getAttributeValue());
|
|
super.moveEntityWithHeading(strafe, forward);
|
|
}
|
|
|
|
if (this.onGround)
|
|
{
|
|
this.jumpPower = 0.0F;
|
|
this.setHorseJumping(false);
|
|
}
|
|
|
|
this.prevLswingAmount = this.lswingAmount;
|
|
double d1 = this.posX - this.prevX;
|
|
double d0 = this.posZ - this.prevZ;
|
|
float f2 = ExtMath.sqrtd(d1 * d1 + d0 * d0) * 4.0F;
|
|
|
|
if (f2 > 1.0F)
|
|
{
|
|
f2 = 1.0F;
|
|
}
|
|
|
|
this.lswingAmount += (f2 - this.lswingAmount) * 0.4F;
|
|
this.limbSwing += this.lswingAmount;
|
|
}
|
|
else
|
|
{
|
|
this.stepHeight = 0.5F;
|
|
this.jumpMovement = 0.02F;
|
|
super.moveEntityWithHeading(strafe, forward);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* (abstract) Protected helper method to write subclass entity data to NBT.
|
|
*/
|
|
public void writeEntityToNBT(TagObject tagCompound)
|
|
{
|
|
super.writeEntityToNBT(tagCompound);
|
|
tagCompound.setBool("EatingHaystack", this.isEatingHaystack());
|
|
tagCompound.setBool("ChestedHorse", this.isChested());
|
|
tagCompound.setBool("HasReproduced", this.getHasReproduced());
|
|
tagCompound.setBool("Bred", this.isBreeding());
|
|
tagCompound.setInt("Type", this.getHorseType());
|
|
tagCompound.setInt("Variant", this.getHorseVariant());
|
|
tagCompound.setInt("Temper", this.getTemper());
|
|
tagCompound.setBool("Tame", this.isTame());
|
|
// tagCompound.setString("Owner", this.getOwnerId());
|
|
|
|
if (this.isChested())
|
|
{
|
|
TagObjectList nbttaglist = new TagObjectList();
|
|
|
|
for (int i = 2; i < this.horseChest.getSizeInventory(); ++i)
|
|
{
|
|
ItemStack itemstack = this.horseChest.getStackInSlot(i);
|
|
|
|
if (itemstack != null)
|
|
{
|
|
TagObject nbttagcompound = new TagObject();
|
|
nbttagcompound.setByte("Slot", (byte)i);
|
|
itemstack.writeToNBT(nbttagcompound);
|
|
nbttaglist.add(nbttagcompound);
|
|
}
|
|
}
|
|
|
|
tagCompound.setTagList("Items", nbttaglist);
|
|
}
|
|
|
|
if (this.horseChest.getStackInSlot(1) != null)
|
|
{
|
|
tagCompound.setTag("ArmorItem", this.horseChest.getStackInSlot(1).writeToNBT(new TagObject()));
|
|
}
|
|
|
|
if (this.horseChest.getStackInSlot(0) != null)
|
|
{
|
|
tagCompound.setTag("SaddleItem", this.horseChest.getStackInSlot(0).writeToNBT(new TagObject()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* (abstract) Protected helper method to read subclass entity data from NBT.
|
|
*/
|
|
public void readEntityFromNBT(TagObject tagCompund)
|
|
{
|
|
super.readEntityFromNBT(tagCompund);
|
|
this.setEatingHaystack(tagCompund.getBool("EatingHaystack"));
|
|
this.setBreeding(tagCompund.getBool("Bred"));
|
|
this.setChested(tagCompund.getBool("ChestedHorse"));
|
|
this.setHasReproduced(tagCompund.getBool("HasReproduced"));
|
|
this.setHorseType(tagCompund.getInt("Type"));
|
|
this.setHorseVariant(tagCompund.getInt("Variant"));
|
|
this.setTemper(tagCompund.getInt("Temper"));
|
|
this.setHorseTamed(tagCompund.getBool("Tame"));
|
|
// String s = "";
|
|
//
|
|
// if (tagCompund.hasString("Owner"))
|
|
// {
|
|
// s = tagCompund.getString("Owner");
|
|
// }
|
|
//
|
|
// if (s.length() > 0)
|
|
// {
|
|
// this.setOwnerId(s);
|
|
// }
|
|
|
|
AttributeInstance iattributeinstance = this.getAttributeMap().getAttributeInstanceByName("Speed");
|
|
|
|
if (iattributeinstance != null)
|
|
{
|
|
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(iattributeinstance.getBaseValue() * 0.25D);
|
|
}
|
|
|
|
if (this.isChested())
|
|
{
|
|
TagObjectList nbttaglist = tagCompund.getTagList("Items");
|
|
this.initHorseChest();
|
|
|
|
for (int i = 0; i < nbttaglist.size(); ++i)
|
|
{
|
|
TagObject nbttagcompound = nbttaglist.get(i);
|
|
int j = nbttagcompound.getByte("Slot") & 255;
|
|
|
|
if (j >= 2 && j < this.horseChest.getSizeInventory())
|
|
{
|
|
this.horseChest.setInventorySlotContents(j, ItemStack.loadItemStackFromNBT(nbttagcompound));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (tagCompund.hasTag("ArmorItem"))
|
|
{
|
|
ItemStack itemstack = ItemStack.loadItemStackFromNBT(tagCompund.getTag("ArmorItem"));
|
|
|
|
if (itemstack != null && isArmorItem(itemstack.getItem()))
|
|
{
|
|
this.horseChest.setInventorySlotContents(1, itemstack);
|
|
}
|
|
}
|
|
|
|
if (tagCompund.hasTag("SaddleItem"))
|
|
{
|
|
ItemStack itemstack1 = ItemStack.loadItemStackFromNBT(tagCompund.getTag("SaddleItem"));
|
|
|
|
if (itemstack1 != null && itemstack1.getItem() == Items.saddle)
|
|
{
|
|
this.horseChest.setInventorySlotContents(0, itemstack1);
|
|
}
|
|
}
|
|
else if (tagCompund.getBool("Saddle"))
|
|
{
|
|
this.horseChest.setInventorySlotContents(0, new ItemStack(Items.saddle));
|
|
}
|
|
|
|
this.updateHorseSlots();
|
|
}
|
|
|
|
/**
|
|
* 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 (otherAnimal.getClass() != this.getClass())
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
EntityHorse entityhorse = (EntityHorse)otherAnimal;
|
|
|
|
if (this.canMate() && entityhorse.canMate())
|
|
{
|
|
int i = this.getHorseType();
|
|
int j = entityhorse.getHorseType();
|
|
return i == j || i == 0 && j == 1 || i == 1 && j == 0;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public EntityHorse createChild(EntityLiving ageable)
|
|
{
|
|
EntityHorse entityhorse = (EntityHorse)ageable;
|
|
EntityHorse entityhorse1 = new EntityHorse(this.worldObj);
|
|
int i = this.getHorseType();
|
|
int j = entityhorse.getHorseType();
|
|
int k = 0;
|
|
|
|
if (i == j)
|
|
{
|
|
k = i;
|
|
}
|
|
else if (i == 0 && j == 1 || i == 1 && j == 0)
|
|
{
|
|
k = 2;
|
|
}
|
|
|
|
if (k == 0)
|
|
{
|
|
int i1 = this.rand.zrange(9);
|
|
int l;
|
|
|
|
if (i1 < 4)
|
|
{
|
|
l = this.getHorseVariant() & 255;
|
|
}
|
|
else if (i1 < 8)
|
|
{
|
|
l = entityhorse.getHorseVariant() & 255;
|
|
}
|
|
else
|
|
{
|
|
l = this.rand.zrange(7);
|
|
}
|
|
|
|
int j1 = this.rand.zrange(5);
|
|
|
|
if (j1 < 2)
|
|
{
|
|
l = l | this.getHorseVariant() & 65280;
|
|
}
|
|
else if (j1 < 4)
|
|
{
|
|
l = l | entityhorse.getHorseVariant() & 65280;
|
|
}
|
|
else
|
|
{
|
|
l = l | this.rand.zrange(5) << 8 & 65280;
|
|
}
|
|
|
|
entityhorse1.setHorseVariant(l);
|
|
}
|
|
|
|
entityhorse1.setHorseType(k);
|
|
int d1 = this.getRawMaxHealth() + ageable.getRawMaxHealth() + this.getModifiedMaxHealth();
|
|
entityhorse1.setMaxHealth(d1 / 3);
|
|
double d2 = this.getEntityAttribute(Attributes.HORSE_JUMP_STRENGTH).getBaseValue() + ageable.getEntityAttribute(Attributes.HORSE_JUMP_STRENGTH).getBaseValue() + this.getModifiedJumpStrength();
|
|
entityhorse1.getEntityAttribute(Attributes.HORSE_JUMP_STRENGTH).setBaseValue(d2 / 3.0D);
|
|
double d0 = this.getEntityAttribute(Attributes.MOVEMENT_SPEED).getBaseValue() + ageable.getEntityAttribute(Attributes.MOVEMENT_SPEED).getBaseValue() + this.getModifiedMovementSpeed();
|
|
entityhorse1.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(d0 / 3.0D);
|
|
return entityhorse1;
|
|
}
|
|
|
|
/**
|
|
* 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);
|
|
int i = 0;
|
|
int j = 0;
|
|
|
|
if (livingdata instanceof EntityHorse.GroupData)
|
|
{
|
|
i = ((EntityHorse.GroupData)livingdata).horseType;
|
|
j = ((EntityHorse.GroupData)livingdata).horseVariant & 255 | this.rand.zrange(5) << 8;
|
|
}
|
|
else
|
|
{
|
|
if (this.rand.chance(10))
|
|
{
|
|
i = 1;
|
|
}
|
|
else
|
|
{
|
|
int k = this.rand.zrange(7);
|
|
int l = this.rand.zrange(5);
|
|
i = 0;
|
|
j = k | l << 8;
|
|
}
|
|
|
|
livingdata = new EntityHorse.GroupData(i, j);
|
|
}
|
|
|
|
this.setHorseType(i);
|
|
this.setHorseVariant(j);
|
|
|
|
if (this.rand.chance(5))
|
|
{
|
|
this.setGrowingAge(-24000);
|
|
}
|
|
|
|
if (i != 4 && i != 3)
|
|
{
|
|
this.setMaxHealth(this.getModifiedMaxHealth());
|
|
|
|
if (i == 0)
|
|
{
|
|
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(this.getModifiedMovementSpeed());
|
|
}
|
|
else
|
|
{
|
|
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.17499999701976776D);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.setMaxHealth(15);
|
|
this.getEntityAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.20000000298023224D);
|
|
}
|
|
|
|
if (i != 2 && i != 1)
|
|
{
|
|
this.getEntityAttribute(Attributes.HORSE_JUMP_STRENGTH).setBaseValue(this.getModifiedJumpStrength());
|
|
}
|
|
else
|
|
{
|
|
this.getEntityAttribute(Attributes.HORSE_JUMP_STRENGTH).setBaseValue(0.5D);
|
|
}
|
|
|
|
this.setHealth(this.getMaxHealth());
|
|
return livingdata;
|
|
}
|
|
|
|
public float getGrassEatingAmount(float p_110258_1_)
|
|
{
|
|
return this.prevHeadLean + (this.headLean - this.prevHeadLean) * p_110258_1_;
|
|
}
|
|
|
|
public float getRearingAmount(float p_110223_1_)
|
|
{
|
|
return this.prevRearingAmount + (this.rearingAmount - this.prevRearingAmount) * p_110223_1_;
|
|
}
|
|
|
|
public float getMouthOpennessAngle(float p_110201_1_)
|
|
{
|
|
return this.prevMouthOpenness + (this.mouthOpenness - this.prevMouthOpenness) * p_110201_1_;
|
|
}
|
|
|
|
public void setJumpPower(int jumpPowerIn)
|
|
{
|
|
if (this.isHorseSaddled())
|
|
{
|
|
if (jumpPowerIn < 0)
|
|
{
|
|
jumpPowerIn = 0;
|
|
}
|
|
else
|
|
{
|
|
this.field_110294_bI = true;
|
|
this.makeHorseRear();
|
|
}
|
|
|
|
if (jumpPowerIn >= 90)
|
|
{
|
|
this.jumpPower = 1.0F;
|
|
}
|
|
else
|
|
{
|
|
this.jumpPower = 0.4F + 0.4F * (float)jumpPowerIn / 90.0F;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* "Spawns particles for the horse entity. par1 tells whether to spawn hearts. If it is false, it spawns smoke."
|
|
*/
|
|
protected void spawnHorseParticles(boolean p_110216_1_)
|
|
{
|
|
ParticleType enumparticletypes = p_110216_1_ ? ParticleType.HEART : ParticleType.SMOKE_NORMAL;
|
|
|
|
for (int i = 0; i < 7; ++i)
|
|
{
|
|
double d0 = this.rand.gaussian() * 0.02D;
|
|
double d1 = this.rand.gaussian() * 0.02D;
|
|
double d2 = this.rand.gaussian() * 0.02D;
|
|
this.worldObj.spawnParticle(enumparticletypes, 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, d0, d1, d2);
|
|
}
|
|
}
|
|
|
|
public void handleStatusUpdate(byte id)
|
|
{
|
|
if (id == 7)
|
|
{
|
|
this.spawnHorseParticles(true);
|
|
}
|
|
else if (id == 6)
|
|
{
|
|
this.spawnHorseParticles(false);
|
|
}
|
|
else
|
|
{
|
|
super.handleStatusUpdate(id);
|
|
}
|
|
}
|
|
|
|
public void updateRiderPosition()
|
|
{
|
|
super.updateRiderPosition();
|
|
|
|
if (this.prevRearingAmount > 0.0F)
|
|
{
|
|
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.7F * this.prevRearingAmount;
|
|
float f3 = 0.15F * this.prevRearingAmount;
|
|
this.passenger.setPosition(this.posX + (double)(f2 * f), this.posY + this.getMountedYOffset() + this.passenger.getYOffset() + (double)f3, this.posZ - (double)(f2 * f1));
|
|
|
|
if (this.passenger instanceof EntityLiving)
|
|
{
|
|
((EntityLiving)this.passenger).yawOffset = this.yawOffset;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns randomized max health
|
|
*/
|
|
private int getModifiedMaxHealth()
|
|
{
|
|
return 15 + this.rand.zrange(8) + this.rand.zrange(9);
|
|
}
|
|
|
|
/**
|
|
* Returns randomized jump strength
|
|
*/
|
|
private double getModifiedJumpStrength()
|
|
{
|
|
return 0.4000000059604645D + this.rand.doublev() * 0.2D + this.rand.doublev() * 0.2D + this.rand.doublev() * 0.2D;
|
|
}
|
|
|
|
/**
|
|
* Returns randomized movement speed
|
|
*/
|
|
private double getModifiedMovementSpeed()
|
|
{
|
|
return (0.44999998807907104D + this.rand.doublev() * 0.3D + this.rand.doublev() * 0.3D + this.rand.doublev() * 0.3D) * 0.25D;
|
|
}
|
|
|
|
/**
|
|
* Returns true if given item is horse armor
|
|
*/
|
|
public static boolean isArmorItem(Item p_146085_0_)
|
|
{
|
|
return p_146085_0_ == Items.iron_horse_armor || p_146085_0_ == Items.gold_horse_armor || p_146085_0_ == Items.diamond_horse_armor;
|
|
}
|
|
|
|
/**
|
|
* returns true if this entity is by a ladder, false otherwise
|
|
*/
|
|
public boolean isOnLadder()
|
|
{
|
|
return false;
|
|
}
|
|
|
|
public float getEyeHeight()
|
|
{
|
|
return this.height;
|
|
}
|
|
|
|
// public boolean setSlot(int slot, ItemStack stack)
|
|
// {
|
|
// if (slot == 499 && this.canCarryChest())
|
|
// {
|
|
// if (stack == null && this.isChested())
|
|
// {
|
|
// this.setChested(false);
|
|
// this.initHorseChest();
|
|
// return true;
|
|
// }
|
|
//
|
|
// if (stack != null && stack.getItem() == ItemRegistry.getItemFromBlock(Blocks.chest) && !this.isChested())
|
|
// {
|
|
// this.setChested(true);
|
|
// this.initHorseChest();
|
|
// return true;
|
|
// }
|
|
// }
|
|
//
|
|
// int i = slot - 400;
|
|
//
|
|
// if (i >= 0 && i < 2 && i < this.horseChest.getSizeInventory())
|
|
// {
|
|
// if (i == 0 && stack != null && stack.getItem() != Items.saddle)
|
|
// {
|
|
// return false;
|
|
// }
|
|
// else if (i != 1 || (stack == null || isArmorItem(stack.getItem())) && this.canWearArmor())
|
|
// {
|
|
// this.horseChest.setInventorySlotContents(i, stack);
|
|
// this.updateHorseSlots();
|
|
// return true;
|
|
// }
|
|
// else
|
|
// {
|
|
// return false;
|
|
// }
|
|
// }
|
|
// else
|
|
// {
|
|
// int j = slot - 500 + 2;
|
|
//
|
|
// if (j >= 2 && j < this.horseChest.getSizeInventory())
|
|
// {
|
|
// this.horseChest.setInventorySlotContents(j, stack);
|
|
// return true;
|
|
// }
|
|
// else
|
|
// {
|
|
// return false;
|
|
// }
|
|
// }
|
|
// }
|
|
|
|
public int getLeashColor() {
|
|
return 0x4f3923;
|
|
}
|
|
|
|
public int getColor() {
|
|
return 0x886038;
|
|
}
|
|
|
|
public static class GroupData
|
|
{
|
|
public int horseType;
|
|
public int horseVariant;
|
|
|
|
public GroupData(int type, int variant)
|
|
{
|
|
this.horseType = type;
|
|
this.horseVariant = variant;
|
|
}
|
|
}
|
|
}
|