    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005
    006    import java.util.ArrayList;
    007    import java.util.Random;
    008
    009    import net.minecraftforge.common.IShearable;
    010
    011    public class EntitySheep extends EntityAnimal implements IShearable
    012    {
    013        /**
    014         * Holds the RGB table of the sheep colors - in OpenGL glColor3f values - used to render the sheep colored fleece.
    015         */
    016        public static final float[][] fleeceColorTable = new float[][] {{1.0F, 1.0F, 1.0F}, {0.95F, 0.7F, 0.2F}, {0.9F, 0.5F, 0.85F}, {0.6F, 0.7F, 0.95F}, {0.9F, 0.9F, 0.2F}, {0.5F, 0.8F, 0.1F}, {0.95F, 0.7F, 0.8F}, {0.3F, 0.3F, 0.3F}, {0.6F, 0.6F, 0.6F}, {0.3F, 0.6F, 0.7F}, {0.7F, 0.4F, 0.9F}, {0.2F, 0.4F, 0.8F}, {0.5F, 0.4F, 0.3F}, {0.4F, 0.5F, 0.2F}, {0.8F, 0.3F, 0.3F}, {0.1F, 0.1F, 0.1F}};
    017
    018        /**
    019         * Used to control movement as well as wool regrowth. Set to 40 on handleHealthUpdate and counts down with each
    020         * tick.
    021         */
    022        private int sheepTimer;
    023
    024        /** The eat grass AI task for this mob. */
    025        private EntityAIEatGrass aiEatGrass = new EntityAIEatGrass(this);
    026
    027        public EntitySheep(World par1World)
    028        {
    029            super(par1World);
    030            this.texture = "/mob/sheep.png";
    031            this.setSize(0.9F, 1.3F);
    032            float var2 = 0.23F;
    033            this.getNavigator().setAvoidsWater(true);
    034            this.tasks.addTask(0, new EntityAISwimming(this));
    035            this.tasks.addTask(1, new EntityAIPanic(this, 0.38F));
    036            this.tasks.addTask(2, new EntityAIMate(this, var2));
    037            this.tasks.addTask(3, new EntityAITempt(this, 0.25F, Item.wheat.shiftedIndex, false));
    038            this.tasks.addTask(4, new EntityAIFollowParent(this, 0.25F));
    039            this.tasks.addTask(5, this.aiEatGrass);
    040            this.tasks.addTask(6, new EntityAIWander(this, var2));
    041            this.tasks.addTask(7, new EntityAIWatchClosest(this, EntityPlayer.class, 6.0F));
    042            this.tasks.addTask(8, new EntityAILookIdle(this));
    043        }
    044
    045        /**
    046         * Returns true if the newer Entity AI code should be run
    047         */
    048        protected boolean isAIEnabled()
    049        {
    050            return true;
    051        }
    052
    053        protected void updateAITasks()
    054        {
    055            this.sheepTimer = this.aiEatGrass.func_75362_f();
    056            super.updateAITasks();
    057        }
    058
    059        /**
    060         * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
    061         * use this to react to sunlight and start to burn.
    062         */
    063        public void onLivingUpdate()
    064        {
    065            if (this.worldObj.isRemote)
    066            {
    067                this.sheepTimer = Math.max(0, this.sheepTimer - 1);
    068            }
    069
    070            super.onLivingUpdate();
    071        }
    072
    073        public int getMaxHealth()
    074        {
    075            return 8;
    076        }
    077
    078        protected void entityInit()
    079        {
    080            super.entityInit();
    081            this.dataWatcher.addObject(16, new Byte((byte)0));
    082        }
    083
    084        /**
    085         * Drop 0-2 items of this living's type
    086         */
    087        protected void dropFewItems(boolean par1, int par2)
    088        {
    089            if (!this.getSheared())
    090            {
    091                this.entityDropItem(new ItemStack(Block.cloth.blockID, 1, this.getFleeceColor()), 0.0F);
    092            }
    093        }
    094
    095        /**
    096         * Returns the item ID for the item the mob drops on death.
    097         */
    098        protected int getDropItemId()
    099        {
    100            return Block.cloth.blockID;
    101        }
    102
    103        @SideOnly(Side.CLIENT)
    104        public void handleHealthUpdate(byte par1)
    105        {
    106            if (par1 == 10)
    107            {
    108                this.sheepTimer = 40;
    109            }
    110            else
    111            {
    112                super.handleHealthUpdate(par1);
    113            }
    114        }
    115
    116        @SideOnly(Side.CLIENT)
    117        public float func_70894_j(float par1)
    118        {
    119            return this.sheepTimer <= 0 ? 0.0F : (this.sheepTimer >= 4 && this.sheepTimer <= 36 ? 1.0F : (this.sheepTimer < 4 ? ((float)this.sheepTimer - par1) / 4.0F : -((float)(this.sheepTimer - 40) - par1) / 4.0F));
    120        }
    121
    122        @SideOnly(Side.CLIENT)
    123        public float func_70890_k(float par1)
    124        {
    125            if (this.sheepTimer > 4 && this.sheepTimer <= 36)
    126            {
    127                float var2 = ((float)(this.sheepTimer - 4) - par1) / 32.0F;
    128                return ((float)Math.PI / 5F) + ((float)Math.PI * 7F / 100F) * MathHelper.sin(var2 * 28.7F);
    129            }
    130            else
    131            {
    132                return this.sheepTimer > 0 ? ((float)Math.PI / 5F) : this.rotationPitch / (180F / (float)Math.PI);
    133            }
    134        }
    135
    136        /**
    137         * Called when a player interacts with a mob. e.g. gets milk from a cow, gets into the saddle on a pig.
    138         */
    139        public boolean interact(EntityPlayer par1EntityPlayer)
    140        {
    141            return super.interact(par1EntityPlayer);
    142        }
    143
    144        /**
    145         * (abstract) Protected helper method to write subclass entity data to NBT.
    146         */
    147        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    148        {
    149            super.writeEntityToNBT(par1NBTTagCompound);
    150            par1NBTTagCompound.setBoolean("Sheared", this.getSheared());
    151            par1NBTTagCompound.setByte("Color", (byte)this.getFleeceColor());
    152        }
    153
    154        /**
    155         * (abstract) Protected helper method to read subclass entity data from NBT.
    156         */
    157        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    158        {
    159            super.readEntityFromNBT(par1NBTTagCompound);
    160            this.setSheared(par1NBTTagCompound.getBoolean("Sheared"));
    161            this.setFleeceColor(par1NBTTagCompound.getByte("Color"));
    162        }
    163
    164        /**
    165         * Returns the sound this mob makes while it's alive.
    166         */
    167        protected String getLivingSound()
    168        {
    169            return "mob.sheep.say";
    170        }
    171
    172        /**
    173         * Returns the sound this mob makes when it is hurt.
    174         */
    175        protected String getHurtSound()
    176        {
    177            return "mob.sheep.say";
    178        }
    179
    180        /**
    181         * Returns the sound this mob makes on death.
    182         */
    183        protected String getDeathSound()
    184        {
    185            return "mob.sheep.say";
    186        }
    187
    188        /**
    189         * Plays step sound at given x, y, z for the entity
    190         */
    191        protected void playStepSound(int par1, int par2, int par3, int par4)
    192        {
    193            this.worldObj.playSoundAtEntity(this, "mob.sheep.step", 0.15F, 1.0F);
    194        }
    195
    196        public int getFleeceColor()
    197        {
    198            return this.dataWatcher.getWatchableObjectByte(16) & 15;
    199        }
    200
    201        public void setFleeceColor(int par1)
    202        {
    203            byte var2 = this.dataWatcher.getWatchableObjectByte(16);
    204            this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & 240 | par1 & 15)));
    205        }
    206
    207        /**
    208         * returns true if a sheeps wool has been sheared
    209         */
    210        public boolean getSheared()
    211        {
    212            return (this.dataWatcher.getWatchableObjectByte(16) & 16) != 0;
    213        }
    214
    215        /**
    216         * make a sheep sheared if set to true
    217         */
    218        public void setSheared(boolean par1)
    219        {
    220            byte var2 = this.dataWatcher.getWatchableObjectByte(16);
    221
    222            if (par1)
    223            {
    224                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 | 16)));
    225            }
    226            else
    227            {
    228                this.dataWatcher.updateObject(16, Byte.valueOf((byte)(var2 & -17)));
    229            }
    230        }
    231
    232        /**
    233         * This method is called when a sheep spawns in the world to select the color of sheep fleece.
    234         */
    235        public static int getRandomFleeceColor(Random par0Random)
    236        {
    237            int var1 = par0Random.nextInt(100);
    238            return var1 < 5 ? 15 : (var1 < 10 ? 7 : (var1 < 15 ? 8 : (var1 < 18 ? 12 : (par0Random.nextInt(500) == 0 ? 6 : 0))));
    239        }
    240
    241        /**
    242         * This function is used when two same-species animals in 'love mode' breed to generate the new baby animal.
    243         */
    244        public EntityAnimal spawnBabyAnimal(EntityAnimal par1EntityAnimal)
    245        {
    246            EntitySheep var2 = (EntitySheep)par1EntityAnimal;
    247            EntitySheep var3 = new EntitySheep(this.worldObj);
    248
    249            if (this.rand.nextBoolean())
    250            {
    251                var3.setFleeceColor(this.getFleeceColor());
    252            }
    253            else
    254            {
    255                var3.setFleeceColor(var2.getFleeceColor());
    256            }
    257
    258            return var3;
    259        }
    260
    261        /**
    262         * This function applies the benefits of growing back wool and faster growing up to the acting entity. (This
    263         * function is used in the AIEatGrass)
    264         */
    265        public void eatGrassBonus()
    266        {
    267            this.setSheared(false);
    268
    269            if (this.isChild())
    270            {
    271                int var1 = this.getGrowingAge() + 1200;
    272
    273                if (var1 > 0)
    274                {
    275                    var1 = 0;
    276                }
    277
    278                this.setGrowingAge(var1);
    279            }
    280        }
    281
    282        public void func_82163_bD()
    283        {
    284            this.setFleeceColor(getRandomFleeceColor(this.worldObj.rand));
    285        }
    286
    287        @Override
    288        public boolean isShearable(ItemStack item, World world, int X, int Y, int Z)
    289        {
    290            return !getSheared() && !isChild();
    291        }
    292
    293        @Override
    294        public ArrayList<ItemStack> onSheared(ItemStack item, World world, int X, int Y, int Z, int fortune)
    295        {
    296            ArrayList<ItemStack> ret = new ArrayList<ItemStack>();
    297            setSheared(true);
    298            int i = 1 + rand.nextInt(3);
    299            for (int j = 0; j < i; j++)
    300            {
    301                ret.add(new ItemStack(Block.cloth.blockID, 1, getFleeceColor()));
    302            }
    303            this.worldObj.playSoundAtEntity(this, "mob.sheep.shear", 1.0F, 1.0F);
    304            return ret;
    305        }
    306    }