package cn.infstar.essentialsC.maintenance; import cn.infstar.essentialsC.EssentialsC; import cn.infstar.essentialsC.util.AtomicYamlWriter; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.boss.BarColor; import org.bukkit.boss.BarStyle; import org.bukkit.boss.BossBar; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Player; import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer; import java.io.File; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; import java.util.Locale; import java.util.Set; import java.util.UUID; public final class MaintenanceManager { private static final int CURRENT_CONFIG_VERSION = 1; private final EssentialsC plugin; private final File configFile; private FileConfiguration config; private BossBar bossBar; public MaintenanceManager(EssentialsC plugin) { this.plugin = plugin; this.configFile = new File(plugin.getDataFolder(), "maintenance.yml"); reload(); } public void reload() { if (!configFile.exists()) { plugin.saveResource("maintenance.yml", false); } config = YamlConfiguration.loadConfiguration(configFile); config.addDefault("config-version", CURRENT_CONFIG_VERSION); config.addDefault("enabled", false); config.addDefault("bypass-permission", "essentialsc.maintenance.bypass"); config.addDefault("notify.enabled", true); config.addDefault("notify.permission", "essentialsc.maintenance.notify"); config.addDefault("notify.include-address", false); config.addDefault("whitelist.uuids", List.of()); config.addDefault("whitelist.names", List.of()); config.addDefault("motd.enabled", true); config.addDefault("motd.lines", List.of("&c服务器维护中", "&7请稍后再试")); config.addDefault("kick-message", List.of("&c服务器正在维护", "&7请稍后再进入")); config.addDefault("bossbar.enabled", true); config.addDefault("bossbar.title", "&c服务器正在维护"); config.addDefault("bossbar.color", "RED"); config.addDefault("bossbar.style", "SOLID"); config.addDefault("bossbar.progress", 1.0D); config.options().copyDefaults(true); refreshBossBar(); if (isEnabled()) { kickUnauthorizedPlayers(); } } public boolean isEnabled() { return config.getBoolean("enabled", false); } public OperationResult setEnabled(boolean enabled) { if (isEnabled() == enabled) { return OperationResult.UNCHANGED; } boolean previous = isEnabled(); config.set("enabled", enabled); if (!save()) { config.set("enabled", previous); return OperationResult.SAVE_FAILED; } refreshBossBar(); if (enabled) { kickUnauthorizedPlayers(); } return OperationResult.SUCCESS; } public String getBypassPermission() { return config.getString("bypass-permission", "essentialsc.maintenance.bypass"); } public boolean isNotifyEnabled() { return config.getBoolean("notify.enabled", true); } public String getNotifyPermission() { return config.getString("notify.permission", "essentialsc.maintenance.notify"); } public boolean shouldIncludeAddressInNotification() { return config.getBoolean("notify.include-address", false); } public boolean canJoin(Player player) { return player != null && (player.hasPermission(getBypassPermission()) || isWhitelisted(player)); } public boolean isWhitelisted(Player player) { if (player == null) { return false; } return getWhitelistUuids().contains(player.getUniqueId().toString().toLowerCase(Locale.ROOT)) || getWhitelistNames().contains(normalizeName(player.getName())); } public OperationResult addWhitelistEntry(String input) { String normalized = normalizeEntry(input); if (normalized.isEmpty()) { return OperationResult.UNCHANGED; } UUID uuid = parseUuid(normalized); if (uuid != null) { return addWhitelistUuid(uuid.toString()); } Player onlinePlayer = Bukkit.getPlayerExact(normalized); if (onlinePlayer != null) { return addWhitelistUuid(onlinePlayer.getUniqueId().toString()); } return addWhitelistName(input); } public OperationResult removeWhitelistEntry(String input) { String normalized = normalizeEntry(input); if (normalized.isEmpty()) { return OperationResult.UNCHANGED; } UUID uuid = parseUuid(normalized); if (uuid != null) { return removeWhitelistUuid(uuid.toString()); } Player onlinePlayer = Bukkit.getPlayerExact(normalized); if (onlinePlayer != null) { OperationResult uuidResult = removeWhitelistUuid(onlinePlayer.getUniqueId().toString()); if (uuidResult != OperationResult.UNCHANGED) { return uuidResult; } } return removeWhitelistName(input); } public List getWhitelistEntries() { List entries = new ArrayList<>(); entries.addAll(getWhitelistNames()); entries.addAll(getWhitelistUuids()); return entries; } public int getWhitelistCount() { return getWhitelistEntries().size(); } public boolean isMotdEnabled() { return config.getBoolean("motd.enabled", true); } public String getMotd() { return colorizeLines(config.getStringList("motd.lines")); } public String getKickMessage() { return colorizeLines(config.getStringList("kick-message")); } public void refreshBossBar() { clearBossBar(); if (!isEnabled() || !isBossBarEnabled()) { return; } bossBar = plugin.getServer().createBossBar( colorize(config.getString("bossbar.title", "&c服务器正在维护")), readBossBarColor(), readBossBarStyle() ); bossBar.setProgress(readBossBarProgress()); bossBar.setVisible(true); for (Player player : plugin.getServer().getOnlinePlayers()) { addBossBarPlayer(player); } } public void addBossBarPlayer(Player player) { if (bossBar == null || player == null || !player.isOnline()) { return; } bossBar.addPlayer(player); } public void removeBossBarPlayer(Player player) { if (bossBar != null && player != null) { bossBar.removePlayer(player); } } private void kickUnauthorizedPlayers() { String message = getKickMessage(); for (Player player : List.copyOf(plugin.getServer().getOnlinePlayers())) { if (!canJoin(player)) { player.kick(LegacyComponentSerializer.legacySection().deserialize(message)); } } } public void shutdown() { clearBossBar(); } private void clearBossBar() { if (bossBar == null) { return; } bossBar.removeAll(); bossBar = null; } private boolean isBossBarEnabled() { return config.getBoolean("bossbar.enabled", true); } private BarColor readBossBarColor() { try { return BarColor.valueOf(config.getString("bossbar.color", "RED").toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException ignored) { return BarColor.RED; } } private BarStyle readBossBarStyle() { try { return BarStyle.valueOf(config.getString("bossbar.style", "SOLID").toUpperCase(Locale.ROOT)); } catch (IllegalArgumentException ignored) { return BarStyle.SOLID; } } private double readBossBarProgress() { double progress = config.getDouble("bossbar.progress", 1.0D); if (!Double.isFinite(progress)) { return 1.0D; } return Math.max(0.0D, Math.min(1.0D, progress)); } private OperationResult addWhitelistUuid(String uuid) { return updateWhitelist("whitelist.uuids", uuid.toLowerCase(Locale.ROOT), true); } private OperationResult addWhitelistName(String name) { return updateWhitelist("whitelist.names", normalizeName(name), true); } private OperationResult removeWhitelistUuid(String uuid) { return updateWhitelist("whitelist.uuids", uuid.toLowerCase(Locale.ROOT), false); } private OperationResult removeWhitelistName(String name) { return updateWhitelist("whitelist.names", normalizeName(name), false); } private OperationResult updateWhitelist(String path, String value, boolean add) { if (value == null || value.isBlank()) { return OperationResult.UNCHANGED; } List previousEntries = new ArrayList<>(config.getStringList(path)); Set entries = path.endsWith(".names") ? getWhitelistNames() : getWhitelistUuids(); boolean changed; if (add) { changed = entries.add(value); } else { changed = entries.remove(value); } if (!changed) { return OperationResult.UNCHANGED; } config.set(path, new ArrayList<>(entries)); if (!save()) { config.set(path, previousEntries); return OperationResult.SAVE_FAILED; } refreshBossBar(); if (isEnabled()) { kickUnauthorizedPlayers(); } return OperationResult.SUCCESS; } private Set getWhitelistUuids() { Set entries = new LinkedHashSet<>(); for (String value : config.getStringList("whitelist.uuids")) { String normalized = normalizeEntry(value).toLowerCase(Locale.ROOT); if (!normalized.isEmpty()) { entries.add(normalized); } } return entries; } private Set getWhitelistNames() { Set entries = new LinkedHashSet<>(); for (String value : config.getStringList("whitelist.names")) { String normalized = normalizeName(value); if (!normalized.isEmpty()) { entries.add(normalized); } } return entries; } private UUID parseUuid(String input) { try { return UUID.fromString(input); } catch (IllegalArgumentException ignored) { return null; } } private String normalizeEntry(String input) { return input == null ? "" : input.trim(); } private String normalizeName(String input) { return normalizeEntry(input).toLowerCase(Locale.ROOT); } private String colorizeLines(List lines) { if (lines == null || lines.isEmpty()) { return ""; } return String.join("\n", lines.stream() .map(this::colorize) .toList()); } private String colorize(String text) { return ChatColor.translateAlternateColorCodes('&', text == null ? "" : text); } private boolean save() { try { AtomicYamlWriter.save(config, configFile); return true; } catch (Exception e) { plugin.getLogger().warning("保存 maintenance.yml 失败: " + e.getMessage()); return false; } } public enum OperationResult { SUCCESS, UNCHANGED, SAVE_FAILED } }