001package net.minecraft.entity.item;
002
003import cpw.mods.fml.relauncher.Side;
004import cpw.mods.fml.relauncher.SideOnly;
005import net.minecraft.entity.Entity;
006import net.minecraft.item.ItemStack;
007import net.minecraft.nbt.NBTTagCompound;
008import net.minecraft.util.MathHelper;
009import net.minecraft.world.World;
010
011public class EntityFireworkRocket extends Entity
012{
013    /** The age of the firework in ticks. */
014    private int fireworkAge;
015
016    /**
017     * The lifetime of the firework in ticks. When the age reaches the lifetime the firework explodes.
018     */
019    private int lifetime;
020
021    public EntityFireworkRocket(World par1World)
022    {
023        super(par1World);
024        this.setSize(0.25F, 0.25F);
025    }
026
027    protected void entityInit()
028    {
029        this.dataWatcher.addObjectByDataType(8, 5);
030    }
031
032    @SideOnly(Side.CLIENT)
033
034    /**
035     * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
036     * length * 64 * renderDistanceWeight Args: distance
037     */
038    public boolean isInRangeToRenderDist(double par1)
039    {
040        return par1 < 4096.0D;
041    }
042
043    public EntityFireworkRocket(World par1World, double par2, double par4, double par6, ItemStack par8ItemStack)
044    {
045        super(par1World);
046        this.fireworkAge = 0;
047        this.setSize(0.25F, 0.25F);
048        this.setPosition(par2, par4, par6);
049        this.yOffset = 0.0F;
050        int i = 1;
051
052        if (par8ItemStack != null && par8ItemStack.hasTagCompound())
053        {
054            this.dataWatcher.updateObject(8, par8ItemStack);
055            NBTTagCompound nbttagcompound = par8ItemStack.getTagCompound();
056            NBTTagCompound nbttagcompound1 = nbttagcompound.getCompoundTag("Fireworks");
057
058            if (nbttagcompound1 != null)
059            {
060                i += nbttagcompound1.getByte("Flight");
061            }
062        }
063
064        this.motionX = this.rand.nextGaussian() * 0.001D;
065        this.motionZ = this.rand.nextGaussian() * 0.001D;
066        this.motionY = 0.05D;
067        this.lifetime = 10 * i + this.rand.nextInt(6) + this.rand.nextInt(7);
068    }
069
070    @SideOnly(Side.CLIENT)
071
072    /**
073     * Sets the velocity to the args. Args: x, y, z
074     */
075    public void setVelocity(double par1, double par3, double par5)
076    {
077        this.motionX = par1;
078        this.motionY = par3;
079        this.motionZ = par5;
080
081        if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
082        {
083            float f = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
084            this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI);
085            this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)f) * 180.0D / Math.PI);
086        }
087    }
088
089    /**
090     * Called to update the entity's position/logic.
091     */
092    public void onUpdate()
093    {
094        this.lastTickPosX = this.posX;
095        this.lastTickPosY = this.posY;
096        this.lastTickPosZ = this.posZ;
097        super.onUpdate();
098        this.motionX *= 1.15D;
099        this.motionZ *= 1.15D;
100        this.motionY += 0.04D;
101        this.moveEntity(this.motionX, this.motionY, this.motionZ);
102        float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
103        this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
104
105        for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)f) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
106        {
107            ;
108        }
109
110        while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
111        {
112            this.prevRotationPitch += 360.0F;
113        }
114
115        while (this.rotationYaw - this.prevRotationYaw < -180.0F)
116        {
117            this.prevRotationYaw -= 360.0F;
118        }
119
120        while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
121        {
122            this.prevRotationYaw += 360.0F;
123        }
124
125        this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
126        this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
127
128        if (this.fireworkAge == 0)
129        {
130            this.worldObj.playSoundAtEntity(this, "fireworks.launch", 3.0F, 1.0F);
131        }
132
133        ++this.fireworkAge;
134
135        if (this.worldObj.isRemote && this.fireworkAge % 2 < 2)
136        {
137            this.worldObj.spawnParticle("fireworksSpark", this.posX, this.posY - 0.3D, this.posZ, this.rand.nextGaussian() * 0.05D, -this.motionY * 0.5D, this.rand.nextGaussian() * 0.05D);
138        }
139
140        if (!this.worldObj.isRemote && this.fireworkAge > this.lifetime)
141        {
142            this.worldObj.setEntityState(this, (byte)17);
143            this.setDead();
144        }
145    }
146
147    @SideOnly(Side.CLIENT)
148    public void handleHealthUpdate(byte par1)
149    {
150        if (par1 == 17 && this.worldObj.isRemote)
151        {
152            ItemStack itemstack = this.dataWatcher.getWatchableObjectItemStack(8);
153            NBTTagCompound nbttagcompound = null;
154
155            if (itemstack != null && itemstack.hasTagCompound())
156            {
157                nbttagcompound = itemstack.getTagCompound().getCompoundTag("Fireworks");
158            }
159
160            this.worldObj.func_92088_a(this.posX, this.posY, this.posZ, this.motionX, this.motionY, this.motionZ, nbttagcompound);
161        }
162
163        super.handleHealthUpdate(par1);
164    }
165
166    /**
167     * (abstract) Protected helper method to write subclass entity data to NBT.
168     */
169    public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
170    {
171        par1NBTTagCompound.setInteger("Life", this.fireworkAge);
172        par1NBTTagCompound.setInteger("LifeTime", this.lifetime);
173        ItemStack itemstack = this.dataWatcher.getWatchableObjectItemStack(8);
174
175        if (itemstack != null)
176        {
177            NBTTagCompound nbttagcompound1 = new NBTTagCompound();
178            itemstack.writeToNBT(nbttagcompound1);
179            par1NBTTagCompound.setCompoundTag("FireworksItem", nbttagcompound1);
180        }
181    }
182
183    /**
184     * (abstract) Protected helper method to read subclass entity data from NBT.
185     */
186    public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
187    {
188        this.fireworkAge = par1NBTTagCompound.getInteger("Life");
189        this.lifetime = par1NBTTagCompound.getInteger("LifeTime");
190        NBTTagCompound nbttagcompound1 = par1NBTTagCompound.getCompoundTag("FireworksItem");
191
192        if (nbttagcompound1 != null)
193        {
194            ItemStack itemstack = ItemStack.loadItemStackFromNBT(nbttagcompound1);
195
196            if (itemstack != null)
197            {
198                this.dataWatcher.updateObject(8, itemstack);
199            }
200        }
201    }
202
203    @SideOnly(Side.CLIENT)
204    public float getShadowSize()
205    {
206        return 0.0F;
207    }
208
209    /**
210     * Gets how bright this entity is.
211     */
212    public float getBrightness(float par1)
213    {
214        return super.getBrightness(par1);
215    }
216
217    @SideOnly(Side.CLIENT)
218    public int getBrightnessForRender(float par1)
219    {
220        return super.getBrightnessForRender(par1);
221    }
222
223    /**
224     * If returns false, the item will not inflict any damage against entities.
225     */
226    public boolean canAttackWithItem()
227    {
228        return false;
229    }
230}