gpt4 book ai didi

java - 使用计时器删除 ListenerAdapter

转载 作者:行者123 更新时间:2023-11-30 10:01:50 24 4
gpt4 key购买 nike

所以我有以下问题,我想在文本 channel 上制作一个迷你游戏,问题是,我想创建某种超时,这样人们就不会创建多个只会使机器人。我用来加载我的游戏事件的命令(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); 这样的事情。

最佳答案

您的问题是您的this 引用了最近的类声明。在这种情况下,这是由您的 new TimeTask() { ... 创建的匿名类。要引用实际注册为监听器的外部类,您必须改用 MinigameEvent.this

Read More

我强烈建议使用没有此问题的 lambda 表达式。另一件需要注意的事情是您使用计时器会导致线程泄漏,因为它们永远不会被您的代码关闭 ( How to cleanup a timer )。更好的是使用单个 ScheduledExecutorService您应该重新使用它来安排您需要的一切,而不是为每个任务创建一个新的。一旦您的进程结束,它就可以关闭(就像 JDA 中的 onShutdown 事件,它在调用 shutdown() 时触发)。

关于java - 使用计时器删除 ListenerAdapter,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57262823/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com