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

如何将存储Player与Integer的HashMap持久化到文件中

解决玩家计时器数据持久化问题

首先要明确:不能直接存储Player对象,因为它是服务器运行时的实例,无法被序列化保存,重启后会失效。我们需要用玩家的UUID作为唯一标识来存储数据,先修改你的Map:

// 把原来的Player键换成UUID
public static Map<UUID, Integer> playerSeconds = new HashMap<>();

下面用Bukkit自带的YAML文件实现数据的保存与加载,无需额外依赖,适合新手:

1. 核心工具方法(写在插件主类中)

加载所有玩家数据

在插件启用时调用,从文件读取数据到Map:

public void loadPlayerTimes() {
    // 数据文件存放在插件的数据文件夹下,比如 plugins/你的插件名/player_times.yml
    File dataFile = new File(getDataFolder(), "player_times.yml");
    
    // 如果文件夹或文件不存在,先创建
    if (!dataFile.exists()) {
        try {
            getDataFolder().mkdirs(); // 创建插件数据目录
            dataFile.createNewFile(); // 创建空文件
        } catch (IOException e) {
            getLogger().severe("创建数据文件失败: " + e.getMessage());
            e.printStackTrace();
        }
        return;
    }

    // 加载YAML配置
    YamlConfiguration config = YamlConfiguration.loadConfiguration(dataFile);
    // 遍历所有存储的UUID,转换后存入Map
    for (String uuidStr : config.getKeys(false)) {
        try {
            UUID uuid = UUID.fromString(uuidStr);
            int seconds = config.getInt(uuidStr);
            playerSeconds.put(uuid, seconds);
        } catch (IllegalArgumentException e) {
            getLogger().warning("无效的UUID格式: " + uuidStr);
        }
    }
}

保存单个玩家数据

玩家退出时调用,保存该玩家的计时器数值:

public void savePlayerTime(Player player) {
    UUID uuid = player.getUniqueId();
    Integer seconds = playerSeconds.get(uuid);
    if (seconds == null) return; // 无数据则跳过

    File dataFile = new File(getDataFolder(), "player_times.yml");
    YamlConfiguration config = YamlConfiguration.loadConfiguration(dataFile);
    
    // 将UUID转为字符串作为键,存储数值
    config.set(uuid.toString(), seconds);
    try {
        config.save(dataFile);
    } catch (IOException e) {
        getLogger().severe("保存玩家 " + player.getName() + " 的数据失败: " + e.getMessage());
        e.printStackTrace();
    }
}

保存所有玩家数据

插件关闭时调用,防止遗漏未退出玩家的数据:

public void saveAllPlayerTimes() {
    File dataFile = new File(getDataFolder(), "player_times.yml");
    YamlConfiguration config = YamlConfiguration.loadConfiguration(dataFile);
    
    // 遍历Map,批量写入所有数据
    for (Map.Entry<UUID, Integer> entry : playerSeconds.entrySet()) {
        config.set(entry.getKey().toString(), entry.getValue());
    }
    try {
        config.save(dataFile);
    } catch (IOException e) {
        getLogger().severe("保存所有玩家数据失败: " + e.getMessage());
        e.printStackTrace();
    }
}

2. 注册事件监听,处理玩家加入/退出

让你的插件主类实现Listener接口,然后注册事件并编写处理逻辑:

public class YourPlugin extends JavaPlugin implements Listener {

    public static Map<UUID, Integer> playerSeconds = new HashMap<>();

    @Override
    public void onEnable() {
        // 插件启用时加载数据
        loadPlayerTimes();
        // 注册事件监听器
        getServer().getPluginManager().registerEvents(this, this);
        getLogger().info("插件已启用,数据加载完成");
    }

    @Override
    public void onDisable() {
        // 插件关闭时保存所有数据
        saveAllPlayerTimes();
        getLogger().info("插件已关闭,数据保存完成");
    }

    // 玩家加入服务器时触发
    @EventHandler
    public void onPlayerJoin(PlayerJoinEvent event) {
        Player player = event.getPlayer();
        UUID uuid = player.getUniqueId();
        
        // 如果玩家是第一次加入,默认设置计时器为0(可根据需求修改)
        playerSeconds.putIfAbsent(uuid, 0);
        
        // 可以给玩家发送提示
        player.sendMessage("欢迎回来!你的计时器剩余 " + playerSeconds.get(uuid) + " 秒");
    }

    // 玩家退出服务器时触发
    @EventHandler
    public void onPlayerQuit(PlayerQuitEvent event) {
        Player player = event.getPlayer();
        // 保存该玩家的数据
        savePlayerTime(player);
        // 从Map中移除,节省内存
        playerSeconds.remove(player.getUniqueId());
    }

    // 上面的loadPlayerTimes、savePlayerTime、saveAllPlayerTimes方法放在这里
}

3. 替换原有代码中的Map使用方式

原来你操作seconds的地方,都要改成用UUID来访问:

// 示例:给玩家设置计时器数值
playerSeconds.put(player.getUniqueId(), 120);

// 示例:获取玩家当前计时器数值
int currentTime = playerSeconds.getOrDefault(player.getUniqueId(), 0);

注意事项

  • 确保你的插件主类继承了JavaPlugin,事件方法上的@EventHandler注解不要忘记,否则事件不会触发。
  • 数据文件会自动生成在服务器目录/plugins/你的插件名/player_times.yml,可以直接打开查看或修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:57:47