Кейс · HotlineTrade · DayZ
Два файла, из которых вырос портал сервера
Магазин на HotlineTrade у всех одинаковый, и менять в нём можно ровно два файла. Этого хватило, чтобы на dayzhhz.ru появились вики, карта и прайс торговцев, которых нет ни у кого из соседей.
- 2 файла
- весь доступ к чужой CMS
- 12 КБ
- глобальный бандл на всех страницах
- 1261
- позиция в прайсе, с именами вместо классов
Сайт есть у всех, а пользы от него мало
HOTLINETRADE выдаёт владельцу сервера готовый магазин: товары, оплата, автоматическая выдача. Это работает, и именно поэтому на нём сидят сотни серверов. Но сайт у всех получается один и тот же. Игрок заходит, покупает сет, закрывает вкладку.
А вопросы у него остаются те же, что и были. Где безопасная зона. Сколько стоит патрон у автоторговца. Когда следующий рестарт. Что вообще лежит в сете за 500 рублей. Всё это живёт в Discord, в закреплённых сообщениях, которые никто не читает, и в ответах администрации по кругу.
Сайт для этого подходит лучше Discord. Проблема в том, что сайт вам не принадлежит.
Что вообще можно менять
CMS закрытая, на Inertia.js. Исходников нет и не будет. В панели доступны ровно два файла, которые подключаются на каждой странице:
js_custom.jsstyle_custom.css
Всё. Ни шаблонов, ни роутов, ни API, ни сборки. Отсюда обычно делается вывод, что кастомизация на HotlineTrade заканчивается на перекраске кнопок.
Вывод неверный. Два файла на каждой странице - это точка входа. Дальше вопрос только в том, насколько аккуратно вы ей распорядитесь.
Ловушка, в которую я сам влез первой же версией
На сервере HeadhunterZ не было ничего: оба файла пустые, всё писалось с нуля. Первая версия вышла быстро, 602 строки JavaScript и 1690 строк CSS, и держалась она на одной строке:
document.addEventListener("inertia:navigate", boostrap);
Инициализация висела только на событии навигации Inertia, и последствий было два, оба неприятные. На холодной загрузке, когда игрок пришёл по прямой ссылке, скрипт не срабатывал вообще. А на каждом переходе внутри сайта он вешал ещё один комплект обработчиков поверх предыдущего: походил по разделам, получил пять копий одного и того же слушателя и подтормаживающую страницу.
Ловушка неочевидная, потому что Inertia ведёт себя не как обычный сайт: переходы идут
без перезагрузки, так что наивный DOMContentLoaded не работает тоже. Правильный ответ
здесь - один комплект наблюдателей за DOM на загрузку страницы, которые сами замечают,
что контент переехал. Ровно с этого и началась вторая версия, с которой сайт живёт
сейчас.
Если вам уже писали кастом под HotlineTrade, откройте js_custom.js и посмотрите на
последние строки. Эта штука встречается постоянно.
Что в итоге стоит на dayzhhz.ru
Дальше по нарастающей, от мелочей до того, ради чего всё затевалось.
Мониторинг с временем рестарта. В баннер онлайна дописывается строка с ближайшим рестартом и обратным отсчётом, которая подсвечивается за десять минут до него. Считается в UTC, чтобы игрок из другого пояса видел своё время, а не московское.
Баннер рейд-тайма. Появляется, когда рейд идёт или начнётся в ближайшие сутки, и молчит в остальное время. Показывать его всю неделю бессмысленно: это перестаёт быть новостью и становится шумом.
Состав сета прямо в карточке товара. Магазин отдаёт конфигурацию сета в разметке карточки. Я разбираю её и рисую боковую панель: что именно входит, в какой слот, какого размера рюкзак, что на оружии навешано. Карточка появляется мгновенно, а размеры инвентаря дозагружаются отдельным запросом и дорисовываются, когда придут. Если не придут, карточка просто останется без них: это рабочее состояние, а не ошибка.
Вики сервера. 20 страниц, 14 готовых: правила, рейды, ивенты, крафт, бусты, валюта, кланы. С оглавлением, поиском и нормальной вёрсткой. Тексты лежат в markdown и собираются в один файл данных.
Интерактивная карта. 57 зон и 47 точек: безопасные зоны, торговцы, места падения спецгруза, зоны патрульного вертолёта, полоса запрета строительства вдоль берега. Координаты игровые, в метрах, взяты из конфигов сервера, а не нарисованы на глаз. Одноимённые зоны одного вида сливаются в одну фигуру через SVG-маску, иначе на пересечениях получается грязь из дуг и потемнений.
Прайс всех торговцев. 8 торговцев, 1261 позиция, с поиском и фильтром по категориям.
Цены берутся из настоящего TraderConfig.txt сервера, то есть разойтись с игрой они
не могут в принципе.
Прайс, из-за которого всё усложнилось
Прайс выглядит как самая простая часть работы. Взять конфиг торговцев, разложить в таблицу. Час работы.
Пока не посмотришь, что в конфиге лежит. А лежит там вот это:
HH_PKM, izh43shotgun, HH_Mag_VR80_30Rnd
Игроку нужно «ПКМ», «ИЖ-43» и «Магазин VR80 на 30 патронов». Прайс из классов это не прайс, это дамп базы, который читать невозможно.
Названия предметов лежат в самой игре и в модах, внутри PBO-архивов. Путь получился
такой: распаковать PBO, вытащить из них stringtable.csv и config.bin, прогнать
конфиги через CfgConvert из DayZ Tools, собрать словарь классов. Работает.
Дальше выяснилось, что половина модпака обфусцирована. ClothingHH2, VestHH,
Head_gearHH, медицина, майнинг, машины: эти PBO не открывает даже официальный
инструмент, он честно отвечает «Obfuscated PBO». Имён оттуда не достать ничем.
Часть вытаскивается обходным путём. Сервер переносит чужой предмет к себе под своим
классом, но локаль исходного мода никуда не девается, и по якорному слову класса
имя находится. Правило пришлось сузить, чтобы HH_Cassette_Recorder не получил имя
кассеты, а магазин имя оружия. Всё, что найдено так, помечено как догадка и проверено
глазами.
Остаток добивается с другой стороны: я написал собственный мод под DayZ, который при запуске игры обходит конфиг предметов изнутри и выгружает его в JSON. 11625 классов с размерами, весом, слотами и навеской. Заодно отсюда же берутся размеры инвентаря для карточек магазина.
Сверху лежит ручной словарь: туда идут серверные предметы, которых нет нигде, и исправления там, где автоматика ошиблась. Прогон инструментов эти правки не затирает.
Итог: в прайсе все 1261 позиция с человеческими названиями. В полном списке предметов 217 классов из 985 так и остались классами, у них имён нет нигде, кроме как у администрации сервера.
Это тот случай, когда задача на час превращается в три дня. И ровно это отличает рабочий прайс от таблицы, которую игроки не открывают.
Как это устроено, чтобы не сломать магазин
Соблазн очевидный: свалить всё в js_custom.js и забыть. Так делать нельзя, этот файл
грузится на каждой странице магазина, включая оплату.
Поэтому в глобальном бандле лежит только то, что нужно везде: мониторинг, рейд-тайм,
сайдбар, мелочи оформления. 12 килобайт. Плюс два загрузчика: увидев на странице пустой
<div id="hhz-wiki"> или <div id="hhz-map">, бандл подтягивает тяжёлую часть с
отдельного сервера.
В самой CMS при этом лежит буквально один пустой div на страницу. Всё остальное, код, тексты, карта и цены, живёт в одном репозитории и деплоится оттуда. Добавить статью в вики означает добавить markdown-файл и запушить, а не лезть в админку CMS.
Руками в панель заливаются только те самые два файла, и только когда менялась общая часть.
Что это даёт владельцу сервера
Честно, без выдуманных процентов: сквозной аналитики до и после я не ставил, и обещать вам рост доната на цифрах не буду.
Что происходит по механике:
- Повторяющиеся вопросы уходят из Discord на страницу, куда можно дать ссылку один раз.
- Прайс превращается в витрину: игрок видит, что есть на сервере и сколько стоит, ещё до того как зайти в игру.
- Карточка товара перестаёт быть котом в мешке, состав сета виден целиком.
- Новичок разбирается в правилах и особенностях сервера до первого вайпа, а не после жалобы в поддержку.
- Сайт становится поводом вернуться, а не разовой кассой.
Сколько это заняло
Первая рабочая версия поднялась за четыре дня: 83 коммита, около 2700 строк TypeScript, плюс мод-выгрузчик для игры. Быстро получилось не потому, что задача простая, а потому что во второй версии архитектура встала правильно: один репозиторий, три цели сборки, контент отдельно от кода.
Для следующего сервера повторять эту дорогу целиком не нужно. Движок вики, карта, прайс и разбор конфигов торговцев уже написаны. Меняются данные, стиль под ваш сайт и то, что специфично именно для вашего мод-пака.
Сделаю то же самое вашему серверу
Беру сайт на HotlineTrade и довожу его до портала: вики, карта, прайс, ТТХ в карточках магазина. Под ключ, от первого созвона до залитых в CMS файлов. Напишите, какой у вас сервер и что болит.