    001    package net.minecraft.src;
    002
    003    public class EntitySlime extends EntityLiving implements IMob
    004    {
    005        public float field_70813_a;
    006        public float field_70811_b;
    007        public float field_70812_c;
    008
    009        /** the time between each jump of the slime */
    010        private int slimeJumpDelay = 0;
    011
    012        public EntitySlime(World par1World)
    013        {
    014            super(par1World);
    015            this.texture = "/mob/slime.png";
    016            int var2 = 1 << this.rand.nextInt(3);
    017            this.yOffset = 0.0F;
    018            this.slimeJumpDelay = this.rand.nextInt(20) + 10;
    019            this.setSlimeSize(var2);
    020        }
    021
    022        protected void entityInit()
    023        {
    024            super.entityInit();
    025            this.dataWatcher.addObject(16, new Byte((byte)1));
    026        }
    027
    028        protected void setSlimeSize(int par1)
    029        {
    030            this.dataWatcher.updateObject(16, new Byte((byte)par1));
    031            this.setSize(0.6F * (float)par1, 0.6F * (float)par1);
    032            this.setPosition(this.posX, this.posY, this.posZ);
    033            this.setEntityHealth(this.getMaxHealth());
    034            this.experienceValue = par1;
    035        }
    036
    037        public int getMaxHealth()
    038        {
    039            int var1 = this.getSlimeSize();
    040            return var1 * var1;
    041        }
    042
    043        /**
    044         * Returns the size of the slime.
    045         */
    046        public int getSlimeSize()
    047        {
    048            return this.dataWatcher.getWatchableObjectByte(16);
    049        }
    050
    051        /**
    052         * (abstract) Protected helper method to write subclass entity data to NBT.
    053         */
    054        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    055        {
    056            super.writeEntityToNBT(par1NBTTagCompound);
    057            par1NBTTagCompound.setInteger("Size", this.getSlimeSize() - 1);
    058        }
    059
    060        /**
    061         * (abstract) Protected helper method to read subclass entity data from NBT.
    062         */
    063        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    064        {
    065            super.readEntityFromNBT(par1NBTTagCompound);
    066            this.setSlimeSize(par1NBTTagCompound.getInteger("Size") + 1);
    067        }
    068
    069        /**
    070         * Returns the name of a particle effect that may be randomly created by EntitySlime.onUpdate()
    071         */
    072        protected String getSlimeParticle()
    073        {
    074            return "slime";
    075        }
    076
    077        /**
    078         * Returns the name of the sound played when the slime jumps.
    079         */
    080        protected String getJumpSound()
    081        {
    082            return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
    083        }
    084
    085        /**
    086         * Called to update the entity's position/logic.
    087         */
    088        public void onUpdate()
    089        {
    090            if (!this.worldObj.isRemote && this.worldObj.difficultySetting == 0 && this.getSlimeSize() > 0)
    091            {
    092                this.isDead = true;
    093            }
    094
    095            this.field_70811_b += (this.field_70813_a - this.field_70811_b) * 0.5F;
    096            this.field_70812_c = this.field_70811_b;
    097            boolean var1 = this.onGround;
    098            super.onUpdate();
    099            int var2;
    100
    101            if (this.onGround && !var1)
    102            {
    103                var2 = this.getSlimeSize();
    104
    105                for (int var3 = 0; var3 < var2 * 8; ++var3)
    106                {
    107                    float var4 = this.rand.nextFloat() * (float)Math.PI * 2.0F;
    108                    float var5 = this.rand.nextFloat() * 0.5F + 0.5F;
    109                    float var6 = MathHelper.sin(var4) * (float)var2 * 0.5F * var5;
    110                    float var7 = MathHelper.cos(var4) * (float)var2 * 0.5F * var5;
    111                    this.worldObj.spawnParticle(this.getSlimeParticle(), this.posX + (double)var6, this.boundingBox.minY, this.posZ + (double)var7, 0.0D, 0.0D, 0.0D);
    112                }
    113
    114                if (this.makesSoundOnLand())
    115                {
    116                    this.func_85030_a(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) / 0.8F);
    117                }
    118
    119                this.field_70813_a = -0.5F;
    120            }
    121            else if (!this.onGround && var1)
    122            {
    123                this.field_70813_a = 1.0F;
    124            }
    125
    126            this.func_70808_l();
    127
    128            if (this.worldObj.isRemote)
    129            {
    130                var2 = this.getSlimeSize();
    131                this.setSize(0.6F * (float)var2, 0.6F * (float)var2);
    132            }
    133        }
    134
    135        protected void updateEntityActionState()
    136        {
    137            this.despawnEntity();
    138            EntityPlayer var1 = this.worldObj.getClosestVulnerablePlayerToEntity(this, 16.0D);
    139
    140            if (var1 != null)
    141            {
    142                this.faceEntity(var1, 10.0F, 20.0F);
    143            }
    144
    145            if (this.onGround && this.slimeJumpDelay-- <= 0)
    146            {
    147                this.slimeJumpDelay = this.getJumpDelay();
    148
    149                if (var1 != null)
    150                {
    151                    this.slimeJumpDelay /= 3;
    152                }
    153
    154                this.isJumping = true;
    155
    156                if (this.makesSoundOnJump())
    157                {
    158                    this.func_85030_a(this.getJumpSound(), this.getSoundVolume(), ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F) * 0.8F);
    159                }
    160
    161                this.moveStrafing = 1.0F - this.rand.nextFloat() * 2.0F;
    162                this.moveForward = (float)(1 * this.getSlimeSize());
    163            }
    164            else
    165            {
    166                this.isJumping = false;
    167
    168                if (this.onGround)
    169                {
    170                    this.moveStrafing = this.moveForward = 0.0F;
    171                }
    172            }
    173        }
    174
    175        protected void func_70808_l()
    176        {
    177            this.field_70813_a *= 0.6F;
    178        }
    179
    180        /**
    181         * Gets the amount of time the slime needs to wait between jumps.
    182         */
    183        protected int getJumpDelay()
    184        {
    185            return this.rand.nextInt(20) + 10;
    186        }
    187
    188        protected EntitySlime createInstance()
    189        {
    190            return new EntitySlime(this.worldObj);
    191        }
    192
    193        /**
    194         * Will get destroyed next tick.
    195         */
    196        public void setDead()
    197        {
    198            int var1 = this.getSlimeSize();
    199
    200            if (!this.worldObj.isRemote && var1 > 1 && this.getHealth() <= 0)
    201            {
    202                int var2 = 2 + this.rand.nextInt(3);
    203
    204                for (int var3 = 0; var3 < var2; ++var3)
    205                {
    206                    float var4 = ((float)(var3 % 2) - 0.5F) * (float)var1 / 4.0F;
    207                    float var5 = ((float)(var3 / 2) - 0.5F) * (float)var1 / 4.0F;
    208                    EntitySlime var6 = this.createInstance();
    209                    var6.setSlimeSize(var1 / 2);
    210                    var6.setLocationAndAngles(this.posX + (double)var4, this.posY + 0.5D, this.posZ + (double)var5, this.rand.nextFloat() * 360.0F, 0.0F);
    211                    this.worldObj.spawnEntityInWorld(var6);
    212                }
    213            }
    214
    215            super.setDead();
    216        }
    217
    218        /**
    219         * Called by a player entity when they collide with an entity
    220         */
    221        public void onCollideWithPlayer(EntityPlayer par1EntityPlayer)
    222        {
    223            if (this.canDamagePlayer())
    224            {
    225                int var2 = this.getSlimeSize();
    226
    227                if (this.canEntityBeSeen(par1EntityPlayer) && this.getDistanceSqToEntity(par1EntityPlayer) < 0.6D * (double)var2 * 0.6D * (double)var2 && par1EntityPlayer.attackEntityFrom(DamageSource.causeMobDamage(this), this.getAttackStrength()))
    228                {
    229                    this.func_85030_a("mob.attack", 1.0F, (this.rand.nextFloat() - this.rand.nextFloat()) * 0.2F + 1.0F);
    230                }
    231            }
    232        }
    233
    234        /**
    235         * Indicates weather the slime is able to damage the player (based upon the slime's size)
    236         */
    237        protected boolean canDamagePlayer()
    238        {
    239            return this.getSlimeSize() > 1;
    240        }
    241
    242        /**
    243         * Gets the amount of damage dealt to the player when "attacked" by the slime.
    244         */
    245        protected int getAttackStrength()
    246        {
    247            return this.getSlimeSize();
    248        }
    249
    250        /**
    251         * Returns the sound this mob makes when it is hurt.
    252         */
    253        protected String getHurtSound()
    254        {
    255            return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
    256        }
    257
    258        /**
    259         * Returns the sound this mob makes on death.
    260         */
    261        protected String getDeathSound()
    262        {
    263            return "mob.slime." + (this.getSlimeSize() > 1 ? "big" : "small");
    264        }
    265
    266        /**
    267         * Returns the item ID for the item the mob drops on death.
    268         */
    269        protected int getDropItemId()
    270        {
    271            return this.getSlimeSize() == 1 ? Item.slimeBall.shiftedIndex : 0;
    272        }
    273
    274        /**
    275         * Checks if the entity's current position is a valid location to spawn this entity.
    276         */
    277        public boolean getCanSpawnHere()
    278        {
    279            Chunk var1 = this.worldObj.getChunkFromBlockCoords(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ));
    280
    281            if (this.worldObj.getWorldInfo().getTerrainType().handleSlimeSpawnReduction(rand, worldObj))
    282            {
    283                return false;
    284            }
    285            else
    286            {
    287                if (this.getSlimeSize() == 1 || this.worldObj.difficultySetting > 0)
    288                {
    289                    if (this.worldObj.getBiomeGenForCoords(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posZ)) == BiomeGenBase.swampland && this.posY > 50.0D && this.posY < 70.0D && this.worldObj.getBlockLightValue(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY), MathHelper.floor_double(this.posZ)) <= this.rand.nextInt(8))
    290                    {
    291                        return super.getCanSpawnHere();
    292                    }
    293
    294                    if (this.rand.nextInt(10) == 0 && var1.getRandomWithSeed(987234911L).nextInt(10) == 0 && this.posY < 40.0D)
    295                    {
    296                        return super.getCanSpawnHere();
    297                    }
    298                }
    299
    300                return false;
    301            }
    302        }
    303
    304        /**
    305         * Returns the volume for the sounds this mob makes.
    306         */
    307        protected float getSoundVolume()
    308        {
    309            return 0.4F * (float)this.getSlimeSize();
    310        }
    311
    312        /**
    313         * The speed it takes to move the entityliving's rotationPitch through the faceEntity method. This is only currently
    314         * use in wolves.
    315         */
    316        public int getVerticalFaceSpeed()
    317        {
    318            return 0;
    319        }
    320
    321        /**
    322         * Returns true if the slime makes a sound when it jumps (based upon the slime's size)
    323         */
    324        protected boolean makesSoundOnJump()
    325        {
    326            return this.getSlimeSize() > 0;
    327        }
    328
    329        /**
    330         * Returns true if the slime makes a sound when it lands after a jump (based upon the slime's size)
    331         */
    332        protected boolean makesSoundOnLand()
    333        {
    334            return this.getSlimeSize() > 2;
    335        }
    336    }