package net.minecraft.entity; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; import java.util.Iterator; import java.util.List; import java.util.UUID; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.entity.ai.EntityAITasks; import net.minecraft.entity.ai.EntityJumpHelper; import net.minecraft.entity.ai.EntityLookHelper; import net.minecraft.entity.ai.EntityMoveHelper; import net.minecraft.entity.ai.EntitySenses; import net.minecraft.entity.ai.attributes.AttributeModifier; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.monster.EntityCreeper; import net.minecraft.entity.monster.EntityGhast; import net.minecraft.entity.monster.IMob; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.Item; import net.minecraft.item.ItemArmor; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemSword; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagFloat; import net.minecraft.nbt.NBTTagList; import net.minecraft.network.play.server.S1BPacketEntityAttach; import net.minecraft.pathfinding.PathNavigate; import net.minecraft.stats.AchievementList; import net.minecraft.util.MathHelper; import net.minecraft.world.EnumDifficulty; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.common.ForgeHooks; import cpw.mods.fml.common.eventhandler.Event.Result; import net.minecraftforge.event.ForgeEventFactory; public abstract class EntityLiving extends EntityLivingBase { /** Number of ticks since this EntityLiving last produced its sound */ public int livingSoundTime; /** The experience points the Entity gives. */ protected int experienceValue; private EntityLookHelper lookHelper; private EntityMoveHelper moveHelper; /** Entity jumping helper */ private EntityJumpHelper jumpHelper; private EntityBodyHelper bodyHelper; private PathNavigate navigator; /** Passive tasks (wandering, look, idle, ...) */ public final EntityAITasks tasks; /** Fighting tasks (used by monsters, wolves, ocelots) */ public final EntityAITasks targetTasks; /** The active target the Task system uses for tracking */ private EntityLivingBase attackTarget; private EntitySenses senses; /** Equipment (armor and held item) for this entity. */ private ItemStack[] equipment = new ItemStack[5]; /** Chances for each equipment piece from dropping when this entity dies. */ protected float[] equipmentDropChances = new float[5]; /** Whether this entity can pick up items from the ground. */ private boolean canPickUpLoot; /** Whether this entity should NOT despawn. */ private boolean persistenceRequired; protected float defaultPitch; /** This entity's current target. */ private Entity currentTarget; /** How long to keep a specific target entity */ protected int numTicksToChaseTarget; private boolean isLeashed; private Entity leashedToEntity; private NBTTagCompound leashNBTTag; private static final String __OBFID = "CL_00001550"; public EntityLiving(World p_i1595_1_) { super(p_i1595_1_); this.tasks = new EntityAITasks(p_i1595_1_ != null && p_i1595_1_.theProfiler != null ? p_i1595_1_.theProfiler : null); this.targetTasks = new EntityAITasks(p_i1595_1_ != null && p_i1595_1_.theProfiler != null ? p_i1595_1_.theProfiler : null); this.lookHelper = new EntityLookHelper(this); this.moveHelper = new EntityMoveHelper(this); this.jumpHelper = new EntityJumpHelper(this); this.bodyHelper = new EntityBodyHelper(this); this.navigator = new PathNavigate(this, p_i1595_1_); this.senses = new EntitySenses(this); for (int i = 0; i < this.equipmentDropChances.length; ++i) { this.equipmentDropChances[i] = 0.085F; } } protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getAttributeMap().registerAttribute(SharedMonsterAttributes.followRange).setBaseValue(16.0D); } public EntityLookHelper getLookHelper() { return this.lookHelper; } public EntityMoveHelper getMoveHelper() { return this.moveHelper; } public EntityJumpHelper getJumpHelper() { return this.jumpHelper; } public PathNavigate getNavigator() { return this.navigator; } /** * returns the EntitySenses Object for the EntityLiving */ public EntitySenses getEntitySenses() { return this.senses; } /** * Gets the active target the Task system uses for tracking */ public EntityLivingBase getAttackTarget() { return this.attackTarget; } /** * Sets the active target the Task system uses for tracking */ public void setAttackTarget(EntityLivingBase p_70624_1_) { this.attackTarget = p_70624_1_; ForgeHooks.onLivingSetAttackTarget(this, p_70624_1_); } /** * Returns true if this entity can attack entities of the specified class. */ public boolean canAttackClass(Class p_70686_1_) { return EntityCreeper.class != p_70686_1_ && EntityGhast.class != p_70686_1_; } /** * 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() {} protected void entityInit() { super.entityInit(); this.dataWatcher.addObject(11, Byte.valueOf((byte)0)); this.dataWatcher.addObject(10, ""); } /** * Get number of ticks, at least during which the living entity will be silent. */ public int getTalkInterval() { return 80; } /** * Plays living's sound at its position */ public void playLivingSound() { String s = this.getLivingSound(); if (s != null) { this.playSound(s, this.getSoundVolume(), this.getSoundPitch()); } } /** * Gets called every tick from main Entity class */ public void onEntityUpdate() { super.onEntityUpdate(); this.worldObj.theProfiler.startSection("mobBaseTick"); if (this.isEntityAlive() && this.rand.nextInt(1000) < this.livingSoundTime++) { this.livingSoundTime = -this.getTalkInterval(); this.playLivingSound(); } this.worldObj.theProfiler.endSection(); } /** * Get the experience points the entity currently has. */ protected int getExperiencePoints(EntityPlayer p_70693_1_) { if (this.experienceValue > 0) { int i = this.experienceValue; ItemStack[] aitemstack = this.getInventory(); for (int j = 0; j < aitemstack.length; ++j) { if (aitemstack[j] != null && this.equipmentDropChances[j] <= 1.0F) { i += 1 + this.rand.nextInt(3); } } return i; } else { return this.experienceValue; } } /** * Spawns an explosion particle around the Entity's location */ public void spawnExplosionParticle() { for (int i = 0; i < 20; ++i) { double d0 = this.rand.nextGaussian() * 0.02D; double d1 = this.rand.nextGaussian() * 0.02D; double d2 = this.rand.nextGaussian() * 0.02D; double d3 = 10.0D; this.worldObj.spawnParticle("explode", this.posX + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width - d0 * d3, this.posY + (double)(this.rand.nextFloat() * this.height) - d1 * d3, this.posZ + (double)(this.rand.nextFloat() * this.width * 2.0F) - (double)this.width - d2 * d3, d0, d1, d2); } } /** * Called to update the entity's position/logic. */ public void onUpdate() { super.onUpdate(); if (!this.worldObj.isRemote) { this.updateLeashedState(); } } protected float func_110146_f(float p_110146_1_, float p_110146_2_) { if (this.isAIEnabled()) { this.bodyHelper.updateRenderAngles(); return p_110146_2_; } else { return super.func_110146_f(p_110146_1_, p_110146_2_); } } /** * Returns the sound this mob makes while it's alive. */ protected String getLivingSound() { return null; } protected Item getDropItem() { return Item.getItemById(0); } /** * Drop 0-2 items of this living's type */ protected void dropFewItems(boolean p_70628_1_, int p_70628_2_) { Item item = this.getDropItem(); if (item != null) { int j = this.rand.nextInt(3); if (p_70628_2_ > 0) { j += this.rand.nextInt(p_70628_2_ + 1); } for (int k = 0; k < j; ++k) { this.dropItem(item, 1); } } } /** * (abstract) Protected helper method to write subclass entity data to NBT. */ public void writeEntityToNBT(NBTTagCompound tagCompound) { super.writeEntityToNBT(tagCompound); tagCompound.setBoolean("CanPickUpLoot", this.canPickUpLoot()); tagCompound.setBoolean("PersistenceRequired", this.persistenceRequired); NBTTagList nbttaglist = new NBTTagList(); NBTTagCompound nbttagcompound1; for (int i = 0; i < this.equipment.length; ++i) { nbttagcompound1 = new NBTTagCompound(); if (this.equipment[i] != null) { this.equipment[i].writeToNBT(nbttagcompound1); } nbttaglist.appendTag(nbttagcompound1); } tagCompound.setTag("Equipment", nbttaglist); NBTTagList nbttaglist1 = new NBTTagList(); for (int j = 0; j < this.equipmentDropChances.length; ++j) { nbttaglist1.appendTag(new NBTTagFloat(this.equipmentDropChances[j])); } tagCompound.setTag("DropChances", nbttaglist1); tagCompound.setString("CustomName", this.getCustomNameTag()); tagCompound.setBoolean("CustomNameVisible", this.getAlwaysRenderNameTag()); tagCompound.setBoolean("Leashed", this.isLeashed); if (this.leashedToEntity != null) { nbttagcompound1 = new NBTTagCompound(); if (this.leashedToEntity instanceof EntityLivingBase) { nbttagcompound1.setLong("UUIDMost", this.leashedToEntity.getUniqueID().getMostSignificantBits()); nbttagcompound1.setLong("UUIDLeast", this.leashedToEntity.getUniqueID().getLeastSignificantBits()); } else if (this.leashedToEntity instanceof EntityHanging) { EntityHanging entityhanging = (EntityHanging)this.leashedToEntity; nbttagcompound1.setInteger("X", entityhanging.field_146063_b); nbttagcompound1.setInteger("Y", entityhanging.field_146064_c); nbttagcompound1.setInteger("Z", entityhanging.field_146062_d); } tagCompound.setTag("Leash", nbttagcompound1); } } /** * (abstract) Protected helper method to read subclass entity data from NBT. */ public void readEntityFromNBT(NBTTagCompound tagCompund) { super.readEntityFromNBT(tagCompund); this.setCanPickUpLoot(tagCompund.getBoolean("CanPickUpLoot")); this.persistenceRequired = tagCompund.getBoolean("PersistenceRequired"); if (tagCompund.hasKey("CustomName", 8) && tagCompund.getString("CustomName").length() > 0) { this.setCustomNameTag(tagCompund.getString("CustomName")); } this.setAlwaysRenderNameTag(tagCompund.getBoolean("CustomNameVisible")); NBTTagList nbttaglist; int i; if (tagCompund.hasKey("Equipment", 9)) { nbttaglist = tagCompund.getTagList("Equipment", 10); for (i = 0; i < this.equipment.length; ++i) { this.equipment[i] = ItemStack.loadItemStackFromNBT(nbttaglist.getCompoundTagAt(i)); } } if (tagCompund.hasKey("DropChances", 9)) { nbttaglist = tagCompund.getTagList("DropChances", 5); for (i = 0; i < nbttaglist.tagCount(); ++i) { this.equipmentDropChances[i] = nbttaglist.getFloatAt(i); } } this.isLeashed = tagCompund.getBoolean("Leashed"); if (this.isLeashed && tagCompund.hasKey("Leash", 10)) { this.leashNBTTag = tagCompund.getCompoundTag("Leash"); } } public void setMoveForward(float p_70657_1_) { this.moveForward = p_70657_1_; } /** * set the movespeed used for the new AI system */ public void setAIMoveSpeed(float p_70659_1_) { super.setAIMoveSpeed(p_70659_1_); this.setMoveForward(p_70659_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(); this.worldObj.theProfiler.startSection("looting"); if (!this.worldObj.isRemote && this.canPickUpLoot() && !this.dead && this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing")) { List list = this.worldObj.getEntitiesWithinAABB(EntityItem.class, this.boundingBox.expand(1.0D, 0.0D, 1.0D)); Iterator iterator = list.iterator(); while (iterator.hasNext()) { EntityItem entityitem = (EntityItem)iterator.next(); if (!entityitem.isDead && entityitem.getEntityItem() != null) { ItemStack itemstack = entityitem.getEntityItem(); int i = getArmorPosition(itemstack); if (i > -1) { boolean flag = true; ItemStack itemstack1 = this.getEquipmentInSlot(i); if (itemstack1 != null) { if (i == 0) { if (itemstack.getItem() instanceof ItemSword && !(itemstack1.getItem() instanceof ItemSword)) { flag = true; } else if (itemstack.getItem() instanceof ItemSword && itemstack1.getItem() instanceof ItemSword) { ItemSword itemsword = (ItemSword)itemstack.getItem(); ItemSword itemsword1 = (ItemSword)itemstack1.getItem(); if (itemsword.func_150931_i() == itemsword1.func_150931_i()) { flag = itemstack.getMetadata() > itemstack1.getMetadata() || itemstack.hasTagCompound() && !itemstack1.hasTagCompound(); } else { flag = itemsword.func_150931_i() > itemsword1.func_150931_i(); } } else { flag = false; } } else if (itemstack.getItem() instanceof ItemArmor && !(itemstack1.getItem() instanceof ItemArmor)) { flag = true; } else if (itemstack.getItem() instanceof ItemArmor && itemstack1.getItem() instanceof ItemArmor) { ItemArmor itemarmor = (ItemArmor)itemstack.getItem(); ItemArmor itemarmor1 = (ItemArmor)itemstack1.getItem(); if (itemarmor.damageReduceAmount == itemarmor1.damageReduceAmount) { flag = itemstack.getMetadata() > itemstack1.getMetadata() || itemstack.hasTagCompound() && !itemstack1.hasTagCompound(); } else { flag = itemarmor.damageReduceAmount > itemarmor1.damageReduceAmount; } } else { flag = false; } } if (flag) { if (itemstack1 != null && this.rand.nextFloat() - 0.1F < this.equipmentDropChances[i]) { this.entityDropItem(itemstack1, 0.0F); } if (itemstack.getItem() == Items.diamond && entityitem.getThrower() != null) { EntityPlayer entityplayer = this.worldObj.getPlayerEntityByName(entityitem.getThrower()); if (entityplayer != null) { entityplayer.triggerAchievement(AchievementList.field_150966_x); } } this.setCurrentItemOrArmor(i, itemstack); this.equipmentDropChances[i] = 2.0F; this.persistenceRequired = true; this.onItemPickup(entityitem, 1); entityitem.setDead(); } } } } } this.worldObj.theProfiler.endSection(); } /** * Returns true if the newer Entity AI code should be run */ protected boolean isAIEnabled() { return false; } /** * Determines if an entity can be despawned, used on idle far away entities */ protected boolean canDespawn() { return true; } /** * Makes the entity despawn if requirements are reached */ protected void despawnEntity() { Result result = null; if (this.persistenceRequired) { this.entityAge = 0; } else if ((this.entityAge & 0x1F) == 0x1F && (result = ForgeEventFactory.canEntityDespawn(this)) != Result.DEFAULT) { if (result == Result.DENY) { this.entityAge = 0; } else { this.setDead(); } } else { EntityPlayer entityplayer = this.worldObj.getClosestPlayerToEntity(this, -1.0D); if (entityplayer != null) { double d0 = entityplayer.posX - this.posX; double d1 = entityplayer.posY - this.posY; double d2 = entityplayer.posZ - this.posZ; double d3 = d0 * d0 + d1 * d1 + d2 * d2; if (this.canDespawn() && d3 > 16384.0D) { this.setDead(); } if (this.entityAge > 600 && this.rand.nextInt(800) == 0 && d3 > 1024.0D && this.canDespawn()) { this.setDead(); } else if (d3 < 1024.0D) { this.entityAge = 0; } } } } protected void updateAITasks() { ++this.entityAge; this.worldObj.theProfiler.startSection("checkDespawn"); this.despawnEntity(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.startSection("sensing"); this.senses.clearSensingCache(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.startSection("targetSelector"); this.targetTasks.onUpdateTasks(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.startSection("goalSelector"); this.tasks.onUpdateTasks(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.startSection("navigation"); this.navigator.onUpdateNavigation(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.startSection("mob tick"); this.updateAITick(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.startSection("controls"); this.worldObj.theProfiler.startSection("move"); this.moveHelper.onUpdateMoveHelper(); this.worldObj.theProfiler.endStartSection("look"); this.lookHelper.onUpdateLook(); this.worldObj.theProfiler.endStartSection("jump"); this.jumpHelper.doJump(); this.worldObj.theProfiler.endSection(); this.worldObj.theProfiler.endSection(); } protected void updateEntityActionState() { super.updateEntityActionState(); this.moveStrafing = 0.0F; this.moveForward = 0.0F; this.despawnEntity(); float f = 8.0F; if (this.rand.nextFloat() < 0.02F) { EntityPlayer entityplayer = this.worldObj.getClosestPlayerToEntity(this, (double)f); if (entityplayer != null) { this.currentTarget = entityplayer; this.numTicksToChaseTarget = 10 + this.rand.nextInt(20); } else { this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F; } } if (this.currentTarget != null) { this.faceEntity(this.currentTarget, 10.0F, (float)this.getVerticalFaceSpeed()); if (this.numTicksToChaseTarget-- <= 0 || this.currentTarget.isDead || this.currentTarget.getDistanceSqToEntity(this) > (double)(f * f)) { this.currentTarget = null; } } else { if (this.rand.nextFloat() < 0.05F) { this.randomYawVelocity = (this.rand.nextFloat() - 0.5F) * 20.0F; } this.rotationYaw += this.randomYawVelocity; this.rotationPitch = this.defaultPitch; } boolean flag1 = this.isInWater(); boolean flag = this.handleLavaMovement(); if (flag1 || flag) { this.isJumping = this.rand.nextFloat() < 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 40; } /** * Changes pitch and yaw so that the entity calling the function is facing the entity provided as an argument. */ public void faceEntity(Entity p_70625_1_, float p_70625_2_, float p_70625_3_) { double d0 = p_70625_1_.posX - this.posX; double d2 = p_70625_1_.posZ - this.posZ; double d1; if (p_70625_1_ instanceof EntityLivingBase) { EntityLivingBase entitylivingbase = (EntityLivingBase)p_70625_1_; d1 = entitylivingbase.posY + (double)entitylivingbase.getEyeHeight() - (this.posY + (double)this.getEyeHeight()); } else { d1 = (p_70625_1_.boundingBox.minY + p_70625_1_.boundingBox.maxY) / 2.0D - (this.posY + (double)this.getEyeHeight()); } double d3 = (double)MathHelper.sqrt_double(d0 * d0 + d2 * d2); float f2 = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F; float f3 = (float)(-(Math.atan2(d1, d3) * 180.0D / Math.PI)); this.rotationPitch = this.updateRotation(this.rotationPitch, f3, p_70625_3_); this.rotationYaw = this.updateRotation(this.rotationYaw, f2, p_70625_2_); } /** * Arguments: current rotation, intended rotation, max increment. */ private float updateRotation(float p_70663_1_, float p_70663_2_, float p_70663_3_) { float f3 = MathHelper.wrapAngleTo180_float(p_70663_2_ - p_70663_1_); if (f3 > p_70663_3_) { f3 = p_70663_3_; } if (f3 < -p_70663_3_) { f3 = -p_70663_3_; } return p_70663_1_ + f3; } /** * Checks if the entity's current position is a valid location to spawn this entity. */ public boolean getCanSpawnHere() { return this.worldObj.checkNoEntityCollision(this.boundingBox) && this.worldObj.getCollidingBoundingBoxes(this, this.boundingBox).isEmpty() && !this.worldObj.isAnyLiquid(this.boundingBox); } /** * Returns render size modifier */ public float getRenderSizeModifier() { return 1.0F; } /** * Will return how many at most can spawn in a chunk at once. */ public int getMaxSpawnedInChunk() { return 4; } /** * The maximum height from where the entity is alowed to jump (used in pathfinder) */ public int getMaxFallHeight() { if (this.getAttackTarget() == null) { return 3; } else { int i = (int)(this.getHealth() - this.getMaxHealth() * 0.33F); i -= (3 - this.worldObj.difficultySetting.getDifficultyId()) * 4; if (i < 0) { i = 0; } return i + 3; } } /** * Returns the item that this EntityLiving is holding, if any. */ public ItemStack getHeldItem() { return this.equipment[0]; } /** * 0: Tool in Hand; 1-4: Armor */ public ItemStack getEquipmentInSlot(int p_71124_1_) { return this.equipment[p_71124_1_]; } public ItemStack func_130225_q(int p_130225_1_) { return this.equipment[p_130225_1_ + 1]; } /** * Sets the held item, or an armor slot. Slot 0 is held item. Slot 1-4 is armor. Params: Item, slot */ public void setCurrentItemOrArmor(int slotIn, ItemStack itemStackIn) { this.equipment[slotIn] = itemStackIn; } /** * returns the inventory of this entity (only used in EntityPlayerMP it seems) */ public ItemStack[] getInventory() { return this.equipment; } /** * Drop the equipment for this entity. */ protected void dropEquipment(boolean p_82160_1_, int p_82160_2_) { for (int j = 0; j < this.getInventory().length; ++j) { ItemStack itemstack = this.getEquipmentInSlot(j); boolean flag1 = this.equipmentDropChances[j] > 1.0F; if (itemstack != null && (p_82160_1_ || flag1) && this.rand.nextFloat() - (float)p_82160_2_ * 0.01F < this.equipmentDropChances[j]) { if (!flag1 && itemstack.isItemStackDamageable()) { int k = Math.max(itemstack.getMaxDurability() - 25, 1); int l = itemstack.getMaxDurability() - this.rand.nextInt(this.rand.nextInt(k) + 1); if (l > k) { l = k; } if (l < 1) { l = 1; } itemstack.setMetadata(l); } this.entityDropItem(itemstack, 0.0F); } } } /** * Makes entity wear random armor based on difficulty */ protected void addRandomArmor() { if (this.rand.nextFloat() < 0.15F * this.worldObj.getTensionFactorForBlock(this.posX, this.posY, this.posZ)) { int i = this.rand.nextInt(2); float f = this.worldObj.difficultySetting == EnumDifficulty.HARD ? 0.1F : 0.25F; if (this.rand.nextFloat() < 0.095F) { ++i; } if (this.rand.nextFloat() < 0.095F) { ++i; } if (this.rand.nextFloat() < 0.095F) { ++i; } for (int j = 3; j >= 0; --j) { ItemStack itemstack = this.func_130225_q(j); if (j < 3 && this.rand.nextFloat() < f) { break; } if (itemstack == null) { Item item = getArmorItemForSlot(j + 1, i); if (item != null) { this.setCurrentItemOrArmor(j + 1, new ItemStack(item)); } } } } } public static int getArmorPosition(ItemStack p_82159_0_) { if (p_82159_0_.getItem() != Item.getItemFromBlock(Blocks.pumpkin) && p_82159_0_.getItem() != Items.skull) { if (p_82159_0_.getItem() instanceof ItemArmor) { switch (((ItemArmor)p_82159_0_.getItem()).armorType) { case 0: return 4; case 1: return 3; case 2: return 2; case 3: return 1; } } return 0; } else { return 4; } } /** * Gets the vanilla armor Item that can go in the slot specified for the given tier. * * @param armorSlot The armor slot number (1-4) * @param itemTier Vanilla item material tier (0=leather, 1=gold, 2=chain, 3=iron, 4=diamond) */ public static Item getArmorItemForSlot(int armorSlot, int itemTier) { switch (armorSlot) { case 4: if (itemTier == 0) { return Items.leather_helmet; } else if (itemTier == 1) { return Items.golden_helmet; } else if (itemTier == 2) { return Items.chainmail_helmet; } else if (itemTier == 3) { return Items.iron_helmet; } else if (itemTier == 4) { return Items.diamond_helmet; } case 3: if (itemTier == 0) { return Items.leather_chestplate; } else if (itemTier == 1) { return Items.golden_chestplate; } else if (itemTier == 2) { return Items.chainmail_chestplate; } else if (itemTier == 3) { return Items.iron_chestplate; } else if (itemTier == 4) { return Items.diamond_chestplate; } case 2: if (itemTier == 0) { return Items.leather_leggings; } else if (itemTier == 1) { return Items.golden_leggings; } else if (itemTier == 2) { return Items.chainmail_leggings; } else if (itemTier == 3) { return Items.iron_leggings; } else if (itemTier == 4) { return Items.diamond_leggings; } case 1: if (itemTier == 0) { return Items.leather_boots; } else if (itemTier == 1) { return Items.golden_boots; } else if (itemTier == 2) { return Items.chainmail_boots; } else if (itemTier == 3) { return Items.iron_boots; } else if (itemTier == 4) { return Items.diamond_boots; } default: return null; } } /** * Enchants the entity's armor and held item based on difficulty */ protected void enchantEquipment() { float f = this.worldObj.getTensionFactorForBlock(this.posX, this.posY, this.posZ); if (this.getHeldItem() != null && this.rand.nextFloat() < 0.25F * f) { EnchantmentHelper.addRandomEnchantment(this.rand, this.getHeldItem(), (int)(5.0F + f * (float)this.rand.nextInt(18))); } for (int i = 0; i < 4; ++i) { ItemStack itemstack = this.func_130225_q(i); if (itemstack != null && this.rand.nextFloat() < 0.5F * f) { EnchantmentHelper.addRandomEnchantment(this.rand, itemstack, (int)(5.0F + f * (float)this.rand.nextInt(18))); } } } public IEntityLivingData onSpawnWithEgg(IEntityLivingData p_110161_1_) { this.getEntityAttribute(SharedMonsterAttributes.followRange).applyModifier(new AttributeModifier("Random spawn bonus", this.rand.nextGaussian() * 0.05D, 1)); return p_110161_1_; } /** * 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() { return false; } /** * Gets the name of this command sender (usually username, but possibly "Rcon") */ public String getCommandSenderName() { return this.hasCustomNameTag() ? this.getCustomNameTag() : super.getCommandSenderName(); } /** * Enable the Entity persistence */ public void enablePersistence() { this.persistenceRequired = true; } public void setCustomNameTag(String p_94058_1_) { this.dataWatcher.updateObject(10, p_94058_1_); } public String getCustomNameTag() { return this.dataWatcher.getWatchableObjectString(10); } public boolean hasCustomNameTag() { return this.dataWatcher.getWatchableObjectString(10).length() > 0; } public void setAlwaysRenderNameTag(boolean p_94061_1_) { this.dataWatcher.updateObject(11, Byte.valueOf((byte)(p_94061_1_ ? 1 : 0))); } public boolean getAlwaysRenderNameTag() { return this.dataWatcher.getWatchableObjectByte(11) == 1; } @SideOnly(Side.CLIENT) public boolean getAlwaysRenderNameTagForRender() { return this.getAlwaysRenderNameTag(); } public void setEquipmentDropChance(int p_96120_1_, float p_96120_2_) { this.equipmentDropChances[p_96120_1_] = p_96120_2_; } public boolean canPickUpLoot() { return this.canPickUpLoot; } public void setCanPickUpLoot(boolean p_98053_1_) { this.canPickUpLoot = p_98053_1_; } public boolean isNoDespawnRequired() { return this.persistenceRequired; } /** * First layer of player interaction */ public final boolean interactFirst(EntityPlayer player) { if (this.getLeashed() && this.getLeashedToEntity() == player) { this.clearLeashed(true, !player.capabilities.isCreativeMode); return true; } else { ItemStack itemstack = player.inventory.getCurrentItem(); if (itemstack != null && itemstack.getItem() == Items.lead && this.allowLeashing()) { if (!(this instanceof EntityTameable) || !((EntityTameable)this).isTamed()) { this.setLeashedToEntity(player, true); --itemstack.stackSize; return true; } if (((EntityTameable)this).func_152114_e(player)) { this.setLeashedToEntity(player, true); --itemstack.stackSize; return true; } } return this.interact(player) ? true : super.interactFirst(player); } } /** * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig. */ protected boolean interact(EntityPlayer p_70085_1_) { return false; } /** * Applies logic related to leashes, for example dragging the entity or breaking the leash. */ protected void updateLeashedState() { if (this.leashNBTTag != null) { this.recreateLeash(); } if (this.isLeashed) { if (this.leashedToEntity == null || this.leashedToEntity.isDead) { this.clearLeashed(true, true); } } } /** * Removes the leash from this entity. Second parameter tells whether to send a packet to surrounding players. */ public void clearLeashed(boolean p_110160_1_, boolean p_110160_2_) { if (this.isLeashed) { this.isLeashed = false; this.leashedToEntity = null; if (!this.worldObj.isRemote && p_110160_2_) { this.dropItem(Items.lead, 1); } if (!this.worldObj.isRemote && p_110160_1_ && this.worldObj instanceof WorldServer) { ((WorldServer)this.worldObj).getEntityTracker().sendToAllTrackingEntity(this, new S1BPacketEntityAttach(1, this, (Entity)null)); } } } public boolean allowLeashing() { return !this.getLeashed() && !(this instanceof IMob); } public boolean getLeashed() { return this.isLeashed; } public Entity getLeashedToEntity() { return this.leashedToEntity; } /** * Sets the entity to be leashed to. * * @param entityIn The entity to be tethered to * @param sendAttachNotification Whether to send an attaching notification packet to surrounding players. */ public void setLeashedToEntity(Entity entityIn, boolean sendAttachNotification) { this.isLeashed = true; this.leashedToEntity = entityIn; if (!this.worldObj.isRemote && sendAttachNotification && this.worldObj instanceof WorldServer) { ((WorldServer)this.worldObj).getEntityTracker().sendToAllTrackingEntity(this, new S1BPacketEntityAttach(1, this, this.leashedToEntity)); } } private void recreateLeash() { if (this.isLeashed && this.leashNBTTag != null) { if (this.leashNBTTag.hasKey("UUIDMost", 4) && this.leashNBTTag.hasKey("UUIDLeast", 4)) { UUID uuid = new UUID(this.leashNBTTag.getLong("UUIDMost"), this.leashNBTTag.getLong("UUIDLeast")); List list = this.worldObj.getEntitiesWithinAABB(EntityLivingBase.class, this.boundingBox.expand(10.0D, 10.0D, 10.0D)); Iterator iterator = list.iterator(); while (iterator.hasNext()) { EntityLivingBase entitylivingbase = (EntityLivingBase)iterator.next(); if (entitylivingbase.getUniqueID().equals(uuid)) { this.leashedToEntity = entitylivingbase; break; } } } else if (this.leashNBTTag.hasKey("X", 99) && this.leashNBTTag.hasKey("Y", 99) && this.leashNBTTag.hasKey("Z", 99)) { int i = this.leashNBTTag.getInteger("X"); int j = this.leashNBTTag.getInteger("Y"); int k = this.leashNBTTag.getInteger("Z"); EntityLeashKnot entityleashknot = EntityLeashKnot.getKnotForBlock(this.worldObj, i, j, k); if (entityleashknot == null) { entityleashknot = EntityLeashKnot.func_110129_a(this.worldObj, i, j, k); } this.leashedToEntity = entityleashknot; } else { this.clearLeashed(false, true); } } this.leashNBTTag = null; } }