Chimera Launcher

Посмотреть и раскритиковать

Я писал этот лаунчер для себя: хотел запускать Windows-игры на Linux и не держать в голове, чем Lutris отличается от Heroic и какой префикс к чему относится. Получилось приложение на Rust и GTK4, которым я пользуюсь каждый день.

Буду рад замечаниям. Особенно тем, что начинаются со слов «так делать нельзя, потому что».

Что посмотреть за пять минут

  1. Главная — что умеет, со снимками экрана.
  2. Исходники — всё дерево прямо в браузере. Или git clone https://project-chimera.ru/launcher/git/chimera-launcher.git
  3. Журнал разработки — что ломалось и чем чинилось. Там же видно, как я принимаю решения.
  4. Что уходит в сеть — таблица по каждому случаю.

Решения, о которых хочется поспорить

Каждое выбрано осознанно, но ни одно не бесспорно.

Настройки в четыре слоя

Значение настройки берётся из четырёх мест по порядку: умолчание, профиль сообщества, общие настройки, настройка этой игры. Выбор человека сильнее всех остальных слоёв.

Команда chl settings <игра> печатает итоговое значение и слой, из которого оно пришло. Без этого вопрос «почему игра запускается вот так» остаётся без ответа.

Спорно: четыре слоя сложнее двух. Я выбрал их, потому что советы сообщества нельзя класть в тот же файл, что и выбор человека — иначе чужой совет однажды перепишет ваш.

Один префикс на все игры

Wine-префикс — это «диск C:» для игры. Обычно на каждую игру заводят свой. Здесь он общий.

Спорно: общий префикс ломается сразу для всех игр. Взамен он не съедает по 3–6 ГБ на игру, а перед каждым изменением лаунчер снимает копию и умеет откатиться.

Настройки доходят до игр Steam без перезапуска Steam

Steam не перечитывает параметры запуска, пока его не перезапустишь (баг steam-for-linux#6443). Поэтому лаунчер ставит себя в compatibilitytools.d отдельным слоем совместимости: Steam запускает наш скрипт, он выставляет окружение и передаёт управление Proton.

Спорно: лезть в каталог чужой программы. Взамен настройки применяются на следующем запуске игры, а не после перезапуска Steam.

Витрина Epic: мы врали о себе, и защита ловила именно это

Перед сайтом Epic стоит Cloudflare, и встроенный браузер сутки упирался в «подтвердите, что вы человек». Я перебрал пять версий и все пять оказались мимо: защита от межсайтового отслеживания, нестабильный внешний адрес из-за туннеля, подмена внутренних признаков страницы, строка родного лаунчера Epic, разные строки для разных хостов. Каждая что-то чинила и ломала соседнее.

Причина была проще всех догадок. WebKitGTK называется Safari-подобной строкой, и это правда: у него нет ни navigator.userAgentData, ни остального, что есть у настоящего Chrome. Назвавшись Chrome, движок начинает противоречить сам себе — а Cloudflare ровно это и сверяет: заявленное против наблюдаемого. Увидев расхождение, он поднимает проверку до галочки, которую WebKitGTK уже не проходит.

Подмена строки убрана вовсе. Сайт видит Safari, каким браузер и является, и пропускает без единой проверки. Вход в витрину при этом берётся из токена лаунчера: пароль не вводится, галочка не появляется.

Тот же урок читается в исходниках Heroic: его preload подменяет navigator.platform и navigator.userAgentData — но только когда строка говорит «Windows». То есть он не выдаёт себя за чужой браузер, а следит, чтобы заявленное сходилось с наблюдаемым. Обработки Cloudflare у него нет вовсе.

Спорно: полтора десятка правок, каждая из которых лечила симптом очередной лжи о себе, — это полтора десятка мест, где я не проверил основание. Записано в журнал разработки как есть, вместе с ошибочными выводами по дороге.

Видеокарту выбирает человек, а не лаунчер

На машине с двумя видеокартами Vulkan отдаёт их списком, и нулевым устройством идёт встроенная в процессор. Нулевое берут все — и DXVK, и VKD3D, и всё, что переводит DirectX в Vulkan. То есть игры по умолчанию шли на встроенной, а дискретная простаивала, и внешне это неотличимо от «игра тяжёлая».

Настройка «Видеокарта» показывает найденные карты списком, с пометкой «дискретная» или «встроенная», и выбор уходит в слой Mesa device_select.

Спорно: очевидное умолчание — подставлять дискретную самим. Не делаю, потому что список стоит запуска vulkaninfo, а это двести миллисекунд на каждый запуск игры ради выбора, который человек делает один раз.

Сессия Steam берётся у клиента Steam

Витрина Steam внутри лаунчера открывается под аккаунтом. Лаунчер в Steam не входит и пароля не знает: он читает локальный файл cookies клиента Steam и берёт оттуда пять записей для двух доменов магазина.

Спорно сильнее всего. Читать чужие cookies — приём из арсенала другого жанра. Поэтому настройка выключается, а на странице «Приватность» написано, что именно читается и куда попадает.

Что я и сам считаю слабым

  • У записи игры нет поля «магазин». Epic и GOG пишутся одинаково, поэтому установленная игра из магазина попадает на обе вкладки библиотеки.
  • Число запусков у игр Steam своё, неполное. Наигранное время лаунчер берёт у самого Steam, а вот запусков Steam не считает вовсе — их видно только те, что сделаны отсюда. Поэтому средняя длина сессии считается лишь по своим запускам.
  • Нет оверлея поверх игры. Окно поверх игры не решает задачу: нужен слой Vulkan и перехват ввода.
  • Записи экрана нет. Хоткей зарезервирован, реализации нет.
  • Зеркало репозитория только на чтение. Прислать изменения пока некуда.
  • Тесты интерфейса проверяют сборку, а не поведение. Логика вынесена в чистые функции и покрыта, но щелчки по кнопкам никто не проверяет.

Куда писать

Про код и решения

Скажите мне напрямую. Зеркало пока только на чтение, так что обсуждение идёт словами, а не пул-реквестами.

Про баг в работе

Из лаунчера: «Диагностика» → «Отправить отчёт». Он соберёт нужное под симптом и покажет целиком до отправки.

Про игру, которая не идёт

Карточка игры → «Префикс» → «Поделиться своим опытом». Так наполняется база запусков.