Jump to content


Photo

Статья: YML и все-все-все...


  • Please log in to reply
No replies to this topic

#1 vasco

vasco

    торговец черным деревом на пенсии

  • Администраторы
  • Active Posts1784

Posted 07.12.2015 - 15:14

- Гляди, Пятачок!
- Ой, выходит... то есть... входит!
- Входит!!
- И выхо-о-одит! И входит... Замечательно выходит!
- И выходит! И входит! Хе-хе!
м/ф "Винни-пух"

Вся система настроек майнкрафт серверов и плагинов для них держится на конфигурационных файлах. Традиционно в качестве формата конфигов для mc-серверов используется YAML (он же YML) - формат сериализации данных, базирующийся на сдвиге выражения описания элемента данных относительно начала строки. Чтобы наглядно показать, о чем идет речь, приведу следующий пример (в нем начальные пробелы заменены на точки):
settings:[paste][/paste][paste][/paste]debug: false[paste][/paste][paste][/paste]save-user-cache-on-stop-only: false[paste][/paste][paste][/paste]filter-creative-items: true[paste][/paste][paste][/paste]moved-wrongly-threshold: 0[paste][/paste]0625[paste][/paste][paste][/paste]moved-too-quickly-threshold: 100[paste][/paste]0[paste][/paste][paste][/paste]bungeecord: false[paste][/paste][paste][/paste]late-bind: false[paste][/paste][paste][/paste]sample-count: 12[paste][/paste][paste][/paste]player-shuffle: 0[paste][/paste][paste][/paste]user-cache-size: 1000[paste][/paste][paste][/paste]int-cache-limit: 1024[paste][/paste][paste][/paste]timeout-time: 60[paste][/paste][paste][/paste]restart-on-crash: true[paste][/paste][paste][/paste]restart-script: [paste][/paste]/start[paste][/paste]sh[paste][/paste][paste][/paste]netty-threads: 4[paste][/paste][paste][/paste]attribute:[paste][/paste][paste][/paste][paste][/paste][paste][/paste]maxHealth:[paste][/paste][paste][/paste][paste][/paste][paste][/paste][paste][/paste][paste][/paste]max: 2048[paste][/paste]0[paste][/paste][paste][/paste][paste][/paste][paste][/paste]movementSpeed:[paste][/paste][paste][/paste][paste][/paste][paste][/paste][paste][/paste][paste][/paste]max: 2048[paste][/paste]0[paste][/paste][paste][/paste][paste][/paste][paste][/paste]attackDamage:[paste][/paste][paste][/paste][paste][/paste][paste][/paste][paste][/paste][paste][/paste]max: 2048[paste][/paste]0
Как можно заметить, уровень вложенности элементов в данном примере регулируется не знаками препинания, как это принято в нормальных языках программирования, а сдвигом на два пробела вправо относительно начала строки. Таким образом, элемент settings для всех остальных является корневым и содержит в качестве дочерних элементы различных типов: логические (debug: false), строковые (restart-script: ./start.sh), целочисленные (sample-count: 12) и дробные (moved-wrongly-threshold: 0.0625). Кроме того, он также содержит в себе другие комплексные элементы (например, attribute), которые, в свою очередь, также включают в себя набор дочерних элементов. Причем эти дочерние элементы сдвинуты еще на два пробела вправо (maxHealth, movementSpeed, attackDamage), что говорит интерпретатору о том, что они принадлежат не корневому элементу settings, а его дочернему элементу attribute, который обрабатывается в данный момент.

Описание каждого элемента данных состоит из его имени и значения, указанного через двоеточие с пробелом (!). Комплексные элементы (имеющие дочерние подэлементы) могут иметь формат как именованного списка (как в вышеприведенном примере), так и неименованного списка, в котором подэлементы перечисляются следующим образом (опять же ведущие пробелы и пробел между тире и значением заменены на точки):
[paste][/paste][paste][/paste]replace-commands:[paste][/paste][paste][/paste]-[paste][/paste]setblock[paste][/paste][paste][/paste]-[paste][/paste]summon[paste][/paste][paste][/paste]-[paste][/paste]testforblock[paste][/paste][paste][/paste]-[paste][/paste]tellraw
Обратите внимание, подэлементы комплексного элемента replace-commands не имеют имен, только значения. И все равно относительно родительского элемента эти значения сдвинуты на два символа вправо, только в вместо первого пробела указывается символ '-' как признак элемента неименованного списка. Обычно именованные списки YML-формата называются ассоциативными массивами, а неименованные - просто списками или массивами.

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

Использовать вместо пробелов символы табуляции (например, для замены 4-х пробелов) запрещено, это расценивается как попытка к бегству ошибка. Вообще, YML очень критичен к качеству кода, малейшая ошибка в сдвиге (особенно в сдвиге) или последовательности управляющих символов ведет к исключению и прекращению дальнейшей обработки файла. Поэтому по-первости, пока твердо не усвоил вышеописанные особенности формата, сервер у меня отказывался стартовать порой после самых мелких изменений в конфиге.

Лучше всего для редактирования YML-файлов подходит Notepad++. Во-первых, это сам по себе отличная замена виндовому нотпаду. Во-вторых, у него есть подсветка синтаксиса всех основных текстовых форматов и языков программирования. Не обошли вниманием и YML. В третьих, он отлично поддерживает функцию "смарт-таб", автоматически вставляя нужное количество пробелов (или символов табуляции) при переходе на новую строку. И в четвертых, для каждого типа файлов у него можно включить или отключить преобразование табуляции в пробелы и определить количество заменяемых пробелов. После этого в YML-файлах уровень вложенности можно увеличивать (и уменьшать) просто нажатием клавиши "Таб" (альт-таб).

Вот такой интересный формат. Со своими недостатками (серьезными, на мой взгляд), но, тем не менее, позволяющий описывать достаточно серьезные структуры (имеется опыт создания YML-конфига на 3500 строк - нормально работает, как ни странно).

Однако в последнее время (примерно с версии 1.7.10) образовалась тенденция перехода к другому не менее известному формату - JSON. Он пользуется не меньшей популярностью и заслуженным уважением, особенно в кругах приверженцев си-подобных языков программирования. Наверное, за столь любимые фигурные скобки. Собственно, на них (а также использовании прямых скобок) все и построено. В качестве примера привожу кусок бан-листа нового формата (с версии 1.7.10):
[  {    "uuid": "27a854c8-8965-4d2a-a6fd-23e64dfdc825",    "name": "MrBadBoy",    "created": "2015-07-23 20:13:51 +0400",    "source": "operator",    "expires": "forever",    "reason": "нарушение правил сервера"  },  {    "uuid": "7675832b-a75b-291c-fb09-3b1a043f35fa",    "name": "_SuPeR_NaGiBaToR_",    "created": "2015-08-16 12:28:47 +0400",    "source": "admin",    "expires": "forever",    "reason": "неадекватность"  }]
Основные моменты при написании конфига в формате JSON следующие:

    [*]символы пробела, переноса строки и табуляции в обработке не участвуют и могут вставляться в любом месте и в любом количестве для улучшения читабельности
    [*]объект - это ассоциативный массив, список подэлементов (именованных) которого заключается в фигурные скобки (перечисляются через запятую в виде пар "ключ: значение").
    [*]массив - это неименованный список, значения которого заключаются в прямые скобки, где перечисляются через запятую.
    [*]названия элементов заключаются в двойные кавычки (некоторые JSON-парсеры допускают использование одинарных кавычек, но лучше соблюдать стандарт оформления).
    [*]значения элементов могут представлять собой строковое значение (заключенное в двойные кавычки), целое или дробное число, логический литерал true или false, определяющем логическое значение, а также литерал null, определяющий нулевое значение. Кроме того, в качестве значения может выступать вложенный объект в фигурных скобках или вложенный массив в прямых скобках.
    [/list]Корневым элементом JSON структуры может являться либо объект либо массив, то есть весь конфиг в JSON-формате должен быть обернут либо в прямые либо в фигурные скобки.

    В остальном, на форматирование JSON-структуры не налагается никаких ограничений, одинаково правильно работает как структура, приведенная выше, так и ее сжатый аналог:
    [{"uuid":"27a854c8-8965-4d2a-a6fd-23e64dfdc825","name":"MrBadBoy","created":"2015-07-2320:13:51+0400","source":"operator","expires":"forever","reason":"нарушение правил сервера"},{"uuid":"7675832b-a75b-291c-fb09-3b1a043f35fa","name":"_SuPeR_NaGiBaToR_","created":"2015-08-1612:28:47+0400","source":"admin","expires":"forever","reason":"неадекватность"}]
    Эта особенность позволяет использовать JSON как формат описания данных, передаваемых по сети, в частности, он активно используется в веб-технологиях (см. AJAX). Он же используется в запросах на моджанговские серверы, когда требуется, например, по UUID персонажа получить список его переименований.

    И YML и JSON прекрасно парсятся стандартными средствами явы, на выходе получается древовидная структура, состоящая в основном из объектов Map<String,Object> либо массивов (списков) List<Object>, дальнейшая обработка которых при наличии минимальных навыков не представляет труда. Все это также работает и в обратную сторону: на выходе можно получить либо YML-файл либо JSON-строку.

    В качестве примеров обоих форматов можете заглянуть в корневую папку своего сервера и обозреть там файлы server.properties, bukkit.yml, [spigot.yml - если есть], help.yml - YML формат. Или файлы banned-players.json, banned-ips.json, ops.json - как пример использования JSON-формата (если у вас сервер версии 1.7.10 и выше).

    В заключение даю ссылку на отличный онлайн-валидатор (система проверки синтаксиса) для разных типов файлов (в том числе для YML и JSON): http://codebeautify.org/.

    Статья получилась небольшая и вроде как не имеющая прямого отношения к написанию плагинов для баккита. Однако конфигурационные файлы - это неотъемлемая часть любой программы (плагина в том числе), и умение правильно с ними обращаться совершенно необходимо для того, чтобы писать правильно работающие вещи. Хотя, матов поначалу было собрано в трехэтажные конструкции - не выговорить (в основном по поводу YML).
    А что подумал Кролик, никто не узнал, потому что он был очень воспитанный.
    м/ф "Винни-Пух"


    • avttrue likes this


0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users