2016-10-21 4 views
2
  • Bukkit/Патрубок API - https://hub.spigotmc.org/javadocs/spigot/
    Хорошо, что я пытаюсь сделать систему учебник для моего сервера. Я часто видел людей, отображающих текст следующим образом:Перебор текста с различной задержкой длины между ними

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

    .., который ужасно. Как вы знаете, это рассылает чат и делает его нечитаемым.
    Так что вместо этого я использую runnables для отображения текста с определенной задержкой. Я мог бы легко сделать runnable с той же определенной задержкой (т. Е. 30 тиков), но мне бы хотелось, чтобы runnable имел задержку, основанную на length() String.

    Я попытался сделать это следующим образом:

    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)); 
        } 
    } 
    

    С этим, да, она принимает длину строки, но for loop продолжается до следующей строки перед работоспособным проявившей текст.
    Так что если у меня были эти предложения, например (в правильном порядке):

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


    заказ будет

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

    Что я должен делать?

ответ

0

Ну, никто не ответил .. Закончился сам решить, но я не горжусь этим кодом. Пришлось использовать 2 runnables ..
Если кто-то заинтересован, я оставлю код здесь.

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); 
} 

Это может быть использован следующим образом, в качестве примера:
send(player, 30, "&a", "Welcome to %s, %p!", "Enter the stuff you want to show here!", "They're all in the right order!");

1

Вы можете рассмотреть вопрос о проведении одного отдельного объекта (т.е. Singleton.), Который действует как принтер для печати всех сообщений. Это позволит избежать слишком большого количества потоков.

В приведенном ниже решении используется BlockingQueue, чтобы поток печати ожидал следующего сообщения. Когда сообщение не находится в очереди, метод run() будет ждать, не потребляя много CPU.

Решение поставляется в двух вариантах: - если вы раскомментируете первый msgQueue - вы получите блокирующее поведение sendMessage; метод будет ждать, пока все элементы будут напечатаны. - если вы не одобряете второй msgQueue - сообщения будут добавлены в очередь, не ожидая печати.

Я добавил ExecutorService для управления потоком, поскольку Oracle/Java видит это как хорошую практику для управления потоками с помощью ExecutorServices. Как только MessagePrinter не нужен - ему сигнализирует «executor.shutdownNow();» и заканчивается мирно.

Надеюсь, это поможет.

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

Может быть просто STH так:

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; 
    } 
} 

таким образом, каждое сообщение получает dalayed всех задержек, рассчитанные ранее.

Внимание: это еще не проверено