Plugin Résolu [Mon plugin] Supprimer flèches, effets de potion et particules

ShE3py

Développeur en autodidacte
Support
26 Septembre 2015
2 430
56
343
247
19
Mìlhüsa
Enfaite dans tous les langages de programmation orientés objet il y a plusieurs type de portée ;
- Lorsqu'elle est déclarée dans la classe, toute la classe y a accès
- Lorsqu'elle est déclarée dans un bloc d'instruction {}, elle est dite locale: Seul le bloc y a accès.

Code:
public class Foo {
   public int a; // a est accessible dans toute la classe

   public void f1(String b) { // b juste dans la fonction
       for(float c = 0; c < 2; c += 0.5f) { // c juste dans la boucle for
          // a, b & c accessibles
       }

       // a & b accessibles
    }

    public int f2() {
        // seulement a est accessible
        return -1;
    }
}
(j'ai pas de tabulation sur mon tel j'ai du faire avec les moyens du bord)

Donc au lieu de créer ton ArrayList dans ton if, créer-le dans ta classe.
Et fait list.contains(id) pour tester si la liste contient l'ID, list.remove(id) pour le supprimer une fois que t'as détruit la flèche.

Après ta liste je te conseil de mettre la template ArrayList<Integer> (int n'est pas une classe, et ne marche pas), comme ça t'aura des avertissements si jamais tu tentes de faire un list.contains(x) avec x != int sur les IDEs récentes.
 

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Bonjour, merci pour les explications et merci pour le conseil.
Je vais paraître embêtant mais si je sors l'ArrayList de la condition if et du bloc d'instruction de l'événement PlayerInteractEvent, je ne peux pas récupérer la variable arrow, qui correspond à la flèche projetée. De même, si je sors la ligne suivante :
Code:
Arrow arrow = player.launchProjectile(Arrow.class, ploc.getLocation().getDirection().normalize().multiply(8));
elle ne fait plus partie de la condition, et ça ne sert plus à rien... Donc j'ai encore besoin d'une indication si possible. :)
En tout cas, merci pour ton précieux aide !
 

ShE3py

Développeur en autodidacte
Support
26 Septembre 2015
2 430
56
343
247
19
Mìlhüsa
Je ferais un truc comme ça moi :
Code:
import java.util.ArrayList;
import java.util.List;

import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.entity.Arrow;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.entity.EntityDamageByEntityEvent;
import org.bukkit.event.entity.ProjectileHitEvent;
import org.bukkit.event.player.PlayerInteractEvent;
import org.bukkit.inventory.ItemStack;

public class WeaponsEventHandler {
   // liste des balles actives
   private static List<Integer> activeBullets = new ArrayList<>();
   
   @EventHandler
    public void onInteract(PlayerInteractEvent e) {
        Player player = e.getPlayer();
        Action action = e.getAction();
        ItemStack it = e.getItem();
        Location ploc = player.getLocation();
         
        if(it == null) return;
       
        if(it.getType() == Material.WOOD_HOE && it.hasItemMeta() && it.getItemMeta().hasDisplayName() && it.getItemMeta().getDisplayName().equalsIgnoreCase("§fPistol")) {
            if(action == Action.RIGHT_CLICK_AIR || action == Action.RIGHT_CLICK_BLOCK) {
               // on lance une flèche
                Arrow arrow = player.launchProjectile(Arrow.class, ploc.getDirection().normalize().multiply(8));
               
                // on l'ajoute à la liste des balles actives
                activeBullets.add(arrow.getEntityId());
            }
        }
    }
   
   @EventHandler
    public void onProjectileHit(ProjectileHitEvent e) {
       // si l'entité n'est pas une flèche ou n'est pas dans la liste des balles actives, on quitte la méthode
       if(e.getEntityType() != EntityType.ARROW || !activeBullets.contains(e.getEntity().getEntityId())) return;
       
       // si c'est un bloc qui a été touché, on supprime la balle du monde & de la liste des actifs
       if(e.getHitBlock() != null) {
           activeBullets.remove(e.getEntity().getEntityId());
           e.getEntity().remove();
       }
    }
   
   @EventHandler
   public void onEntityDamagedByEntity(EntityDamageByEntityEvent e) {
       // si l'entité n'est pas une flèche ou n'est pas dans la liste des balles actives, on quitte la méthode
       if(e.getDamager().getType() != EntityType.ARROW || !activeBullets.contains(e.getDamager().getEntityId())) return;
       
       // c'est notre balle, on augmente les dégâts
       e.setDamage(e.getDamage() * 2);
       
       // et on supprime la balle du monde & de la liste
       activeBullets.remove(e.getEntity().getEntityId());
       e.getEntity().remove();
   }
}

Le code compile mais je l'ai pas testé.
Note: je vérifie que c'est un bloc qui a été touché car sinon il n'y aura pas de dégâts (je pense).
 

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Bonsoir, merci beaucoup encore une fois pour ton aide, mais malheureusement le code ne fonctionne pas. :/
Je vais faire des tests mais je crains ne pas trouver le problème.
 

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Le problème semble se situer dans le bloc d'instruction suivant :
Code:
 public void onProjectileHit(ProjectileHitEvent e) {
J'ai ajouté cela dedans :
Code:
Bukkit.broadcastMessage("Bloc touché, flèche supprimée !");
Evidemment, je ne reçois pas le message... L'ID de l'entité est pourtant bien récupérée, c'est toujours 2205.
Pour moi, les conditions ne sont pas vérifiées. Mais pourquoi ? :/
 
Dernière édition:

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Excusez-moi, je me permets de demander encore de l'aide, comme on dit "up" :)
Je n'ai toujours pas réussi à résoudre le problème :/
 

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Second up, je crains ne plus reçevoir d'aide pourtant si près du but...
Merci pour ceux qui aideront éventuellement ! :)
 

ShE3py

Développeur en autodidacte
Support
26 Septembre 2015
2 430
56
343
247
19
Mìlhüsa
Désolé du temps de réponse,

Quand tu as dit que ça marchais pas je croyais que le code n'était pas exécuté, par qu'une exception soit lancée (IndexOutOfBoundException).
L'erreur est toute conne, pour les lignes
Code:
activeBullets.remove(e.getEntity().getEntityId());

activeBullets est une liste d'Integers, mais Entity#getEntityId() renvois un int. Résultat: il appelle la méthod List#remove(int) à la place de List#remove(Integer), et la méthode avec un int enlève l'élément à l'index spécifié, d'où le IndexOutOfBoundException. Pour enlever l'objet, il suffit de caster l'int en Integer :
Code:
activeBullets.remove((Integer) e.getEntity().getEntityId());

Donc sur les deux lignes.
Enfaite si tu connais les templates s'est juste que List<T> a deux méthodes, List#remove(int) qui enlève à l'index spécifié et List#remove(T) qui enlève l'élément spécifié.
 

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Merci beaucoup pour ta réponse qui en plus est expliquée ! :)
Je vais ajouter l'invisibilité et les particules maintenant !
 

iKreal

Poseur de cobblestone
30 Octobre 2015
40
2
23
20
Voilà qui est intéressant (et embêtant)... On ne peut pas appliquer un effet de potion à une flèche... Du coup je ne sais vraiment pas comment faire là. J'ai regardé des forums anglais mais je n'y ai pas trouvé la solution...