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.player.EntityPlayer;
007import net.minecraft.entity.projectile.EntitySmallFireball;
008import net.minecraft.item.Item;
009import net.minecraft.util.DamageSource;
010import net.minecraft.util.MathHelper;
011import net.minecraft.world.World;
012
013public class EntityBlaze extends EntityMob
014{
015    /** Random offset used in floating behaviour */
016    private float heightOffset = 0.5F;
017
018    /** ticks until heightOffset is randomized */
019    private int heightOffsetUpdateTime;
020    private int field_70846_g;
021
022    public EntityBlaze(World par1World)
023    {
024        super(par1World);
025        this.texture = "/mob/fire.png";
026        this.isImmuneToFire = true;
027        this.experienceValue = 10;
028    }
029
030    public int getMaxHealth()
031    {
032        return 20;
033    }
034
035    protected void entityInit()
036    {
037        super.entityInit();
038        this.dataWatcher.addObject(16, new Byte((byte)0));
039    }
040
041    /**
042     * Returns the sound this mob makes while it's alive.
043     */
044    protected String getLivingSound()
045    {
046        return "mob.blaze.breathe";
047    }
048
049    /**
050     * Returns the sound this mob makes when it is hurt.
051     */
052    protected String getHurtSound()
053    {
054        return "mob.blaze.hit";
055    }
056
057    /**
058     * Returns the sound this mob makes on death.
059     */
060    protected String getDeathSound()
061    {
062        return "mob.blaze.death";
063    }
064
065    @SideOnly(Side.CLIENT)
066    public int getBrightnessForRender(float par1)
067    {
068        return 15728880;
069    }
070
071    /**
072     * Gets how bright this entity is.
073     */
074    public float getBrightness(float par1)
075    {
076        return 1.0F;
077    }
078
079    /**
080     * Called frequently so the entity can update its state every tick as required. For example, zombies and skeletons
081     * use this to react to sunlight and start to burn.
082     */
083    public void onLivingUpdate()
084    {
085        if (!this.worldObj.isRemote)
086        {
087            if (this.isWet())
088            {
089                this.attackEntityFrom(DamageSource.drown, 1);
090            }
091
092            --this.heightOffsetUpdateTime;
093
094            if (this.heightOffsetUpdateTime <= 0)
095            {
096                this.heightOffsetUpdateTime = 100;
097                this.heightOffset = 0.5F + (float)this.rand.nextGaussian() * 3.0F;
098            }
099
100            if (this.getEntityToAttack() != null && this.getEntityToAttack().posY + (double)this.getEntityToAttack().getEyeHeight() > this.posY + (double)this.getEyeHeight() + (double)this.heightOffset)
101            {
102                this.motionY += (0.30000001192092896D - this.motionY) * 0.30000001192092896D;
103            }
104        }
105
106        if (this.rand.nextInt(24) == 0)
107        {
108            this.worldObj.playSoundEffect(this.posX + 0.5D, this.posY + 0.5D, this.posZ + 0.5D, "fire.fire", 1.0F + this.rand.nextFloat(), this.rand.nextFloat() * 0.7F + 0.3F);
109        }
110
111        if (!this.onGround && this.motionY < 0.0D)
112        {
113            this.motionY *= 0.6D;
114        }
115
116        for (int i = 0; i < 2; ++i)
117        {
118            this.worldObj.spawnParticle("largesmoke", this.posX + (this.rand.nextDouble() - 0.5D) * (double)this.width, this.posY + this.rand.nextDouble() * (double)this.height, this.posZ + (this.rand.nextDouble() - 0.5D) * (double)this.width, 0.0D, 0.0D, 0.0D);
119        }
120
121        super.onLivingUpdate();
122    }
123
124    /**
125     * Basic mob attack. Default to touch of death in EntityCreature. Overridden by each mob to define their attack.
126     */
127    protected void attackEntity(Entity par1Entity, float par2)
128    {
129        if (this.attackTime <= 0 && par2 < 2.0F && par1Entity.boundingBox.maxY > this.boundingBox.minY && par1Entity.boundingBox.minY < this.boundingBox.maxY)
130        {
131            this.attackTime = 20;
132            this.attackEntityAsMob(par1Entity);
133        }
134        else if (par2 < 30.0F)
135        {
136            double d0 = par1Entity.posX - this.posX;
137            double d1 = par1Entity.boundingBox.minY + (double)(par1Entity.height / 2.0F) - (this.posY + (double)(this.height / 2.0F));
138            double d2 = par1Entity.posZ - this.posZ;
139
140            if (this.attackTime == 0)
141            {
142                ++this.field_70846_g;
143
144                if (this.field_70846_g == 1)
145                {
146                    this.attackTime = 60;
147                    this.func_70844_e(true);
148                }
149                else if (this.field_70846_g <= 4)
150                {
151                    this.attackTime = 6;
152                }
153                else
154                {
155                    this.attackTime = 100;
156                    this.field_70846_g = 0;
157                    this.func_70844_e(false);
158                }
159
160                if (this.field_70846_g > 1)
161                {
162                    float f1 = MathHelper.sqrt_float(par2) * 0.5F;
163                    this.worldObj.playAuxSFXAtEntity((EntityPlayer)null, 1009, (int)this.posX, (int)this.posY, (int)this.posZ, 0);
164
165                    for (int i = 0; i < 1; ++i)
166                    {
167                        EntitySmallFireball entitysmallfireball = new EntitySmallFireball(this.worldObj, this, d0 + this.rand.nextGaussian() * (double)f1, d1, d2 + this.rand.nextGaussian() * (double)f1);
168                        entitysmallfireball.posY = this.posY + (double)(this.height / 2.0F) + 0.5D;
169                        this.worldObj.spawnEntityInWorld(entitysmallfireball);
170                    }
171                }
172            }
173
174            this.rotationYaw = (float)(Math.atan2(d2, d0) * 180.0D / Math.PI) - 90.0F;
175            this.hasAttacked = true;
176        }
177    }
178
179    /**
180     * Called when the mob is falling. Calculates and applies fall damage.
181     */
182    protected void fall(float par1) {}
183
184    /**
185     * Returns the item ID for the item the mob drops on death.
186     */
187    protected int getDropItemId()
188    {
189        return Item.blazeRod.itemID;
190    }
191
192    /**
193     * Returns true if the entity is on fire. Used by render to add the fire effect on rendering.
194     */
195    public boolean isBurning()
196    {
197        return this.func_70845_n();
198    }
199
200    /**
201     * Drop 0-2 items of this living's type. @param par1 - Whether this entity has recently been hit by a player. @param
202     * par2 - Level of Looting used to kill this mob.
203     */
204    protected void dropFewItems(boolean par1, int par2)
205    {
206        if (par1)
207        {
208            int j = this.rand.nextInt(2 + par2);
209
210            for (int k = 0; k < j; ++k)
211            {
212                this.dropItem(Item.blazeRod.itemID, 1);
213            }
214        }
215    }
216
217    public boolean func_70845_n()
218    {
219        return (this.dataWatcher.getWatchableObjectByte(16) & 1) != 0;
220    }
221
222    public void func_70844_e(boolean par1)
223    {
224        byte b0 = this.dataWatcher.getWatchableObjectByte(16);
225
226        if (par1)
227        {
228            b0 = (byte)(b0 | 1);
229        }
230        else
231        {
232            b0 &= -2;
233        }
234
235        this.dataWatcher.updateObject(16, Byte.valueOf(b0));
236    }
237
238    /**
239     * Checks to make sure the light is not too bright where the mob is spawning
240     */
241    protected boolean isValidLightLevel()
242    {
243        return true;
244    }
245
246    /**
247     * Returns the amount of damage a mob should deal.
248     */
249    public int getAttackStrength(Entity par1Entity)
250    {
251        return 6;
252    }
253}