    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.Iterator;
    006    import java.util.List;
    007
    008    public class EntityFishHook extends Entity
    009    {
    010        /** The tile this entity is on, X position */
    011        private int xTile;
    012
    013        /** The tile this entity is on, Y position */
    014        private int yTile;
    015
    016        /** The tile this entity is on, Z position */
    017        private int zTile;
    018        private int inTile;
    019        private boolean inGround;
    020        public int shake;
    021        public EntityPlayer angler;
    022        private int ticksInGround;
    023        private int ticksInAir;
    024
    025        /** the number of ticks remaining until this fish can no longer be caught */
    026        private int ticksCatchable;
    027
    028        /**
    029         * The entity that the fishing rod is connected to, if any. When you right click on the fishing rod and the hook
    030         * falls on to an entity, this it that entity.
    031         */
    032        public Entity bobber;
    033        private int fishPosRotationIncrements;
    034        private double fishX;
    035        private double fishY;
    036        private double fishZ;
    037        private double fishYaw;
    038        private double fishPitch;
    039        @SideOnly(Side.CLIENT)
    040        private double velocityX;
    041        @SideOnly(Side.CLIENT)
    042        private double velocityY;
    043        @SideOnly(Side.CLIENT)
    044        private double velocityZ;
    045
    046        public EntityFishHook(World par1World)
    047        {
    048            super(par1World);
    049            this.xTile = -1;
    050            this.yTile = -1;
    051            this.zTile = -1;
    052            this.inTile = 0;
    053            this.inGround = false;
    054            this.shake = 0;
    055            this.ticksInAir = 0;
    056            this.ticksCatchable = 0;
    057            this.bobber = null;
    058            this.setSize(0.25F, 0.25F);
    059            this.ignoreFrustumCheck = true;
    060        }
    061
    062        @SideOnly(Side.CLIENT)
    063        public EntityFishHook(World par1World, double par2, double par4, double par6, EntityPlayer par8EntityPlayer)
    064        {
    065            this(par1World);
    066            this.setPosition(par2, par4, par6);
    067            this.ignoreFrustumCheck = true;
    068            this.angler = par8EntityPlayer;
    069            par8EntityPlayer.fishEntity = this;
    070        }
    071
    072        public EntityFishHook(World par1World, EntityPlayer par2EntityPlayer)
    073        {
    074            super(par1World);
    075            this.xTile = -1;
    076            this.yTile = -1;
    077            this.zTile = -1;
    078            this.inTile = 0;
    079            this.inGround = false;
    080            this.shake = 0;
    081            this.ticksInAir = 0;
    082            this.ticksCatchable = 0;
    083            this.bobber = null;
    084            this.ignoreFrustumCheck = true;
    085            this.angler = par2EntityPlayer;
    086            this.angler.fishEntity = this;
    087            this.setSize(0.25F, 0.25F);
    088            this.setLocationAndAngles(par2EntityPlayer.posX, par2EntityPlayer.posY + 1.62D - (double)par2EntityPlayer.yOffset, par2EntityPlayer.posZ, par2EntityPlayer.rotationYaw, par2EntityPlayer.rotationPitch);
    089            this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
    090            this.posY -= 0.10000000149011612D;
    091            this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
    092            this.setPosition(this.posX, this.posY, this.posZ);
    093            this.yOffset = 0.0F;
    094            float var3 = 0.4F;
    095            this.motionX = (double)(-MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var3);
    096            this.motionZ = (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * MathHelper.cos(this.rotationPitch / 180.0F * (float)Math.PI) * var3);
    097            this.motionY = (double)(-MathHelper.sin(this.rotationPitch / 180.0F * (float)Math.PI) * var3);
    098            this.calculateVelocity(this.motionX, this.motionY, this.motionZ, 1.5F, 1.0F);
    099        }
    100
    101        protected void entityInit() {}
    102
    103        @SideOnly(Side.CLIENT)
    104
    105        /**
    106         * Checks if the entity is in range to render by using the past in distance and comparing it to its average edge
    107         * length * 64 * renderDistanceWeight Args: distance
    108         */
    109        public boolean isInRangeToRenderDist(double par1)
    110        {
    111            double var3 = this.boundingBox.getAverageEdgeLength() * 4.0D;
    112            var3 *= 64.0D;
    113            return par1 < var3 * var3;
    114        }
    115
    116        public void calculateVelocity(double par1, double par3, double par5, float par7, float par8)
    117        {
    118            float var9 = MathHelper.sqrt_double(par1 * par1 + par3 * par3 + par5 * par5);
    119            par1 /= (double)var9;
    120            par3 /= (double)var9;
    121            par5 /= (double)var9;
    122            par1 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
    123            par3 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
    124            par5 += this.rand.nextGaussian() * 0.007499999832361937D * (double)par8;
    125            par1 *= (double)par7;
    126            par3 *= (double)par7;
    127            par5 *= (double)par7;
    128            this.motionX = par1;
    129            this.motionY = par3;
    130            this.motionZ = par5;
    131            float var10 = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
    132            this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(par1, par5) * 180.0D / Math.PI);
    133            this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(par3, (double)var10) * 180.0D / Math.PI);
    134            this.ticksInGround = 0;
    135        }
    136
    137        @SideOnly(Side.CLIENT)
    138
    139        /**
    140         * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
    141         * posY, posZ, yaw, pitch
    142         */
    143        public void setPositionAndRotation2(double par1, double par3, double par5, float par7, float par8, int par9)
    144        {
    145            this.fishX = par1;
    146            this.fishY = par3;
    147            this.fishZ = par5;
    148            this.fishYaw = (double)par7;
    149            this.fishPitch = (double)par8;
    150            this.fishPosRotationIncrements = par9;
    151            this.motionX = this.velocityX;
    152            this.motionY = this.velocityY;
    153            this.motionZ = this.velocityZ;
    154        }
    155
    156        @SideOnly(Side.CLIENT)
    157
    158        /**
    159         * Sets the velocity to the args. Args: x, y, z
    160         */
    161        public void setVelocity(double par1, double par3, double par5)
    162        {
    163            this.velocityX = this.motionX = par1;
    164            this.velocityY = this.motionY = par3;
    165            this.velocityZ = this.motionZ = par5;
    166        }
    167
    168        /**
    169         * Called to update the entity's position/logic.
    170         */
    171        public void onUpdate()
    172        {
    173            super.onUpdate();
    174
    175            if (this.fishPosRotationIncrements > 0)
    176            {
    177                double var21 = this.posX + (this.fishX - this.posX) / (double)this.fishPosRotationIncrements;
    178                double var22 = this.posY + (this.fishY - this.posY) / (double)this.fishPosRotationIncrements;
    179                double var23 = this.posZ + (this.fishZ - this.posZ) / (double)this.fishPosRotationIncrements;
    180                double var7 = MathHelper.wrapAngleTo180_double(this.fishYaw - (double)this.rotationYaw);
    181                this.rotationYaw = (float)((double)this.rotationYaw + var7 / (double)this.fishPosRotationIncrements);
    182                this.rotationPitch = (float)((double)this.rotationPitch + (this.fishPitch - (double)this.rotationPitch) / (double)this.fishPosRotationIncrements);
    183                --this.fishPosRotationIncrements;
    184                this.setPosition(var21, var22, var23);
    185                this.setRotation(this.rotationYaw, this.rotationPitch);
    186            }
    187            else
    188            {
    189                if (!this.worldObj.isRemote)
    190                {
    191                    ItemStack var1 = this.angler.getCurrentEquippedItem();
    192
    193                    if (this.angler.isDead || !this.angler.isEntityAlive() || var1 == null || var1.getItem() != Item.fishingRod || this.getDistanceSqToEntity(this.angler) > 1024.0D)
    194                    {
    195                        this.setDead();
    196                        this.angler.fishEntity = null;
    197                        return;
    198                    }
    199
    200                    if (this.bobber != null)
    201                    {
    202                        if (!this.bobber.isDead)
    203                        {
    204                            this.posX = this.bobber.posX;
    205                            this.posY = this.bobber.boundingBox.minY + (double)this.bobber.height * 0.8D;
    206                            this.posZ = this.bobber.posZ;
    207                            return;
    208                        }
    209
    210                        this.bobber = null;
    211                    }
    212                }
    213
    214                if (this.shake > 0)
    215                {
    216                    --this.shake;
    217                }
    218
    219                if (this.inGround)
    220                {
    221                    int var19 = this.worldObj.getBlockId(this.xTile, this.yTile, this.zTile);
    222
    223                    if (var19 == this.inTile)
    224                    {
    225                        ++this.ticksInGround;
    226
    227                        if (this.ticksInGround == 1200)
    228                        {
    229                            this.setDead();
    230                        }
    231
    232                        return;
    233                    }
    234
    235                    this.inGround = false;
    236                    this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
    237                    this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
    238                    this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
    239                    this.ticksInGround = 0;
    240                    this.ticksInAir = 0;
    241                }
    242                else
    243                {
    244                    ++this.ticksInAir;
    245                }
    246
    247                Vec3 var20 = this.worldObj.func_82732_R().getVecFromPool(this.posX, this.posY, this.posZ);
    248                Vec3 var2 = this.worldObj.func_82732_R().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
    249                MovingObjectPosition var3 = this.worldObj.rayTraceBlocks(var20, var2);
    250                var20 = this.worldObj.func_82732_R().getVecFromPool(this.posX, this.posY, this.posZ);
    251                var2 = this.worldObj.func_82732_R().getVecFromPool(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
    252
    253                if (var3 != null)
    254                {
    255                    var2 = this.worldObj.func_82732_R().getVecFromPool(var3.hitVec.xCoord, var3.hitVec.yCoord, var3.hitVec.zCoord);
    256                }
    257
    258                Entity var4 = null;
    259                List var5 = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
    260                double var6 = 0.0D;
    261                Iterator var8 = var5.iterator();
    262                double var13;
    263
    264                while (var8.hasNext())
    265                {
    266                    Entity var9 = (Entity)var8.next();
    267
    268                    if (var9.canBeCollidedWith() && (var9 != this.angler || this.ticksInAir >= 5))
    269                    {
    270                        float var10 = 0.3F;
    271                        AxisAlignedBB var11 = var9.boundingBox.expand((double)var10, (double)var10, (double)var10);
    272                        MovingObjectPosition var12 = var11.calculateIntercept(var20, var2);
    273
    274                        if (var12 != null)
    275                        {
    276                            var13 = var20.distanceTo(var12.hitVec);
    277
    278                            if (var13 < var6 || var6 == 0.0D)
    279                            {
    280                                var4 = var9;
    281                                var6 = var13;
    282                            }
    283                        }
    284                    }
    285                }
    286
    287                if (var4 != null)
    288                {
    289                    var3 = new MovingObjectPosition(var4);
    290                }
    291
    292                if (var3 != null)
    293                {
    294                    if (var3.entityHit != null)
    295                    {
    296                        if (var3.entityHit.attackEntityFrom(DamageSource.causeThrownDamage(this, this.angler), 0))
    297                        {
    298                            this.bobber = var3.entityHit;
    299                        }
    300                    }
    301                    else
    302                    {
    303                        this.inGround = true;
    304                    }
    305                }
    306
    307                if (!this.inGround)
    308                {
    309                    this.moveEntity(this.motionX, this.motionY, this.motionZ);
    310                    float var24 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
    311                    this.rotationYaw = (float)(Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);
    312
    313                    for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)var24) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
    314                    {
    315                        ;
    316                    }
    317
    318                    while (this.rotationPitch - this.prevRotationPitch >= 180.0F)
    319                    {
    320                        this.prevRotationPitch += 360.0F;
    321                    }
    322
    323                    while (this.rotationYaw - this.prevRotationYaw < -180.0F)
    324                    {
    325                        this.prevRotationYaw -= 360.0F;
    326                    }
    327
    328                    while (this.rotationYaw - this.prevRotationYaw >= 180.0F)
    329                    {
    330                        this.prevRotationYaw += 360.0F;
    331                    }
    332
    333                    this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
    334                    this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
    335                    float var25 = 0.92F;
    336
    337                    if (this.onGround || this.isCollidedHorizontally)
    338                    {
    339                        var25 = 0.5F;
    340                    }
    341
    342                    byte var27 = 5;
    343                    double var26 = 0.0D;
    344
    345                    for (int var29 = 0; var29 < var27; ++var29)
    346                    {
    347                        double var14 = this.boundingBox.minY + (this.boundingBox.maxY - this.boundingBox.minY) * (double)(var29 + 0) / (double)var27 - 0.125D + 0.125D;
    348                        double var16 = this.boundingBox.minY + (this.boundingBox.maxY - this.boundingBox.minY) * (double)(var29 + 1) / (double)var27 - 0.125D + 0.125D;
    349                        AxisAlignedBB var18 = AxisAlignedBB.getAABBPool().addOrModifyAABBInPool(this.boundingBox.minX, var14, this.boundingBox.minZ, this.boundingBox.maxX, var16, this.boundingBox.maxZ);
    350
    351                        if (this.worldObj.isAABBInMaterial(var18, Material.water))
    352                        {
    353                            var26 += 1.0D / (double)var27;
    354                        }
    355                    }
    356
    357                    if (var26 > 0.0D)
    358                    {
    359                        if (this.ticksCatchable > 0)
    360                        {
    361                            --this.ticksCatchable;
    362                        }
    363                        else
    364                        {
    365                            short var28 = 500;
    366
    367                            if (this.worldObj.canLightningStrikeAt(MathHelper.floor_double(this.posX), MathHelper.floor_double(this.posY) + 1, MathHelper.floor_double(this.posZ)))
    368                            {
    369                                var28 = 300;
    370                            }
    371
    372                            if (this.rand.nextInt(var28) == 0)
    373                            {
    374                                this.ticksCatchable = this.rand.nextInt(30) + 10;
    375                                this.motionY -= 0.20000000298023224D;
    376                                this.worldObj.playSoundAtEntity(this, "random.splash", 0.25F, 1.0F + (this.rand.nextFloat() - this.rand.nextFloat()) * 0.4F);
    377                                float var30 = (float)MathHelper.floor_double(this.boundingBox.minY);
    378                                int var15;
    379                                float var17;
    380                                float var31;
    381
    382                                for (var15 = 0; (float)var15 < 1.0F + this.width * 20.0F; ++var15)
    383                                {
    384                                    var31 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    385                                    var17 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    386                                    this.worldObj.spawnParticle("bubble", this.posX + (double)var31, (double)(var30 + 1.0F), this.posZ + (double)var17, this.motionX, this.motionY - (double)(this.rand.nextFloat() * 0.2F), this.motionZ);
    387                                }
    388
    389                                for (var15 = 0; (float)var15 < 1.0F + this.width * 20.0F; ++var15)
    390                                {
    391                                    var31 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    392                                    var17 = (this.rand.nextFloat() * 2.0F - 1.0F) * this.width;
    393                                    this.worldObj.spawnParticle("splash", this.posX + (double)var31, (double)(var30 + 1.0F), this.posZ + (double)var17, this.motionX, this.motionY, this.motionZ);
    394                                }
    395                            }
    396                        }
    397                    }
    398
    399                    if (this.ticksCatchable > 0)
    400                    {
    401                        this.motionY -= (double)(this.rand.nextFloat() * this.rand.nextFloat() * this.rand.nextFloat()) * 0.2D;
    402                    }
    403
    404                    var13 = var26 * 2.0D - 1.0D;
    405                    this.motionY += 0.03999999910593033D * var13;
    406
    407                    if (var26 > 0.0D)
    408                    {
    409                        var25 = (float)((double)var25 * 0.9D);
    410                        this.motionY *= 0.8D;
    411                    }
    412
    413                    this.motionX *= (double)var25;
    414                    this.motionY *= (double)var25;
    415                    this.motionZ *= (double)var25;
    416                    this.setPosition(this.posX, this.posY, this.posZ);
    417                }
    418            }
    419        }
    420
    421        /**
    422         * (abstract) Protected helper method to write subclass entity data to NBT.
    423         */
    424        public void writeEntityToNBT(NBTTagCompound par1NBTTagCompound)
    425        {
    426            par1NBTTagCompound.setShort("xTile", (short)this.xTile);
    427            par1NBTTagCompound.setShort("yTile", (short)this.yTile);
    428            par1NBTTagCompound.setShort("zTile", (short)this.zTile);
    429            par1NBTTagCompound.setByte("inTile", (byte)this.inTile);
    430            par1NBTTagCompound.setByte("shake", (byte)this.shake);
    431            par1NBTTagCompound.setByte("inGround", (byte)(this.inGround ? 1 : 0));
    432        }
    433
    434        /**
    435         * (abstract) Protected helper method to read subclass entity data from NBT.
    436         */
    437        public void readEntityFromNBT(NBTTagCompound par1NBTTagCompound)
    438        {
    439            this.xTile = par1NBTTagCompound.getShort("xTile");
    440            this.yTile = par1NBTTagCompound.getShort("yTile");
    441            this.zTile = par1NBTTagCompound.getShort("zTile");
    442            this.inTile = par1NBTTagCompound.getByte("inTile") & 255;
    443            this.shake = par1NBTTagCompound.getByte("shake") & 255;
    444            this.inGround = par1NBTTagCompound.getByte("inGround") == 1;
    445        }
    446
    447        @SideOnly(Side.CLIENT)
    448        public float getShadowSize()
    449        {
    450            return 0.0F;
    451        }
    452
    453        public int catchFish()
    454        {
    455            if (this.worldObj.isRemote)
    456            {
    457                return 0;
    458            }
    459            else
    460            {
    461                byte var1 = 0;
    462
    463                if (this.bobber != null)
    464                {
    465                    double var2 = this.angler.posX - this.posX;
    466                    double var4 = this.angler.posY - this.posY;
    467                    double var6 = this.angler.posZ - this.posZ;
    468                    double var8 = (double)MathHelper.sqrt_double(var2 * var2 + var4 * var4 + var6 * var6);
    469                    double var10 = 0.1D;
    470                    this.bobber.motionX += var2 * var10;
    471                    this.bobber.motionY += var4 * var10 + (double)MathHelper.sqrt_double(var8) * 0.08D;
    472                    this.bobber.motionZ += var6 * var10;
    473                    var1 = 3;
    474                }
    475                else if (this.ticksCatchable > 0)
    476                {
    477                    EntityItem var13 = new EntityItem(this.worldObj, this.posX, this.posY, this.posZ, new ItemStack(Item.fishRaw));
    478                    double var3 = this.angler.posX - this.posX;
    479                    double var5 = this.angler.posY - this.posY;
    480                    double var7 = this.angler.posZ - this.posZ;
    481                    double var9 = (double)MathHelper.sqrt_double(var3 * var3 + var5 * var5 + var7 * var7);
    482                    double var11 = 0.1D;
    483                    var13.motionX = var3 * var11;
    484                    var13.motionY = var5 * var11 + (double)MathHelper.sqrt_double(var9) * 0.08D;
    485                    var13.motionZ = var7 * var11;
    486                    this.worldObj.spawnEntityInWorld(var13);
    487                    this.angler.addStat(StatList.fishCaughtStat, 1);
    488                    this.angler.worldObj.spawnEntityInWorld(new EntityXPOrb(this.angler.worldObj, this.angler.posX, this.angler.posY + 0.5D, this.angler.posZ + 0.5D, this.rand.nextInt(3) + 1));
    489                    var1 = 1;
    490                }
    491
    492                if (this.inGround)
    493                {
    494                    var1 = 2;
    495                }
    496
    497                this.setDead();
    498                this.angler.fishEntity = null;
    499                return var1;
    500            }
    501        }
    502
    503        /**
    504         * Will get destroyed next tick.
    505         */
    506        public void setDead()
    507        {
    508            super.setDead();
    509
    510            if (this.angler != null)
    511            {
    512                this.angler.fishEntity = null;
    513            }
    514        }
    515    }