    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.ai.EntityAIAttackOnCollide;
    007import net.minecraft.entity.ai.EntityAIAvoidEntity;
    008import net.minecraft.entity.ai.EntityAICreeperSwell;
    009import net.minecraft.entity.ai.EntityAIHurtByTarget;
    010import net.minecraft.entity.ai.EntityAILookIdle;
    011import net.minecraft.entity.ai.EntityAINearestAttackableTarget;
    012import net.minecraft.entity.ai.EntityAISwimming;
    013import net.minecraft.entity.ai.EntityAIWander;
    014import net.minecraft.entity.ai.EntityAIWatchClosest;
    015import net.minecraft.entity.effect.EntityLightningBolt;
    016import net.minecraft.entity.passive.EntityOcelot;
    017import net.minecraft.entity.player.EntityPlayer;
    018import net.minecraft.item.Item;
    019import net.minecraft.nbt.NBTTagCompound;
    020import net.minecraft.util.DamageSource;
    021import net.minecraft.world.World;
    022
    023public class EntityCreeper extends EntityMob
    024{
    025    /**
    026     * Time when this creeper was last in an active state (Messed up code here, probably causes creeper animation to go
    027     * weird)
    028     */
    029    private int lastActiveTime;
    030
    031    /**
    032     * The amount of time since the creeper was close enough to the player to ignite
    033     */
    034    private int timeSinceIgnited;
    035    private int fuseTime = 30;
    036
    037    /** Explosion radius for this creeper. */
    038    private int explosionRadius = 3;
    039
    040    public EntityCreeper(World par1World)
    041    {
    042        super(par1World);
    043        this.texture = "/mob/creeper.png";
    044        this.tasks.addTask(1, new EntityAISwimming(this));
    045        this.tasks.addTask(2, new EntityAICreeperSwell(this));
    046        this.tasks.addTask(3, new EntityAIAvoidEntity(this, EntityOcelot.class, 6.0F, 0.25F, 0.3F));
    047        this.tasks.addTask(4, new EntityAIAttackOnCollide(this, 0.25F, false));
    048        this.tasks.addTask(5, new EntityAIWander(this, 0.2F));
    049        this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F));
    050        this.tasks.addTask(6, new EntityAILookIdle(this));
    051        this.targetTasks.addTask(1, new EntityAINearestAttackableTarget(this, EntityPlayer.class, 16.0F, 0, true));
    052        this.targetTasks.addTask(2, new EntityAIHurtByTarget(this, false));
    053    }
    054
    055    /**
    056     * Returns true if the newer Entity AI code should be run
    057     */
    058    public boolean isAIEnabled()
    059    {
    060        return true;
    061    }
    062
    063    public int func_82143_as()
    064    {
    065        return this.getAttackTarget() == null ? 3 : 3 + (this.health - 1);
    066    }
    067
    068    /**
    069     * Called when the mob is falling. Calculates and applies fall damage.
    070     */
    071    protected void fall(float par1)
    072    {
    073        super.fall(par1);
    074        this.timeSinceIgnited = (int)((float)this.timeSinceIgnited + par1 * 1.5F);
    075
    076        if (this.timeSinceIgnited > this.fuseTime - 5)
    077        {
    078            this.timeSinceIgnited = this.fuseTime - 5;
    079        }
    080    }
    081
    082    public int getMaxHealth()
    083    {
    084        return 20;
    085    }
    086
    087    protected void entityInit()
    088    {
    089        super.entityInit();
    090        this.dataWatcher.addObject(16, Byte.valueOf((byte) - 1));
    091        this.dataWatcher.addObject(17, Byte.valueOf((byte)0));
    092    }
    093
    094    /**
    095     * (abstract) Protected helper method to write subclass entity data to NBT.
    096     */
    097    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    098    {
    099        super.writeEntityToNBT(par1NBTTagCompound);
    100
    101        if (this.dataWatcher.getWatchableObjectByte(17) == 1)
    102        {
    103            par1NBTTagCompound.setBoolean("powered", true);
    104        }
    105
    106        par1NBTTagCompound.setShort("Fuse", (short)this.fuseTime);
    107        par1NBTTagCompound.setByte("ExplosionRadius", (byte)this.explosionRadius);
    108    }
    109
    110    /**
    111     * (abstract) Protected helper method to read subclass entity data from NBT.
    112     */
    113    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    114    {
    115        super.readEntityFromNBT(par1NBTTagCompound);
    116        this.dataWatcher.updateObject(17, Byte.valueOf((byte)(par1NBTTagCompound.getBoolean("powered") ? 1 : 0)));
    117
    118        if (par1NBTTagCompound.hasKey("Fuse"))
    119        {
    120            this.fuseTime = par1NBTTagCompound.getShort("Fuse");
    121        }
    122
    123        if (par1NBTTagCompound.hasKey("ExplosionRadius"))
    124        {
    125            this.explosionRadius = par1NBTTagCompound.getByte("ExplosionRadius");
    126        }
    127    }
    128
    129    /**
    130     * Called to update the entity's position/logic.
    131     */
    132    public void onUpdate()
    133    {
    134        if (this.isEntityAlive())
    135        {
    136            this.lastActiveTime = this.timeSinceIgnited;
    137            int i = this.getCreeperState();
    138
    139            if (i > 0 && this.timeSinceIgnited == 0)
    140            {
    141                this.playSound("random.fuse", 1.0F, 0.5F);
    142            }
    143
    144            this.timeSinceIgnited += i;
    145
    146            if (this.timeSinceIgnited < 0)
    147            {
    148                this.timeSinceIgnited = 0;
    149            }
    150
    151            if (this.timeSinceIgnited >= this.fuseTime)
    152            {
    153                this.timeSinceIgnited = this.fuseTime;
    154
    155                if (!this.worldObj.isRemote)
    156                {
    157                    boolean flag = this.worldObj.getGameRules().getGameRuleBooleanValue("mobGriefing");
    158
    159                    if (this.getPowered())
    160                    {
    161                        this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)(this.explosionRadius * 2), flag);
    162                    }
    163                    else
    164                    {
    165                        this.worldObj.createExplosion(this, this.posX, this.posY, this.posZ, (float)this.explosionRadius, flag);
    166                    }
    167
    168                    this.setDead();
    169                }
    170            }
    171        }
    172
    173        super.onUpdate();
    174    }
    175
    176    /**
    177     * Returns the sound this mob makes when it is hurt.
    178     */
    179    protected String getHurtSound()
    180    {
    181        return "mob.creeper.say";
    182    }
    183
    184    /**
    185     * Returns the sound this mob makes on death.
    186     */
    187    protected String getDeathSound()
    188    {
    189        return "mob.creeper.death";
    190    }
    191
    192    /**
    193     * Called when the mob's health reaches 0.
    194     */
    195    public void onDeath(DamageSource par1DamageSource)
    196    {
    197        super.onDeath(par1DamageSource);
    198
    199        if (par1DamageSource.getEntity() instanceof EntitySkeleton)
    200        {
    201            int i = Item.record13.itemID + this.rand.nextInt(Item.recordWait.itemID - Item.record13.itemID + 1);
    202            this.dropItem(i, 1);
    203        }
    204    }
    205
    206    public boolean attackEntityAsMob(Entity par1Entity)
    207    {
    208        return true;
    209    }
    210
    211    /**
    212     * Returns true if the creeper is powered by a lightning bolt.
    213     */
    214    public boolean getPowered()
    215    {
    216        return this.dataWatcher.getWatchableObjectByte(17) == 1;
    217    }
    218
    219    @SideOnly(Side.CLIENT)
    220
    221    /**
    222     * Params: (Float)Render tick. Returns the intensity of the creeper's flash when it is ignited.
    223     */
    224    public float getCreeperFlashIntensity(float par1)
    225    {
    226        return ((float)this.lastActiveTime + (float)(this.timeSinceIgnited - this.lastActiveTime) * par1) / (float)(this.fuseTime - 2);
    227    }
    228
    229    /**
    230     * Returns the item ID for the item the mob drops on death.
    231     */
    232    protected int getDropItemId()
    233    {
    234        return Item.gunpowder.itemID;
    235    }
    236
    237    /**
    238     * Returns the current state of creeper, -1 is idle, 1 is 'in fuse'
    239     */
    240    public int getCreeperState()
    241    {
    242        return this.dataWatcher.getWatchableObjectByte(16);
    243    }
    244
    245    /**
    246     * Sets the state of creeper, -1 to idle and 1 to be 'in fuse'
    247     */
    248    public void setCreeperState(int par1)
    249    {
    250        this.dataWatcher.updateObject(16, Byte.valueOf((byte)par1));
    251    }
    252
    253    /**
    254     * Called when a lightning bolt hits the entity.
    255     */
    256    public void onStruckByLightning(EntityLightningBolt par1EntityLightningBolt)
    257    {
    258        super.onStruckByLightning(par1EntityLightningBolt);
    259        this.dataWatcher.updateObject(17, Byte.valueOf((byte)1));
    260    }
    261}