    001    package net.minecraft.src;
    002
    003    import cpw.mods.fml.common.Side;
    004    import cpw.mods.fml.common.asm.SideOnly;
    005    import java.util.List;
    006
    007    public abstract class EntityFireball extends Entity
    008    {
    009        private int xTile = -1;
    010        private int yTile = -1;
    011        private int zTile = -1;
    012        private int inTile = 0;
    013        private boolean inGround = false;
    014        public EntityLiving shootingEntity;
    015        private int ticksAlive;
    016        private int ticksInAir = 0;
    017        public double accelerationX;
    018        public double accelerationY;
    019        public double accelerationZ;
    020
    021        public EntityFireball(World par1World)
    022        {
    023            super(par1World);
    024            this.setSize(1.0F, 1.0F);
    025        }
    026
    027        protected void entityInit() {}
    028
    029        @SideOnly(Side.CLIENT)
    030
    031        /**
    032         * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
    033         * length * 64 * renderDistanceWeight Args: distance
    034         */
    035        public boolean isInRangeToRenderDist(double par1)
    036        {
    037            double var3 = this.boundingBox.getAverageEdgeLength() * 4.0D;
    038            var3 *= 64.0D;
    039            return par1 < var3 * var3;
    040        }
    041
    042        public EntityFireball(World par1World, double par2, double par4, double par6, double par8, double par10, double par12)
    043        {
    044            super(par1World);
    045            this.setSize(1.0F, 1.0F);
    046            this.setLocationAndAngles(par2, par4, par6, this.rotationYaw, this.rotationPitch);
    047            this.setPosition(par2, par4, par6);
    048            double var14 = (double)MathHelper.sqrt_double(par8 * par8 + par10 * par10 + par12 * par12);
    049            this.accelerationX = par8 / var14 * 0.1D;
    050            this.accelerationY = par10 / var14 * 0.1D;
    051            this.accelerationZ = par12 / var14 * 0.1D;
    052        }
    053
    054        public EntityFireball(World par1World, EntityLiving par2EntityLiving, double par3, double par5, double par7)
    055        {
    056            super(par1World);
    057            this.shootingEntity = par2EntityLiving;
    058            this.setSize(1.0F, 1.0F);
    059            this.setLocationAndAngles(par2EntityLiving.posX, par2EntityLiving.posY, par2EntityLiving.posZ, par2EntityLiving.rotationYaw, par2EntityLiving.rotationPitch);
    060            this.setPosition(this.posX, this.posY, this.posZ);
    061            this.yOffset = 0.0F;
    062            this.motionX = this.motionY = this.motionZ = 0.0D;
    063            par3 += this.rand.nextGaussian() * 0.4D;
    064            par5 += this.rand.nextGaussian() * 0.4D;
    065            par7 += this.rand.nextGaussian() * 0.4D;
    066            double var9 = (double)MathHelper.sqrt_double(par3 * par3 + par5 * par5 + par7 * par7);
    067            this.accelerationX = par3 / var9 * 0.1D;
    068            this.accelerationY = par5 / var9 * 0.1D;
    069            this.accelerationZ = par7 / var9 * 0.1D;
    070        }
    071
    072        /**
    073         * Called to update the entity's position/logic.
    074         */
    075        public void onUpdate()
    076        {
    077            if (!this.worldObj.isRemote && (this.shootingEntity != null && this.shootingEntity.isDead || !this.worldObj.blockExists((int)this.posX, (int)this.posY, (int)this.posZ)))
    078            {
    079                this.setDead();
    080            }
    081            else
    082            {
    083                super.onUpdate();
    084                this.setFire(1);
    085
    086                if (this.inGround)
    087                {
    088                    int var1 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
    089
    090                    if (var1 == this.inTile)
    091                    {
    092                        ++this.ticksAlive;
    093
    094                        if (this.ticksAlive == 600)
    095                        {
    096                            this.setDead();
    097                        }
    098
    099                        return;
    100                    }
    101
    102                    this.inGround = false;
    103                    this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
    104                    this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
    105                    this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
    106                    this.ticksAlive = 0;
    107                    this.ticksInAir = 0;
    108                }
    109                else
    110                {
    111                    ++this.ticksInAir;
    112                }
    113
    114                Vec3 var15 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
    115                Vec3 var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
    116                MovingObjectPosition var3 = this.worldObj.rayTraceBlocks(var15, var2);
    117                var15 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
    118                var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
    119
    120                if (var3 != null)
    121                {
    122                    var2 = this.worldObj.getWorldVec3Pool().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord, var3.hitVec.zCoord);
    123                }
    124
    125                Entity var4 = null;
    126                List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
    127                double var6 = 0.0D;
    128
    129                for (int var8 = 0; var8 < var5.size(); ++var8)
    130                {
    131                    Entity var9 = (Entity)var5.get(var8);
    132
    133                    if (var9.canBeCollidedWith() && (!var9.isEntityEqual(this.shootingEntity) || this.ticksInAir >= 25))
    134                    {
    135                        float var10 = 0.3F;
    136                        AxisAlignedBB var11 = var9.boundingBox.expand((double)var10, (double)var10, (double)var10);
    137                        MovingObjectPosition var12 = var11.calculateIntercept(var15, var2);
    138
    139                        if (var12 != null)
    140                        {
    141                            double var13 = var15.distanceTo(var12.hitVec);
    142
    143                            if (var13 < var6 || var6 == 0.0D)
    144                            {
    145                                var4 = var9;
    146                                var6 = var13;
    147                            }
    148                        }
    149                    }
    150                }
    151
    152                if (var4 != null)
    153                {
    154                    var3 = new MovingObjectPosition(var4);
    155                }
    156
    157                if (var3 != null)
    158                {
    159                    this.onImpact(var3);
    160                }
    161
    162                this.posX += this.motionX;
    163                this.posY += this.motionY;
    164                this.posZ += this.motionZ;
    165                float var16 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
    166                this.rotationYaw = (float)(Math.atan2(this.motionZ, this.motionX) * 180.0D / Math.PI) + 90.0F;
    167
    168                for (this.rotationPitch = (float)(Math.atan2((double)var16, this.motionY) * 180.0D / Math.PI) - 90.0F; this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
    169                {
    170                    ;
    171                }
    172
    173                while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
    174                {
    175                    this.prevRotationPitch += 360.0F;
    176                }
    177
    178                while (this.rotationYaw - this.prevRotationYaw < -180.0F)
    179                {
    180                    this.prevRotationYaw -= 360.0F;
    181                }
    182
    183                while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
    184                {
    185                    this.prevRotationYaw += 360.0F;
    186                }
    187
    188                this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
    189                this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
    190                float var17 = this.getMotionFactor();
    191
    192                if (this.isInWater())
    193                {
    194                    for (int var19 = 0; var19 < 4; ++var19)
    195                    {
    196                        float var18 = 0.25F;
    197                        this.worldObj.spawnParticle("bubble", this.posX - this.motionX * (double)var18, this.posY - this.motionY * (double)var18, this.posZ - this.motionZ * (double)var18, this.motionX, this.motionY, this.motionZ);
    198                    }
    199
    200                    var17 = 0.8F;
    201                }
    202
    203                this.motionX += this.accelerationX;
    204                this.motionY += this.accelerationY;
    205                this.motionZ += this.accelerationZ;
    206                this.motionX *= (double)var17;
    207                this.motionY *= (double)var17;
    208                this.motionZ *= (double)var17;
    209                this.worldObj.spawnParticle("smoke", this.posX, this.posY + 0.5D, this.posZ, 0.0D, 0.0D, 0.0D);
    210                this.setPosition(this.posX, this.posY, this.posZ);
    211            }
    212        }
    213
    214        /**
    215         * Return the motion factor for this projectile. The factor is multiplied by the original motion.
    216         */
    217        protected float getMotionFactor()
    218        {
    219            return 0.95F;
    220        }
    221
    222        /**
    223         * Called when this EntityFireball hits a block or entity.
    224         */
    225        protected abstract void onImpact(MovingObjectPosition var1);
    226
    227        /**
    228         * (abstract) Protected helper method to write subclass entity data to NBT.
    229         */
    230        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    231        {
    232            par1NBTTagCompound.setShort("xTile", (short)this.xTile);
    233            par1NBTTagCompound.setShort("yTile", (short)this.yTile);
    234            par1NBTTagCompound.setShort("zTile", (short)this.zTile);
    235            par1NBTTagCompound.setByte("inTile", (byte)this.inTile);
    236            par1NBTTagCompound.setByte("inGround", (byte)(this.inGround ? 1 : 0));
    237            par1NBTTagCompound.setTag("direction", this.newDoubleNBTList(new double[] {this.motionX, this.motionY, this.motionZ}));
    238        }
    239
    240        /**
    241         * (abstract) Protected helper method to read subclass entity data from NBT.
    242         */
    243        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    244        {
    245            this.xTile = par1NBTTagCompound.getShort("xTile");
    246            this.yTile = par1NBTTagCompound.getShort("yTile");
    247            this.zTile = par1NBTTagCompound.getShort("zTile");
    248            this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
    249            this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
    250
    251            if (par1NBTTagCompound.hasKey("direction"))
    252            {
    253                NBTTagList var2 = par1NBTTagCompound.getTagList("direction");
    254                this.motionX = ((NBTTagDouble)var2.tagAt(0)).data;
    255                this.motionY = ((NBTTagDouble)var2.tagAt(1)).data;
    256                this.motionZ = ((NBTTagDouble)var2.tagAt(2)).data;
    257            }
    258            else
    259            {
    260                this.setDead();
    261            }
    262        }
    263
    264        /**
    265         * Returns true if other Entities should be prevented from moving through this Entity.
    266         */
    267        public boolean canBeCollidedWith()
    268        {
    269            return true;
    270        }
    271
    272        public float getCollisionBorderSize()
    273        {
    274            return 1.0F;
    275        }
    276
    277        /**
    278         * Called when the entity is attacked.
    279         */
    280        public boolean attackEntityFrom(DamageSource par1DamageSource, int par2)
    281        {
    282            if (this.func_85032_ar())
    283            {
    284                return false;
    285            }
    286            else
    287            {
    288                this.setBeenAttacked();
    289
    290                if (par1DamageSource.getEntity() != null)
    291                {
    292                    Vec3 var3 = par1DamageSource.getEntity().getLookVec();
    293
    294                    if (var3 != null)
    295                    {
    296                        this.motionX = var3.xCoord;
    297                        this.motionY = var3.yCoord;
    298                        this.motionZ = var3.zCoord;
    299                        this.accelerationX = this.motionX * 0.1D;
    300                        this.accelerationY = this.motionY * 0.1D;
    301                        this.accelerationZ = this.motionZ * 0.1D;
    302                    }
    303
    304                    if (par1DamageSource.getEntity() instanceof EntityLiving)
    305                    {
    306                        this.shootingEntity = (EntityLiving)par1DamageSource.getEntity();
    307                    }
    308
    309                    return true;
    310                }
    311                else
    312                {
    313                    return false;
    314                }
    315            }
    316        }
    317
    318        @SideOnly(Side.CLIENT)
    319        public float getShadowSize()
    320        {
    321            return 0.0F;
    322        }
    323
    324        /**
    325         * Gets how bright this entity is.
    326         */
    327        public float getBrightness(float par1)
    328        {
    329            return 1.0F;
    330        }
    331
    332        @SideOnly(Side.CLIENT)
    333        public int getBrightnessForRender(float par1)
    334        {
    335            return 15728880;
    336        }
    337    }