Solved ItemSpawnEvent: Get Projectile that Caused Item to Spawn

Discussion in 'Plugin Development' started by hockeygoalie5, Oct 7, 2012.

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

    hockeygoalie5

    Here's a tricky one. I'm creating a plugin where you are given items based on your job. These items can not be manipulated in any way (e.g., moved in your inventory, dropped, etc.). I want to make it so when an arrow is launched from a bow that a person received for free because of their job, it won't spawn an arrow item when it hits the ground. However, if it was fired from a bow that someone got by other means, it will. So far, I've been able to give metadata to the projectile if it has been fired from a job-given bow:
    Code:
    @EventHandler
    public void onProjectileLaunch(ProjectileLaunchEvent e) {
        if(e.getEntity().getShooter() != null) {
            if(e.getEntity().getShooter() instanceof Player) {
                Player player = (Player) e.getEntity().getShooter();
                if(Job.isJobItem(player.getItemInHand())) {
                    e.getEntity().setMetadata("nospawn", new FixedMetadataValue(new LightRP(), true));
                }
            }
        }
    }
    
    I've also detected when an arrow hits the ground, if it's from a job-given bow:
    Code:
    @EventHandler
    public void onProjectileHit(ProjectileHitEvent e) {
        if(e.getEntity().hasMetadata("nospawn")) {
            LightRP.log.info("Yes.");
        }
    }
    
    How will I be able to, from a onProjectileHit method, stop the arrow from spawning? Or, how can I use an onItemSpawn method to get the projectile that spawned the arrow, check its metadata, then take action?
     
  2. Did you try a simple e.remove() in the ProjectileHitEvent?
     
  3. Offline

    hockeygoalie5

    V10lator Wouldn't that remove the projectile? I want the projectile to hit, just not spawn an arrow that can be picked up. I was hoping there was a way to set the projectile itself to spawn nothing, or to at least get the item the projectile spawned.
     
  4. I see, I think you can set that while launching the arrow...
    https://github.com/Bukkit/CraftBukk...raftbukkit/entity/CraftLivingEntity.java#L277 <- this will shoot a pickable arrow (like sooted from a player).
    https://github.com/Bukkit/CraftBukk...aft/server/PathfinderGoalArrowAttack.java#L77 <- this is used if a skeleton shots an arrow, so not pickable.
    Now if we look into the EntityArrow we find this: https://github.com/Bukkit/CraftBukk...ava/net/minecraft/server/EntityArrow.java#L45 and guess what? This variable is public!
    So all you have to do is this:
    Code:java
    1. @EventHandler
    2. public void onProjectileLaunch(ProjectileLaunchEvent e) {
    3. if(e.getEntity().getShooter() != null) {
    4. if(e.getEntity().getShooter() instanceof Player) {
    5. Player player = (Player) e.getEntity().getShooter();
    6. if(Job.isJobItem(player.getItemInHand())) {
    7. ((CraftArrow)e.getEntity()).getHandle().fromPlayer = 0;
    8. }
    9. }
    10. }
    11. }

    For that to work you need the craftbukkit.jar instead of the bukkit.jar into your build path and I didn't test it.

    //Edit: Side note: There is no item till the player picks it up, it's still the arrow entity till then:
    https://github.com/Bukkit/CraftBukk...va/net/minecraft/server/EntityArrow.java#L358 - As you see it creates a new item, calls the pickup event and if it isn't cancelled gives the item to the player.
     
  5. Offline

    hockeygoalie5

    That looks good! I did see a method for projectiles to change who shot it, so I'll try just changing that to skeleton instead. Thanks for researching it!
     
Thread Status:
Not open for further replies.

Share This Page