    001package net.minecraft.entity.monster;
    002
    003import cpw.mods.fml.relauncher.Side;
    004import cpw.mods.fml.relauncher.SideOnly;
    005import net.minecraft.entity.Entity;
    006import net.minecraft.entity.EnumCreatureAttribute;
    007import net.minecraft.item.Item;
    008import net.minecraft.potion.Potion;
    009import net.minecraft.potion.PotionEffect;
    010import net.minecraft.util.MathHelper;
    011import net.minecraft.world.World;
    012
    013public class EntitySpider extends EntityMob
    014{
    015    public EntitySpider(World par1World)
    016    {
    017        super(par1World);
    018        this.texture = "/mob/spider.png";
    019        this.setSize(1.4F, 0.9F);
    020        this.moveSpeed = 0.8F;
    021    }
    022
    023    protected void entityInit()
    024    {
    025        super.entityInit();
    026        this.dataWatcher.addObject(16, new Byte((byte)0));
    027    }
    028
    029    /**
    030     * Called to update the entity's position/logic.
    031     */
    032    public void onUpdate()
    033    {
    034        super.onUpdate();
    035
    036        if (!this.worldObj.isRemote)
    037        {
    038            this.setBesideClimbableBlock(this.isCollidedHorizontally);
    039        }
    040    }
    041
    042    public int getMaxHealth()
    043    {
    044        return 16;
    045    }
    046
    047    /**
    048     * Returns the Y offset from the entity's position for any entity riding this one.
    049     */
    050    public double getMountedYOffset()
    051    {
    052        return (double)this.height * 0.75D - 0.5D;
    053    }
    054
    055    /**
    056     * Finds the closest player within 16 blocks to attack, or null if this Entity isn't interested in attacking
    057     * (Animals, Spiders at day, peaceful PigZombies).
    058     */
    059    protected Entity findPlayerToAttack()
    060    {
    061        float f = this.getBrightness(1.0F);
    062
    063        if (f < 0.5F)
    064        {
    065            double d0 = 16.0D;
    066            return this.worldObj.getClosestVulnerablePlayerToEntity(this, d0);
    067        }
    068        else
    069        {
    070            return null;
    071        }
    072    }
    073
    074    /**
    075     * Returns the sound this mob makes while it's alive.
    076     */
    077    protected String getLivingSound()
    078    {
    079        return "mob.spider.say";
    080    }
    081
    082    /**
    083     * Returns the sound this mob makes when it is hurt.
    084     */
    085    protected String getHurtSound()
    086    {
    087        return "mob.spider.say";
    088    }
    089
    090    /**
    091     * Returns the sound this mob makes on death.
    092     */
    093    protected String getDeathSound()
    094    {
    095        return "mob.spider.death";
    096    }
    097
    098    /**
    099     * Plays step sound at given x, y, z for the entity
    100     */
    101    protected void playStepSound(int par1, int par2, int par3, int par4)
    102    {
    103        this.playSound("mob.spider.step", 0.15F, 1.0F);
    104    }
    105
    106    /**
    107     * Basic mob attack. Default to touch of death in EntityCreature. Overridden by each mob to define their attack.
    108     */
    109    protected void attackEntity(Entity par1Entity, float par2)
    110    {
    111        float f1 = this.getBrightness(1.0F);
    112
    113        if (f1 > 0.5F && this.rand.nextInt(100) == 0)
    114        {
    115            this.entityToAttack = null;
    116        }
    117        else
    118        {
    119            if (par2 > 2.0F && par2 < 6.0F && this.rand.nextInt(10) == 0)
    120            {
    121                if (this.onGround)
    122                {
    123                    double d0 = par1Entity.posX - this.posX;
    124                    double d1 = par1Entity.posZ - this.posZ;
    125                    float f2 = MathHelper.sqrt_double(d0 * d0 + d1 * d1);
    126                    this.motionX = d0 / (double)f2 * 0.5D * 0.800000011920929D + this.motionX * 0.20000000298023224D;
    127                    this.motionZ = d1 / (double)f2 * 0.5D * 0.800000011920929D + this.motionZ * 0.20000000298023224D;
    128                    this.motionY = 0.4000000059604645D;
    129                }
    130            }
    131            else
    132            {
    133                super.attackEntity(par1Entity, par2);
    134            }
    135        }
    136    }
    137
    138    /**
    139     * Returns the item ID for the item the mob drops on death.
    140     */
    141    protected int getDropItemId()
    142    {
    143        return Item.silk.itemID;
    144    }
    145
    146    /**
    147     * Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param
    148     * par2 - Level of Looting used to kill this mob.
    149     */
    150    protected void dropFewItems(boolean par1, int par2)
    151    {
    152        super.dropFewItems(par1, par2);
    153
    154        if (par1 && (this.rand.nextInt(3) == 0 || this.rand.nextInt(1 + par2) > 0))
    155        {
    156            this.dropItem(Item.spiderEye.itemID, 1);
    157        }
    158    }
    159
    160    /**
    161     * returns true if this entity is by a ladder, false otherwise
    162     */
    163    public boolean isOnLadder()
    164    {
    165        return this.isBesideClimbableBlock();
    166    }
    167
    168    /**
    169     * Sets the Entity inside a web block.
    170     */
    171    public void setInWeb() {}
    172
    173    @SideOnly(Side.CLIENT)
    174
    175    /**
    176     * How large the spider should be scaled.
    177     */
    178    public float spiderScaleAmount()
    179    {
    180        return 1.0F;
    181    }
    182
    183    /**
    184     * Get this Entity's EnumCreatureAttribute
    185     */
    186    public EnumCreatureAttribute getCreatureAttribute()
    187    {
    188        return EnumCreatureAttribute.ARTHROPOD;
    189    }
    190
    191    public boolean isPotionApplicable(PotionEffect par1PotionEffect)
    192    {
    193        return par1PotionEffect.getPotionID() == Potion.poison.id ? false : super.isPotionApplicable(par1PotionEffect);
    194    }
    195
    196    /**
    197     * Returns true if the WatchableObject (Byte) is 0x01 otherwise returns false. The WatchableObject is updated using
    198     * setBesideClimableBlock.
    199     */
    200    public boolean isBesideClimbableBlock()
    201    {
    202        return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
    203    }
    204
    205    /**
    206     * Updates the WatchableObject (Byte) created in entityInit(), setting it to 0x01 if par1 is true or 0x00 if it is
    207     * false.
    208     */
    209    public void setBesideClimbableBlock(boolean par1)
    210    {
    211        byte b0 = this.dataWatcher.getWatchableObjectByte(16);
    212
    213        if (par1)
    214        {
    215            b0 = (byte)(b0 | 1);
    216        }
    217        else
    218        {
    219            b0 &= -2;
    220        }
    221
    222        this.dataWatcher.updateObject(16, Byte.valueOf(b0));
    223    }
    224
    225    /**
    226     * Initialize this creature.
    227     */
    228    public void initCreature()
    229    {
    230        if (this.worldObj.rand.nextInt(100) == 0)
    231        {
    232            EntitySkeleton entityskeleton = new EntitySkeleton(this.worldObj);
    233            entityskeleton.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, 0.0F);
    234            entityskeleton.initCreature();
    235            this.worldObj.spawnEntityInWorld(entityskeleton);
    236            entityskeleton.mountEntity(this);
    237        }
    238    }
    239}