Plugin Comment empêcher qu'un item utilisable ne soit utilisé si

Monsieur Yaourt

Architecte en herbe
2 Septembre 2014
61
4
112
Bonsoir, je m'entraine a dev en java sur spigot, j'ai tenté de créer un plugin qui ajoute des fonctionnalités aux enderpearl (cooldown notamment)
Le plugin est fonctionnel, cependant quand le joueur a le cooldown et qu'il utilise une enderpearl il n'est pas téléporté mais l'enderpearl est quand même "consommé" (enlever de l'inventaire du joueur). J'ai tenté un setCancelled mais ça ne fonctionne pas, quelqu'un pourrait me dire comment faire ça ?

Code:
                if (cooldown.containsKey(player.getUniqueId()) && timeleft > 0) {

                    player.sendMessage(cg.getConfig().getString("message.OnCooldown").replace("&", "§")
                            .replace("%time%", String.valueOf(timeleft)));
                    event.setCancelled(true);
                    return;
 
PlayerTeleportEvent ne gère que l'action lorsque l'enderpearl se casse en touchant un bloc, le lanceur est téléporté ; l'item a déjà été consommé, donc annuler la téléportation n'annule pas la consommation de l'item.
Pour ce que tu veux faire, ce serait plus intelligent de passer par ProjectileLaunchEvent, en empêchant directement le joueur de lancer une enderpearl s'il est en cooldown.

Sinon pour commenter un peu ton code :
Java:
cg.getConfig().getString("message.OnCooldown").replace("&", "§").replace("%time%", String.valueOf(timeleft))
  • Pour remplacer un seul caractère, préfère passer par un char plutôt qu'un CharSequence ;
    .replace('&', '§')

    En utilisant des guillemets « " », tu utilises une fonction qui doit considérer les cas où les deux paramètres ont plusieurs caractères et une taille potentiellement différente, ce qui est généralement plus lent que la version avec juste deux fois un unique caractère.

  • Tu risques de remplacer incorrectement des « Bro & Cie », il faut que tu vérifies que le « &x » représente bien un code couleur Minecraft.
    Utilises CharColor#translateAlternateColorCodes :
    Java:
    String text = ChatColor.translateAlternateColorCodes('&', cf.getConfig().getString("message.enderpearl_cooling_down"));
    
    // avec une expression régulière :
    String text = cf.getConfig().getString("message.enderpearl_cooling_down").replaceAll("&([0-9a-fk-or])", "§$1");

  • Préfère sauvegarder le résultat intermédiaire (avec le %time%) au lieu de convertir tous les & en § à chaque fois que le message est nécessaire.

Désolé pour le temps de réponse, je suis allergique à la chaleur et la saison ne m'aide pas vraiment, dis-moi si je dois reformuler ou développer quelque chose.
 
Dernière édition:
  • J'aime
Reactions: Monsieur Yaourt
Bonjour !

Sinon, tu peux simplement ajouter une enderpearl à l'inventaire du joueur ?
J'ai du mal à voir si y'a une faille à ce système...
 
Sinon, tu peux simplement ajouter une enderpearl à l'inventaire du joueur ?
J'ai du mal à voir si y'a une faille à ce système...
  • Le problème de vérifier le cooldown à la téléportation et non au lancement, c'est qu'il est possible de lancer plusieurs enderpearls en même temps ;
    • C'est plus logique d'empêcher d'utiliser une enderpearl directement au lieu d'avoir un message d'erreur quelques instants après.​
    • Les joueurs peuvent tricher en lançant plusieurs enderpearls, pour se téléporter à la première qui tombe et récupérer toutes les autres.
  • Si le joueur n'a qu'une seule enderpearl, l'item sera probablement redonné dans un autre slot que celui initial ;
    • Si les joueurs rangent leur inventaire, ça titille un peu d'avoir son enderpearl toujours sur un mauvais slot.​
    • Il faut prendre en compte le cas où le joueur aurait ramassé un item entre-temps, et a donc un inventaire plein.
  • Il est possible que l'enderpearl ne se casse jamais (tourner lancée dans le vide par ex.), donc aucune téléportation et le joueur ne récupérera jamais son enderpearl ;

  • De la même manière, il est possible qu'un plugin tue l'enderpearl en vol (anti-lag par ex.) ;

  • Il est possible qu'un plugin annule la téléportation en amont (WorldGuard par ex.) ;
    • Dans ce cas-là, il suffit d'écouter l'évènement même lorsque celui-ci est annulé pour regive l'item (@EventHandler(ignoreCancelled = false)), ce qui force la fonction à toujours être appelée.
  • Même si dans Bukkit le joueur qui a lancé le projectile se récupère avec Projectile#getShooter(), ce n'est pas le shooter qui est représenté par la variable mais bien l'Owner comme sauvegardé dans le tag NBT.
    • En d'autres termes, qui doit être téléporté par l'enderpearl, ou qui doit prendre le kill dans le cas d'une flèche.​
    • Même si en vanilla le lanceur et le propriétaire du projectile sont toujours le même, l'on parle d'un serveur avec des plugins.
      Il se peut qu'un plugin ait fait apparaître une enderpearl (arme, boule de neige qui se transforme en enderpearl à travers un portail, etc.) avec un joueur en Owner même si celui-ci n'a jamais eu d'enderpearl. Tu donneras donc une enderpearl que le joueur n'a jamais eu et n'est pas supposé avoir.​

Je viens de vérifier le code source de Minecraft, annuler l'évènement ProjectileLaunchEvent annule bien l'interaction, pas d'entité (enderpearl), ni de son, ni d'incrémentation de la statistique d'enderpearls utilisés, ni de consommation (-1) du stack d'enderpearls.
 
  • Le problème de vérifier le cooldown à la téléportation et non au lancement, c'est qu'il est possible de lancer plusieurs enderpearls en même temps ;
    • C'est plus logique d'empêcher d'utiliser une enderpearl directement au lieu d'avoir un message d'erreur quelques instants après.​
    • Les joueurs peuvent tricher en lançant plusieurs enderpearls, pour se téléporter à la première qui tombe et récupérer toutes les autres.​
  • Si le joueur n'a qu'une seule enderpearl, l'item sera probablement redonné dans un autre slot que celui initial ;
    • Si les joueurs rangent leur inventaire, ça titille un peu d'avoir son enderpearl toujours sur un mauvais slot.​
    • Il faut prendre en compte le cas où le joueur aurait ramassé un item entre-temps, et a donc un inventaire plein.​
  • Il est possible que l'enderpearl ne se casse jamais (tourner lancée dans le vide par ex.), donc aucune téléportation et le joueur ne récupérera jamais son enderpearl ;

  • De la même manière, il est possible qu'un plugin tue l'enderpearl en vol (anti-lag par ex.) ;

  • Il est possible qu'un plugin annule la téléportation en amont (WorldGuard par ex.) ;
    • Dans ce cas-là, il suffit d'écouter l'évènement même lorsque celui-ci est annulé pour regive l'item (@EventHandler(ignoreCancelled = false)), ce qui force la fonction à toujours être appelée.​
  • Même si dans Bukkit le joueur qui a lancé le projectile se récupère avec Projectile#getShooter(), ce n'est pas le shooter qui est représenté par la variable mais bien l'Owner comme sauvegardé dans le tag NBT.
    • En d'autres termes, qui doit être téléporté par l'enderpearl, ou qui doit prendre le kill dans le cas d'une flèche.​
    • Même si en vanilla le lanceur et le propriétaire du projectile sont toujours le même, l'on parle d'un serveur avec des plugins.
      Il se peut qu'un plugin ait fait apparaître une enderpearl (arme, boule de neige qui se transforme en enderpearl à travers un portail, etc.) avec un joueur en Owner même si celui-ci n'a jamais eu d'enderpearl. Tu donneras donc une enderpearl que le joueur n'a jamais eu et n'est pas supposé avoir.​

Je viens de vérifier le code source de Minecraft, annuler l'évènement ProjectileLaunchEvent annule bien l'interaction, pas d'entité (enderpearl), ni de son, ni d'incrémentation de la statistique d'enderpearls utilisés, ni de consommation (-1) du stack d'enderpearls.
Je vois.
 
Bonjour !

Sinon, tu peux simplement ajouter une enderpearl à l'inventaire du joueur ?
J'ai du mal à voir si y'a une faille à ce système...
Give une enderpearl aurait été une mauvaise idée je pense mais dans tous les cas le code que j'avais écrit été assez catastrophique il a entièrement changé et du coup j'utilise deux fonctions PlayerTeleportEvent et PlayerIntercatEvent et désormais c'est PlayerInteract qui effectue la vérification concernant le cooldown
 
Give une enderpearl aurait été une mauvaise idée je pense mais dans tous les cas le code que j'avais écrit été assez catastrophique il a entièrement changé et du coup j'utilise deux fonctions PlayerTeleportEvent et PlayerIntercatEvent et désormais c'est PlayerInteract qui effectue la vérification concernant le cooldown
Les fonctions n'ont pas de sens en java !