【发布时间】:2019-12-07 07:46:45
【问题描述】:
所以我有以下问题,我想在文本频道上制作一个小游戏,问题是,我想创建某种超时,这样人们就不会创建多个“listenerAdapter”实例,这只会使机器人。 我用来加载我的游戏事件的命令(ListenerAdapter 如下)。
@Override
public void handle(List<String> args, GuildMessageReceivedEvent event) {
// TODO Auto-generated method stub
TextChannel channel = event.getChannel();
channel.sendMessage("please type \"joingame\" to join! ").queue();
event.getJDA().addEventListener(new MinigameEvent(channel, event.getAuthor(), event));
}
那么,我用来加载玩家的代码如下:
public class MinigameEvent extends ListenerAdapter {
private final long channelId, authorId;
private final int players=3;
private ArraySet<User> users;
private String textMsg;
private Message target;
private GuildMessageReceivedEvent outTimerEvent;
private boolean cancelEvent;
public MinigameEvent(MessageChannel channel, User author, GuildMessageReceivedEvent outTimerEvent) {
this.channelId = channel.getIdLong();
this.authorId = author.getIdLong();
this.outTimerEvent=outTimerEvent;
cancelEvent=false;
this.timeOut(channel);
users=new ArraySet<User>();
users.add(author);
textMsg=("registered users: "+author.getName());
channel.sendMessage(textMsg).queue((new Consumer<Message>()
{
@Override
public void accept(Message t)
{
target = t;
}
}));
}
@Override
public void onMessageReceived(MessageReceivedEvent event) {
if(event.getAuthor().isBot()) {
return;
}
//not respond on other channels
if (event.getChannel().getIdLong() != channelId) {
return;
}
MessageChannel channel = event.getChannel();
String content = event.getMessage().getContentRaw();
if(content.equalsIgnoreCase("joingame")) {
users.add(event.getAuthor());
textMsg=textMsg+", "+event.getAuthor().getName();
target.editMessage(textMsg).queue();
if(users.size()==players) {
event.getChannel().sendMessage("starting").queue();
event.getJDA().removeEventListener(this);
}
}
if(content.equalsIgnoreCase("cancel") && event.getAuthor().getIdLong()==authorId) {
cancelEvent=true;
event.getJDA().removeEventListener(this);
event.getChannel().sendMessage("this game has been canceled").queue();
}
}
private void timeOut(MessageChannel channel) {
Timer timer = new Timer();
TimerTask cooldown = new TimerTask() {
@Override
public void run() {
if(cancelEvent) {
return;
}
if(users.size()<players) {
outTimerEvent.getJDA().removeEventListener(this);
try {
destroyEvent();
} catch (Throwable e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
channel.sendMessage("not enough players, the game has been cancelled").queue();
}else {
return;
}
}
};
timer.schedule(cooldown, 10000L);
}
private void destroyEvent() throws Throwable {
this.finalize();
}
}
当我到达 3 个人时,侦听器适配器停止按预期工作,当事件的作者(使用 !minigame 命令的人)类型取消时也是如此。但是当计时器关闭时,它会发送消息表明游戏已取消,但侦听器适配器仍在运行,如果有人尝试加入,它将允许他这样做。
我目前通过使用 finalize 方法解决了这个问题,但我认为你可以做一些类似 event.getJDA().removeEventListener(this); 的事情。
【问题讨论】:
-
你为什么不能写它,这样你就可以创建一个Listener类的单例。所以第一次实例化时,它会创建一个静态单例。然后后续调用将返回相同的实例。
-
@WJS 我可能会调查,但问题是,它必须适用于不同的服务器,因此可能需要多个实例
标签: java discord-jda