Jump to content

Recommended Posts

Posted

My modification specializes in tamable mobs. One feature I am fixing is turning off friendly fire; in this case with arrows. I have successfully turned off damage inflicted by players using arrows but as a side effect, arrows bounce off these tamable mobs. This can lead to player shooting themselves or accidentally shooting other tamable mobs instead.

 

How might I make arrows simply pass through these tamables and not cause damage?

 

If it matters, below is what I currently use to nullify friendly fire in the tamable's entity class:

@Override
public boolean attackEntityFrom(DamageSource damageSource, float damageAmount)
{
if (this.isEntityInvulnerable())
{
	return false;
}
else
{
	if (damageSource instanceof EntityDamageSource && this.isTamed() && this.getOwner() == damageSource.getEntity())
	{
		if(this.getOwner() instanceof EntityPlayer)
		{
			EntityPlayer entityPlayer = (EntityPlayer)this.getOwner();

			if(!entityPlayer.capabilities.isCreativeMode)
			{
				if (damageSource.getSourceOfDamage() instanceof EntityArrow)
				{
                                                 // I realize setting this to true keeps arrows from bouncing off 
                                                 // but that deletes arrows. I want them to pass through.
					 return false;
				 }

				 return true;
			 }
		 }
	}

	 return super.attackEntityFrom(damageSource, damageAmount);
}
}

 

Maybe if possible, see if whatever solution this might be could be applied to any player shot projectiles such as from other mods. If not, no big loss.

Posted

There isn't really a great way to do this, but one way is to subscribe to EntityJoinWorldEvent, check for EntityArrow, and replace it with your own arrow class that has overridden #onUpdate to rewrite the targeting logic to ignore friendly units BEFORE trying to attack them and thus before killing the arrow entity.

 

Downside is it won't work very well with other mods that add arrows, as you either don't bother replacing modded arrows or the modded arrows get replaced and lose whatever specialness they were supposed to have.

 

It'll be interesting to see if anyone has a more robust solution.

Posted

Thanks coolAlias! Not ideal but it is good enough for my needs. And your Zelda Sword Skills on Github helped me get this far!

 

I think I got everything working but I have an odd problem. The new arrows seem to behave correctly but look rather strange.

 

If I just log in, and shoot a few rounds, everything looks fine like this:

width=800 height=432http://img11.deviantart.net/2dab/i/2016/178/8/f/bowtrouble1_by_fuzzyacornindustries-da7wca2.jpg[/img]

 

But if move, such as to pick up the arrows and return to the same spot to shoot some rounds, this happens:

width=800 height=433http://img05.deviantart.net/21a7/i/2016/178/6/d/bowtrouble2_by_fuzzyacornindustries-da7wcw3.jpg[/img]

 

I am guessing this is a client side issue? I cannot tell for sure.

 

Below is what I have done to get this to work.

 

The new arrow class, pretty much a copy paste as is with a new main constructor and two line changes in the onUpdate() function. One at the beginning to skip the EntityArrow onUpdate() function and this line:

 

if (entity1.canBeCollidedWith() && (entity1 != this.shootingEntity || this.ticksInAir >= 5) && !(entity1 instanceof TamablePokemon))

 

The whole class:

public class PokemonMDArrow extends EntityArrow implements IProjectile
{
private int field_145791_d = -1;
private int field_145792_e = -1;
private int field_145789_f = -1;
private Block field_145790_g;
private int inData;
private boolean inGround;
/** 1 if the player can pick up the arrow */
public int canBePickedUp;
/** Seems to be some sort of timer for animating an arrow. */
public int arrowShake;
/** The owner of this arrow. */
public Entity shootingEntity;
private int ticksInGround;
private int ticksInAir;
private double damage = 2.0D;
/** The amount of knockback an arrow applies when it hits a mob. */
private int knockbackStrength;

public PokemonMDArrow(World p_i1753_1_)
{
	super(p_i1753_1_);
	this.renderDistanceWeight = 10.0D;
	this.setSize(0.5F, 0.5F);
}

public PokemonMDArrow(World world, Entity entityLivingBasePar, double posX, double posY, double posZ, double motionX, double motionY, double motionZ, float rotationYaw, float rotationPitch)
{
	super(world);
	this.renderDistanceWeight = 10.0D;
	this.shootingEntity = entityLivingBasePar;

	this.canBePickedUp = 1;

	this.setSize(0.5F, 0.5F);


	this.setLocationAndAngles(this.shootingEntity.posX, this.shootingEntity.posY + (double)this.shootingEntity.getEyeHeight(), this.shootingEntity.posZ, this.shootingEntity.rotationYaw, this.shootingEntity.rotationPitch);
	this.posX -= (double)(MathHelper.cos(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);
	this.posY -= 0.10000000149011612D;
	this.posZ -= (double)(MathHelper.sin(this.rotationYaw / 180.0F * (float)Math.PI) * 0.16F);

	this.setPosition(this.posX, this.posY, this.posZ);
	this.yOffset = 0.0F;

	this.posX = posX;
	this.posY = posY;
	this.posZ = posZ;

        this.motionX = motionX;
        this.motionY = motionY;
        this.motionZ = motionZ;

        this.prevRotationYaw = this.rotationYaw = rotationYaw;
        this.prevRotationPitch = this.rotationPitch = rotationPitch;
}

    protected void entityInit()
    {
        this.dataWatcher.addObject(16, Byte.valueOf((byte)0));
    }

    /**
     * Similar to setArrowHeading, it's point the throwable entity to a x, y, z direction.
     */
    public void setThrowableHeading(double p_70186_1_, double p_70186_3_, double p_70186_5_, float p_70186_7_, float p_70186_8_)
    {
        float f2 = MathHelper.sqrt_double(p_70186_1_ * p_70186_1_ + p_70186_3_ * p_70186_3_ + p_70186_5_ * p_70186_5_);
        p_70186_1_ /= (double)f2;
        p_70186_3_ /= (double)f2;
        p_70186_5_ /= (double)f2;
        p_70186_1_ += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)p_70186_8_;
        p_70186_3_ += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)p_70186_8_;
        p_70186_5_ += this.rand.nextGaussian() * (double)(this.rand.nextBoolean() ? -1 : 1) * 0.007499999832361937D * (double)p_70186_8_;
        p_70186_1_ *= (double)p_70186_7_;
        p_70186_3_ *= (double)p_70186_7_;
        p_70186_5_ *= (double)p_70186_7_;
        this.motionX = p_70186_1_;
        this.motionY = p_70186_3_;
        this.motionZ = p_70186_5_;
        float f3 = MathHelper.sqrt_double(p_70186_1_ * p_70186_1_ + p_70186_5_ * p_70186_5_);
        this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(p_70186_1_, p_70186_5_) * 180.0D / Math.PI);
        this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(p_70186_3_, (double)f3) * 180.0D / Math.PI);
        this.ticksInGround = 0;
    }

    /**
     * Sets the position and rotation. Only difference from the other one is no bounding on the rotation. Args: posX,
     * posY, posZ, yaw, pitch
     */
    @SideOnly(Side.CLIENT)
    public void setPositionAndRotation2(double p_70056_1_, double p_70056_3_, double p_70056_5_, float p_70056_7_, float p_70056_8_, int p_70056_9_)
    {
        this.setPosition(p_70056_1_, p_70056_3_, p_70056_5_);
        this.setRotation(p_70056_7_, p_70056_8_);
    }

    /**
     * Sets the velocity to the args. Args: x, y, z
     */
    @SideOnly(Side.CLIENT)
    public void setVelocity(double p_70016_1_, double p_70016_3_, double p_70016_5_)
    {
        this.motionX = p_70016_1_;
        this.motionY = p_70016_3_;
        this.motionZ = p_70016_5_;

        if (this.prevRotationPitch == 0.0F && this.prevRotationYaw == 0.0F)
        {
            float f = MathHelper.sqrt_double(p_70016_1_ * p_70016_1_ + p_70016_5_ * p_70016_5_);
            this.prevRotationYaw = this.rotationYaw = (float)(Math.atan2(p_70016_1_, p_70016_5_) * 180.0D / Math.PI);
            this.prevRotationPitch = this.rotationPitch = (float)(Math.atan2(p_70016_3_, (double)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);
            this.ticksInGround = 0;
        }
    }

/**
 * Called to update the entity's position/logic.
 */
@Override
public void onUpdate()
{
	this.onEntityUpdate();

	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, (double)f) * 180.0D / Math.PI);
	}

	Block block = this.worldObj.getBlock(this.field_145791_d, this.field_145792_e, this.field_145789_f);

	if (block.getMaterial() != Material.air)
	{
		block.setBlockBoundsBasedOnState(this.worldObj, this.field_145791_d, this.field_145792_e, this.field_145789_f);
		AxisAlignedBB axisalignedbb = block.getCollisionBoundingBoxFromPool(this.worldObj, this.field_145791_d, this.field_145792_e, this.field_145789_f);

		if (axisalignedbb != null && axisalignedbb.isVecInside(Vec3.createVectorHelper(this.posX, this.posY, this.posZ)))
		{
			this.inGround = true;
		}
	}

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

	if (this.inGround)
	{
		int j = this.worldObj.getBlockMetadata(this.field_145791_d, this.field_145792_e, this.field_145789_f);

		if (block == this.field_145790_g && j == this.inData)
		{
			++this.ticksInGround;

			if (this.ticksInGround == 1200)
			{
				this.setDead();
			}
		}
		else
		{
			this.inGround = false;
			this.motionX *= (double)(this.rand.nextFloat() * 0.2F);
			this.motionY *= (double)(this.rand.nextFloat() * 0.2F);
			this.motionZ *= (double)(this.rand.nextFloat() * 0.2F);
			this.ticksInGround = 0;
			this.ticksInAir = 0;
		}
	}
	else
	{
		++this.ticksInAir;
		Vec3 vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
		Vec3 vec3 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);
		MovingObjectPosition movingobjectposition = this.worldObj.func_147447_a(vec31, vec3, false, true, false);
		vec31 = Vec3.createVectorHelper(this.posX, this.posY, this.posZ);
		vec3 = Vec3.createVectorHelper(this.posX + this.motionX, this.posY + this.motionY, this.posZ + this.motionZ);

		if (movingobjectposition != null)
		{
			vec3 = Vec3.createVectorHelper(movingobjectposition.hitVec.xCoord, movingobjectposition.hitVec.yCoord, movingobjectposition.hitVec.zCoord);
		}

		Entity entity = null;
		List list = this.worldObj.getEntitiesWithinAABBExcludingEntity(this, this.boundingBox.addCoord(this.motionX, this.motionY, this.motionZ).expand(1.0D, 1.0D, 1.0D));
		double d0 = 0.0D;
		int i;
		float f1;

		for (i = 0; i < list.size(); ++i)
		{
			Entity entity1 = (Entity)list.get(i);

			if (entity1.canBeCollidedWith() && (entity1 != this.shootingEntity || this.ticksInAir >= 5) && !(entity1 instanceof TamablePokemon))
			{
				f1 = 0.3F;
				AxisAlignedBB axisalignedbb1 = entity1.boundingBox.expand((double)f1, (double)f1, (double)f1);
				MovingObjectPosition movingobjectposition1 = axisalignedbb1.calculateIntercept(vec31, vec3);

				if (movingobjectposition1 != null)
				{
					double d1 = vec31.distanceTo(movingobjectposition1.hitVec);

					if (d1 < d0 || d0 == 0.0D)
					{
						entity = entity1;
						d0 = d1;
					}
				}
			}
		}

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

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

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

		float f2;
		float f4;

		if (movingobjectposition != null)
		{
			if (movingobjectposition.entityHit != null)
			{
				f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
				int k = MathHelper.ceiling_double_int((double)f2 * this.damage);

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

				DamageSource damagesource = null;

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

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

				if (movingobjectposition.entityHit.attackEntityFrom(damagesource, (float)k))
				{
					if (movingobjectposition.entityHit instanceof EntityLivingBase)
					{
						EntityLivingBase entitylivingbase = (EntityLivingBase)movingobjectposition.entityHit;

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

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

							if (f4 > 0.0F)
							{
								movingobjectposition.entityHit.addVelocity(this.motionX * (double)this.knockbackStrength * 0.6000000238418579D / (double)f4, 0.1D, this.motionZ * (double)this.knockbackStrength * 0.6000000238418579D / (double)f4);
							}
						}

						if (this.shootingEntity != null && this.shootingEntity instanceof EntityLivingBase)
						{
							EnchantmentHelper.func_151384_a(entitylivingbase, this.shootingEntity);
							EnchantmentHelper.func_151385_b((EntityLivingBase)this.shootingEntity, entitylivingbase);
						}

						if (this.shootingEntity != null && movingobjectposition.entityHit != this.shootingEntity && movingobjectposition.entityHit instanceof EntityPlayer && this.shootingEntity instanceof EntityPlayerMP)
						{
							((EntityPlayerMP)this.shootingEntity).playerNetServerHandler.sendPacket(new S2BPacketChangeGameState(6, 0.0F));
						}
					}

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

					if (!(movingobjectposition.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;
					this.ticksInAir = 0;
				}
			}
			else
			{
				this.field_145791_d = movingobjectposition.blockX;
				this.field_145792_e = movingobjectposition.blockY;
				this.field_145789_f = movingobjectposition.blockZ;
				this.field_145790_g = this.worldObj.getBlock(this.field_145791_d, this.field_145792_e, this.field_145789_f);
				this.inData = this.worldObj.getBlockMetadata(this.field_145791_d, this.field_145792_e, this.field_145789_f);
				this.motionX = (double)((float)(movingobjectposition.hitVec.xCoord - this.posX));
				this.motionY = (double)((float)(movingobjectposition.hitVec.yCoord - this.posY));
				this.motionZ = (double)((float)(movingobjectposition.hitVec.zCoord - this.posZ));
				f2 = MathHelper.sqrt_double(this.motionX * this.motionX + this.motionY * this.motionY + this.motionZ * this.motionZ);
				this.posX -= this.motionX / (double)f2 * 0.05000000074505806D;
				this.posY -= this.motionY / (double)f2 * 0.05000000074505806D;
				this.posZ -= this.motionZ / (double)f2 * 0.05000000074505806D;
				this.playSound("random.bowhit", 1.0F, 1.2F / (this.rand.nextFloat() * 0.2F + 0.9F));
				this.inGround = true;
				this.arrowShake = 7;
				this.setIsCritical(false);

				if (this.field_145790_g.getMaterial() != Material.air)
				{
					this.field_145790_g.onEntityCollidedWithBlock(this.worldObj, this.field_145791_d, this.field_145792_e, this.field_145789_f, this);
				}
			}
		}

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

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

		for (this.rotationPitch = (float)(Math.atan2(this.motionY, (double)f2) * 180.0D / Math.PI); this.rotationPitch - this.prevRotationPitch < -180.0F; this.prevRotationPitch -= 360.0F)
		{
			;
		}

		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 f3 = 0.99F;
		f1 = 0.05F;

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

			f3 = 0.8F;
		}

		if (this.isWet())
		{
			this.extinguish();
		}

		this.motionX *= (double)f3;
		this.motionY *= (double)f3;
		this.motionZ *= (double)f3;
		this.motionY -= (double)f1;
		this.setPosition(this.posX, this.posY, this.posZ);
		this.func_145775_I();
	}
}

    /**
     * (abstract) Protected helper method to write subclass entity data to NBT.
     */
    public void writeEntityToNBT(NBTTagCompound p_70014_1_)
    {
        p_70014_1_.setShort("xTile", (short)this.field_145791_d);
        p_70014_1_.setShort("yTile", (short)this.field_145792_e);
        p_70014_1_.setShort("zTile", (short)this.field_145789_f);
        p_70014_1_.setShort("life", (short)this.ticksInGround);
        p_70014_1_.setByte("inTile", (byte)Block.getIdFromBlock(this.field_145790_g));
        p_70014_1_.setByte("inData", (byte)this.inData);
        p_70014_1_.setByte("shake", (byte)this.arrowShake);
        p_70014_1_.setByte("inGround", (byte)(this.inGround ? 1 : 0));
        p_70014_1_.setByte("pickup", (byte)this.canBePickedUp);
        p_70014_1_.setDouble("damage", this.damage);
    }

    /**
     * (abstract) Protected helper method to read subclass entity data from NBT.
     */
    public void readEntityFromNBT(NBTTagCompound p_70037_1_)
    {
        this.field_145791_d = p_70037_1_.getShort("xTile");
        this.field_145792_e = p_70037_1_.getShort("yTile");
        this.field_145789_f = p_70037_1_.getShort("zTile");
        this.ticksInGround = p_70037_1_.getShort("life");
        this.field_145790_g = Block.getBlockById(p_70037_1_.getByte("inTile") & 255);
        this.inData = p_70037_1_.getByte("inData") & 255;
        this.arrowShake = p_70037_1_.getByte("shake") & 255;
        this.inGround = p_70037_1_.getByte("inGround") == 1;

        if (p_70037_1_.hasKey("damage", 99))
        {
            this.damage = p_70037_1_.getDouble("damage");
        }

        if (p_70037_1_.hasKey("pickup", 99))
        {
            this.canBePickedUp = p_70037_1_.getByte("pickup");
        }
        else if (p_70037_1_.hasKey("player", 99))
        {
            this.canBePickedUp = p_70037_1_.getBoolean("player") ? 1 : 0;
        }
    }

    /**
     * Called by a player entity when they collide with an entity
     */
    public void onCollideWithPlayer(EntityPlayer p_70100_1_)
    {
        if (!this.worldObj.isRemote && this.inGround && this.arrowShake <= 0)
        {
            boolean flag = this.canBePickedUp == 1 || this.canBePickedUp == 2 && p_70100_1_.capabilities.isCreativeMode;

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

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

    /**
     * returns if this entity triggers Block.onEntityWalking on the blocks they walk on. used for spiders and wolves to
     * prevent them from trampling crops
     */
    protected boolean canTriggerWalking()
    {
        return false;
    }

    @SideOnly(Side.CLIENT)
    public float getShadowSize()
    {
        return 0.0F;
    }

    public void setDamage(double p_70239_1_)
    {
        this.damage = p_70239_1_;
    }

    public double getDamage()
    {
        return this.damage;
    }

    /**
     * Sets the amount of knockback the arrow applies when it hits a mob.
     */
    public void setKnockbackStrength(int p_70240_1_)
    {
        this.knockbackStrength = p_70240_1_;
    }

    /**
     * If returns false, the item will not inflict any damage against entities.
     */
    public boolean canAttackWithItem()
    {
        return false;
    }

    /**
     * Whether the arrow has a stream of critical hit particles flying behind it.
     */
    public void setIsCritical(boolean p_70243_1_)
    {
        byte b0 = this.dataWatcher.getWatchableObjectByte(16);

        if (p_70243_1_)
        {
            this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 | 1)));
        }
        else
        {
            this.dataWatcher.updateObject(16, Byte.valueOf((byte)(b0 & -2)));
        }
    }

    /**
     * Whether the arrow has a stream of critical hit particles flying behind it.
     */
    public boolean getIsCritical()
    {
        byte b0 = this.dataWatcher.getWatchableObjectByte(16);
        return (b0 & 1) != 0;
    }
}

 

The onEntityJoinWorld() in my event handle:


@SubscribeEvent
public void onEntityJoinWorld(EntityJoinWorldEvent event) 
{
	if (event.entity.getClass() != PokemonMDArrow.class && event.entity.getClass() == EntityArrow.class)
	{
		if (!event.entity.worldObj.isRemote) 
		{
			if(((EntityArrow)event.entity).shootingEntity instanceof EntityPlayer)
			{
				PokemonMDArrow pokmeonMDArrow = new PokemonMDArrow(((EntityArrow)event.entity).worldObj, ((EntityArrow)event.entity).shootingEntity,
						((EntityArrow)event.entity).posX, ((EntityArrow)event.entity).posY, ((EntityArrow)event.entity).posZ,
						((EntityArrow)event.entity).motionX, ((EntityArrow)event.entity).motionY, ((EntityArrow)event.entity).motionZ, 
						((EntityArrow)event.entity).rotationYaw, ((EntityArrow)event.entity).rotationPitch);

				pokmeonMDArrow.worldObj.spawnEntityInWorld(pokmeonMDArrow);
			}

		}

		event.entity.setDead();
	}
}

 

The Render class, a copy paste with just a change to the Entity class accepted:

@SideOnly(Side.CLIENT)
public class RenderPokemonMDArrow extends Render
{
    private static final ResourceLocation arrowTextures = new ResourceLocation("textures/entity/arrow.png");

    /**
     * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
     * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
     * (Render<T extends Entity) and this method has signature public void func_76986_a(T entity, double d, double d1,
     * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
     */
    public void doRender(PokemonMDArrow p_76986_1_, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_)
    {
        this.bindEntityTexture(p_76986_1_);
        GL11.glPushMatrix();
        GL11.glTranslatef((float)p_76986_2_, (float)p_76986_4_, (float)p_76986_6_);
        GL11.glRotatef(p_76986_1_.prevRotationYaw + (p_76986_1_.rotationYaw - p_76986_1_.prevRotationYaw) * p_76986_9_ - 90.0F, 0.0F, 1.0F, 0.0F);
        GL11.glRotatef(p_76986_1_.prevRotationPitch + (p_76986_1_.rotationPitch - p_76986_1_.prevRotationPitch) * p_76986_9_, 0.0F, 0.0F, 1.0F);
        Tessellator tessellator = Tessellator.instance;
        byte b0 = 0;
        float f2 = 0.0F;
        float f3 = 0.5F;
        float f4 = (float)(0 + b0 * 10) / 32.0F;
        float f5 = (float)(5 + b0 * 10) / 32.0F;
        float f6 = 0.0F;
        float f7 = 0.15625F;
        float f8 = (float)(5 + b0 * 10) / 32.0F;
        float f9 = (float)(10 + b0 * 10) / 32.0F;
        float f10 = 0.05625F;
        GL11.glEnable(GL12.GL_RESCALE_NORMAL);
        float f11 = (float)p_76986_1_.arrowShake - p_76986_9_;

        if (f11 > 0.0F)
        {
            float f12 = -MathHelper.sin(f11 * 3.0F) * f11;
            GL11.glRotatef(f12, 0.0F, 0.0F, 1.0F);
        }

        GL11.glRotatef(45.0F, 1.0F, 0.0F, 0.0F);
        GL11.glScalef(f10, f10, f10);
        GL11.glTranslatef(-4.0F, 0.0F, 0.0F);
        GL11.glNormal3f(f10, 0.0F, 0.0F);
        tessellator.startDrawingQuads();
        tessellator.addVertexWithUV(-7.0D, -2.0D, -2.0D, (double)f6, (double)f8);
        tessellator.addVertexWithUV(-7.0D, -2.0D, 2.0D, (double)f7, (double)f8);
        tessellator.addVertexWithUV(-7.0D, 2.0D, 2.0D, (double)f7, (double)f9);
        tessellator.addVertexWithUV(-7.0D, 2.0D, -2.0D, (double)f6, (double)f9);
        tessellator.draw();
        GL11.glNormal3f(-f10, 0.0F, 0.0F);
        tessellator.startDrawingQuads();
        tessellator.addVertexWithUV(-7.0D, 2.0D, -2.0D, (double)f6, (double)f8);
        tessellator.addVertexWithUV(-7.0D, 2.0D, 2.0D, (double)f7, (double)f8);
        tessellator.addVertexWithUV(-7.0D, -2.0D, 2.0D, (double)f7, (double)f9);
        tessellator.addVertexWithUV(-7.0D, -2.0D, -2.0D, (double)f6, (double)f9);
        tessellator.draw();

        for (int i = 0; i < 4; ++i)
        {
            GL11.glRotatef(90.0F, 1.0F, 0.0F, 0.0F);
            GL11.glNormal3f(0.0F, 0.0F, f10);
            tessellator.startDrawingQuads();
            tessellator.addVertexWithUV(-8.0D, -2.0D, 0.0D, (double)f2, (double)f4);
            tessellator.addVertexWithUV(8.0D, -2.0D, 0.0D, (double)f3, (double)f4);
            tessellator.addVertexWithUV(8.0D, 2.0D, 0.0D, (double)f3, (double)f5);
            tessellator.addVertexWithUV(-8.0D, 2.0D, 0.0D, (double)f2, (double)f5);
            tessellator.draw();
        }

        GL11.glDisable(GL12.GL_RESCALE_NORMAL);
        GL11.glPopMatrix();
    }

    /**
     * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
     */
    protected ResourceLocation getEntityTexture(PokemonMDArrow p_110775_1_)
    {
        return arrowTextures;
    }

    /**
     * Returns the location of an entity's texture. Doesn't seem to be called unless you call Render.bindEntityTexture.
     */
    protected ResourceLocation getEntityTexture(Entity p_110775_1_)
    {
        return this.getEntityTexture((PokemonMDArrow)p_110775_1_);
    }

    /**
     * Actually renders the given argument. This is a synthetic bridge method, always casting down its argument and then
     * handing it off to a worker function which does the actual work. In all probabilty, the class Render is generic
     * (Render<T extends Entity) and this method has signature public void func_76986_a(T entity, double d, double d1,
     * double d2, float f, float f1). But JAD is pre 1.5 so doesn't do that.
     */
    public void doRender(Entity p_76986_1_, double p_76986_2_, double p_76986_4_, double p_76986_6_, float p_76986_8_, float p_76986_9_)
    {
        this.doRender((PokemonMDArrow)p_76986_1_, p_76986_2_, p_76986_4_, p_76986_6_, p_76986_8_, p_76986_9_);
    }
}

 

If anything else needs to be shown, just let me know. (yes, I would normally clean up the unnamed variable names. I wait until

Posted

EntityArrow does some special-casing on its spawn packet, so whenever you extend it you need to implement IEntityAdditionalSpawnData and perform the same special casing to your own arrow:

@Override
public void writeSpawnData(ByteArrayDataOutput buffer) {
buffer.writeInt(this.shootingEntity != null ? this.shootingEntity.entityId : -1);
}

@Override
public void readSpawnData(ByteArrayDataInput buffer) {
// Replicate EntityArrow's special spawn packet handling from NetClientHandler#handleVehicleSpawn:
Entity shooter = worldObj.getEntityByID(buffer.readInt());
if (shooter instanceof EntityLivingBase) {
	this.shootingEntity = (EntityLivingBase) shooter;
}
}

Strangely enough, that fixed the crooked arrow issue for me.

Posted

Nice! It works lovely. I think there is a version difference with what you gave me. Mine ended up as:

 

@Override
public void writeSpawnData(ByteBuf buffer) 
{
	buffer.writeInt(this.shootingEntity != null ? this.shootingEntity.getEntityId() : -1);

}

@Override
public void readSpawnData(ByteBuf buffer) 
{
	// Replicate EntityArrow's special spawn packet handling from NetClientHandler#handleVehicleSpawn:
	Entity shooter = worldObj.getEntityByID(buffer.readInt());

	if (shooter instanceof EntityLivingBase) 
	{
		this.shootingEntity = (EntityLivingBase) shooter;
	}
}

 

Thanks coolAlias, you are the best!

 

And if someone else is reading this page to add your own custom arrow, don't copy my code from the my previous post. It has several issues I am now finding since my last post. I'll see to fixing them.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • I have been trying to solve a consistent crashing issue on my brother's computer where it will crash during the "Scanning Mod Candidates" phase of the loading process that starts when you click the play button on the Minecraft launcher. The issue seems to stem from a missing library that it mentions in the log file I provide below. I might I'm missing the bigger issue here for a smaller one but hopefully someone can find what I'm missing. Here's all of the stuff that I've been able to figure out so far: 1. It has nothing to do with mods, the crash happened with a real modpack, and even when I made a custom modpack and launched it without putting ANY mods into it (That is where the log file comes from by the way). 2. I have tried to find this class like a file in the Minecraft folders, but I've had no luck finding it (I don't think it works like that, but since I really don't understand how it works, I just figured I'd try). 3. I haven't seen anyone else have this issue before. 4. I know that my modpack (with mods) does work since I've run it on my computer, and it works fantastic. For some reason my brother's computer can't seem to run anything through curseforge. 5. This is for Minecraft version 1.20.1, Minecraft launcher version 3.4.50-2.1.3, forge 47.3.0, and curseforge app version 1.256.0.21056 6. My brother is using a Dell laptop from 6 years ago running Windows 10 (If you think more info on this would help, please ask as I do have it. I'm just choosing not to put it here for now). 7. I have reinstalled the curseforge app and installed Minecraft version 1.20.1. I have not reinstalled Minecraft or forge 47.3.0 but I didn't know if that would help. 8. I had an error code of 1 Please let me know if there is anything else that I am missing that you would like me to add to this post/add in a comment! Lastly, many thanks in advance to whoever can help! ------------- LOG FILE (latest.log) ------------- (from /Users/<NAME OF USER>/cursforge/minecraft/Instances/<THE NAME OF MY EMPTY MODPACK>/logs/latest.log) (This was made after running an empty modpack with same versions for all apps) ("[REDACTED]" is not the actual text from the log, it is me replacing text I figured wouldn't be necessary for fixing and would hurt my privacy) https://pastebin.com/hxXvGGEK ------------- DEBUG.LOG (I realized that I should have put this here first after I had done all of the work on putting latest.log in) -------------------- (again, "[REDACTED]" is not the actual text from the log, it is me replacing text I figured wouldn't be necessary for fixing and would hurt my privacy) https://pastebin.com/Fmh8GHYs
    • Pastebin... https://pastebin.com/Y3iZ85L5   Brand new profile, does not point to a mod as far as I can tell, my fatal message just has something about mixins. Don't know much about reading logs like this, but am genuinely stuck, please help. Java updated, pc restarted.
    • Fastfund recovery helps an individual to get back their scammed funds irrespective of nationality, Romance scam funds and Broker's scam, all kinds of scam funds are 100% accurately recovered without disappointment, their goal is to give all those who seek help to recover lost satisfaction of funds recovery within 72 hours After countless hours of research and desperate attempts to find a solution, I stumbled upon FASTFUND RECOVERY. It was like finding an oasis in the middle of a desert. Their website promised to help victims of scams reclaim what was rightfully theirs, and I instantly knew I had to give them a shot. Before diving headfirst into the recovery process, I wanted to make sure that FASTFUND RECOVERY was the real deal. So, I did my due diligence and looked into their expertise and reputation. To my relief, I found that they had an impeccable track record, successfully assisting countless individuals in recovering their lost funds. Their team consisted of experts in cybersecurity and financial fraud, armed with the knowledge and tools needed to tackle even the most intricate scams. With their reputation preceding them, I felt a renewed sense of hope. FASTFUND RECOVERY successfully came to my aid and got back the amount I lost to these scammers and for this, I am sending this article for clarification. The info of FASTFUND RECOVERY is email: Fastfundrecovery8 (@)Gmail (.) com. Web fastfundrecovery(.)com. (W/A 1 807/500/7554)
    • I was playing minecraft, forge 47.3.0 and 1.20.1, but when i tried to play minecraft now only crashes, i need help please. here is the crash report: https://securelogger.net/files/e6640a4f-9ed0-4acc-8d06-2e500c77aaaf.txt
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.