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

Spigot插件事件类无法读取命令类HashSet存储数据问题

问题根因

你在事件监听器类里手动new HashCommand()创建了一个全新的HashCommand实例,这个实例和你注册命令时传给Spigot的HashCommand实例是完全独立的两个对象,各自持有自己的HashSet<UUID> players集合:

  • 执行开关命令时,修改的是注册命令用的那个HashCommand实例里的集合数据
  • 玩家钓鱼触发事件时,读取的是监听器内部自己new出来的新HashCommand实例里的集合,这个集合从初始化开始就没有存入任何玩家数据,自然判断永远返回false,固定走else分支
    你之前尝试的修改存储字段类型、调整判断逻辑、改写HashSet初始化写法都没有触碰到问题核心,和这些操作无关。
修复方案

不要在监听器内部新建HashCommand实例,把注册命令时用到的同一个HashCommand实例传入监听器,保证两边操作的是同一个集合。更规范的实现是将玩家状态存储逻辑从命令类中抽离,降低代码耦合。

修正后代码

主类注册逻辑(你之前未贴出该部分,给出参考实现)

@Override
public void onEnable() {
    // 整个插件生命周期只实例化一次命令类
    HashCommand hashCommand = new HashCommand();
    // 注册命令时使用该实例
    getCommand("你的功能命令名").setExecutor(hashCommand);
    // 将同一个实例传入监听器,再注册监听器
    getServer().getPluginManager().registerEvents(new FishListener(hashCommand), this);
}

注意:原监听器类名Event和Java/Bukkit内置类重名,极易导包错误,这里改名为语义更清晰的FishListener

修正后的命令类

import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import java.util.HashSet;
import java.util.UUID;

public class HashCommand implements CommandExecutor {
    // 集合设为私有,禁止外部类直接修改
    private final HashSet<UUID> enabledPlayers = new HashSet<>();

    // 对外提供玩家状态判断方法
    public boolean isPlayerEnabled(Player player) {
        return enabledPlayers.contains(player.getUniqueId());
    }

    // 对外提供状态切换方法
    public boolean togglePlayerState(Player player) {
        UUID playerUuid = player.getUniqueId();
        if (enabledPlayers.contains(playerUuid)) {
            enabledPlayers.remove(playerUuid);
            return false;
        }
        enabledPlayers.add(playerUuid);
        return true;
    }

    @Override
    public boolean onCommand(CommandSender sender, Command command, String label, String[] args) {
        if (!(sender instanceof Player)) {
            sender.sendMessage("仅玩家可执行此命令");
            return true;
        }
        Player player = (Player) sender;
        boolean currentState = togglePlayerState(player);
        player.sendMessage(currentState ? "§a功能已开启" : "§c功能已关闭");
        return true;
    }
}

修正后的监听器类

import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerFishEvent;

public class FishListener implements Listener {
    private final HashCommand hashCommand;

    // 构造方法接收外部传入的命令类实例,不自己新建
    public FishListener(HashCommand hashCommand) {
        this.hashCommand = hashCommand;
    }

    @EventHandler
    public void onPlayerCastRod(PlayerFishEvent event) {
        Player player = event.getPlayer();
        if (hashCommand.isPlayerEnabled(player)) {
            player.sendMessage("§a成功触发钓鱼功能");
            return;
        }
        player.sendMessage("§c你未开启该功能,请先执行开关命令开启");
    }
}

额外注意点

  • 命令执行完成后按Spigot开发规范应返回true,你之前代码返回false会让服务端自动向命令发送者输出命令的usage帮助信息,属于逻辑错误
  • 不要用public修饰存储核心数据的集合字段,避免其他类误修改集合内容引发难以排查的bug,通过公开方法做访问控制更安全
  • 如果后续功能迭代,建议把玩家状态存储逻辑单独抽成一个独立的管理类,不需要依赖命令类实例传递数据,代码耦合度更低

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:45:07