Войти или зарегистрироваться
  • Вы находитесь в сообществе Rubukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на различные языки плагины наших коллег из других стран.

Плагин [DEV] XConfiguration v1.2 - универсальная библиотека для работы с конфигурациями

Метки:
Теги Теги
bukkit config spigot yaml

CoolBoy

Активный участник
Пользователь
Баллы
96
Имя в Minecraft
Xezard
Версия плагина: 1.1
Протестирован на версиях: [1.14.4]
(Должен работать и на более старых версиях)
SpigotMC: [Ссылка]
GitHub: [Ссылка]

XConfiguration - это универсальная библиотека на основе аннотаций для взаимодействия с конфигурациями Bukkit / Spigot. С её помощью можно автоматически создавать / перезагружать конфигурации, оставлять в них комментарии, а главное, автоматически сохранять и получать объекты Java из конфигурации.

Сначала указываем репозиторий jitpack:
  • Gradle:
YAML:
repositories {
   maven { url 'https://jitpack.io' }
}
  • Maven:
YAML:
<repository>
   <id>jitpack.io</id>
   <url>https://jitpack.io</url>
</repository>
Затем добавляем XConfiguration в зависимость:
  • Gradle:
YAML:
dependencies {
   implementation 'com.github.Xezard:XConfiguration:1.0-RELEASE'
}
  • Maven:
YAML:
<dependency>
   <groupId>com.github.Xezard</groupId>
   <artifactId>XConfiguration</artifactId>
   <version>1.0-RELEASE</version>
</dependency>
Начнём с простейшего примера:
Java:
public class MessagesConfiguration
extends Configuration
{
   public MessagesConfiguration(Plugin plugin)
   {
       super(plugin, "messages.yml");
   }

   @Setter
   @Getter
   @ConfigurationField("Hello-world")
   public String helloWorld = "Hello, world!";
}
Прежде всего, нужно создать класс конфигурации. Этот класс должен быть унаследован от класса Configuration. В конструкторе суперкласса передаём ссылку на основной класс плагина (это который extends JavaPlugin) и имя файла для конфигурации. Внутри класса все объявленные поля, помеченные @ConfigurationField - считаются полями конфигурации. Значение аннотации @ConfigurationField - это путь к значению поля в конфигурации.

В основном классе плагина:
Java:
public class Main
extends JavaPlugin
{
    /*
     * Создаём новый обьект класса нашей конфигурации и сразу же инициализируем его.
     */
    private MessagesConfiguration messagesConfiguration = new MessagesConfiguration(this);

    @Override
    public void onEnable()
    {
        /*
         * Этот метод автоматически создаёт файл конфигурации,
         * если тот ещё не был создан. Кроме того, он автоматически
         * заполняет класс конфигурации значениями из конфига
         * и наоборот, заполняет конфигурацию значениями из класса,
         * если в файле конфигурации ещё нет соответствующих полей.
         *
         * Этот же метод также можно вызывать когда
         * нужно перезагрузить конфигурацию плагина.
         */
        this.messagesConfiguration.load();

        /*
         * После загрузки нашего конфига мы можем использовать
         * любые значения из него.
         */
        this.getLogger().info(this.messagesConfiguration.getHelloWorld());
    }
    @Override
    public void onDisable()
    {
        this.messagesConfiguration = null;
    }
}
При определении полей конфигурации можно также указать к ним комментарии:
Java:
public class MessagesConfiguration
extends Configuration
{
    public MessagesConfiguration(Plugin plugin)
    {
        super(plugin, "messages.yml");
    }

    @Setter
    @Getter
    @ConfigurationField
    (
        value = "Hello-world.With-comment-above",
        comments =
        {
            @Comment
            (
                path = "Hello-world",
                comments = {"# Single-line comment"}
            ),
 
            @Comment
            (
                path = "With-comment-above",
                comments =
                {
                    "",
                    "  # Indented comment"
                }
            )
       }
   )
   public String helloWorld = "Hello, world!";
}
Примечания:
  • Путь комментария всегда должен содержать часть пути поля конфигурации.
  • Каждая строка комментария должна содержать символ # в начале. Использование пустых строк также допускается.
После вызова метода load() можно будет увидеть следующую конфигурацию:
YAML:
# Single-line comment
Hello-world:

  # Indented comment
  With-comment-above: Hello, world!
А как насчет полей с вашими собственными типами? Легко.
Создадим наш класс:
Java:
@Data
@AllArgsConstructor
@SerializableAs("Pojo")
public class POJO
implements ConfigurationSerializable
{
    private String name;

    private int id;

    @Override
    public Map<String, Object> serialize()
    {
        return Map.of("Name", this.name, "Id", this.id);
    }

    public static POJO deserialize(Map<String, Object> serialized)
    {
        return new POJO((String) serialized.get("Name"), (int) serialized.get("Id"));
    }
}
Чтобы использовать наш класс в конфигурации, мы должны реализовать интерфейс ConfigurationSerializable и 2 метода: 'Map <String, Object> serialize()' и 'POJO deserialize (Map <String, Object> serialized)'. Они будут использоваться для сериализации и десериализации нашего объекта.

После этого в классе конфигурации:
Java:
public class MessagesConfiguration
extends Configuration
{
    public MessagesConfiguration(Plugin plugin)
    {
        super(plugin, "messages.yml");
    }

    @Setter
    @Getter
    @ConfigurationField("POJO")
    public POJO pojo = new POJO("pojo", 1);
}
Теперь после загрузки конфигурации можно автоматически получить уже сериализованный объект :D
Допустим, наш обьект может сериализоваться самостоятельно в строку, но, при этом
мы не можем редактировать класс этого обьекта (класс чужой библиотеки, например):
Java:
@Data
@AllArgsConstructor
public class POJO
{
   private String name;
 
   private int id;
 
   public String serialize()
   {
       return this.name + ":" + this.id;
   }

   public static POJO deserialize(String string)
   {
       String[] parts = string.split(":");
     
        return new POJO(parts[0], Integer.parseInt(parts[1]));
   }
}
В этом случае мы можем создать класс сериализации, специально под этот обьект:
Java:
@EqualsAndHashCode(callSuper = true)
public class ConfigurationDataPOJO
extends AbstractConfigurationData<POJO>
{
    public ConfigurationDataPOJO()
    {
        super(POJO.class);
    }
 
    @Override
    public void set(FileConfiguration configuration, String path, POJO value, Class<?>... type)
    {
        configuration.set(path, value.serialize());
    }

    @Override
    public POJO get(FileConfiguration configuration, String path, Class<?>... type)
    {
        return POJO.deserialize(configuration.getString(path));
    }

    @Override
    public POJO get(FileConfiguration configuration, String path, POJO def, Class<?>... type)
    {
        POJO pojo = this.get(configuration, path, type);
     
        return pojo == null ? def : pojo;
    }

    @Override
    public boolean isValid(FileConfiguration configuration, String path)
    {
        return configuration.isString(path);
    }

    @Override
    public POJO getDefault()
    {
        return new POJO("null", 0);
    }
}
И зарегестрировать его в ConfigurationManager:
Java:
public class Main
extends JavaPlugin
{
    private MessagesConfiguration messagesConfiguration = new MessagesConfiguration(this);
 
    private ConfigurationDataPOJO configurationDataPOJO = new ConfigurationDataPOJO();

    @Override
    public void onEnable()
    {
        ConfigurationManager.register(configurationDataPOJO);
     
        this.messagesConfiguration.load();

        this.getLogger().info(this.messagesConfiguration.getPojo());
    }
 
    @Override
    public void onDisable()
    {
        ConfigurationManager.unregister(configurationDataPOJO);
      
        this.messagesConfiguration = null;
    }
}
z7OynOOTIhE.jpg

hUlgdEQBgtE.jpg

Скачать: [Ссылка]

Лог изменений:
Версия 1.2:
  • Исправлены дубликаты комментариев при вызове метода .load().
  • Исправлена перезапись значений конфигурации значениями из класса конфигурации.
Версия 1.1:
  • Добавлена поддержка Java 8 и выше.
  • Теперь все поля в конфигурации генерируются в том порядке, в котором указаны в классе конфигурации.
Версия 1.0:
  • Релиз.
 
Последнее редактирование:
Всё, конечно же, почти идеально, но слишком жирная изначальная запись всего этого (4 строки грубо говоря)
 
Updated v.1.2:
  • Исправлены дубликаты комментариев при вызове метода .load().
  • Исправлена перезапись значений конфигурации значениями из класса конфигурации.
 
конечно прикольно, но разве не удобнее будет так:

Код:
public class MessagesConfiguration
    extends Configuration {
  public MessagesConfiguration(Plugin plugin) {
    super(plugin, "messages.yml");
  }

  @ConfigurationSection("Hello-world") //Если не указано имя, то можно использовать имя класса. '_' заменять на '-'
  @Getter
  @Setter
  private HelloWorld helloWorldSection = new HelloWorld();

  //Это можно будет вынести в отдельный класс
  @Comment({"Коментарий для секции"})
  public static class HelloWorld {
    @ConfigurationFiled("With-comment-above") //Если не указано имя, то можно использовать имя поля. '_' заменять на '-'
    @Comment({"Коментарий для поля"})
    @Getter
    @Setter
    private String helloWorld = "Hello World";
  }
  @ConfigurationFiled()
  @Getter
  @Setter
  private String joinMessage = "Hello, %Player%";
}

Как по мне, это более читаемо, и практичнее. Например вместо целого конфига, можно будет передавать только необходимые секции, которые необходимы для реализации нужной функции.

И почему бы не вынести бакитовский конфиг в отельную либу, чтобы можно было использовать это не только в баккит плагинах? Если вдруг тебе лень, то вот - https://mega.nz/#!2VwnHIhT!n8onesZNGyrcVIRqhCEHtgL8LiJDlYUWR0ZMQVKqleI . Я это делал на версии 1.13, не знаю менялось ли что либо в новых версиях.
 
конечно прикольно, но разве не удобнее будет так:

Код:
public class MessagesConfiguration
    extends Configuration {
  public MessagesConfiguration(Plugin plugin) {
    super(plugin, "messages.yml");
  }

  @ConfigurationSection("Hello-world") //Если не указано имя, то можно использовать имя класса. '_' заменять на '-'
  @Getter
  @Setter
  private HelloWorld helloWorldSection = new HelloWorld();

  //Это можно будет вынести в отдельный класс
  @Comment({"Коментарий для секции"})
  public static class HelloWorld {
    @ConfigurationFiled("With-comment-above") //Если не указано имя, то можно использовать имя поля. '_' заменять на '-'
    @Comment({"Коментарий для поля"})
    @Getter
    @Setter
    private String helloWorld = "Hello World";
  }
  @ConfigurationFiled()
  @Getter
  @Setter
  private String joinMessage = "Hello, %Player%";
}

Как по мне, это более читаемо, и практичнее. Например вместо целого конфига, можно будет передавать только необходимые секции, которые необходимы для реализации нужной функции.

И почему бы не вынести бакитовский конфиг в отельную либу, чтобы можно было использовать это не только в баккит плагинах? Если вдруг тебе лень, то вот - https://mega.nz/#!2VwnHIhT!n8onesZNGyrcVIRqhCEHtgL8LiJDlYUWR0ZMQVKqleI . Я это делал на версии 1.13, не знаю менялось ли что либо в новых версиях.
Толковое предложение, глянем, может быть прикручу всё это в будущих версиях. Спасибо :coffee:
Какой ужас! Лучше HOCON юзать.
99% паблик плагинов юзают yaml для конфигураций. Этот плагин - для паблика. Естественно на собственном проекте можно использовать самый передовой код и последние модные библиотеки для всего - но нужно ли ими делиться с другими?)
 
Уж лучше ими, чем каким то высером. Да тот же yamlbeans будет куда удобнее.
Создаешь простой pojo класс и он сериализуется, без говна и палок.
 
Последнее редактирование:
Уж лучше ими, чем каким то высером. Да тот же yamlbeans будет куда удобнее.
Создаешь простой pojo класс и он сериализуется, без говна и палок.
Круто. Теперь иди на spigotmc и объясни всем какой yamlbeans и HOCON крутой. А пока что все юзают yaml баккита и особо не парятся)
 

Поделиться этой страницей

Назад
Верх