Hook Arrow Hitting Block

Discussion in 'Plugin Development' started by SycoPrime, Feb 4, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    SycoPrime

    Is there a way to hook when an arrow hits a block?
    And hopefully to then determine if the arrow is on fire.

    I'm hoping to make it so that flaming arrows can light (flammable) blocks on fire when they hit them.
     
  2. Offline

    SycoPrime

    Aright, so maybe the trick is in a custom craftbukkit dealie. So I looked into CraftBukkit's EntityArrow, which is this:

    Code:
    package net.minecraft.server;
    
    import java.util.List;
    import java.util.Random;
    import org.bukkit.craftbukkit.CraftServer;
    import org.bukkit.event.entity.EntityDamageByProjectileEvent;
    import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
    import org.bukkit.plugin.PluginManager;
    
    public class EntityArrow extends Entity
    {
      private int c = -1;
      private int d = -1;
      private int e = -1;
      private int f = 0;
      private boolean ak = false;
      public int a = 0;
      public EntityLiving b;
      private int al;
      private int am = 0;
    
      public EntityArrow(World world) {
        super(world);
        a(0.5F, 0.5F);
      }
    
      public EntityArrow(World world, double d0, double d1, double d2) {
        super(world);
        a(0.5F, 0.5F);
        a(d0, d1, d2);
        this.height = 0.0F;
      }
    
      public EntityArrow(World world, EntityLiving entityliving) {
        super(world);
        this.b = entityliving;
        a(0.5F, 0.5F);
        c(entityliving.locX, entityliving.locY + entityliving.w(), entityliving.locZ, entityliving.yaw, entityliving.pitch);
        this.locX -= MathHelper.b(this.yaw / 180.0F * 3.141593F) * 0.16F;
        this.locY -= 0.1000000014901161D;
        this.locZ -= MathHelper.a(this.yaw / 180.0F * 3.141593F) * 0.16F;
        a(this.locX, this.locY, this.locZ);
        this.height = 0.0F;
        this.motX = (-MathHelper.a(this.yaw / 180.0F * 3.141593F) * MathHelper.b(this.pitch / 180.0F * 3.141593F));
        this.motZ = (MathHelper.b(this.yaw / 180.0F * 3.141593F) * MathHelper.b(this.pitch / 180.0F * 3.141593F));
        this.motY = (-MathHelper.a(this.pitch / 180.0F * 3.141593F));
        a(this.motX, this.motY, this.motZ, 1.5F, 1.0F);
      }
      protected void a() {
      }
    
      public void a(double d0, double d1, double d2, float f, float f1) {
        float f2 = MathHelper.a(d0 * d0 + d1 * d1 + d2 * d2);
    
        d0 /= f2;
        d1 /= f2;
        d2 /= f2;
        d0 += this.random.nextGaussian() * 0.007499999832361937D * f1;
        d1 += this.random.nextGaussian() * 0.007499999832361937D * f1;
        d2 += this.random.nextGaussian() * 0.007499999832361937D * f1;
        d0 *= f;
        d1 *= f;
        d2 *= f;
        this.motX = d0;
        this.motY = d1;
        this.motZ = d2;
        float f3 = MathHelper.a(d0 * d0 + d2 * d2);
    
        this.lastYaw = (this.yaw = (float)(Math.atan2(d0, d2) * 180.0D / 3.141592741012573D));
        this.lastPitch = (this.pitch = (float)(Math.atan2(d1, f3) * 180.0D / 3.141592741012573D));
        this.al = 0;
      }
    
      public void b_() {
        super.b_();
        if ((this.lastPitch == 0.0F) && (this.lastYaw == 0.0F)) {
          float f = MathHelper.a(this.motX * this.motX + this.motZ * this.motZ);
    
          this.lastYaw = (this.yaw = (float)(Math.atan2(this.motX, this.motZ) * 180.0D / 3.141592741012573D));
          this.lastPitch = (this.pitch = (float)(Math.atan2(this.motY, f) * 180.0D / 3.141592741012573D));
        }
    
        if (this.a > 0) {
          this.a -= 1;
        }
    
        if (this.ak) {
          int i = this.world.getTypeId(this.c, this.d, this.e);
    
          if (i == this.f) {
            this.al += 1;
            if (this.al == 1200) {
              q();
            }
    
            return;
          }
    
          this.ak = false;
          this.motX *= this.random.nextFloat() * 0.2F;
          this.motY *= this.random.nextFloat() * 0.2F;
          this.motZ *= this.random.nextFloat() * 0.2F;
          this.al = 0;
          this.am = 0;
        } else {
          this.am += 1;
        }
    
        Vec3D vec3d = Vec3D.b(this.locX, this.locY, this.locZ);
        Vec3D vec3d1 = Vec3D.b(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
        MovingObjectPosition movingobjectposition = this.world.a(vec3d, vec3d1);
    
        vec3d = Vec3D.b(this.locX, this.locY, this.locZ);
        vec3d1 = Vec3D.b(this.locX + this.motX, this.locY + this.motY, this.locZ + this.motZ);
        if (movingobjectposition != null) {
          vec3d1 = Vec3D.b(movingobjectposition.f.a, movingobjectposition.f.b, movingobjectposition.f.c);
        }
    
        Entity entity = null;
        List list = this.world.b(this, this.boundingBox.a(this.motX, this.motY, this.motZ).b(1.0D, 1.0D, 1.0D));
        double d0 = 0.0D;
    
        for (int j = 0; j < list.size(); j++) {
          Entity entity1 = (Entity)list.get(j);
    
          if ((entity1.c_()) && ((entity1 != this.b) || (this.am >= 5))) {
            float f1 = 0.3F;
            AxisAlignedBB axisalignedbb = entity1.boundingBox.b(f1, f1, f1);
            MovingObjectPosition movingobjectposition1 = axisalignedbb.a(vec3d, vec3d1);
    
            if (movingobjectposition1 != null) {
              double d1 = vec3d.a(movingobjectposition1.f);
    
              if ((d1 < d0) || (d0 == 0.0D)) {
                entity = entity1;
                d0 = d1;
              }
            }
          }
        }
    
        if (entity != null) {
          movingobjectposition = new MovingObjectPosition(entity);
        }
    
        if (movingobjectposition != null) {
          if (movingobjectposition.g != null)
          {
            boolean stick;
            boolean stick;
            if ((entity instanceof EntityLiving)) {
              CraftServer server = ((WorldServer)this.world).getServer();
    
              org.bukkit.entity.Entity shooter = this.b == null ? null : this.b.getBukkitEntity();
              org.bukkit.entity.Entity damagee = movingobjectposition.g.getBukkitEntity();
              org.bukkit.entity.Entity projectile = getBukkitEntity();
    
              EntityDamageEvent.DamageCause damageCause = EntityDamageEvent.DamageCause.ENTITY_ATTACK;
              int damage = 4;
    
              EntityDamageByProjectileEvent event = new EntityDamageByProjectileEvent(shooter, damagee, projectile, damageCause, damage);
              server.getPluginManager().callEvent(event);
              boolean stick;
              if (!event.isCancelled())
              {
                stick = movingobjectposition.g.a(this.b, event.getDamage());
              }
              else
                stick = !event.getBounce();
            }
            else {
              stick = movingobjectposition.g.a(this.b, 4);
            }
            if (stick)
            {
              this.world.a(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
              q();
            } else {
              this.motX *= -0.1000000014901161D;
              this.motY *= -0.1000000014901161D;
              this.motZ *= -0.1000000014901161D;
              this.yaw += 180.0F;
              this.lastYaw += 180.0F;
              this.am = 0;
            }
          } else {
            this.c = movingobjectposition.b;
            this.d = movingobjectposition.c;
            this.e = movingobjectposition.d;
            this.f = this.world.getTypeId(this.c, this.d, this.e);
            this.motX = (float)(movingobjectposition.f.a - this.locX);
            this.motY = (float)(movingobjectposition.f.b - this.locY);
            this.motZ = (float)(movingobjectposition.f.c - this.locZ);
            float f2 = MathHelper.a(this.motX * this.motX + this.motY * this.motY + this.motZ * this.motZ);
            this.locX -= this.motX / f2 * 0.0500000007450581D;
            this.locY -= this.motY / f2 * 0.0500000007450581D;
            this.locZ -= this.motZ / f2 * 0.0500000007450581D;
            this.world.a(this, "random.drr", 1.0F, 1.2F / (this.random.nextFloat() * 0.2F + 0.9F));
            this.ak = true;
            this.a = 7;
          }
        }
    
        this.locX += this.motX;
        this.locY += this.motY;
        this.locZ += this.motZ;
        float f2 = MathHelper.a(this.motX * this.motX + this.motZ * this.motZ);
        this.yaw = (float)(Math.atan2(this.motX, this.motZ) * 180.0D / 3.141592741012573D);
    
        for (this.pitch = (float)(Math.atan2(this.motY, f2) * 180.0D / 3.141592741012573D); this.pitch - this.lastPitch < -180.0F; this.lastPitch -= 360.0F);
        while (this.pitch - this.lastPitch >= 180.0F) {
          this.lastPitch += 360.0F;
        }
    
        while (this.yaw - this.lastYaw < -180.0F) {
          this.lastYaw -= 360.0F;
        }
    
        while (this.yaw - this.lastYaw >= 180.0F) {
          this.lastYaw += 360.0F;
        }
    
        this.pitch = (this.lastPitch + (this.pitch - this.lastPitch) * 0.2F);
        this.yaw = (this.lastYaw + (this.yaw - this.lastYaw) * 0.2F);
        float f3 = 0.99F;
    
        float f1 = 0.03F;
        if (v()) {
          for (int k = 0; k < 4; k++) {
            float f4 = 0.25F;
    
            this.world.a("bubble", this.locX - this.motX * f4, this.locY - this.motY * f4, this.locZ - this.motZ * f4, this.motX, this.motY, this.motZ);
          }
    
          f3 = 0.8F;
        }
    
        this.motX *= f3;
        this.motY *= f3;
        this.motZ *= f3;
        this.motY -= f1;
        a(this.locX, this.locY, this.locZ);
      }
    
      public void a(NBTTagCompound nbttagcompound) {
        nbttagcompound.a("xTile", (short)this.c);
        nbttagcompound.a("yTile", (short)this.d);
        nbttagcompound.a("zTile", (short)this.e);
        nbttagcompound.a("inTile", (byte)this.f);
        nbttagcompound.a("shake", (byte)this.a);
        nbttagcompound.a("inGround", (byte)(this.ak ? 1 : 0));
      }
    
      public void b(NBTTagCompound nbttagcompound) {
        this.c = nbttagcompound.c("xTile");
        this.d = nbttagcompound.c("yTile");
        this.e = nbttagcompound.c("zTile");
        this.f = (nbttagcompound.b("inTile") & 0xFF);
        this.a = (nbttagcompound.b("shake") & 0xFF);
        this.ak = (nbttagcompound.b("inGround") == 1);
      }
    
      public void b(EntityHuman entityhuman) {
        if ((!this.world.isStatic) && 
          (this.ak) && (this.b == entityhuman) && (this.a <= 0) && (entityhuman.inventory.a(new ItemStack(Item.ARROW, 1)))) {
          this.world.a(this, "random.pop", 0.2F, ((this.random.nextFloat() - this.random.nextFloat()) * 0.7F + 1.0F) * 2.0F);
          entityhuman.c(this, 1);
          q();
        }
      }
    }
    "a" appears to be a function which deals with moving the arrow, and "b" a function which deals with collision, but I can't see any parts that deal with blocks, only entities.
     
  3. Offline

    feverdream

    Dont link to craftbukkit in your code. Thats BAD.

    If the bukkit interface does not have what you need, submit a patch to extend bukkit.

    Have you looked at Entity* hooks for getting hit by an error? I could have sworn I saw something the last I checked, but I could be wrong.
     
  4. Offline

    xpansive

    The part that deals with the collision with blocks is here (its in "b_"):
    Code:
    if (this.ak) {
          int i = this.world.getTypeId(this.c, this.d, this.e);
    
    You'll need to implement a event listener or something to make it useful, though. You could also have it so when someone uses another item (like a stick) it shoots a arrow and waits for the variables c, d, or e (x, y and z) to be something other than -1.
     
  5. Offline

    SycoPrime

    Submit a patch, like do it myself? Or a request for a patch to be done?

    http://javadoc.lukegb.com/Bukkit/de/d38/classorg_1_1bukkit_1_1event_1_1entity_1_1EntityListener.html
    Entity listener will tell you when an entity is hit by an arrow, but not a block.

    Okay, sweet. Good start!
    I'm afraid I don't quite understand that. I get the first part, about doing entity.shootarrow, but wouldn't you be waiting for velocities to be != -1, not location, which seems to be all I can get out of the entity?
     
  6. Offline

    xpansive

    Sorry, worded that wrong.
    c d and e are the x, y and z pos of the block the arrow is stuck into. If its still in the air, it will be -1.
    Like this (make sure you do it in a separate thread):

    Code:
    while (entity.getHandle().c != -1);
     
  7. Offline

    SycoPrime

    So is there any way to do this without editing the crafkbukkit code?
    Or do I override just the arrow class in my plugin?
     
  8. Offline

    Stevenpcc

Thread Status:
Not open for further replies.

Share This Page