You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spigot 1.19中PlayerJoinEvent封禁玩家踢人逻辑失效问题求助

问题分析与修复方案

核心问题点

  • 条件分支逻辑错误:前两个if/else if已覆盖所有玩家情况(首次加入/非首次加入),导致封禁判断的分支永远不会执行。
  • MongoDB查询条件错误:用Player对象作为查询条件,而数据库中存储的是玩家名字字符串,无法匹配到目标数据。
  • 资源泄漏:每次触发事件都新建MongoClient,会快速耗尽数据库连接资源。
  • 封禁状态判断脱节:依赖Bukkit内置的isBanned(),但自定义封禁数据存在MongoDB中,两者状态可能不同步。

修复后的代码

package xyz.foresthosting.testplugin.events;

import com.mongodb.client.MongoCollection;
import org.bson.Document;
import xyz.foresthosting.testplugin.TestPlugin;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerJoinEvent;

public class PlayerJoin implements Listener {
    private final TestPlugin plugin;
    private final MongoCollection<Document> bansCollection;

    // 构造函数传入预初始化的Mongo集合,避免重复创建连接
    public PlayerJoin(TestPlugin plugin, MongoCollection<Document> bansCollection) {
        this.plugin = plugin;
        this.bansCollection = bansCollection;
    }

    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        String playerName = player.getName();

        // 优先检查封禁记录
        Document banRecord = bansCollection.find(new Document("name", playerName)).first();
        if (banRecord != null) {
            String staff = banRecord.getString("staff");
            String reason = banRecord.getString("reason");
            // 执行踢人并终止后续逻辑
            player.kickPlayer(ChatColor.RED + "你已被服务器封禁!\n原因: " + reason + "\n执行人员: " + staff);
            event.setJoinMessage(null);
            return;
        }

        // 处理欢迎消息逻辑
        if (!player.hasPlayedBefore()) {
            event.setJoinMessage(ChatColor.GREEN + "欢迎加入服务器 " + playerName + "!祝你游戏愉快。");
        } else {
            event.setJoinMessage(ChatColor.GREEN + "欢迎回来 " + playerName + "!");
        }
    }
}

额外优化建议

  1. 复用MongoDB连接:在插件主类中仅初始化一次MongoClient和集合,通过构造函数传递给监听器:
    // 主类示例代码
    private MongoCollection<Document> bansCollection;
    
    @Override
    public void onEnable() {
        // 初始化MongoDB连接(仅执行一次)
        MongoClient mongoClient = new MongoClient("mongodb://admin:<nopasswordforyou>@185.209.223.136:2002");
        MongoDatabase database = mongoClient.getDatabase("test");
        this.bansCollection = database.getCollection("bans");
        // 注册监听器时传入集合实例
        getServer().getPluginManager().registerEvents(new PlayerJoin(this, bansCollection), this);
    }
    
  2. 异步处理数据库查询:数据库操作属于阻塞操作,建议用Bukkit异步任务执行,避免卡住服务器主线程:
    plugin.getServer().getScheduler().runTaskAsynchronously(plugin, () -> {
        Document banRecord = bansCollection.find(new Document("name", playerName)).first();
        // 踢人、消息设置必须回到主线程执行
        plugin.getServer().getScheduler().runTask(plugin, () -> {
            if (banRecord != null) {
                String staff = banRecord.getString("staff");
                String reason = banRecord.getString("reason");
                player.kickPlayer(ChatColor.RED + "你已被服务器封禁!\n原因: " + reason + "\n执行人员: " + staff);
                event.setJoinMessage(null);
            } else {
                if (!player.hasPlayedBefore()) {
                    event.setJoinMessage(ChatColor.GREEN + "欢迎加入服务器 " + playerName + "!祝你游戏愉快。");
                } else {
                    event.setJoinMessage(ChatColor.GREEN + "欢迎回来 " + playerName + "!");
                }
            }
        });
    });
    
  3. 添加异常捕获:给MongoDB操作增加异常处理,避免插件因数据库连接失败而崩溃。

内容的提问来源于stack exchange,提问作者Knife worm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:14:55