Solved Destroy Arrow

Discussion in 'Plugin Development' started by Xp10d3, May 17, 2021.

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

    Xp10d3

    Basically I'm creating a basic bridge server and don't want players to pick up arrows after they fire it. Essentially have the same arrow mechanics as Lunar and Minemen. There are multiple ways to approach this such as canceling pickup event and destroying the packet, but for performance sake, I'd like to just destroy the arrow once the it lands on a block. Any ideas on how to approach this?
     
  2. Offline

    KarimAKL

    @Xp10d3 Listen to the ProjectileHitEvent.
     
  3. Offline

    Xp10d3

    Thanks! How would I check if the arrow lands on a block though? I've checked a few forum posts and examples, but none of them seemed helpful.

    EDIT: wait im dumb. mbmbmbmbmbmb
    Code:java
    1.  
    2. @EventHandler
    3. public void onHit(ProjectileHitEvent event) {
    4. Projectile is = event.getEntity();
    5. if (is instanceof Arrow) {
    6. Arrow arrow = (Arrow) is;
    7. if (arrow.isOnGround()) {
    8.  
    9. }
    10. }
    11. }
    12.  
     
  4. Offline

    KarimAKL

  5. Offline

    Xp10d3

  6. Offline

    Xp10d3

  7. Offline

    Shqep

    ProjectileHitEvent should still fire even if the projectile hits a block or a player. Theoretically, you can track hit projectiles, put their UUIDs or something in a list, then another event handler (PlayerPickupItemEvent) should see if the UUID of the item being picked up exists within that list, if it does, remove it?
    Additional info (?): the event will fire once if the projectile is an egg, a snowball or an arrow (1.8), but it will keep firing if it's a fishing rod until you pull the rod back.

    If so, just listening to the event and and event.getEntity().remove() works.
     
  8. Online

    davidclue

    @Xp10d3 Just get the arrow and check for nearby entities with a radius of 0 in the ProjectileHitEvent and if it hit a block then the list will be empty, it may still trigger if the arrow hits an item or something so just check if the entity in the list is an instance of a LivingEntity.
     
  9. Offline

    Xp10d3

    Alright; I'll try that. Thanks! :D

    I don't believe I can check if it hits a block (since #getHitBlock doesn't exist for 1.8 :C ), but that is helpful; thanks :)

    EDIT:
    Currently what I have:
    Code:java
    1.  
    2. @EventHandler
    3. public void onHit(ProjectileHitEvent event) {
    4. if (event.getEntityType().equals(EntityType.ARROW)) {
    5. arrowUUID.add(event.getEntity().getUniqueId());
    6. }
    7. }
    8. ...
    9. @EventHandler
    10. public void onPickup(PlayerPickupItemEvent event) {
    11. Iterator<UUID> uuid = arrowUUID.iterator();
    12. while (uuid.hasNext()) {
    13. UUID uuidD = uuid.next();
    14. if (uuidD.equals(event.getItem().getUniqueId())) {
    15. event.setCancelled(true);
    16. event.getItem().remove();
    17. uuid.remove();
    18. }
    19. }
    20. }
    21.  
     
    Last edited: May 24, 2021
  10. Offline

    Shqep

    @Xp10d3
    I can't confirm that it will work with UUIDs as I stored them as Entities to test.
    And using an iterator is only advised if you're removing items at the same time as you're iterating through the list, but in this case, you only need to remove that exact item you have.
    Code:Java
    1. // Removes the item and it isn't necessary to check if that item exists in the list.
    2. list.remove(item)
     
  11. Offline

    Xp10d3

    Ah I see mb. Thanks. Well if it doesn't work I can prob just check if the item is an arrow specifically:
    Code:java
    1.  
    2. if (event.getItem().equals(new ItemStack(Material.ARROW)) {
    3. event.setCancelled(true)
    4. event.removeItem();
    5. }
    6.  

    or something similar
     
  12. Offline

    Shqep

    @Xp10d3
    If you're creating a new ItemStack like that, it's not going to be return as true, ever. You're comparing an Item object to an ItemStack, worse is that the ItemStack is just freshly created.
    Your code was partly right, try this:
    Code:Java
    1. if (list.contains(item.getUniqueId())) {
    2. event.setCancelled(true);
    3. item.remove();
    4. list.remove(item.getUniqueId());
    5. }
     
  13. Online

    davidclue

    No, I am not saying use getHitBlock. I am saying that in the ProjectileHitEvent use e.getEntity().getNearbyEntities(0, 0, 0).isEmpty() and if that is true then the arrow hit a block, however if it is false then it hit an entity and the arrow is stuck on them, so just get the entity from the list and now you have it.
     
  14. Offline

    Xp10d3

    Sorry for the late reply; seems to work :D

    Code:java
    1.  
    2. List<UUID> arrowUUID = new ArrayList<UUID>();
    3. @EventHandler
    4. public void onHit(ProjectileHitEvent event) {
    5. if (event.getEntityType().equals(EntityType.ARROW)) {
    6. arrowUUID.add(event.getEntity().getUniqueId());
    7. }
    8. }
    9. @EventHandler
    10. public void onPickup(PlayerPickupItemEvent event) {
    11. Iterator<UUID> uuid = arrowUUID.iterator();
    12. while (uuid.hasNext()) {
    13. UUID uuidD = uuid.next();
    14. if (uuidD.equals(event.getItem().getUniqueId())) {
    15. event.setCancelled(true);
    16. event.getItem().remove();
    17. uuid.remove();
    18. }
    19. }
    20. }
    21.  


    Ah I see. I guess I could've done that. Thanks for the help anyways though :)
     
Thread Status:
Not open for further replies.

Share This Page