Config Manager
Полное руководство по Config Manager: BaseConfig lifecycle, типобезопасный доступ, reload-пайплайн, эволюция YAML и эксплуатация в проде.
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() делает:
- Проверяет наличие файла в data-folder.
- Если нет — копирует ресурс через
saveResource. - Загружает YAML в
config. - Если
update=true— запускает updater. - Вызывает
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(...)
Позволяет парсить удобные значения:
30s5m1h1d
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, а у старых пользователей файл старой версии.
Подход:
- Включайте
update=true. - Держите default-значения в
loadValues. - Логируйте отсутствие критичных ключей.
- Версионируйте конфиги и миграции.
10. Валидация конфигов
Рекомендовано:
- численные диапазоны (например
maxPlayers > 0), - допустимые enum-строки,
- существование миров/файлов,
- отсутствие пустых обязательных ключей.
Если конфиг некорректный, отдавайте понятный лог с путём ключа.
11. Ошибки и диагностика
Файл не создаётся
fileNameне существует в ресурсах jar,- проблемы с правами на файловую систему.
Поля остаются null
- забыли вызвать
reloadConfig()в конструкторе/старте.
Reload ничего не меняет
- сервис читает
configнапрямую и кеширует старое значение, loadValues()не обновляет нужные поля.
12. Антипаттерны
- Использовать
configнапрямую в 20 местах проекта. - Делать
reloadConfigиз нескольких потоков без контроля. - Не задавать default-ы.
- Смешивать parsing и game-side effects.
13. Production-практики
- Логируйте ключевые параметры на старте (без секретов).
- На reload печатайте краткий отчёт, что перечитано.
- Все критичные значения дублируйте проверкой валидности.
- Для опасных настроек добавьте «safe mode» fallback.
14. Большой FAQ
Где хранить секреты (пароли БД)?
Лучше в env-переменных/внешних секретах, а не в публично распространяемом YAML.
Можно ли хранить большие списки в YAML?
Можно, но если данные активно меняются и велики, лучше вынести в БД.
Что делать при несовместимом изменении формата?
Сделать явную миграцию и backward-compatible чтение на переходный период.
15. Чеклист конфиг-слоя
- Каждый YAML имеет свой класс-наследник.
- Все поля читаются в
loadValues. - Есть default-значения.
- Есть reload-регистрация.
- Есть логи по ошибкам ключей.
При такой структуре конфиги перестают быть источником случайных багов и становятся стабильным API вашего плагина.