Skip to content

Config Manager

Полное руководство по Config Manager: BaseConfig lifecycle, типобезопасный доступ, reload-пайплайн, эволюция YAML и эксплуатация в проде.

Обновлено: 01 янв. 1980 г.Чтение: ~3 мин

Config Manager

Config Manager в NextLib нужен, чтобы работа с YAML была управляемой и предсказуемой в долгоживущем плагине.

1. Зачем нужен этот модуль

Типичный хаос без Config Manager:

  • config.getString(...) разбросан по всему проекту,
  • после reload часть сервисов видит старые значения,
  • ошибки в ключах обнаруживаются случайно,
  • обновление структуры конфига болезненно.

BaseConfig решает это контрактом жизненного цикла.

2. BaseConfig: контракт

Конструкторы:

BaseConfig(JavaPlugin plugin, String fileName, boolean update)
BaseConfig(JavaPlugin plugin, String fileName)

Поля/доступ:

  • protected FileConfiguration config — актуальная YAML-конфигурация.

Абстрактный метод:

  • protected abstract void loadValues() — место, где вы парсите config в типизированные поля.

3. Жизненный цикл reloadConfig()

reloadConfig() делает:

  1. Проверяет наличие файла в data-folder.
  2. Если нет — копирует ресурс через saveResource.
  3. Загружает YAML в config.
  4. Если update=true — запускает updater.
  5. Вызывает loadValues().

Смысл: в остальном коде вы используете уже типизированные поля класса, а не «сырой» YAML.

4. Полный пример наследника

public final class MainConfig extends BaseConfig {
    private int maxPlayers;
    private boolean pvpEnabled;
    private String motd;
    private List<String> allowedWorlds;

    public MainConfig(JavaPlugin plugin) {
        super(plugin, "config.yml", true);
        reloadConfig();
    }

    @Override
    protected void loadValues() {
        maxPlayers = config.getInt("limits.maxPlayers", 50);
        pvpEnabled = config.getBoolean("gameplay.pvp", true);
        motd = config.getString("messages.motd", "Welcome");
        allowedWorlds = config.getStringList("worlds.allowed");
    }

    public int getMaxPlayers() { return maxPlayers; }
    public boolean isPvpEnabled() { return pvpEnabled; }
    public String getMotd() { return motd; }
    public List<String> getAllowedWorlds() { return allowedWorlds; }
}

5. Что должно жить в loadValues(), а что нет

Должно

  • чтение ключей,
  • преобразование типов,
  • нормализация значений,
  • базовая валидация,
  • установка default.

Не должно

  • тяжёлая бизнес-логика,
  • сетевые вызовы,
  • SQL-запросы,
  • игровые side effects.

6. ConfigUtil helpers

parseTime(...)

Позволяет парсить удобные значения:

  • 30s
  • 5m
  • 1h
  • 1d

getWorld(...)

Безопасно получает World по имени из конфигурации.

Эти helper-ы убирают дублирование в каждом конфиг-классе.

7. Структура конфигов для большого проекта

Рекомендуемый набор:

  • MainConfig — ядро настроек.
  • MessagesConfig — тексты/шаблоны.
  • GameplayConfig — механики.
  • RewardsConfig — награды.
  • GuiConfig — внешние GUI-настройки (если нужны вне YAML меню).

Принцип: один класс-наследник = один YAML-файл.

8. Reload интеграция

context.reload().register(new Reloadable() {
    @Override
    public String id() { return "config.main"; }

    @Override
    public void reload() {
        mainConfig.reloadConfig();
        messagesConfig.reloadConfig();
    }
});

Это создаёт единый контролируемый пайплайн перезагрузки.

9. Эволюция схемы YAML

Проблема: вы добавили новые ключи в config.yml, а у старых пользователей файл старой версии.

Подход:

  1. Включайте update=true.
  2. Держите default-значения в loadValues.
  3. Логируйте отсутствие критичных ключей.
  4. Версионируйте конфиги и миграции.

10. Валидация конфигов

Рекомендовано:

  • численные диапазоны (например maxPlayers > 0),
  • допустимые enum-строки,
  • существование миров/файлов,
  • отсутствие пустых обязательных ключей.

Если конфиг некорректный, отдавайте понятный лог с путём ключа.

11. Ошибки и диагностика

Файл не создаётся

  • fileName не существует в ресурсах jar,
  • проблемы с правами на файловую систему.

Поля остаются null

  • забыли вызвать reloadConfig() в конструкторе/старте.

Reload ничего не меняет

  • сервис читает config напрямую и кеширует старое значение,
  • loadValues() не обновляет нужные поля.

12. Антипаттерны

  • Использовать config напрямую в 20 местах проекта.
  • Делать reloadConfig из нескольких потоков без контроля.
  • Не задавать default-ы.
  • Смешивать parsing и game-side effects.

13. Production-практики

  1. Логируйте ключевые параметры на старте (без секретов).
  2. На reload печатайте краткий отчёт, что перечитано.
  3. Все критичные значения дублируйте проверкой валидности.
  4. Для опасных настроек добавьте «safe mode» fallback.

14. Большой FAQ

Где хранить секреты (пароли БД)?

Лучше в env-переменных/внешних секретах, а не в публично распространяемом YAML.

Можно ли хранить большие списки в YAML?

Можно, но если данные активно меняются и велики, лучше вынести в БД.

Что делать при несовместимом изменении формата?

Сделать явную миграцию и backward-compatible чтение на переходный период.

15. Чеклист конфиг-слоя

  • Каждый YAML имеет свой класс-наследник.
  • Все поля читаются в loadValues.
  • Есть default-значения.
  • Есть reload-регистрация.
  • Есть логи по ошибкам ключей.

При такой структуре конфиги перестают быть источником случайных багов и становятся стабильным API вашего плагина.