- Версия(и) Minecraft
- 1.0+
Список сокращений
Лаунчер - программа для загрузки и запуска игры;ОС - операционная система;
JRE - Java Runtime Environment, программное обеспечение для запуска Java приложений;
Ассеты - игровые ресурсы;
Нативы - библиотеки для выполнения Java приложения на определенной платформе (семейство ОС);
Гб - гигабайт (1024 мегабайта);
Мб - мегабайт (1024 килобайта);
ОЗУ - Оперативно Запоминающее Устройство, если проще, оперативная память;
JVM - Виртуальная Машина Java, среда выполнения Java приложения;
Токен - ключ доступа, используемый для авторизации на серверах игры(доступ к скинам и Realms)
Вступ
Лаунчер занимается запуском игры, загрузкой игровых файлов, подключением скинов и тд. Здесь мы разберем конкретно процесс запуска и повторим его в простой оболочке - батнике (исполняемый скрипт для командной строки Windows). Для удобства давайте выстроим примерный процесс запуска игры с помощью лаунчера:- Получение нужной информации о системе (разрядность JRE, семейство ОС);
- Аутентификация пользователя;
- Получение идентификатора пользователя и токена;
- Построение строки запуска;
- Выполнение строки запуска и скрытие лаунчера (для логирования возможных ошибок);
- Завершение процесса лаунчера после завершение процесса игры.
--argument
а JVM аргументы, -argument
.1. Базовая строка запуска
Откроем обычный блокнот и созданим в удобном месте файл с расширением .bat. Теперь, закроем блокнот и откроем созданный файл с помощью программы Notepad++. Перед дальнейшим редактированием советую отключить авто преобразование в UTF-8. Для этого снимем в настройках эту галочку:Для удобства будем использовать переменные. Для создания переменной используем запись типа
set имя=значение
. Создадим переменные с папками игры:
start.bat:
set dir=%AppData%\.minecraft
set ast=%AppData%\.minecraft\assets
set nat=%AppData%\.minecraft\natives
set lib=%AppData%\.minecraft\libraries
javaw аргументы[I]jvm главный[/I]класс программные_аргументы
Первое слово указывает запускаемое приложение из системных переменных(устанавливаются с установкой JRE), потом идут все JVM аргументы, указывается главный класс и в конце программные аргументы.
1. 1. 1. Аргументы JVM. Куча
Куча - это та область оперативной памяти компьютера, которая может быть использована Java приложением. Её размер задается двумя аргументами. Один задает её начальный размер, а второй, максимальный. Также, важно отметить, что лучше делать её фиксированной, ибо когда приложению не хватает начального объема, оно увеличивает его на какое-то значение, вплоть до максимально, что часто вызывает подлагивание. Начальный размер определяется аргументом -Xms4G
а максимальный -Xmx4G
. Буква G обозначает гигабайты, M - мегабайты. Ещё можно также этот объём памяти зарезервировать в самой ОС с помощью аргумета -XX:+AlwaysPreTouch
Получается мы делаем фиксированную кучу равной 4Гб ОЗУ и сразу же резервируем данный объём на уровне ОС. Теперь наша строка выглядит так:javaw -Xms4G -Xmx4G -XX:+AlwaysPreTouch
1. 1. 2. Аргументы JVM. Сборщик мусора
Сборщик мусора - это компонент JVM, который высвобождает ОЗУ методом очистки неиспользуемых данных, таких как промежуточные результаты вычислений. Сборщики мусора есть разные. разберем два самых популярных, они же ConcMarkSweepGC и G1GC. Не будем подробно вдаваться в принципы их работы, но уточню, что первый более эффективен для работы с малыми объёмами кучи в 1Гб и меньше. Второй более эффективен для кучи размером в 2Гб и больше. Эти сборщики мусора также имеют свои настройки.Для первого ключевыми настройками есть пауза перед очистками и количество используемых потоков (процессорных) для очистки. Пауза задается миллисекундами и более эффективное значение определяется путем проб, но обычно используется диапазон 250-1000мс. Потоки же настраиваются автоматически. Вот пример настройки первого сборщика мусора:
-XX:+UseConcMarkSweepGC -XX:MaxGCPauseMillis=1000
. Мы настроили его так, что очистка производится не больше раза в секунду и использет все доступные процессорные потоки.Второй же сборщик мусора более сложно настроить. Дело в том, что если первый сборщик, грубо говоря просто очищает мусор, то этот разделяет всю кучу на блоки, и очищает мусор с каждого блока, а при очистке приложение останавливается. Для этого сборщика мы настраиваем:
- Процент кучи под новые данные
- Процент кучи для резерва
- Максимальное время для сборки мусора
- Размер блоков, не больше 32М
-XX:+ParallelRefProcEnabled
. Вот пример:
-XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -XX:+ParallelRefProcEnabled
. Мы разрешаем использование экспериментальных аргументов, активируем сборщик и говорим ему распределять по 20% кучи под новые данные и резерв, очистку проводить не дольше 50мс и работать в более эффективном для мультиядерных ЦП режиме.Также, для версий Minecraft 1.14+ и версий Java 11+ есть смысл попробовать новые сборщики мусора. Они работают совсем по другим принцыпам нежели ConcMark или G1 и могут обеспечить более эффективную очистку мусора с меньшим влиянием на FPS/TPS. Первый это
-XX:+UseShenandoahGC
, который по моим наблюдениям является достаточно эффективнее G1. Второй это -XX:+UseZGC
, который является экспериментальным и его рекомендуется использовать с самыми новыми версиями Java. Он пока не показал себя намного эффективнее G1, но он скорее как "задел на будущее". Сами аргументы для активации этих сборщиков считаются экспериментальными, а значит без -XX:+UnlockExperimentalVMOptions
не обойтись. Незабудьте, эти сборщики совсем другие нежели ConcMark или G1, так что при их ипользовании очистите остальные аргументы, которые могут касатся сборщиков мусора. Также, в последних версиях Oracle Java они могут быть вырезаны/деактивированы, поэтому можете попробовать Adopt Open JDK.1. 2. Аргументы JVM. Дополнительно
Есть некоторые дополнительные аргументы, такие как указание названия лаунчера и его версии, указание версии и имени подсистемы DOS для управления файловой системой(иногда убирает проблему записи файлов сохранений):-XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe.heapdump - позволяет корректно записывать файлы дампов памяти при краше игры и адекватно переключатся игре на дискретную графику;
-Dos.name="Windows 10" - указание имени подсистемы DOS;
-Dos.version=10.0 - указание версии подсистемы DOS;
-Dminecraft.launcher.brand=my-best-launcher - название лаунчера;
-Dminecraft.launcher.version=2.0 - версия лаунчера;
-XX:+AggressiveOpts - использовать экспериментальные функции оптимизации.
Пример строки для Windows 10:
Код:
-Xms4G -Xmx4G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe.heapdump -Dos.name="Windows 10" -Dos.version=10.0 -Dminecraft.launcher.brand="console-minecraft-starter" -Dminecraft.launcher.version=2.5
1. 3. Аргументы JVM. Библиотеки
Теперь нужно указать пути к файлу конфигурации логирования (как не странно, не используется в пиратских лаунчерах), нативам и библиотекам игры. Тут мы и будем использовать установленные ранее переменные записью %имя_переменной%
.Файл конфигурации устанавливается аргументом -Dlog4j.configurationFile="%ast%\log_configs\client-1.12.xml", но если у вас нету этого файла, просто не используйте этот аргумент. Он настраивает логирование и архивацию устаревших логов.
Путь к нативам указывается через -Djava.library.path="%nat%". Но эти нативы нужно достать. Обычно, они хранятся в библиотеках игры и распаковываются во временную папку перед каждым запуском. Сами нативы это dll библиотеки от игрового движка LWJGL и нарратора(в новых версиях). Просто распакуйте их в папку
C:\Users\пользователь\AppData\Roaming\.minecraft\natives
а jar-ники с ними обычно находятся по путям libraries\com\mojang\text2speech\
и libraries\org\lwjgl
. Вот нативы для версии игры 1.14.4:А вот составление аргумента игровых библиотек займет наибольшее количество времени. Аргумент имеет вид -Cр "всепутибиблиотек". В скобках нужно указать через двоеточие пути ко всем jar-никам игры (их достаточно много). К примеру так:
-Cp "%lib%\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;%lib%\com\google\guava\guava\21.0\guava-21.0.jar;..."
Вот полный вид аргумента для всех библиотек:
Код:
-cp "%lib%\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;%lib%\com\google\guava\guava\21.0\guava-21.0.jar;%lib%\com\ibm\icu\icu4j-core-mojang\51.2\icu4j-core-mojang-51.2.jar;%lib%\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;%lib%\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;%lib%\com\mojang\brigadier\1.0.17\brigadier-1.0.17.jar;%lib%\com\mojang\datafixerupper\2.0.24\datafixerupper-2.0.24.jar;%lib%\com\mojang\javabridge\1.0.22\javabridge-1.0.22.jar;%lib%\com\mojang\patchy\1.1\patchy-1.1.jar;%lib%\com\mojang\text2speech\1.11.3\text2speech-1.11.3.jar;%lib%\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;%lib%\commons-io\commons-io\2.5\commons-io-2.5.jar;%lib%\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;%lib%\io\netty\netty-all\4.1.25.Final\netty-all-4.1.25.Final.jar;%lib%\it\unimi\dsi\fastutil\8.2.1\fastutil-8.2.1.jar;%lib%\net\java\dev\jna\jna\4.4.0\jna-4.4.0.jar;%lib%\net\java\dev\jna\platform\3.4.0\platform-3.4.0.jar;%lib%\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;%lib%\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;%lib%\net\sf\jopt-simple\jopt-simple\5.0.3\jopt-simple-5.0.3.jar;%lib%\optifine\launchwrapper-of\2.1\launchwrapper-of-2.1.jar;%lib%\optifine\OptiFine\1.14.4_HD_U_F5\OptiFine-1.14.4_HD_U_F5.jar;%lib%\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;%lib%\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar;%lib%\org\apache\httpcomponents\httpclient\4.3.3\httpclient-4.3.3.jar;%lib%\org\apache\httpcomponents\httpcore\4.3.2\httpcore-4.3.2.jar;%lib%\org\apache\logging\log4j\log4j-api\2.8.1\log4j-api-2.8.1.jar;%lib%\org\apache\logging\log4j\log4j-core\2.8.1\log4j-core-2.8.1.jar;%lib%\org\lwjgl\lwjgl\3.2.2\lwjgl-3.2.2.jar;%lib%\org\lwjgl\lwjgl-glfw\3.2.2\lwjgl-glfw-3.2.2.jar;%lib%\org\lwjgl\lwjgl-jemalloc\3.2.2\lwjgl-jemalloc-3.2.2.jar;%lib%\org\lwjgl\lwjgl-openal\3.2.2\lwjgl-openal-3.2.2.jar;%lib%\org\lwjgl\lwjgl-opengl\3.2.2\lwjgl-opengl-3.2.2.jar;%lib%\org\lwjgl\lwjgl-stb\3.2.2\lwjgl-stb-3.2.2.jar;%lib%\oshi-project\oshi-core\1.1\oshi-core-1.1.jar;%lib%\net\minecraft\client\1.14.4-OptiFine_HD_U_F5\1.14.4-OptiFine_HD_U_F5.jar"
2. Главный класс
Главный класс, это как кнопка зажигания в машине, сам небольшой, но запускает все. Для чистой версии это net.minecraft.client.main.Main
а для модифицированной (с OptiFine или Forge) это net.minecraft.launchwrapper.Launch
.3. Программные аргументы
Программные аргументы задают путь для хранения сохранений (миры, настройки, ресурспаки и тд.) путь к ассетам, их индекс и тд. Кроме твикера все они нужны. Обычно запись идет в виде --имя_аргумента значение
. Вот список аргументов:- --username никнейм
- --version версия_игры
- --gameDir папка_сохранений
- --assetsDir папка_ассетов
- --assetIndex индекс_ассетов (типа 1.14, 1.13, 1.12 и тд.)
- --uuid идентификатор_пользователя (если нету, указывайте null)
- --accessToken токен (если нету, указывайте null)
- --userType тип_пользователя (на что влияет не понятно, но надо)
- --versionType тип_версии (может влиять на надпись версии в главном меню игры)
- --tweakClass класс_твикер (в чистой версии не используется, а для OptiFine это optifine.OptiFineTweaker)
Код:
javaw -Xms4G -Xmx4G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe.heapdump -Dos.name="Windows 10" -Dminecraft.launcher.brand="cms" -Dminecraft.launcher.version=2.3 -Dlog4j.configurationFile="%ast%\log_configs\client-1.12.xml" -Djava.library.path="%nat%" -cp "%lib%\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;%lib%\com\google\guava\guava\21.0\guava-21.0.jar;%lib%\com\ibm\icu\icu4j-core-mojang\51.2\icu4j-core-mojang-51.2.jar;%lib%\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;%lib%\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;%lib%\com\mojang\brigadier\1.0.17\brigadier-1.0.17.jar;%lib%\com\mojang\datafixerupper\2.0.24\datafixerupper-2.0.24.jar;%lib%\com\mojang\javabridge\1.0.22\javabridge-1.0.22.jar;%lib%\com\mojang\patchy\1.1\patchy-1.1.jar;%lib%\com\mojang\text2speech\1.11.3\text2speech-1.11.3.jar;%lib%\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;%lib%\commons-io\commons-io\2.5\commons-io-2.5.jar;%lib%\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;%lib%\io\netty\netty-all\4.1.25.Final\netty-all-4.1.25.Final.jar;%lib%\it\unimi\dsi\fastutil\8.2.1\fastutil-8.2.1.jar;%lib%\net\java\dev\jna\jna\4.4.0\jna-4.4.0.jar;%lib%\net\java\dev\jna\platform\3.4.0\platform-3.4.0.jar;%lib%\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;%lib%\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;%lib%\net\sf\jopt-simple\jopt-simple\5.0.3\jopt-simple-5.0.3.jar;%lib%\optifine\launchwrapper-of\2.1\launchwrapper-of-2.1.jar;%lib%\optifine\OptiFine\1.14.4_HD_U_F5\OptiFine-1.14.4_HD_U_F5.jar;%lib%\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;%lib%\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar;%lib%\org\apache\httpcomponents\httpclient\4.3.3\httpclient-4.3.3.jar;%lib%\org\apache\httpcomponents\httpcore\4.3.2\httpcore-4.3.2.jar;%lib%\org\apache\logging\log4j\log4j-api\2.8.1\log4j-api-2.8.1.jar;%lib%\org\apache\logging\log4j\log4j-core\2.8.1\log4j-core-2.8.1.jar;%lib%\org\lwjgl\lwjgl\3.2.2\lwjgl-3.2.2.jar;%lib%\org\lwjgl\lwjgl-glfw\3.2.2\lwjgl-glfw-3.2.2.jar;%lib%\org\lwjgl\lwjgl-jemalloc\3.2.2\lwjgl-jemalloc-3.2.2.jar;%lib%\org\lwjgl\lwjgl-openal\3.2.2\lwjgl-openal-3.2.2.jar;%lib%\org\lwjgl\lwjgl-opengl\3.2.2\lwjgl-opengl-3.2.2.jar;%lib%\org\lwjgl\lwjgl-stb\3.2.2\lwjgl-stb-3.2.2.jar;%lib%\oshi-project\oshi-core\1.1\oshi-core-1.1.jar;%lib%\net\minecraft\client\1.14.4-OptiFine_HD_U_F5\1.14.4-OptiFine_HD_U_F5.jar" net.minecraft.launchwrapper.Launch --username "%usr%" --version 1.14.4-OptiFine_HD_U_F5 --gameDir "%dir%" --assetsDir "%ast%" --assetIndex 1.14 --uuid null --accessToken null --userType mojang --versionType release --tweakClass optifine.OptiFineTweaker
4. Оформление батника
Можно сделать наш лаунчер более интерактивным и привлекательным.Строка
title Launcher
установит имя окна с командами, запись @echo off
отключит вывод команды (не её результат). Также, командой echo ...
вы можете выводить свои сообщения, а с помощью cls
очищать их. Хотите оформление? Используйте color 0a
чтобы задать цвет фона первой цифрой и цвет символов второй буквой. Для установки переменной вводом используйте запись типа set /p usr=^>
(вот справка по кодам, тык)!Также, можно сделать авто скрытие лаунчера после ввода нужных данных. Для этого нужна утилита CMDOW, которая позволяет управлять самим окном консоли. Узнать более подробно о её функционале и скачать её можно здесь. В скачанном архиве по пути
bin\release
понадобится сама утилита (да, вся утилита это один файл). Файл для удобства можно переместить в папку игры в папку bin к примеру. Для скрытия окна консоли используйте команду cmdow.exe @ /HID
предварительно указав путь в переменных. Скрытие делайте до строки запуска, ибо в батнике одна строка выполняется только после конца работы той, что перед ней. А также рекомендуется, после выполнения строки запуска и выхода из игры (завершения работы строки запуска) завершить процесс cmd командой exit
.Важно! Для корректного отображения кириллицы установите кодировку батника на OEM-866!
Вот примерный вид после оформления:
И его код:
start.bat:
@echo off
color 0a
title Minecraft Launcher
set dir=%AppData%\.minecraft
set bin=%AppData%\.minecraft\bin
set run=%AppData%\.minecraft\runtime\bin
set nat=%AppData%\.minecraft\natives
set ast=%AppData%\.minecraft\assets
set lib=%AppData%\.minecraft\libraries
echo Какой никнейм желаете использовать?
set /p usr=^>
cls
echo Сколько гигабайт ОЗУ желаете выделить игре?
set /p ram=^>
cls
"%bin%\cmdow.exe" @ /HID
"%run%\javaw.exe" -Xms%ram%G -Xmx%ram%G -XX:+UnlockExperimentalVMOptions -XX:+UseG1GC -XX:G1NewSizePercent=20 -XX:G1ReservePercent=20 -XX:MaxGCPauseMillis=50 -XX:G1HeapRegionSize=32M -XX:HeapDumpPath=MojangTricksIntelDriversForPerformance_javaw.exe.heapdump -Dos.name="Windows 10" -Dminecraft.launcher.brand="cms" -Dminecraft.launcher.version=2.3 -Dlog4j.configurationFile="%ast%\log_configs\client-1.12.xml" -Djava.library.path="%nat%" -cp "%lib%\com\google\code\gson\gson\2.8.0\gson-2.8.0.jar;%lib%\com\google\guava\guava\21.0\guava-21.0.jar;%lib%\com\ibm\icu\icu4j-core-mojang\51.2\icu4j-core-mojang-51.2.jar;%lib%\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;%lib%\com\mojang\authlib\1.5.25\authlib-1.5.25.jar;%lib%\com\mojang\brigadier\1.0.17\brigadier-1.0.17.jar;%lib%\com\mojang\datafixerupper\2.0.24\datafixerupper-2.0.24.jar;%lib%\com\mojang\javabridge\1.0.22\javabridge-1.0.22.jar;%lib%\com\mojang\patchy\1.1\patchy-1.1.jar;%lib%\com\mojang\text2speech\1.11.3\text2speech-1.11.3.jar;%lib%\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;%lib%\commons-io\commons-io\2.5\commons-io-2.5.jar;%lib%\commons-logging\commons-logging\1.1.3\commons-logging-1.1.3.jar;%lib%\io\netty\netty-all\4.1.25.Final\netty-all-4.1.25.Final.jar;%lib%\it\unimi\dsi\fastutil\8.2.1\fastutil-8.2.1.jar;%lib%\net\java\dev\jna\jna\4.4.0\jna-4.4.0.jar;%lib%\net\java\dev\jna\platform\3.4.0\platform-3.4.0.jar;%lib%\net\java\jinput\jinput\2.0.5\jinput-2.0.5.jar;%lib%\net\java\jutils\jutils\1.0.0\jutils-1.0.0.jar;%lib%\net\sf\jopt-simple\jopt-simple\5.0.3\jopt-simple-5.0.3.jar;%lib%\optifine\launchwrapper-of\2.1\launchwrapper-of-2.1.jar;%lib%\optifine\OptiFine\1.14.4_HD_U_F5\OptiFine-1.14.4_HD_U_F5.jar;%lib%\org\apache\commons\commons-compress\1.8.1\commons-compress-1.8.1.jar;%lib%\org\apache\commons\commons-lang3\3.5\commons-lang3-3.5.jar;%lib%\org\apache\httpcomponents\httpclient\4.3.3\httpclient-4.3.3.jar;%lib%\org\apache\httpcomponents\httpcore\4.3.2\httpcore-4.3.2.jar;%lib%\org\apache\logging\log4j\log4j-api\2.8.1\log4j-api-2.8.1.jar;%lib%\org\apache\logging\log4j\log4j-core\2.8.1\log4j-core-2.8.1.jar;%lib%\org\lwjgl\lwjgl\3.2.2\lwjgl-3.2.2.jar;%lib%\org\lwjgl\lwjgl-glfw\3.2.2\lwjgl-glfw-3.2.2.jar;%lib%\org\lwjgl\lwjgl-jemalloc\3.2.2\lwjgl-jemalloc-3.2.2.jar;%lib%\org\lwjgl\lwjgl-openal\3.2.2\lwjgl-openal-3.2.2.jar;%lib%\org\lwjgl\lwjgl-opengl\3.2.2\lwjgl-opengl-3.2.2.jar;%lib%\org\lwjgl\lwjgl-stb\3.2.2\lwjgl-stb-3.2.2.jar;%lib%\oshi-project\oshi-core\1.1\oshi-core-1.1.jar;%lib%\net\minecraft\client\1.14.4-OptiFine_HD_U_F5\1.14.4-OptiFine_HD_U_F5.jar" net.minecraft.launchwrapper.Launch --username "%usr%" --version 1.14.4-OptiFine_HD_U_F5 --gameDir "%dir%" --assetsDir "%ast%" --assetIndex 1.14 --uuid null --accessToken null --userType mojang --versionType release --tweakClass optifine.OptiFineTweaker
del "%dir%\logs\*.gz"
exit
5. Компиляция в .exe
Возможно вы хотите не запукать какой-то там батник? Можем преобразовать его в обычный .exe с помощью программы Bat To Exe Converter. Можете скачать её здесь. Можете открыть свой батник, немного подредактировать и задать ему иконку или информацию о версии. Если увидите вместо русских надписей кракозябры, не волнуйтесь, после компиляции будет нормально. Когда завершили правки, просто нажмите на компиляцию и укажите путь сохранения и имя файла. Вуаля, теперь наш лаунчер - обычный исполняемый файл.