2016-10-21 1 views
2
  • Bukkit/API Spigot - https://hub.spigotmc.org/javadocs/spigot/
    D'accord, je suis en train de faire un système de tutoriel pour mon serveur. J'ai souvent vu des gens affichant un texte comme celui-ci:par texte avec Itération un retard de longueur différente entre les

    public void send(String...strings) { 
        for (String string : strings) { 
         player.sendMessage(string); 
        } 
    } 
    

    .. ce qui est terrible. Comme vous le savez, il serait spammer le chat et le rendre illisible.
    Donc, à la place, j'utilise des runnables pour afficher le texte dans un certain délai. Je pourrais facilement faire un runnable avec le même delay spécifique (c'est-à-dire 30 ticks), mais j'aimerais que le runnable ait le delay basé sur la longueur() de la String.

    J'ai essayé de le faire comme ceci:

    public void send(String...strings) { 
        for (String string : strings) { 
         new BukkitRunnable() { 
          @Override 
          public void run() { 
           player.sendMessage(string); 
          } 
         }.runTaskLater(my_plugin_instance, (string.length()*2)); 
        } 
    } 
    

    Avec cela, oui, il prend la longueur de la chaîne, mais le for loop continue à la chaîne suivante avant la runnable a affiché le texte.
    Donc, si j'avais ces phrases par exemple (dans l'ordre):

    • Welcome to the server, player!
    • This server is about blablabla, this and that and a bit more of that and this
    • Accept the tutorial?


    L'ordre sera

    • Accept the tutorial?
    • Welcome to the server, player!
    • This server is about blablabla, this and that and a bit more of that and this

    Que dois-je faire?

Répondre

0

Eh bien, personne n'a répondu .. J'ai fini par le résoudre moi-même, mais je ne suis pas fier du code. J'ai dû utiliser 2 runnables ..
Si quelqu'un est intéressé, je vais laisser le code ici.

public void send(Player player, long delay, String basecolor, String... strings) { 
    List<String> str = Arrays.asList(strings); 
    new BukkitRunnable() { 
     int ind = 0; 
     boolean next = true; 
     @Override 
     public void run() { 
      String s = str.get(ind); 
      if (next) { 
       next = false; 
       Bukkit.getScheduler().runTaskLater(YOUR_PLUGIN_INSTANCE, new Runnable() { 
        @Override 
        public void run() { 
          player.sendMessage(ChatColor.translateAlternateColorCodes('&', 
            basecolor + s.replace("%p", player.getName()).replace("%s", server_name))); 
         next = true; 
        } 
       }, (ind == 0 ? 0 : (str.get(ind - 1).length()))); 
       if (ind + 1 < str.size()) { 
        ind++; 
       } else { 
        cancel(); 
       } 
      } 
     } 
    }.runTaskTimer(YOUR_PLUGIN_INSTANCE, delay, 10); 
} 

Cela pourrait être utilisé comme suit, à titre d'exemple:
send(player, 30, "&a", "Welcome to %s, %p!", "Enter the stuff you want to show here!", "They're all in the right order!");

1

Vous voudrez peut-être envisager d'avoir un seul objet (par exemple Singleton.) Qui agit comme une imprimante pour imprimer tous les messages. Cela évitera de créer trop de threads.

La solution ci-dessous utilise BlockingQueue pour que le thread d'impression attende le message suivant. Lorsque le message n'est pas dans la file d'attente, la méthode run() attendra sans consommer beaucoup de CPU.

La solution est disponible en deux versions: - si vous décommentez d'abord msgQueue - vous obtiendrez un comportement de blocage de sendMessage; la méthode attendra que tous les éléments soient imprimés. - Si vous ne souhaitez pas utiliser msgQueue, les messages seront ajoutés à la file d'attente sans attendre l'impression.

J'ai ajouté ExecutorService pour gérer Thread comme Oracle/Java voit cela comme une bonne pratique pour gérer les threads en utilisant ExecutorServices. Une fois MessagePrinter n'est pas nécessaire - il est signalé par "executor.shutdownNow();" et finit paisiblement.

Espérons que cela aide.

package stackoverflow; 

import java.util.Arrays; 
import java.util.concurrent.BlockingQueue; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.LinkedBlockingQueue; 
import java.util.concurrent.TimeUnit; 

class MessagePrinter implements Runnable { 

    private static MessagePrinter instance; 
    private MessagePrinter() {}; 

    // Uncomment the one below to make sendText wait until methods until all items are printed: 
    // BlockingQueue<String> msgQueue = new LinkedBlockingQueue<>(1); 

    // Uncomment the one below to make sendText not wait until messages are printed: 
    BlockingQueue<String> msgQueue = new LinkedBlockingQueue<>(1); 

    public void run() { 
     try { 
      while (true) { 
       String str = msgQueue.take(); 
       Thread.sleep(str.length()); 
       TimeUnit.MILLISECONDS.sleep(str.length() * 10); 

       System.out.println(str); 
      } 
     } catch (InterruptedException e) { 
      System.out.println("Quitting..."); 
      return; 
     } 
    } 

    public void sendText(String... txt) { 
     Arrays.asList(txt).stream().forEach(t -> { 
      try { 
       msgQueue.put(t); 
      } catch (InterruptedException e) { 
       // Received request to terminate. 
       return; 
      } 
     }); 
    } 

    synchronized public static MessagePrinter getInstance() { 
     if (instance == null) 
      instance = new MessagePrinter(); 
     return instance; 
    } 
} 

public class VarDelay { 

    public static void main(String[] args) throws InterruptedException { 
     ExecutorService executor = Executors.newSingleThreadExecutor(); 
     MessagePrinter msp = MessagePrinter.getInstance(); 

     executor.submit(msp); 

     msp.sendText(new String[] {"Welcome to the server, player!", 
       "This server is about blablabla, this and that and a bit more of that and this", 
       "Accept the tutorial?" }); 

     msp.sendText("More text to follow"); 

     // Shutdown: 
     executor.shutdown(); 
     if (!executor.awaitTermination(2, TimeUnit.SECONDS)) { 
      executor.shutdownNow(); 
     } 
    } 
} 
0

Peut-être simplement qc comme ceci:

private void send(final Player player, String...messages) { 

    long delaySum = 0; 

    for (final String message : messages) { 
     Runnable myTask = new Runnable() { 
      public void run() { 
       player.sendMessage(message); 
      } 
     }; 

     this.getServer().getScheduler().runTaskLater(this, myTask, delaySum); 
     delaySum += message.length() * 2; 
    } 
} 

cette façon, chaque message est dalayed par tous les retards calculés avant.

Attention: Ceci n'a pas été testé