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