Клиентский интерфейс и DataCenter

Информация о клиенте, управление окном и запросы queryData к DataCenter.

Отдельное соединение с клиентом

mod.clientInterface — канал связи Toolbox с клиентской частью, отдельный от потока игровых пакетов. Он предоставляет информацию о процессе, управление окном и чтение DataCenter. Для клиентского модуля событие ready означает готовность интерфейса; готовность игровых справочников других модулей этим событием автоматически не гарантируется.

Информация о клиенте

mod.clientInterface.info содержит:

Поле Значение
pid, arch ID процесса и архитектура (x64/ia32)
publisher, platform, environment Издатель, платформа и окружение
language Язык DataCenter
path Путь к папке клиента, предоставленный интерфейсом
majorPatchVersion, minorPatchVersion Части версии патча из ReleaseRevision
protocolVersion Версия протокола/DataCenter, используемая в C_CHECK_VERSION
protocol Карта имен пакетов и opcode
sysmsg Карта имен и ID системных сообщений

В интерфейсе модуля также есть сокращения mod.publisher, mod.platform, mod.environment, mod.language, mod.majorPatchVersion, mod.minorPatchVersion, mod.clientFolder. Это информация о подключенном клиенте, а не о языке сайта или системной локали.

Окно и камера

Метод Назначение
flashWindow(count = 5, interval = 0, allowFocused = false) Мигание окна/кнопки на панели задач; параметры передаются клиенту
hasFocus() Promise с логическим признаком фокуса окна
configureCameraShake(enabled, power = 1.0, speed = 1.0) Включение тряски камеры и ее параметры
async function notifyIfInactive(mod) {
    try {
        if (!(await mod.clientInterface.hasFocus())) {
            mod.clientInterface.flashWindow();
        }
    } catch (error) {
        mod.error('Unable to query window focus:', error);
    }
}

queryData

mod.queryData(query, queryArgs = null, findAll = false, children = true, attributeFilter = null);

Это сокращение для mod.clientInterface.queryData(...). Метод возвращает Promise. findAll: true запрашивает массив узлов, иначе — один результат. Узел содержит attributes и, если запрошены, children; проверяйте наличие результата перед чтением полей.

Путь вида /ItemData/Item@id=?/ выбирает узлы, @ вводит условия, & объединяет условия. Значения ? берутся из queryArgs по порядку. Поддерживаются =, !=, >, >=, <, <=. Массив в параметре равенства означает выбор из набора; в неравенстве — исключение набора. Это язык запросов DataCenter, а не JavaScript или SQL.

Примеры запросов

// A creature name for the current client language.
const creature = await mod.queryData(
    '/StrSheet_Creature/HuntingZone@id=?/String@templateId=?',
    [huntingZoneId, templateId]
);
if (creature) mod.log(creature.attributes.name);

// Skill data with two conditions on the same node.
const skill = await mod.queryData(
    '/SkillData@huntingZoneId=?/Skill@templateId=?&id=?',
    [0, 16060, 10100]
);

// Item names, without child nodes.
const names = await mod.queryData('/StrSheet_Item/String/', [], true, false);
const itemNames = new Map(names.map((node) => [node.attributes.id, node.attributes.string]));

// Abnormality effects are child nodes.
const abnormality = await mod.queryData('/Abnormality/Abnormal@id=?/', [701420]);
if (abnormality) {
    for (const effect of abnormality.children) mod.log(effect.attributes);
}

// Hunting zones belonging to the current continent.
const zones = await mod.queryData(
    '/ContinentData/Continent@id=?/HuntingZone/', [mod.game.me.zone], true
);

// Comparisons and membership.
const ranked = await mod.queryData('/ItemData/Item@rank>=?/', [12], true, false);
const selected = await mod.queryData('/ItemData/Item@rank=?/', [[11, 12, 13]], true, false);

// Only the requested attributes, no children.
const items = await mod.queryData(
    '/ItemData/Item/', [], true, false, ['id', 'combatItemType']
);

Эти фрагменты выполняются внутри async-функции после готовности клиента. Названия таблиц, полей и ID зависят от патча. Для последующих сетевых обработчиков сохраните результат заранее; не делайте одинаковый запрос при каждом пакете.

Ошибки и производительность

Обрабатывайте отклонение Promise через try/catch или .catch(...): неверный запрос, параметры или недоступный интерфейс не должны оставлять необработанную ошибку. Не загружайте весь SkillData, если нужен один навык. Запрос выделяет память на стороне игрового клиента; объемные деревья дороги и для 32-, и для 64-битных клиентов. Используйте children: false, фильтр атрибутов и кеш. Для уже доступных предметов и эффектов сначала проверьте mod.game.data.

Источники: doc/mod/client-interface.md, node_modules/tera-client-interface/index.js, bin/mod.js.