Пакеты модов — различия между версиями
Версия 16:28, 4 мая 2017 | Текущая версия на 12:54, 8 января 2019 | |||
не показана одна промежуточная версия этого же участника | ||||
Строка 1: | Строка 1: | |||
? | {{Блок| | + | [[Category:Модификации]] | |
+ | {{Блок| i |content = version 0.4, 2017-05-04<br /> | |||
+ | * Anton Bobrov, Wargaming.net | |||
+ | * Mikhail Paulyshka, XVM team | |||
+ | * Andrey Andruschyshyn, Independent | |||
+ | * Koreanrandom.com community | |||
+ | License: [https://creativecommons.org/licenses/by-sa/4.0/ CC BY-SA 4.0] | |||
+ | }} | |||
<div class="wot-frame-1"> | <div class="wot-frame-1"> | |||
Строка 6: | Строка 13: | |||
Пакеты это | Пакеты это | |||
способ организации файлов модификаций, в котором весь контент отдельной модификации | способ организации файлов модификаций, в котором весь контент отдельной модификации | |||
? | упакован в один файл. | + | упакован в один файл.<br /> | |
? | В случае использования старой схемы распространения файлов, модификации устанавливаются в каталог | + | В случае использования старой схемы распространения файлов, модификации устанавливаются в каталог {{Intext code|<каталог WoT>/res_mods/<версия WoT>/}}.При этом, файлы разных модификаций располагаются в одних и тех же каталогах, и поэтому зачастую трудно определить, какой файл относится к какой именно модификации. <br/> | |
? | При этом, файлы разных модификаций располагаются в одних и тех же каталогах, и поэтому зачастую трудно определить, какой файл относится к какой именно модификации. Переход на дистрибуцию в пакетах может существенно упростить организацию файлов модификаций: для установки пользователю достаточно скопировать пакет в каталог | + | Переход на дистрибуцию в пакетах может существенно упростить организацию файлов модификаций: для установки пользователю достаточно скопировать пакет в каталог {{Intext code|<каталог WoT>/mods/<версия WoT>/}} , а для деинсталляции удалить ровно тот же файл. | |
== Структура пакета == | == Структура пакета == | |||
? | Пакет представляет собой zip-архив без сжатия | + | Пакет представляет собой zip-архив со следующими свойствами:<br /> | |
+ | * без сжатия | |||
+ | * расширение: {{Intext code|.wotmod}} | |||
+ | * максимальный размер архива: 2 ГиБ - 1 байт (2 147 483 647 байт) | |||
{{Блок| ! | content = Внимание: архивы с компрессией в текущей версии World of Tanks не поддерживаются, поэтому, при | {{Блок| ! | content = Внимание: архивы с компрессией в текущей версии World of Tanks не поддерживаются, поэтому, при | |||
создании архивов необходимо установливать опцию «уровень сжатия» в значение «без сжатия».}} | создании архивов необходимо установливать опцию «уровень сжатия» в значение «без сжатия».}} | |||
+ | {{Блок| ! | content = архивы размером 2 ГиБ и больше в текущей версии World of Tanks не поддерживаются, | |||
+ | поэтому большие пакеты необходимо разбивать на более мелкие, размер каждого из которых не | |||
+ | будет превышает 2 ГиБ - 1 байт.}} | |||
+ | ||||
Внутри себя пакет содержит:<br> | Внутри себя пакет содержит:<br> | |||
? | * обязательно: каталог | + | * обязательно: каталог {{Intext code|/res/}}. Сюда помещаются ресурсы модификации, то есть все те файлы, которые раньше устанавливались в {{Intext code|<каталог WoT>/res_mods/<версия WoT>}} | |
? | * опционально: служебный файл | + | * опционально: служебный файл {{Intext code|meta.xml}} (смотрите '''раздел 5''') | |
? | * опционально: файл | + | * опционально: файл {{Intext code|LICENSE}} с лицензионным соглашением | |
* опционально: любой иной контент, который может понадобиться автору модификации: ссылка на сайт модификации, документация, список изменений и тому подобное.<br> | * опционально: любой иной контент, который может понадобиться автору модификации: ссылка на сайт модификации, документация, список изменений и тому подобное.<br> | |||
Пример структуры пакета: | Пример структуры пакета: | |||
<div class="pre_code monospace"> | <div class="pre_code monospace"> | |||
? | : | + | :/package.wotmod | |
? | :: | + | ::/meta.xml | |
? | :: | + | ::/README.md | |
? | :: | + | ::/LICENSE | |
? | :: | + | ::/res | |
? | ::: | + | :::/scripts | |
? | :::: | + | ::::/client | |
? | ::::: | + | :::::/gui | |
? | :::::: | + | ::::::/mods | |
? | ::::::: | + | :::::::/mod_example.pyc | |
</div> | </div> | |||
== Установка пакета == | == Установка пакета == | |||
? | Пакеты устанавливаются в | + | Пакеты устанавливаются в {{Intext code|<каталог WoT>/mods/<версия WoT>}}. Это может быть как ручное копирование, так и установка посредством инсталятора модификации или сборки модификаций.<br> | |
При необходимости, пакеты могут быть организованы в подкаталоги, что позволяет авторам сборок модификаций выполнять группировку файлов: | При необходимости, пакеты могут быть организованы в подкаталоги, что позволяет авторам сборок модификаций выполнять группировку файлов: | |||
<div class="pre_code monospace"> | <div class="pre_code monospace"> | |||
mods/ | mods/ | |||
? | : | + | :0.9.17.1/ | |
? | :: | + | ::MultiHitLog_2.8.wotmod | |
? | :: | + | ::DamagePanel/ | |
? | ::: | + | :::Some_common_library_3.14.5.wotmod | |
? | ::: | + | :::DamagePanel_2.6.wotmod | |
? | ::: | + | :::DamagePanel_2.8.wotmod | |
? | ::: | + | :::DamagePanel_2.8_patch1.wotmod | |
+ | </div> | |||
+ | == Рекомендации по именованию пакетов == | |||
+ | Для имени пакета (в дальнейшем {{Intext code|package_id}} ) рекомендована следующая схема формирования: | |||
+ | <div class="pre_code monospace"> | |||
+ | package_id = author_id.mod_id | |||
+ | </div> | |||
+ | Где:<br /> | |||
+ | * {{Intext code|author_id}} : идентификатор автора. Может быть сайтом разработчика модификации | |||
+ | ( {{Intext code|com.example}} ) или же просто его никнеймом ( {{Intext code|noname}} ) | |||
+ | * mod_id : идентификатор модификации. Выбирается автором модификации произвольно. | |||
+ | Данное имя используется в файле {{Intext code|meta.xml}} (смотрите '''раздел 5'''), а также как часть имени файла | |||
+ | пакета.<br /> | |||
+ | Пример имён пакетов: | |||
+ | <div class="pre_code monospace"> | |||
+ | com.example.coolmod | |||
+ | noname.supermod | |||
+ | </div> | |||
+ | Имя файла пакета формируется следующим образом: | |||
+ | <div class="pre_code monospace"> | |||
+ | <author_id>.<mod_id>_<mod_version>.wotmod | |||
+ | </div> | |||
+ | Где:<br /> | |||
+ | * {{Intext code|mod_version}} : версия модификации, задаётся автором в {{Intext code|meta.xml}} (смотрите '''раздел 5'''). | |||
+ | Примеры: | |||
+ | <div class="pre_code monospace"> | |||
+ | com.example.coolmod_0.1.wotmod<br /> | |||
+ | noname.supermod_0.2.8.wotmod | |||
+ | </div> | |||
+ | == Файл метаданных {{Intext code|meta.xml}} == | |||
+ | Необязательный файл {{Intext code|meta.xml}} содержит опциональные поля, описывающие модификацию.<br /> | |||
+ | Пример заполнения: | |||
+ | <div class="pre_code monospace"> | |||
+ | <root> | |||
+ | :<!‐‐ Идентификатор пакета ‐‐><br /> | |||
+ | :<id>noname.crosshair</id><br /> | |||
+ | <br /> | |||
+ | :<!‐‐ Версия пакета ‐‐><br /> | |||
+ | :<version>0.2.8</version><br /> | |||
+ | <br /> | |||
+ | :<!‐‐ Имя пакета понятное для пользователя ‐‐><br /> | |||
+ | :<name>Crosshair</name><br /> | |||
+ | <br /> | |||
+ | :<!‐‐ Описание пакета ‐‐><br /> | |||
+ | :<description>New cool Crosshair with feature1.....N</description> | |||
+ | </root> | |||
+ | </div> | |||
+ | Значения из полей {{Intext code|<id>}} и {{Intext code|<version>}} используются для определения порядка монтирования пакетов. Значения полей {{Intext code|<name>}} и {{Intext code|<description>}} в будущем будут использоваться в системе управления модификациями. | |||
+ | ||||
+ | == Загрузка пакетов == | |||
+ | === Порядок загрузки === | |||
+ | Все пакеты, находящиеся в каталоге {{Intext code|<каталог_WoT>/mods/<версия_WoT>/}} , сортируются по значению узла {{Intext code|<id>}} в файле {{Intext code|meta.xml}} и загружаются по порядку. В случае отсутствия файла {{Intext code|meta.xml}} внутри пакета, в качестве идентификатора пакета будет использовано имя файла.<br /> | |||
+ | ||||
+ | Для переопределения порядка загрузки может быть использован файл {{Intext code|load_order.xml}} , который должен находиться в вышеуказанном каталоге.<br /> | |||
+ | ||||
+ | В случае, если все пакеты указаны в {{Intext code|load_order.xml}} , то загрузка выполняется в указанном в файле порядке.<br /> | |||
+ | ||||
+ | В случае, если часть пакетов в {{Intext code|load_order.xml}} не указана, то сначала выполняется загрузка пакетов из {{Intext code|load_order.xml}} , а затем отсутствующих в нём пакетов в алфавитном порядке.<br /> | |||
+ | ||||
+ | '''Внимание:''' в данный момент использование файла {{Intext code|load_orders.xml}} затруднено (смотрите '''раздел 9.4'''). | |||
+ | ||||
+ | ===Совместное использование пакетов и {{Intext code|res_mods}} === | |||
+ | С точки зрения клиента игры, корень виртуальной системы формируется из:<br /> | |||
+ | *{{Intext code|/res_mods/<версия_WoT>}} | |||
+ | *{{Intext code|/mods/<версия_WoT>/<имя_пакета>.wotmod/res/}} | |||
+ | *{{Intext code|/res/packages/*.pkg/}} | |||
+ | *{{Intext code|/res/}} | |||
+ | *Иные пути, указанные в файле {{Intext code|<Каталог_WoT>/paths.xml}} | |||
+ | Пути указаны в порядке уменьшения приоритета. То есть, файлы из {{Intext code|/res_mods/<версия_WoT>/}} имеют наивысший приоритет вне зависимости от содержания {{Intext code|load_order.xml}} | |||
+ | ||||
+ | === Разрешение конфликтов при загрузке === | |||
+ | В общем случае, система пакетов не допускает ситуации, когда в каталоге {{Intext code|res/}} внутри разных пакетов находятся одинаковые файлы. Такая ситуация cчитается конфликтом.<br /> | |||
+ | ||||
+ | В случае обнаружения конфликта, вызвавший его пакет не будет загружен, а пользователю будет | |||
+ | показано соответствующее уведомление. | |||
+ | Например, если пакеты {{Intext code|a.wotmod}} и {{Intext code|b.wotmod}} будут содержать внутри себя файл {{Intext code|res/scripts/entities.xml}} , то {{Intext code|a.wotmod}} будет загружен успешно, а {{Intext code|b.wotmod}} вызовет конфликт и загружен не будет.<br /> | |||
+ | ||||
+ | Для управления обработкой конфликтов можно использовать:<br/> | |||
+ | <br/> | |||
+ | 1. Файл {{Intext code|load_order.xml}} . | |||
+ | <div class="pre_code monospace"> | |||
+ | :<root> | |||
+ | ::<Collection> | |||
+ | :::<pkg>имя_пакета_1.wotmod</pkg> | |||
+ | :::<pkg>имя_пакета_2.wotmod</pkg> | |||
+ | :::<!‐‐ ... ‐‐> | |||
+ | :::<pkg>имя_пакета_N.wotmod</pkg> | |||
+ | ::</Collection> | |||
+ | :</root> | |||
+ | </div> | |||
+ | Пакеты, перечисленные в этом файле, не считаются конфликтующими и загружаются без анализа на пересечение имен файлов.<br/> | |||
+ | <br/> | |||
+ | 2. Значение узлов {{Intext code|<id>}} и {{Intext code|<version>}} из {{Intext code|meta.xml}} .<br/> | |||
+ | При наличии узла {{Intext code|<id>}} в файле {{Intext code|meta.xml}} , имя файла пакета не влияет на порядок загрузки. Пакеты, у которых {{Intext code|<id>}} совпадает, считаются разными версиями или частями одной и той же модификации, и конфликты между ними также не учитываются. Данные пакеты загружаются в порядке увеличения версии.<br /> | |||
+ | ||||
+ | Версии пакетов сравниваются посимвольно согласно таблице ASCII. Поведение совпадает с функцией | |||
+ | [https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/strcmp-wcscmp-mbscmp strcmp()]: | |||
+ | *версия {{Intext code|9.0.0}} приоритетнее версии {{Intext code|10.0.0}} | |||
+ | *версия {{Intext code|b}} приоритетнее версии {{Intext code|B}} | |||
+ | *версия {{Intext code|c<любые символы>}} приоритетнее версии {{Intext code|c}} | |||
+ | *если версии совпадают, то приоритет у пакета, имя файла которого будет первым по алфавиту. | |||
+ | При наличии одноименных файлов внутри разных пакетов, конфликты между которыми разрешены посредством {{Intext code|load_order.xml}} или {{Intext code|meta.xml}} , приоритет имеет файл из пакета, который был подключен последним или имеет наибольшее значение {{Intext code|<version>}} . | |||
+ | ||||
+ | === Исполнение Python-кода === | |||
+ | После монтирования всех пакетов и разрешения конфликтов, происходит исполнение всех {{Intext code|.pyc}} - файлов из каталога {{Intext code|/scripts/client/gui/mods/}} в алфавитном порядке, имя которых начинается с {{Intext code|mod_}} . | |||
+ | В пакете данный файл должен быть расположен по следующему пути: | |||
+ | <div class="pre_code monospace"> | |||
+ | <author_id>.<mod_id>_<version>.wotmod/res/scripts/client/gui/mods/mod_<anything>.pyc | |||
+ | </div> | |||
+ | ||||
+ | == Рекомендованные пути для файлов модификаций == | |||
+ | === Файлы конфигурации === | |||
+ | Для хранения файлов конфигурации модификаций рекомендованно использовать путь | |||
+ | <div class="pre_code monospace"> | |||
+ | <каталог_WoT>/mods/configs/<author_id>.<mod_id>/ | |||
+ | </div> | |||
+ | Где:<br /> | |||
+ | ||||
+ | {{Intext code|author_id}} и {{Intext code|mod_id}} - идентификаторы, описаные в '''разделе 4''' данной спецификации. | |||
+ | === Файлы журналов === | |||
+ | Помимо штатного файла {{Intext code|python.log}} , для хранения журналов рекомендованно использовать путь: | |||
+ | <div class="pre_code monospace"> | |||
+ | <каталог_WoT>/mods/logs/<author_id>.<mod_id>/ | |||
+ | </div> | |||
+ | Где:<br /> | |||
+ | ||||
+ | {{Intext code|author_id}} и {{Intext code|mod_id}} - идентификаторы, описаные в '''разделе 4''' данной спецификации. | |||
+ | === Временные файлы === | |||
+ | Для хранения временных файлов модификации рекомендованно использовать следующий путь: | |||
+ | <div class="pre_code monospace"> | |||
+ | <temp>/world_of_tanks/<author_id>.<mod_id>/ | |||
+ | </div> | |||
+ | Где:<br /> | |||
+ | *{{Intext code|temp}} - путь к каталогу с временными файлами для текущего пользователя в ОС; | |||
+ | *{{Intext code|author_id}} и {{Intext code|mod_id}} - идентификаторы, описаные в '''разделе 4''' данной спецификации. | |||
+ | === Иные файлы модификации === | |||
+ | Для хранения внутри пакета контента, к которому необходимо получить доступ из клиента игры, рекомендованно использовать следующий путь: | |||
+ | <div class="pre_code monospace"> | |||
+ | <имя_пакета>.wotmod/res/mods/<author_id>.<mod_id>/ | |||
+ | </div> | |||
+ | Где:<br /> | |||
+ | ||||
+ | {{Intext code|author_id}} и {{Intext code|mod_id}} - идентификаторы, описаные в '''разделе 4''' данной спецификации. | |||
+ | ||||
+ | == Работа с файлами внутри пакетов == | |||
+ | Для работы с файлами внутри пакетов необходимо использовать модуль {{Intext code|ResMgr}} . | |||
+ | === Типовые операции === | |||
+ | ==== Чтение файла из пакета ==== | |||
+ | <div class="pre_code monospace"> | |||
+ | <pre>#импорт</pre> | |||
+ | import ResMgr<br /> | |||
+ | ||||
+ | <pre>#функция</pre> | |||
+ | def read_file(vfs_path, read_as_binary=True): | |||
+ | :vfs_file = ResMgr.openSection(vfs_path) | |||
+ | :if vfs_file is not None and ResMgr.isFile(vfs_path): | |||
+ | ::if read_as_binary: | |||
+ | :::return str(vfs_file.asBinary) | |||
+ | ::else: | |||
+ | :::return str(vfs_file.asString) | |||
+ | :return None<br /> | |||
+ | <br /> | |||
+ | ||||
+ | <pre>#пример использования</pre> | |||
+ | myscript = read_file('scripts/client/gui/mods/mod_mycoolmod.pyc') | |||
+ | </div> | |||
+ | ||||
+ | ==== Получение списка элементов в каталоге ==== | |||
+ | <div class="pre_code monospace"> | |||
+ | <pre>#импорт</pre> | |||
+ | import ResMgr | |||
+ | <pre>#функция</pre> | |||
+ | def list_directory(vfs_directory): | |||
+ | :result = [] | |||
+ | :folder = ResMgr.openSection(vfs_directory)<br /> | |||
+ | ||||
+ | :if folder is not None and ResMgr.isDir(vfs_directory): | |||
+ | ::for name in folder.keys(): | |||
+ | :::if name not in result: | |||
+ | ::::result.append(name)<br /> | |||
+ | ||||
+ | :return sorted(result) | |||
+ | <pre>#пример использования</pre> | |||
+ | content = list_directory('scripts/client/gui/mods/') | |||
+ | </div> | |||
+ | ||||
+ | ==== Копирование файла из пакета в каталог ==== | |||
+ | <div class="pre_code monospace"> | |||
+ | <pre>#импорт</pre> | |||
+ | import os | |||
+ | import ResMgr | |||
+ | <pre>#функция</pre> | |||
+ | def file_copy(vfs_from, realfs_to) | |||
+ | :realfs_directory = os.path.dirname(realfs_to) | |||
+ | :if not os.path.exists(realfs_directory): | |||
+ | ::os.makedirs(realfs_directory)<br /> | |||
+ | ||||
+ | :vfs_data = file_read(vfs_from) #смотрите 8.1.1 | |||
+ | :if vfs_data: | |||
+ | ::with open(realfs_to, 'wb') as realfs_file: | |||
+ | :::realfs_file.write(vfs_data)<br /> | |||
+ | ||||
+ | <pre>#пример использования</pre> | |||
+ | file_copy('scripts/client/gui/mods/mod_my.pyc','res_mods/0.9.17.1/scripts/client/gui/mods/mod_my. | |||
+ | pyc') | |||
+ | </div> | |||
+ | <br /> | |||
+ | == Известные проблемы == | |||
+ | ||||
+ | === Регистрозависимость имён файлов === | |||
+ | '''Описание проблемы'''<br /> | |||
+ | ||||
+ | На данный момент, при монтировании файлов в виртуальную файловую систему: | |||
+ | *файлы из пакетов монтируются в нижнем регистре | |||
+ | *файлы из {{Intext code|<каталог_WoT>/res_mods/}} монтируются как есть | |||
+ | В результате, если файл содержится как в пакете, так и в {{Intext code|res_mods}} , и при этом содержит хоть один символ в имени в верхнем регистре, то есть вероятность повторной загрузки файла.<br /> | |||
+ | ||||
+ | '''Временное решение'''<br /> | |||
+ | ||||
+ | Использовать для {{Intext code|<каталог_WoT>/res_mods}} только имена файлов и каталогов в нижнем регистре. | |||
+ | ||||
+ | === Работа с файлами GNU Gettext === | |||
+ | '''Описание проблемы'''<br /> | |||
+ | ||||
+ | На данный момент невозможно переопределить {{Intext code|.mo}} -файлы из {{Intext code|<каталог_WoT>/res/text/LC_MESSAGES/}} файлами из пакета.<br /> | |||
+ | ||||
+ | '''Временное решение'''<br /> | |||
+ | ||||
+ | В качестве временного решения, вы можете использовать пакет {{Intext code|net.openwg.vfsgettext}} :<br /> | |||
+ | ||||
+ | https://openwg.net/download/vfsgettext/net.openwg.vfsgettext_1.0.0.wotmod | |||
+ | ||||
+ | === Исполнение {{Intext code|.py}} файлов === | |||
+ | '''Описание проблемы'''<br /> | |||
+ | ||||
+ | На данный момент невозможно исполнение {{Intext code|.py}} -файлов, которые размещены внутри пакета.<br /> | |||
+ | ||||
+ | '''Временное решение'''<br /> | |||
+ | ||||
+ | Размещать в пакете не только {{Intext code|.py}} , но и скомпилированные в байткод {{Intext code|.pyc}} -файлы. | |||
+ | ||||
+ | === Переопределение порядка монтирования пакетов === | |||
+ | '''Описание проблемы'''<br /> | |||
+ | ||||
+ | На данный момент невозможно переопределить порядок монтирования пакетов используя файл {{Intext code|load_order.xml}} .<br /> | |||
+ | ||||
+ | '''Временное решение''' | |||
+ | Нет известного решения. Решение ожидается в скором времени. | |||
+ | ||||
+ | == Приложение А. Список изменений == | |||
+ | === v 0.4 (2017-05-04) === | |||
+ | * Переработано описание разрешения конфликтов между пакетами с помощью файла {{Intext code|load_order.xml}} | |||
+ | === v 0.3 (2017-05-03) === | |||
+ | *добавлена информация про ограничения формата файлов {{Intext code|.wotmod}} | |||
+ | *дополнено описание алгоритма разрешения конфликтов для пакетов с одинаковым идентификатором | |||
+ | === v 0.2 (2017-04-10) === | |||
+ | *переработка оформления: новая вёрстка, разбиение на главы; | |||
+ | *переработано описание схемы именования пакетов | |||
+ | *переработано описание порядка подключения пакетов | |||
+ | *добавлены рекомендации насчёт мест хранения журналов и файлов конфигурации | |||
+ | *добавлены примеры исходного кода для работы с файлами внутри пакетов; | |||
+ | *добавлено описание известных на текущий момент проблем | |||
+ | === v 0.1 (2017-01-13) === | |||
+ | *Первая версия | |||
</div> | </div> |
Текущая версия на 12:54, 8 января 2019
version 0.4, 2017-05-04
- Anton Bobrov, Wargaming.net
- Mikhail Paulyshka, XVM team
- Andrey Andruschyshyn, Independent
- Koreanrandom.com community
License: CC BY-SA 4.0
Содержание
Общая информация
Пакеты это
способ организации файлов модификаций, в котором весь контент отдельной модификации
упакован в один файл.
В случае использования старой схемы распространения файлов, модификации устанавливаются в каталог <каталог WoT>/res_mods/<версия WoT>/.При этом, файлы разных модификаций располагаются в одних и тех же каталогах, и поэтому зачастую трудно определить, какой файл относится к какой именно модификации.
Переход на дистрибуцию в пакетах может существенно упростить организацию файлов модификаций: для установки пользователю достаточно скопировать пакет в каталог <каталог WoT>/mods/<версия WoT>/ , а для деинсталляции удалить ровно тот же файл.
Структура пакета
Пакет представляет собой zip-архив со следующими свойствами:
- без сжатия
- расширение: .wotmod
- максимальный размер архива: 2 ГиБ - 1 байт (2 147 483 647 байт)
Внимание: архивы с компрессией в текущей версии World of Tanks не поддерживаются, поэтому, при создании архивов необходимо установливать опцию «уровень сжатия» в значение «без сжатия».
архивы размером 2 ГиБ и больше в текущей версии World of Tanks не поддерживаются, поэтому большие пакеты необходимо разбивать на более мелкие, размер каждого из которых не будет превышает 2 ГиБ - 1 байт.
Внутри себя пакет содержит:
- обязательно: каталог /res/. Сюда помещаются ресурсы модификации, то есть все те файлы, которые раньше устанавливались в <каталог WoT>/res_mods/<версия WoT>
- опционально: служебный файл meta.xml (смотрите раздел 5)
- опционально: файл LICENSE с лицензионным соглашением
- опционально: любой иной контент, который может понадобиться автору модификации: ссылка на сайт модификации, документация, список изменений и тому подобное.
Пример структуры пакета:
- /package.wotmod
- /meta.xml
- /README.md
- /LICENSE
- /res
- /scripts
- /client
- /gui
- /mods
- /mod_example.pyc
- /mods
- /gui
- /client
- /scripts
Установка пакета
Пакеты устанавливаются в <каталог WoT>/mods/<версия WoT>. Это может быть как ручное копирование, так и установка посредством инсталятора модификации или сборки модификаций.
При необходимости, пакеты могут быть организованы в подкаталоги, что позволяет авторам сборок модификаций выполнять группировку файлов:
mods/
- 0.9.17.1/
- MultiHitLog_2.8.wotmod
- DamagePanel/
- Some_common_library_3.14.5.wotmod
- DamagePanel_2.6.wotmod
- DamagePanel_2.8.wotmod
- DamagePanel_2.8_patch1.wotmod
Рекомендации по именованию пакетов
Для имени пакета (в дальнейшем package_id ) рекомендована следующая схема формирования:
package_id = author_id.mod_id
Где:
- author_id : идентификатор автора. Может быть сайтом разработчика модификации
( com.example ) или же просто его никнеймом ( noname )
- mod_id : идентификатор модификации. Выбирается автором модификации произвольно.
Данное имя используется в файле meta.xml (смотрите раздел 5), а также как часть имени файла
пакета.
Пример имён пакетов:
com.example.coolmod noname.supermod
Имя файла пакета формируется следующим образом:
<author_id>.<mod_id>_<mod_version>.wotmod
Где:
- mod_version : версия модификации, задаётся автором в meta.xml (смотрите раздел 5).
Примеры:
com.example.coolmod_0.1.wotmod
noname.supermod_0.2.8.wotmod
Файл метаданных meta.xml
Необязательный файл meta.xml содержит опциональные поля, описывающие модификацию.
Пример заполнения:
<root>
- <!‐‐ Идентификатор пакета ‐‐>
- <id>noname.crosshair</id>
- <!‐‐ Версия пакета ‐‐>
- <version>0.2.8</version>
- <!‐‐ Имя пакета понятное для пользователя ‐‐>
- <name>Crosshair</name>
- <!‐‐ Описание пакета ‐‐>
- <description>New cool Crosshair with feature1.....N</description>
</root>
Значения из полей <id> и <version> используются для определения порядка монтирования пакетов. Значения полей <name> и <description> в будущем будут использоваться в системе управления модификациями.
Загрузка пакетов
Порядок загрузки
Все пакеты, находящиеся в каталоге <каталог_WoT>/mods/<версия_WoT>/ , сортируются по значению узла <id> в файле meta.xml и загружаются по порядку. В случае отсутствия файла meta.xml внутри пакета, в качестве идентификатора пакета будет использовано имя файла.
Для переопределения порядка загрузки может быть использован файл load_order.xml , который должен находиться в вышеуказанном каталоге.
В случае, если все пакеты указаны в load_order.xml , то загрузка выполняется в указанном в файле порядке.
В случае, если часть пакетов в load_order.xml не указана, то сначала выполняется загрузка пакетов из load_order.xml , а затем отсутствующих в нём пакетов в алфавитном порядке.
Внимание: в данный момент использование файла load_orders.xml затруднено (смотрите раздел 9.4).
Совместное использование пакетов и res_mods
С точки зрения клиента игры, корень виртуальной системы формируется из:
- /res_mods/<версия_WoT>
- /mods/<версия_WoT>/<имя_пакета>.wotmod/res/
- /res/packages/*.pkg/
- /res/
- Иные пути, указанные в файле <Каталог_WoT>/paths.xml
Пути указаны в порядке уменьшения приоритета. То есть, файлы из /res_mods/<версия_WoT>/ имеют наивысший приоритет вне зависимости от содержания load_order.xml
Разрешение конфликтов при загрузке
В общем случае, система пакетов не допускает ситуации, когда в каталоге res/ внутри разных пакетов находятся одинаковые файлы. Такая ситуация cчитается конфликтом.
В случае обнаружения конфликта, вызвавший его пакет не будет загружен, а пользователю будет
показано соответствующее уведомление.
Например, если пакеты a.wotmod и b.wotmod будут содержать внутри себя файл res/scripts/entities.xml , то a.wotmod будет загружен успешно, а b.wotmod вызовет конфликт и загружен не будет.
Для управления обработкой конфликтов можно использовать:
1. Файл load_order.xml .
- <root>
- <Collection>
- <pkg>имя_пакета_1.wotmod</pkg>
- <pkg>имя_пакета_2.wotmod</pkg>
- <!‐‐ ... ‐‐>
- <pkg>имя_пакета_N.wotmod</pkg>
- </Collection>
- <Collection>
- </root>
Пакеты, перечисленные в этом файле, не считаются конфликтующими и загружаются без анализа на пересечение имен файлов.
2. Значение узлов <id> и <version> из meta.xml .
При наличии узла <id> в файле meta.xml , имя файла пакета не влияет на порядок загрузки. Пакеты, у которых <id> совпадает, считаются разными версиями или частями одной и той же модификации, и конфликты между ними также не учитываются. Данные пакеты загружаются в порядке увеличения версии.
Версии пакетов сравниваются посимвольно согласно таблице ASCII. Поведение совпадает с функцией strcmp():
- версия 9.0.0 приоритетнее версии 10.0.0
- версия b приоритетнее версии B
- версия c<любые символы> приоритетнее версии c
- если версии совпадают, то приоритет у пакета, имя файла которого будет первым по алфавиту.
При наличии одноименных файлов внутри разных пакетов, конфликты между которыми разрешены посредством load_order.xml или meta.xml , приоритет имеет файл из пакета, который был подключен последним или имеет наибольшее значение <version> .
Исполнение Python-кода
После монтирования всех пакетов и разрешения конфликтов, происходит исполнение всех .pyc - файлов из каталога /scripts/client/gui/mods/ в алфавитном порядке, имя которых начинается с mod_ . В пакете данный файл должен быть расположен по следующему пути:
<author_id>.<mod_id>_<version>.wotmod/res/scripts/client/gui/mods/mod_<anything>.pyc
Рекомендованные пути для файлов модификаций
Файлы конфигурации
Для хранения файлов конфигурации модификаций рекомендованно использовать путь
<каталог_WoT>/mods/configs/<author_id>.<mod_id>/
Где:
author_id и mod_id - идентификаторы, описаные в разделе 4 данной спецификации.
Файлы журналов
Помимо штатного файла python.log , для хранения журналов рекомендованно использовать путь:
<каталог_WoT>/mods/logs/<author_id>.<mod_id>/
Где:
author_id и mod_id - идентификаторы, описаные в разделе 4 данной спецификации.
Временные файлы
Для хранения временных файлов модификации рекомендованно использовать следующий путь:
<temp>/world_of_tanks/<author_id>.<mod_id>/
Где:
- temp - путь к каталогу с временными файлами для текущего пользователя в ОС;
- author_id и mod_id - идентификаторы, описаные в разделе 4 данной спецификации.
Иные файлы модификации
Для хранения внутри пакета контента, к которому необходимо получить доступ из клиента игры, рекомендованно использовать следующий путь:
<имя_пакета>.wotmod/res/mods/<author_id>.<mod_id>/
Где:
author_id и mod_id - идентификаторы, описаные в разделе 4 данной спецификации.
Работа с файлами внутри пакетов
Для работы с файлами внутри пакетов необходимо использовать модуль ResMgr .
Типовые операции
Чтение файла из пакета
#импорт
import ResMgr
#функция
def read_file(vfs_path, read_as_binary=True):
- vfs_file = ResMgr.openSection(vfs_path)
- if vfs_file is not None and ResMgr.isFile(vfs_path):
- if read_as_binary:
- return str(vfs_file.asBinary)
- else:
- return str(vfs_file.asString)
- if read_as_binary:
- return None
#пример использования
myscript = read_file('scripts/client/gui/mods/mod_mycoolmod.pyc')
Получение списка элементов в каталоге
#импорт
import ResMgr
#функция
def list_directory(vfs_directory):
- result = []
- folder = ResMgr.openSection(vfs_directory)
- if folder is not None and ResMgr.isDir(vfs_directory):
- for name in folder.keys():
- if name not in result:
- result.append(name)
- result.append(name)
- if name not in result:
- for name in folder.keys():
- return sorted(result)
#пример использования
content = list_directory('scripts/client/gui/mods/')
Копирование файла из пакета в каталог
#импорт
import os import ResMgr
#функция
def file_copy(vfs_from, realfs_to)
- realfs_directory = os.path.dirname(realfs_to)
- if not os.path.exists(realfs_directory):
- os.makedirs(realfs_directory)
- os.makedirs(realfs_directory)
- vfs_data = file_read(vfs_from) #смотрите 8.1.1
- if vfs_data:
- with open(realfs_to, 'wb') as realfs_file:
- realfs_file.write(vfs_data)
- realfs_file.write(vfs_data)
- with open(realfs_to, 'wb') as realfs_file:
#пример использования
file_copy('scripts/client/gui/mods/mod_my.pyc','res_mods/0.9.17.1/scripts/client/gui/mods/mod_my. pyc')
Известные проблемы
Регистрозависимость имён файлов
Описание проблемы
На данный момент, при монтировании файлов в виртуальную файловую систему:
- файлы из пакетов монтируются в нижнем регистре
- файлы из <каталог_WoT>/res_mods/ монтируются как есть
В результате, если файл содержится как в пакете, так и в res_mods , и при этом содержит хоть один символ в имени в верхнем регистре, то есть вероятность повторной загрузки файла.
Временное решение
Использовать для <каталог_WoT>/res_mods только имена файлов и каталогов в нижнем регистре.
Работа с файлами GNU Gettext
Описание проблемы
На данный момент невозможно переопределить .mo -файлы из <каталог_WoT>/res/text/LC_MESSAGES/ файлами из пакета.
Временное решение
В качестве временного решения, вы можете использовать пакет net.openwg.vfsgettext :
https://openwg.net/download/vfsgettext/net.openwg.vfsgettext_1.0.0.wotmod
Исполнение .py файлов
Описание проблемы
На данный момент невозможно исполнение .py -файлов, которые размещены внутри пакета.
Временное решение
Размещать в пакете не только .py , но и скомпилированные в байткод .pyc -файлы.
Переопределение порядка монтирования пакетов
Описание проблемы
На данный момент невозможно переопределить порядок монтирования пакетов используя файл load_order.xml .
Временное решение Нет известного решения. Решение ожидается в скором времени.
Приложение А. Список изменений
v 0.4 (2017-05-04)
- Переработано описание разрешения конфликтов между пакетами с помощью файла load_order.xml
v 0.3 (2017-05-03)
- добавлена информация про ограничения формата файлов .wotmod
- дополнено описание алгоритма разрешения конфликтов для пакетов с одинаковым идентификатором
v 0.2 (2017-04-10)
- переработка оформления: новая вёрстка, разбиение на главы;
- переработано описание схемы именования пакетов
- переработано описание порядка подключения пакетов
- добавлены рекомендации насчёт мест хранения журналов и файлов конфигурации
- добавлены примеры исходного кода для работы с файлами внутри пакетов;
- добавлено описание известных на текущий момент проблем
v 0.1 (2017-01-13)
- Первая версия