Bukkit / Spigot API - https://hub.spigotmc.org/javadocs/spigot/
好的,我正在尝试为我的服务器制作教程系统。我经常看到人们显示这样的文字:
public void send(String...strings) {
for (String string : strings) {
player.sendMessage(string);
}
}
..这太可怕了。如您所知,它会对聊天进行垃圾邮件并使其无法读取 因此,我使用runnables以一定的延迟显示文本。我可以轻松地使用相同的特定延迟(即30个滴答)进行运行,但我喜欢runnable基于String的length()进行延迟。
我试着这样做:
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
在runnable显示文本之前继续到下一个字符串。
所以如果我有这些句子(按照正确的顺序):
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 :(得分:1)
您可能需要考虑使用单个对象(即Singleton)作为打印机来打印所有消息。这样可以避免创建过多的线程。
下面的解决方案使用BlockingQueue以使打印线程等待下一条消息。当消息不在队列中时 - run()方法将等待而不会消耗太多CPU。
解决方案有两种形式: - 如果你取消注释第一个msgQueue - 你将获得sendMessage的阻塞行为;该方法将一直等到所有项目都打印出来。 - 如果您推荐第二个msgQueue - 消息将被添加到队列中而无需等待打印。
我添加了ExecutorService来管理Thread,因为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();
}
}
}
答案 1 :(得分: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!");
答案 2 :(得分:0)
也许只是这样:
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;
}
}
通过这种方式,每条消息都会被之前计算的所有延迟所困扰。
注意:尚未经过测试