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
相关产品推荐
相关产品推荐

