arrowsplus.entity.EntityArrowBase.java Source code

Java tutorial

Introduction

Here is the source code for arrowsplus.entity.EntityArrowBase.java

Source

/*******************************************************************************
 * EntityArrowBase.java
 * Copyright (c) 2013 WildBamaBoy.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 ******************************************************************************/

package arrowsplus.entity;

import java.util.List;

import net.minecraft.block.Block;
import net.minecraft.enchantment.EnchantmentThorns;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityEnderman;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.network.packet.Packet70GameEvent;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.DamageSource;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import arrowsplus.core.ArrowsPlus;

import com.google.common.io.ByteArrayDataInput;
import com.google.common.io.ByteArrayDataOutput;

import cpw.mods.fml.common.ObfuscationReflectionHelper;
import cpw.mods.fml.common.registry.IEntityAdditionalSpawnData;

/**
 * Handles how the arrow entity behaves.
 */
public class EntityArrowBase extends EntityArrow implements IEntityAdditionalSpawnData {
    /** The arrow type/damage/metadata value of the arrow fired. */
    public int arrowType;

    /** The bow type/damage/metadata value of the bow that fired this arrow. */
    public int bowType;

    /** How many blocks the arrow has ignored. For Hickory arrow. */
    public int blocksIgnored;

    /** How many ticks the arrow has been in the air. */
    public int inAirTicks;

    /** The arrow's wind resistance value. Subtracted from 0.10. */
    public double windResistance;

    /** Is the bow stuck in the ground? */
    public boolean isInGround;

    public int softMapleCaughtByWindTicks;
    public boolean softMapleIsFlyingIntoAir;

    /**
     * Constructor
     * 
     * @param    world   The world the arrow is being spawned in.
     */
    public EntityArrowBase(World world) {
        super(world);
    }

    /**
     * Constructor
     * 
     * @param    world         The world the arrow is being spawned in.
     * @param    entityLiving   The entity that fired the arrow.
     * @param    velocity      The starting velocity of the arrow.
     * @param    arrowType      The type of arrow that this entity should represent and act like.
     * @param    bowType         The type of bow that fired this arrow.
     */
    public EntityArrowBase(World world, EntityLivingBase entityLiving, float velocity, int arrowType, int bowType) {
        super(world, entityLiving, velocity);
        this.arrowType = arrowType;
        this.bowType = bowType;
        this.inAirTicks = 0;
        this.windResistance = ArrowsPlus.getArrowWindResistanceByWoodType(arrowType);
        this.blocksIgnored = 0;

        //Soft maple "unreliable"
        if (arrowType == 5) {
            if (ArrowsPlus.getBooleanWithProbability(15)) {
                world.playSoundAtEntity(entityLiving, "damage.fallbig", 1.0F, 1.0F);
                setDead();
            }
        }

        this.softMapleIsFlyingIntoAir = false;
        this.softMapleCaughtByWindTicks = 0;
    }

    @Override
    public void onUpdate() {
        this.onEntityUpdate();

        //Representation of EntityArrow onUpdate() code.
        //
        //
        int xTile = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 0);
        int yTile = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 1);
        int zTile = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 2);
        int inTile = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 3);
        int inData = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 4);
        boolean inGround = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 5);
        int ticksInGround = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 9);
        int ticksInAir = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 10);

        if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
            float f = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
            this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D
                    / Math.PI);
            this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(this.motionY, f) * 180.0D / Math.PI);
        }

        int tileId = this.worldObj.getBlockId(xTile, yTile, zTile);

        if (tileId > 0) {
            Block.blocksList[tileId].setBlockBoundsBasedOnState(this.worldObj, xTile, yTile, zTile);
            AxisAlignedBB bb = Block.blocksList[tileId].getCollisionBoundingBoxFromPool(this.worldObj, xTile, yTile,
                    zTile);

            if (bb != null && bb.isVecInside(
                    this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ))) {
                ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, true, 5);
                inGround = true;
            }
        }

        if (this.arrowShake > 0) {
            --this.arrowShake;
        }

        if (inGround) {
            int blockId = this.worldObj.getBlockId(xTile, yTile, zTile);
            int blockData = this.worldObj.getBlockMetadata(xTile, yTile, zTile);

            if (blockId == inTile && blockData == inData) {
                ++ticksInGround;
                ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, new Integer(ticksInGround), 9);

                if (ticksInGround == 1200) {
                    this.setDead();
                }
            }

            else {
                ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, false, 5);
                this.motionX *= this.rand.nextFloat() * 0.2F;
                this.motionY *= this.rand.nextFloat() * 0.2F;
                this.motionZ *= this.rand.nextFloat() * 0.2F;
                ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, new Integer(0), 9);
                ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, new Integer(0), 10);
            }
        }

        else {
            ++ticksInAir;
            Vec3 positionVector = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
            Vec3 motionVector = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX,
                    this.posY + this.motionY, this.posZ + this.motionZ);

            MovingObjectPosition movingObjPosition = this.worldObj.rayTraceBlocks_do_do(positionVector,
                    motionVector, false, true);
            positionVector = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX, this.posY, this.posZ);
            motionVector = this.worldObj.getWorldVec3Pool().getVecFromPool(this.posX + this.motionX,
                    this.posY + this.motionY, this.posZ + this.motionZ);

            if (movingObjPosition != null) {
                motionVector = this.worldObj.getWorldVec3Pool().getVecFromPool(movingObjPosition.hitVec.xCoord,
                        movingObjPosition.hitVec.yCoord, movingObjPosition.hitVec.zCoord);
            }

            Entity entity = null;
            List entitiesInBoundingBox = this.worldObj.getEntitiesWithinAABBExcludingEntity(this,
                    this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
            double baseDistanceToIntercept = 0.0D;

            for (int i = 0; i < entitiesInBoundingBox.size(); ++i) {
                Entity entityInBoundingBox = (Entity) entitiesInBoundingBox.get(i);

                if (entityInBoundingBox.canBeCollidedWith()
                        && (entityInBoundingBox != this.shootingEntity || ticksInAir >= 5)) {
                    AxisAlignedBB expandedBoundingBox = entityInBoundingBox.boundingBox.expand(0.3F, 0.3F, 0.3F);
                    MovingObjectPosition interceptPosition = expandedBoundingBox.calculateIntercept(positionVector,
                            motionVector);

                    if (interceptPosition != null) {
                        double realDistanceToIntercept = positionVector.distanceTo(interceptPosition.hitVec);

                        if (realDistanceToIntercept < baseDistanceToIntercept || baseDistanceToIntercept == 0.0D) {
                            entity = entityInBoundingBox;
                            baseDistanceToIntercept = realDistanceToIntercept;
                        }
                    }
                }
            }

            if (entity != null) {
                movingObjPosition = new MovingObjectPosition(entity);
            }

            if (movingObjPosition != null && movingObjPosition.entityHit != null
                    && movingObjPosition.entityHit instanceof EntityPlayer) {
                EntityPlayer entityplayer = (EntityPlayer) movingObjPosition.entityHit;

                if (entityplayer.capabilities.disableDamage || this.shootingEntity instanceof EntityPlayer
                        && !((EntityPlayer) this.shootingEntity).func_96122_a(entityplayer)) {
                    movingObjPosition = null;
                }
            }

            float damageCalc;
            float unknown;

            if (movingObjPosition != null) {
                if (movingObjPosition.entityHit != null) {
                    damageCalc = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY
                            + this.motionZ * this.motionZ);
                    int damage = MathHelper.ceiling_double_int(getDamage());
                    boolean hasArmor = false;
                    EntityPlayer player = (EntityPlayer) this.shootingEntity;

                    //Account for block penetration
                    damage -= blocksIgnored;

                    if (this.getIsCritical()) {
                        damage += this.rand.nextInt(damage / 2 + 2);
                    }

                    DamageSource damagesource = null;

                    if (this.shootingEntity == null) {
                        damagesource = DamageSource.causeArrowDamage(this, this);
                    }

                    else {
                        damagesource = DamageSource.causeArrowDamage(this, this.shootingEntity);
                    }

                    if (this.isBurning() && !(movingObjPosition.entityHit instanceof EntityEnderman)) {
                        movingObjPosition.entityHit.setFire(5);
                    }

                    if (this.arrowType == 7) {
                        if (player != null) {
                            for (ItemStack stack : player.inventory.armorInventory) {
                                if (stack != null) {
                                    hasArmor = true;
                                    damage = 0;
                                    break;
                                }
                            }
                        }
                    }

                    if (movingObjPosition.entityHit.attackEntityFrom(damagesource, damage)) {
                        if (movingObjPosition.entityHit instanceof EntityLivingBase) {
                            EntityLivingBase entitylivingbase = (EntityLivingBase) movingObjPosition.entityHit;

                            //Sycamore
                            if (this.arrowType == 3) {
                                if (entitylivingbase instanceof EntityPlayer) {
                                    player.triggerAchievement(ArrowsPlus.instance.achievementWitherPlayer);
                                }

                                entitylivingbase.addPotionEffect(new PotionEffect(Potion.wither.id, 7 * 20, 0));
                            }

                            //Gum
                            if (this.arrowType == 4) {
                                entitylivingbase
                                        .addPotionEffect(new PotionEffect(Potion.moveSlowdown.id, 7 * 20, 0));
                            }

                            //Ash
                            if (this.arrowType == 6) {
                                if (worldObj.rand.nextBoolean() && worldObj.rand.nextBoolean()
                                        && worldObj.rand.nextBoolean()) {
                                    entitylivingbase
                                            .addPotionEffect(new PotionEffect(Potion.blindness.id, 7 * 20, 0));

                                    if (entitylivingbase instanceof EntityPlayer) {
                                        player.triggerAchievement(ArrowsPlus.instance.achievementBlindPlayer);
                                    }
                                }
                            }

                            //Beech
                            if (this.arrowType == 7) {
                                if (!hasArmor) {
                                    if (entitylivingbase instanceof EntityPlayer) {
                                        player.triggerAchievement(ArrowsPlus.instance.achievementPoisonPlayer);
                                    }

                                    entitylivingbase.addPotionEffect(new PotionEffect(Potion.poison.id, 7 * 20, 0));
                                }
                            }

                            if (!this.worldObj.isRemote) {
                                entitylivingbase
                                        .setArrowCountInEntity(entitylivingbase.getArrowCountInEntity() + 1);
                            }

                            if (this.getKnockbackStrength() > 0) {
                                unknown = MathHelper
                                        .sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);

                                if (unknown > 0.0F) {
                                    movingObjPosition.entityHit.addVelocity(
                                            this.motionX * this.getKnockbackStrength() * 0.6000000238418579D
                                                    / unknown,
                                            0.1D, this.motionZ * this.getKnockbackStrength() * 0.6000000238418579D
                                                    / unknown);
                                }
                            }

                            if (this.shootingEntity != null) {
                                EnchantmentThorns.func_92096_a(this.shootingEntity, entitylivingbase, this.rand);
                            }

                            if (this.shootingEntity != null && movingObjPosition.entityHit != this.shootingEntity
                                    && movingObjPosition.entityHit instanceof EntityPlayer
                                    && this.shootingEntity instanceof EntityPlayerMP) {
                                ((EntityPlayerMP) this.shootingEntity).playerNetServerHandler
                                        .sendPacketToPlayer(new Packet70GameEvent(6, 0));
                            }
                        }

                        this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));

                        if (!(movingObjPosition.entityHit instanceof EntityEnderman)) {
                            this.setDead();
                        }
                    }

                    else {
                        this.motionX *= -0.10000000149011612D;
                        this.motionY *= -0.10000000149011612D;
                        this.motionZ *= -0.10000000149011612D;
                        this.rotationYaw += 180.0F;
                        this.prevRotationYaw += 180.0F;
                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, new Integer(0), 10);
                    }
                }

                else {
                    //Allow for hard maple block penetration.
                    if (arrowType == 8 && blocksIgnored < 3) {
                        blocksIgnored++;
                    }

                    else {
                        xTile = movingObjPosition.blockX;
                        yTile = movingObjPosition.blockY;
                        zTile = movingObjPosition.blockZ;
                        inTile = worldObj.getBlockId(xTile, yTile, zTile);
                        inData = worldObj.getBlockMetadata(xTile, yTile, zTile);

                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this,
                                new Integer(movingObjPosition.blockX), 0);
                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this,
                                new Integer(movingObjPosition.blockY), 1);
                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this,
                                new Integer(movingObjPosition.blockZ), 2);
                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this,
                                new Integer(this.worldObj.getBlockId(xTile, yTile, zTile)), 3);
                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this,
                                new Integer(this.worldObj.getBlockMetadata(xTile, yTile, zTile)), 4);

                        this.motionX = ((float) (movingObjPosition.hitVec.xCoord - this.posX));
                        this.motionY = ((float) (movingObjPosition.hitVec.yCoord - this.posY));
                        this.motionZ = ((float) (movingObjPosition.hitVec.zCoord - this.posZ));
                        damageCalc = MathHelper.sqrt_double(this.motionX * this.motionX
                                + this.motionY * this.motionY + this.motionZ * this.motionZ);
                        this.posX -= this.motionX / damageCalc * 0.05000000074505806D;
                        this.posY -= this.motionY / damageCalc * 0.05000000074505806D;
                        this.posZ -= this.motionZ / damageCalc * 0.05000000074505806D;
                        this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));

                        inGround = true;
                        ObfuscationReflectionHelper.setPrivateValue(EntityArrow.class, this, true, 5);

                        this.arrowShake = 7;
                        this.setIsCritical(false);

                        if (inTile != 0) {
                            Block.blocksList[inTile].onEntityCollidedWithBlock(this.worldObj, xTile, yTile, zTile,
                                    this);
                        }
                    }
                }
            }

            if (this.getIsCritical()) {
                for (int i = 0; i < 4; ++i) {
                    this.worldObj.spawnParticle("crit", this.posX + this.motionX * i / 4.0D,
                            this.posY + this.motionY * i / 4.0D, this.posZ + this.motionZ * i / 4.0D, -this.motionX,
                            -this.motionY + 0.2D, -this.motionZ);
                }
            }

            this.posX += this.motionX;
            this.posY += this.motionY;
            this.posZ += this.motionZ;
            damageCalc = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionZ * this.motionZ);
            this.rotationYaw = (float) (Math.atan2(this.motionX, this.motionZ) * 180.0D / Math.PI);

            while (this.rotationPitch - this.prevRotationPitch >= 180.0F) {
                this.prevRotationPitch += 360.0F;
            }

            while (this.rotationYaw - this.prevRotationYaw < -180.0F) {
                this.prevRotationYaw -= 360.0F;
            }

            while (this.rotationYaw - this.prevRotationYaw >= 180.0F) {
                this.prevRotationYaw += 360.0F;
            }

            this.rotationPitch = this.prevRotationPitch + (this.rotationPitch - this.prevRotationPitch) * 0.2F;
            this.rotationYaw = this.prevRotationYaw + (this.rotationYaw - this.prevRotationYaw) * 0.2F;
            float motionMultiplier = 0.99F;
            float motionYDecrement = 0.05F;

            if (this.isInWater()) {
                for (int j1 = 0; j1 < 4; ++j1) {
                    unknown = 0.25F;
                    this.worldObj.spawnParticle("bubble", this.posX - this.motionX * unknown,
                            this.posY - this.motionY * unknown, this.posZ - this.motionZ * unknown, this.motionX,
                            this.motionY, this.motionZ);
                }

                motionMultiplier = 0.8F;
            }

            this.motionX *= motionMultiplier;
            this.motionY *= motionMultiplier;
            this.motionZ *= motionMultiplier;
            this.motionY -= motionYDecrement;
            this.setPosition(this.posX, this.posY, this.posZ);
            this.doBlockCollisions();

            try {
                //Account for differences between isInGround and inGround.
                if (!isInGround && inGround) {
                    //The arrow has struck the ground.
                    isInGround = true;

                    if (!worldObj.isRemote) {
                        //Determine if the arrow broke.
                        int probabilityOfBreaking = 0;

                        switch (arrowType) {
                        case 0:
                            probabilityOfBreaking = 25;
                            break;
                        case 1:
                            probabilityOfBreaking = 50;
                            break;
                        case 2:
                            probabilityOfBreaking = 30;
                            break;
                        case 3:
                            probabilityOfBreaking = 30;
                            break;
                        case 4:
                            probabilityOfBreaking = 25;
                            break;
                        case 5:
                            probabilityOfBreaking = 15;
                            break;
                        case 6:
                            probabilityOfBreaking = 75;
                            break;
                        case 7:
                            probabilityOfBreaking = 15;
                            break;
                        case 8:
                            probabilityOfBreaking = 15;
                            break;
                        case 9:
                            probabilityOfBreaking = 100;
                            break;
                        case 10:
                            probabilityOfBreaking = 10;
                            break;
                        case 11:
                            probabilityOfBreaking = 5;
                            break;
                        }

                        if (ArrowsPlus.getBooleanWithProbability(probabilityOfBreaking)) {
                            setDead();
                        }

                        //Sypherus arrow random explosion.
                        if (this.arrowType == 11) {
                            if (worldObj.rand.nextBoolean()) {
                                worldObj.createExplosion(this, posX, posY, posZ, 2.0F, false);
                            }
                        }

                        //Sypherus bow teleportation
                        if (this.bowType == 11) {
                            if (shootingEntity instanceof EntityPlayerMP) {
                                if (ArrowsPlus.getBooleanWithProbability(10)) {
                                    this.worldObj.playSoundEffect(shootingEntity.posX, shootingEntity.posY,
                                            shootingEntity.posZ, "fire.ignite", 1.0F, 1.0F);
                                }

                                else {
                                    EntityPlayerMP entityPlayerMP = (EntityPlayerMP) shootingEntity;
                                    entityPlayerMP.playerNetServerHandler.setPlayerLocation(posX, posY, posZ,
                                            entityPlayerMP.rotationYaw, entityPlayerMP.rotationPitch);
                                    this.worldObj.playSoundEffect(posX, posY, posZ, "mob.endermen.portal", 1.0F,
                                            1.0F);

                                    entityPlayerMP.triggerAchievement(ArrowsPlus.instance.achievementTeleport);
                                }
                            }
                        }

                        //Check for hickory arrow.
                        if (this.arrowType == 9) {
                            int inBlockX = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 0);
                            int inBlockY = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 1);
                            int inBlockZ = ObfuscationReflectionHelper.getPrivateValue(EntityArrow.class, this, 2);

                            if (inBlockX != -1 && inBlockY != -1 && inBlockZ != -1) {
                                int blockId = this.worldObj.getBlockId(inBlockX, inBlockY, inBlockZ);

                                if (blockId != Block.bedrock.blockID) {
                                    this.worldObj.setBlock(inBlockX, inBlockY, inBlockZ, 0);
                                }
                            }
                        }

                    }
                }

                //Still flying.
                else if (!isInGround && !inGround) {
                    if (!worldObj.isRemote) {
                        //Check wind factor.
                        double windFactor = 0.10D - windResistance;

                        //Should wind be applied?
                        if (worldObj.rand.nextBoolean()) {
                            //Should wind apply to X?
                            if (worldObj.rand.nextBoolean()) {
                                //Should wind apply to +X?
                                if (worldObj.rand.nextBoolean()) {
                                    setVel(motionX + windFactor, motionY, motionZ);
                                }

                                //Wind applies to -X.
                                else {
                                    setVel(motionX - windFactor, motionY, motionZ);
                                }
                            }

                            //Should wind apply to Z?
                            if (worldObj.rand.nextBoolean()) {
                                //Should wind apply to +Z?
                                if (worldObj.rand.nextBoolean()) {
                                    setVel(motionX, motionY, motionZ + windFactor);
                                }

                                //Wind applies to -Z.
                                else {
                                    setVel(motionX, motionY, motionZ - windFactor);
                                }
                            }
                        }

                        //Soft maple flying into the wind.
                        if (this.arrowType == 5) {
                            if (!softMapleIsFlyingIntoAir && ArrowsPlus.getBooleanWithProbability(3)) {
                                this.worldObj.playSoundAtEntity(shootingEntity, "mob.enderdragon.wings", 0.5F,
                                        1.0F);
                                softMapleIsFlyingIntoAir = true;
                            }

                            else if (softMapleIsFlyingIntoAir) {
                                if (softMapleCaughtByWindTicks != 20) {
                                    boolean changeX = worldObj.rand.nextBoolean();
                                    boolean changeY = worldObj.rand.nextBoolean();
                                    boolean changeZ = worldObj.rand.nextBoolean();

                                    if (changeX)
                                        setVel(motionX + 0.15D, motionY, motionZ);
                                    if (changeY)
                                        setVel(motionX, motionY + 0.15D, motionZ);
                                    if (changeZ)
                                        setVel(motionX, motionY, motionZ + 0.15D);
                                    softMapleCaughtByWindTicks++;
                                }
                            }
                        }
                    }
                }
            }

            catch (Throwable e) {
                ArrowsPlus.instance.log(e);
            }
        }
    }

    @Override
    public void onCollideWithPlayer(EntityPlayer par1EntityPlayer) {
        if (!this.worldObj.isRemote && this.isInGround && this.arrowShake <= 0) {
            boolean flag = this.canBePickedUp == 1
                    || this.canBePickedUp == 2 && par1EntityPlayer.capabilities.isCreativeMode;

            if (this.canBePickedUp == 1 && !par1EntityPlayer.inventory
                    .addItemStackToInventory(new ItemStack(getItemArrowByArrowType(), 1))) {
                flag = false;
            }

            if (flag) {
                this.playSound("random.pop", 0.2F,
                        ((this.rand.nextFloat() - this.rand.nextFloat()) * 0.7F + 1.0F) * 2.0F);
                par1EntityPlayer.onItemPickup(this, 1);
                this.setDead();
            }
        }
    }

    public double getDamage() {
        return ArrowsPlus.getArrowDamageModifierByWoodType(arrowType)
                + ArrowsPlus.getBowDamageModifierByWoodType(bowType);
    }

    @Override
    public void writeSpawnData(ByteArrayDataOutput data) {
        data.writeInt(arrowType);
        data.writeInt(bowType);
    }

    @Override
    public void readSpawnData(ByteArrayDataInput data) {
        arrowType = data.readInt();
        bowType = data.readInt();
    }

    public void setVel(double par1, double par3, double par5) {
        this.motionX = par1;
        this.motionY = par3;
        this.motionZ = par5;

        if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F) {
            float f = MathHelper.sqrt_double(par1 * par1 + par5 * par5);
            this.prevRotationYaw = this.rotationYaw = (float) (Math.atan2(par1, par5) * 180.0D / Math.PI);
            this.prevRotationPitch = this.rotationPitch = (float) (Math.atan2(par3, f) * 180.0D / Math.PI);
            this.prevRotationPitch = this.rotationPitch;
            this.prevRotationYaw = this.rotationYaw;
            this.setLocationAndAngles(this.posX, this.posY, this.posZ, this.rotationYaw, this.rotationPitch);
        }
    }

    /**
     * Sets the amount of knockback the arrow applies when it hits a mob.
     */
    public int getKnockbackStrength() {
        if (this.arrowType == 8 || this.arrowType == 10) {
            return 1;
        }

        else {
            return 0;
        }
    }

    public Item getItemArrowByArrowType() {
        switch (arrowType) {
        case 0:
            return ArrowsPlus.instance.itemArrowAspen;
        case 1:
            return ArrowsPlus.instance.itemArrowCottonwood;
        case 2:
            return ArrowsPlus.instance.itemArrowAlder;
        case 3:
            return ArrowsPlus.instance.itemArrowSycamore;
        case 4:
            return ArrowsPlus.instance.itemArrowGum;
        case 5:
            return ArrowsPlus.instance.itemArrowSoftMaple;
        case 6:
            return ArrowsPlus.instance.itemArrowAsh;
        case 7:
            return ArrowsPlus.instance.itemArrowBeech;
        case 8:
            return ArrowsPlus.instance.itemArrowHardMaple;
        case 9:
            return ArrowsPlus.instance.itemArrowHickory;
        case 10:
            return ArrowsPlus.instance.itemArrowMahogany;
        case 11:
            return ArrowsPlus.instance.itemArrowSypherus;
        default:
            return null;
        }
    }
}