Plugin bans temporaire

  • Auteur de la discussion Auteur de la discussion LEZIKO
  • Date de début Date de début

LEZIKO

Architecte en herbe
2 Novembre 2021
93
2
69
20
Bonjour, je demande de l'aide aujourd'hui car j'ai créé mon plugin de modération et tout fonctionne j'ai créé ma propre liste de bans, maintenant je souhaiterais faire des bans temporaires avec des arguments comme h, m, d, y pour savoir si on veut bannir en heure, seconde, jours, année... Seulement je n'arrive pas à comprendre comment faire... Les tutos ne sont pas assez explicites voilà pourquoi je demande votre aide,
En vous remerciant,
LEZIKO
 
Salut,

Tu n'arrives pas à faire quoi ?
Calculer le temps sur base des arguments donnés par le joueur ?
Calculer le moment où le ban ne compte plus ?

Ce qu'il faut bien comprendre, c'est que pour tout problème, il y a plusieurs moyen d'y arriver ;) (c'est comme ne math... ils existent plusieurs méthodes pour arriver à la solution).
Donc plutôt que te donner "une" solution, il vaut mieux voir "comment tu imagines la solution" et s'adapter à toi ;)
Donc décris moi, comment tu imagines les choses et où tu es bloqué exactement (n'hésites pas à donner des bouts de code que tu as déjà essayé en utilisant la balise "code") :D


Cordialement,
Detobel36
 
Salut ! Merci pour ta réponse alors pour te répondre dcp j'suis parti sur une idée de convertir chaque unité en mettant: secondes, minutes, heures, semaines, mois et années j'aimerais ensuite que par exemple quand je tempban le joueur par exemple 1y il est ban 1 an et après il peut revenir. Mais je n'ai aucune idee de comment faire pour que le temps passe pour qu'il soit bien deban au bout d'un an. Je met en pièce jointe ce que j'ai fait.
 

Fichiers joints

  • Screenshot_2022-03-03-11-12-02-779.jpg
    Screenshot_2022-03-03-11-12-02-779.jpg
    171.8 KB · Vues : 123
  • Screenshot_2022-03-03-11-15-06-439.jpg
    Screenshot_2022-03-03-11-15-06-439.jpg
    142.2 KB · Vues : 120
Bonjour,

En assumant une commande du style :
Code:
/ban <player> <duration> [<reason>]

Avec la durée représentée par une seule chaîne de caractères de syntaxe « 3d12h » pour 3 jours 12 heures, tout collé parce que sinon les paramètres sont ambiguës (/ban <player> 3d 12h j'aime les pâtes — quels mots appartiennent à la durée et à la raison ?).

Java:
@Override
public boolean onKommand(CommandSender sender, Command command, String label, String[] args) {
   if(args.length < 2) {
      return false;
   }
  
   @SuppressWarnings("deprecation")
   OfflinePlayer playerToBan = sender.getServer().getOfflinePlayer(args[0]);
  
   Duration banDuration;
   try {
      banDuration = DurationParser.parse(args[1]);
   }
   catch(ParseException | ArithmeticException e) {
      sender.sendMessage("§cDurée invalide.");
      return true;
   }
  
   String reason = Arrays.stream(args).skip(2).collect(Collectors.joining(" "));
   if(reason.isEmpty()) reason = null;
  
   Date expires = Date.from(Instant.now().plus(banDuration));
  
   sender.getServer().getBanList(BanList.Type.NAME).addBan(playerToBan.getName(), reason, expires, sender.getName());
   sender.sendMessage("Le joueur " + playerToBan.getName() + " a été banni pendant " + banDuration + '.');
  
   return true;
}
Java:
public class DurationParser {
   // (unit prefix, int-to-duration converter)
   private static final Map<String, IntFunction<TemporalAmount>> UNITS;
  
   static {
      final ImmutableMap.Builder<String, IntFunction<TemporalAmount>> builder = ImmutableMap.builder();
      final BiConsumer<IntFunction<TemporalAmount>, Iterator<String>> registry = (converter, suffixes) -> suffixes.forEachRemaining(suffix -> builder.put(suffix, converter));
      final BiConsumer<TemporalUnit, Iterator<String>> temporalUnit = (unit, suffixes) -> registry.accept((d) -> unit.getDuration().multipliedBy(d), suffixes);
     
      // Modifier les unités ici
      temporalUnit.accept(ChronoUnit.SECONDS, Iterators.forArray("s", "second, seconds"));
      temporalUnit.accept(ChronoUnit.MINUTES, Iterators.forArray("m", "mn", "min", "minute", "minutes"));
      temporalUnit.accept(ChronoUnit.HOURS, Iterators.forArray("h", "hour", "hours"));
      temporalUnit.accept(ChronoUnit.DAYS, Iterators.forArray("d", "day", "days"));
      temporalUnit.accept(ChronoUnit.MONTHS, Iterators.forArray("mt", "month", "months"));
      temporalUnit.accept(ChronoUnit.YEARS, Iterators.forArray("y", "year", "years"));
     
      UNITS = builder.build();
      for(String suffix : UNITS.keySet()) {
         if(suffix == null || suffix.isEmpty() || Character.digit(suffix.charAt(0), 10) >= 0) {
            throw new IllegalArgumentException("Suffixes must starts with a non-digit: " + suffix);
         }
      }
   }
  
   /**
    * Transforme la chaîne de caractères passée en argument en une {@link Duration}.
    *
    * @param str la chaîne à convertir
    * @return la durée convertie
    * @throws ParseException si une unité de temps n'est pas reconnue, qu'un nombre
    * est présent sans unité, ou que la chaîne ne commence pas par un chiffre
    * @throws ArithmeticException en cas de dépassement numérique
    */
   @CheckReturnValue
   public static Duration parse(String str) throws ParseException {
      // the sum of all time (quantity, unit) pairs
      Duration sum = Duration.ZERO;
     
      if(str == null || str.isEmpty()) {
         return sum; // duh.
      }
     
      // in the case you want to write your quantities in base 2.
      // note that radix > 10 will collide with a- unit suffixes.
      final int radix = 10;
     
      char c = str.charAt(0);
      int digit = Character.digit(c, radix);
     
      if(digit < 0) {
         throw new ParseException("Expecting a digit, got a character", 0);
      }
     
      // the current time quantity
      int value = digit;
     
      // the current time unit
      StringBuilder suffix = new StringBuilder();
     
      for(int i = 1; i < str.length(); ++i) {
         c = str.charAt(i);
         digit = Character.digit(c, radix);
        
         if(digit >= 0) {
            // if we got a digit after some characters,
            // push the current (quantity, unit) to the sum
            if(suffix.length() != 0) {
               sum = pushTemporalPair(sum, value, suffix, i);
              
               value = digit;
               suffix.setLength(0);
            }
            else {
               // else add the current digit to the current quantity
               value = Math.addExact(Math.multiplyExact(value, radix), digit);
            }
         }
         else {
            // we got a non-digit character
            suffix.append(c);
         }
      }
     
      if(suffix.length() != 0) {
         // push the last (quantity, unit) pair
         sum = pushTemporalPair(sum, value, suffix, str.length());
      }
      else if(value != 0) {
         throw new ParseException("Got " + value + " without a time unit.", str.length());
      }
     
      return sum;
   }
  
   @CheckReturnValue
   private static TemporalAmount parseTemporalUnit(int value, @NotNull String suffix, int offset) throws ParseException {
      var converter = UNITS.get(suffix);
      if(converter == null) {
         throw new ParseException("Unknown time unit: " + suffix, offset - suffix.length());
      }
     
      return converter.apply(value);
   }
  
   @CheckReturnValue
   private static Duration pushTemporalPair(@NotNull Duration sum, int value, @NotNull StringBuilder suffix, int offset) throws ParseException {
      return sum.plus(Duration.from(parseTemporalUnit(value, suffix.toString(), offset)));
   }
}

L'idée consiste simplement à mettre tous les suffixes dans un tableau qui associe à chaque suffixe une fonction qui convertit le nombre avec une certaine unité (minutes, heures, etc.) en une TemporalAmount — typiquement des nanosecondes.

La fonction de conversion lit la chaîne caractère par caractère, en commençant avec une durée S = 0, puis en détectant les transitions chiffres et non-chiffres ; pour « 12min306s » elle lira 12 et « min », en lisant le chiffre suivant 3 elle remarquera qu'elle a déjà un couple (nombre, unité) non-nul, donc elle convertira (12, min) en 12 minutes, calculera S = S + 12 minutes, réinitialisera le couple à (0, <mot vide>), mettra le nombre qu'elle est en train de lire dedans, puis continuera de parcourir la chaîne de caractères avec une durée S = 12 minutes, et un couple en construction (3, <mot vide>).

À la fin le programme se retrouve avec S = 12 minutes et un couple (306, s), qu'il reconvertit en durée, calcule S = S + 306 secondes, puis renvoit le résultat de 17 minutes et 6 secondes.

Tu me diras si ça marche, je n'ai pas vraiment essayé.

Cordialement,
ShE3py
 
Bonjour,

En assumant une commande du style :
Code:
/ban <player> <duration> [<reason>]

Avec la durée représentée par une seule chaîne de caractères de syntaxe « 3d12h » pour 3 jours 12 heures, tout collé parce que sinon les paramètres sont ambiguës (/ban <player> 3d 12h j'aime les pâtes — quels mots appartiennent à la durée et à la raison ?).

Java:
@Override
public boolean onKommand(CommandSender sender, Command command, String label, String[] args) {
   if(args.length < 2) {
      return false;
   }
 
   @SuppressWarnings("deprecation")
   OfflinePlayer playerToBan = sender.getServer().getOfflinePlayer(args[0]);
 
   Duration banDuration;
   try {
      banDuration = DurationParser.parse(args[1]);
   }
   catch(ParseException | ArithmeticException e) {
      sender.sendMessage("§cDurée invalide.");
      return true;
   }
 
   String reason = Arrays.stream(args).skip(2).collect(Collectors.joining(" "));
   if(reason.isEmpty()) reason = null;
 
   Date expires = Date.from(Instant.now().plus(banDuration));
 
   sender.getServer().getBanList(BanList.Type.NAME).addBan(playerToBan.getName(), reason, expires, sender.getName());
   sender.sendMessage("Le joueur " + playerToBan.getName() + " a été banni pendant " + banDuration + '.');
 
   return true;
}
Java:
public class DurationParser {
   // (unit prefix, int-to-duration converter)
   private static final Map<String, IntFunction<TemporalAmount>> UNITS;
 
   static {
      final ImmutableMap.Builder<String, IntFunction<TemporalAmount>> builder = ImmutableMap.builder();
      final BiConsumer<IntFunction<TemporalAmount>, Iterator<String>> registry = (converter, suffixes) -> suffixes.forEachRemaining(suffix -> builder.put(suffix, converter));
      final BiConsumer<TemporalUnit, Iterator<String>> temporalUnit = (unit, suffixes) -> registry.accept((d) -> unit.getDuration().multipliedBy(d), suffixes);
    
      // Modifier les unités ici
      temporalUnit.accept(ChronoUnit.SECONDS, Iterators.forArray("s", "second, seconds"));
      temporalUnit.accept(ChronoUnit.MINUTES, Iterators.forArray("m", "mn", "min", "minute", "minutes"));
      temporalUnit.accept(ChronoUnit.HOURS, Iterators.forArray("h", "hour", "hours"));
      temporalUnit.accept(ChronoUnit.DAYS, Iterators.forArray("d", "day", "days"));
      temporalUnit.accept(ChronoUnit.MONTHS, Iterators.forArray("mt", "month", "months"));
      temporalUnit.accept(ChronoUnit.YEARS, Iterators.forArray("y", "year", "years"));
    
      UNITS = builder.build();
      for(String suffix : UNITS.keySet()) {
         if(suffix == null || suffix.isEmpty() || Character.digit(suffix.charAt(0), 10) >= 0) {
            throw new IllegalArgumentException("Suffixes must starts with a non-digit: " + suffix);
         }
      }
   }
 
   /**
    * Transforme la chaîne de caractères passée en argument en une {@link Duration}.
    *
    * @param str la chaîne à convertir
    * @return la durée convertie
    * @throws ParseException si une unité de temps n'est pas reconnue, qu'un nombre
    * est présent sans unité, ou que la chaîne ne commence pas par un chiffre
    * @throws ArithmeticException en cas de dépassement numérique
    */
   @CheckReturnValue
   public static Duration parse(String str) throws ParseException {
      // the sum of all time (quantity, unit) pairs
      Duration sum = Duration.ZERO;
    
      if(str == null || str.isEmpty()) {
         return sum; // duh.
      }
    
      // in the case you want to write your quantities in base 2.
      // note that radix > 10 will collide with a- unit suffixes.
      final int radix = 10;
    
      char c = str.charAt(0);
      int digit = Character.digit(c, radix);
    
      if(digit < 0) {
         throw new ParseException("Expecting a digit, got a character", 0);
      }
    
      // the current time quantity
      int value = digit;
    
      // the current time unit
      StringBuilder suffix = new StringBuilder();
    
      for(int i = 1; i < str.length(); ++i) {
         c = str.charAt(i);
         digit = Character.digit(c, radix);
       
         if(digit >= 0) {
            // if we got a digit after some characters,
            // push the current (quantity, unit) to the sum
            if(suffix.length() != 0) {
               sum = pushTemporalPair(sum, value, suffix, i);
             
               value = digit;
               suffix.setLength(0);
            }
            else {
               // else add the current digit to the current quantity
               value = Math.addExact(Math.multiplyExact(value, radix), digit);
            }
         }
         else {
            // we got a non-digit character
            suffix.append(c);
         }
      }
    
      if(suffix.length() != 0) {
         // push the last (quantity, unit) pair
         sum = pushTemporalPair(sum, value, suffix, str.length());
      }
      else if(value != 0) {
         throw new ParseException("Got " + value + " without a time unit.", str.length());
      }
    
      return sum;
   }
 
   @CheckReturnValue
   private static TemporalAmount parseTemporalUnit(int value, @NotNull String suffix, int offset) throws ParseException {
      var converter = UNITS.get(suffix);
      if(converter == null) {
         throw new ParseException("Unknown time unit: " + suffix, offset - suffix.length());
      }
    
      return converter.apply(value);
   }
 
   @CheckReturnValue
   private static Duration pushTemporalPair(@NotNull Duration sum, int value, @NotNull StringBuilder suffix, int offset) throws ParseException {
      return sum.plus(Duration.from(parseTemporalUnit(value, suffix.toString(), offset)));
   }
}

L'idée consiste simplement à mettre tous les suffixes dans un tableau qui associe à chaque suffixe une fonction qui convertit le nombre avec une certaine unité (minutes, heures, etc.) en une TemporalAmount — typiquement des nanosecondes.

La fonction de conversion lit la chaîne caractère par caractère, en commençant avec une durée S = 0, puis en détectant les transitions chiffres et non-chiffres ; pour « 12min306s » elle lira 12 et « min », en lisant le chiffre suivant 3 elle remarquera qu'elle a déjà un couple (nombre, unité) non-nul, donc elle convertira (12, min) en 12 minutes, calculera S = S + 12 minutes, réinitialisera le couple à (0, <mot vide>), mettra le nombre qu'elle est en train de lire dedans, puis continuera de parcourir la chaîne de caractères avec une durée S = 12 minutes, et un couple en construction (3, <mot vide>).

À la fin le programme se retrouve avec S = 12 minutes et un couple (306, s), qu'il reconvertit en durée, calcule S = S + 306 secondes, puis renvoit le résultat de 17 minutes et 6 secondes.

Tu me diras si ça marche, je n'ai pas vraiment essayé.

Cordialement,
ShE3py
Salut, je te remercie j'vais essayer ça et surtout essayer de bien tout comprendre encore une fois merci beaucoup ;)