package org.branulf.playertime; import com.google.gson.*; import net.fabricmc.api.EnvType; import net.fabricmc.loader.api.FabricLoader; import java.io.*; import java.nio.file.*; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class ModConfig { public static final Gson GSON = new GsonBuilder().setPrettyPrinting().create(); public final Path configPath; // 配置项 public int webPort = 60048; public String language = "zh_cn"; public static boolean whitelistOnly = true; // 默认只记录白名单玩家 public int saveIntervalMinutes = 5; // 默认每5分钟保存一次 public ModConfig(Path configDir) throws IOException { if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { this.configPath = configDir.resolve("config").resolve("playertime-config.json"); } else { this.configPath = configDir.resolve("playertime-config.json"); } if (!Files.exists(this.configPath.getParent())) { Files.createDirectories(this.configPath.getParent()); } loadConfig(); } // 加载配置 public void loadConfig() { if (!Files.exists(configPath)) { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件未找到,正在创建默认配置: {}", configPath); saveConfig(); // 创建默认配置并保存 return; } try (Reader reader = Files.newBufferedReader(configPath)) { JsonElement jsonElement = JsonParser.parseReader(reader); if (jsonElement == null || !jsonElement.isJsonObject()) { PlayerTimeMod.LOGGER.warn("[在线时间] 配置文件为空或格式错误,正在使用默认配置并覆盖: {}", configPath); saveConfig(); // 使用默认配置并覆盖 return; } JsonObject json = jsonElement.getAsJsonObject(); // 读取 webPort if (json.has("webPort") && json.get("webPort").isJsonPrimitive() && json.get("webPort").getAsJsonPrimitive().isNumber()) { webPort = json.get("webPort").getAsInt(); if (webPort < 1 || webPort > 65535) { PlayerTimeMod.LOGGER.warn("[在线时间] 配置文件中的 webPort ({}) 无效,使用默认值 {}", webPort, 60048); webPort = 60048; } } else { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少或 webPort 格式错误,使用默认值 {}", webPort); // 不立即保存,等待所有字段读取完毕再决定是否保存 } // 读取 language if (json.has("language") && json.get("language").isJsonPrimitive() && json.get("language").getAsJsonPrimitive().isString()) { language = json.get("language").getAsString(); } else { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少或 language 格式错误,使用默认值 {}", language); } // 读取 whitelistOnly if (json.has("whitelistOnly") && json.get("whitelistOnly").isJsonPrimitive() && json.get("whitelistOnly").getAsJsonPrimitive().isBoolean()) { whitelistOnly = json.get("whitelistOnly").getAsBoolean(); } else { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少或 whitelistOnly 格式错误,使用默认值 {}", whitelistOnly); } // 读取 saveIntervalMinutes if (json.has("saveIntervalMinutes") && json.get("saveIntervalMinutes").isJsonPrimitive() && json.get("saveIntervalMinutes").getAsJsonPrimitive().isNumber()) { saveIntervalMinutes = json.get("saveIntervalMinutes").getAsInt(); if (saveIntervalMinutes < 0) { PlayerTimeMod.LOGGER.warn("[在线时间] 配置文件中的 saveIntervalMinutes ({}) 无效,使用默认值 {}", saveIntervalMinutes, 5); saveIntervalMinutes = 5; } } else { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少或 saveIntervalMinutes 格式错误,使用默认值 {}", saveIntervalMinutes); } // 检查是否有新字段需要添加到配置文件 if (!json.has("webPort") || !json.has("language") || !json.has("whitelistOnly") || !json.has("saveIntervalMinutes")) { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件缺少部分字段,正在添加并保存。"); saveConfig(); // 保存以添加新字段 } else { PlayerTimeMod.LOGGER.info("[在线时间] 配置文件加载成功: {}", configPath); } } catch (IOException e) { PlayerTimeMod.LOGGER.error("[在线时间] 无法读取配置文件 {},使用默认配置", configPath, e); saveConfig(); // 发生IO错误,尝试保存默认配置 } catch (JsonParseException e) { PlayerTimeMod.LOGGER.error("[在线时间] 配置文件 {} 格式错误,使用默认配置", configPath, e); saveConfig(); // 发生JSON解析错误,尝试保存默认配置 } catch (Exception e) { PlayerTimeMod.LOGGER.error("[在线时间] 加载配置文件 {} 时发生未知错误,使用默认配置", configPath, e); saveConfig(); // 发生未知错误,尝试保存默认配置 } } // 保存配置 public void saveConfig() { JsonObject json = new JsonObject(); json.addProperty("webPort", webPort); json.addProperty("language", language); json.addProperty("whitelistOnly", whitelistOnly); json.addProperty("saveIntervalMinutes", saveIntervalMinutes); try { Files.createDirectories(configPath.getParent()); try (Writer writer = Files.newBufferedWriter(configPath)) { GSON.toJson(json, writer); } PlayerTimeMod.LOGGER.info("[在线时间] 配置已成功保存到 {}", configPath); } catch (Exception e) { PlayerTimeMod.LOGGER.error("[在线时间] 保存配置失败到 {}", configPath, e); } notifyConfigChanged(); } // 获取端口 public int getWebPort() { return webPort; } // 获取语言 public String getLanguage() { if (FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT) { try { net.minecraft.client.MinecraftClient client = net.minecraft.client.MinecraftClient.getInstance(); if (client != null) { String clientLang = client.options.language; if (clientLang != null && !clientLang.isEmpty()) { return clientLang; } } } catch (Exception e) { PlayerTimeMod.LOGGER.warn("[在线时间] 无法获取客户端语言,使用配置值", e); } } return language; } // 获取是否只记录白名单 public boolean isWhitelistOnly() { return whitelistOnly; } // 获取保存间隔(分钟) public int getSaveIntervalMinutes() { return saveIntervalMinutes; } private static final List listeners = new CopyOnWriteArrayList<>(); public interface ConfigChangeListener { void onConfigChanged(ModConfig config); } public static void addChangeListener(ConfigChangeListener listener) { listeners.add(listener); } private void notifyConfigChanged() { for (ConfigChangeListener listener : listeners) { listener.onConfigChanged(this); } } }