# Лаунчер Minecraft: Java edition Є така гра, називається Minecraft. Ця гра запускається через "лаунчер". :::info **launcher**: з англійської "to launch" --- запустити, наприклад, "to launch a rocket" --- запустити ракету. **Запускатор**, **запускальщик** по нашому. ::: Навіть якщо ви запускаєте гру даблкліком на робочому столі, це запускає лаунчер, з якого запускається сама гра. Для скачування Майнкрафту (особливо якщо ми говоримо про Java edition) достатньо скачати лаунчер, а лаунчер зможе скачати саму гру і запустити її. Окрім стандартного лаунчера, існує повно інших лаунчерів: - MultiMC - TLauncher - GDLauncher - ... - кожен піратський сервер випускає свої лаунчери, які загружають свою "особливу" версію майкрафту, з фіксами, плагінами, патчами, модами, текстурпаками і тп. Я якось написав свій лаунчер. І я хотів би щоб ви також зрозуміли як це робиться. :::info Якщо комусь цікаво подивитись мій код --- ось він: - https://gist.github.com/danbst/a335b93f515606975bc1e6425ce9fecb ::: ## Технічні терміни - **операційна система** (ОС), **платформа** --- Windows, Linux або MacOS. - кросплатформернність --- підтримка кількох операційних систем. Як правило один і той же лаунчер файл не буде працювати на різних системах, тому потрібні платформо-специфічні версії - **файл** --- дані на диску. Найважливішим є те, що ці дані мають ім'я ("шлях до файлу") і залишаються після того як комп'ютер вимикається. Ці дані можна дістати програмно, якщо знати шлях до файлу - **папка**, **директорія** --- частина шляху до файлу до останнього слешу. Тобто, в шляху `C:\Users\test\somefile.exe` папкою буде `C:\Users\test\` - **ресурси** --- файли для закачки. Файли можуть бути будь-які --- картинки, екзешники, аудіо, текстові, ... - **ассети** --- список ресурсів, тобто, пакет файлів на закачку. - **артефакт** (artifact) --- фактично те саме, що і ресурс, але з точки зору розробника. Також може бути архівом і містити додаткову інформацію --- час створення, хеш, і тп. - **сервер ресурсів** --- сервер, з якого викачуються ресурси. Може співпадати з ігровим сервером, а може бути і стороннім. Якщо ресурс має хеш, то це дозволяє робити дзеркала серверів ресурсів - дзеркало --- альтернативний сервер, копія в іншому місці - **launcher** --- система, яка дозволяє запускати гру. Часто включає в себе докачку додаткових файлів (DLC), автентифікацію (логін-пароль) і верифікацію файлів гри (античіт) - **клієнт** --- та частина гри, яка знаходиться на комп'ютерів гравця. Іноді є просто папкою з файлами десь на диску, тому її можна переносити по диску. Але часто деякі файли роблять зашивки на шляхи, і переносити з місця на місце стає неможливим. - **версія** --- клієнт гри з іншим набором файлів та фіч. Якщо розробник додає нові фічі, то він називає їх новою версією, яку юзер може наново скачати - альфа версія --- версія з новими фічами і не дуже відтестована - бета версія --- версія з новими фічами і відтестована альфа-тестерами - реліз кандидат --- версія, відтестована бета-тестерами - реліз --- офіційний пакет гри, як правило це останній реліз-кандидат - патч версія --- версія після релізної, де виправляють баги та хаки, які не відловили тестери, альфа-тестери, бета-тестери та реліз-кандидат тестери - **параметри**, **аргументи** --- при запуску програми з командного рядка вказуються після назви програми. Дозволяють передавати в програму додаткові параметри (як це робить в функціях в Python). - **сервер** --- код, який отримує запити з клієнтів і реалізує механіку мультиплеєра. Як правило знаходиться НЕ НА комп'ютері гравця, але для деяких ігор можна запускати сервер на своєму комп'ютері. - **Java** --- мова програмування та крос-платформенна віртуальна машина. - **ліби**, **бібліотеки** --- куски коду (скопмпільованого або некомпільованого), які розширують або спрощують роботу з мовою програмування. Можуть використовуватися як і при компіляції, так і при фінальному запуску програми. - LWJGL --- бібліотека для Java для роботи з OpenGL (3D-графіка) - **.jar** --- файловий формат для біблотеки в Java. Є ZIP-архівом, тобто, його можна розпакувати архіватором. Містить скомпільовані класи Java - **Java аргументи** --- параметри запуску `java.exe`. Контролюють технічні нюанси, наприклад, кількість оперативної пам'яті та список біблотек для використання - **classpath** --- список шляхів бібліотек Java. Розділювач крапка з комою (на відновсі) або двокрапка (на лінуксі і MacOS). https://en.wikipedia.org/wiki/Classpath - **хеш** --- коротка послідовність символів, яка є "унікальною" для різних послдовностей даних. "Унікальною" в лапках, бо насправді існують два набори різних даних, які мають одинаковий хеш, але знайти такі пари майже нереально. - **JSON** --- текстовий формат даних. Складається з словників, списків, рядків та чисел. Його можуть читати та створювати всі мови програмування, тому він використовується для обміну даними між різними середовищами, і особливо його любить інтернет - **словник** --- структура даних, яка є набором пар "ключ-значення". Ключі в словнику завжди унікальні, значення можуть повторюватись. - **індекс** --- (тут) документ, який вказує лінки на файли які треба скачувати. Тобто, містить не файли для закачки, а список лінків для закачки - **парсинг** --- отримування структурної інформації з рядка. Наприклад, з рядків `"01.10.2021"` та `"2021-04-21"` (які є датами у різних форматах) дістати інформацію про "рік" можна тільки після парсингу - **запит**, **реквест** (request) --- взаємодія з інтернет сервером. Може бути запит на закачку документу, може бути запит на викачку файлу. ## Маніфест версій :::info https://launchermeta.mojang.com/mc/game/version_manifest.json ::: В цьому файлі знаходиться інформація про всі версії, які підтримуються для запуску стандартним лаунчером. ![](https://i.imgur.com/I1Hgeon.png) Це файл у форматі JSON. Ключ `"latest"` вказує на останню версію клієнта, а ключ `"versions"` є списком всіх можливих версій Майкрафта. Окрім снепшот версій є ще `release` версії: ![](https://i.imgur.com/uUE9iAV.png) І є різні альфа і бета версії: ![](https://i.imgur.com/543rHDW.png) :::info **Завдання:** Написати код, який пише на екран дату релізу найпершої версії майнкрафту, використовуючи маніфест версій. ::: :::info **Завдання:** Написати код, який виводить на екран всі релізні версії майнкрафту. ::: :::info **Завдання:** Написати код, який порахує, скільки різних версій майнкрафту (релізних і нерелізних) було випущено в кожен з років 2009--2021. ::: ## Пакетний індекс :::info Адреса, яка знаходиться в `url` ключі версії з маніфесту версій. Наприклад, https://launchermeta.mojang.com/v1/packages/dc5f9e134da9e18a2db42ddc246aba5cdfe28d3c/1.2.1.json ::: Пакетний індекс містить багато інформації про файли (з яких складається клієнт) і додаткову інформацію про те, як робити запуск. ![](https://i.imgur.com/hZKeVQx.png) - **assetIndex** вказує на список ассетів. Список ассетів знаходиться в іншому документі - **downloads** вказує на основні файли для завантаження. Наприклад, основний файл для запуску клієнту. Файл є ресурсом, тому скачується з серверу ресурсів (про це пізніше) - **libraries** вказує на додаткові бібліотеки для завантаження. Бібліотеки відповідають за 3Д графіку і інші системні задачі - **mainClass** вказує який клас з `.jar` клієнту треба запускати (нюанси Java) - **minecraftArguments** параметри запуску - і всякі інші параметри, непотрібні для запуску гри ### Сторонні ліби Окремо про бібліотеки в цьому документів. Інформація про лібу може бути "простою" (коли треба просто скачати і покласти в папку): ![](https://i.imgur.com/5vB5ju5.png) А може бути складною. :::info В яку папку класти бібліотеку? В принципі, це неважливо, головне потім вказати правильний шлях до бібліотеки у class path аргументі лаунчера. ::: #### Ліба для версії Деякі ліби доступні тільки для певних версій. Наприклад, ця ліба потрібна для всіх версій MacOS **окрім** 10.5.x ![](https://i.imgur.com/a8ZsB3t.png) А ось ця ліба потрібна **тільки** для MacOS версій 10.5.x ![](https://i.imgur.com/rvEJ47m.png) Тобто, механізм "правил" ("rules") дозволяє для різних версій викачувати різні версії різних біблотек. Наприклад, в цьому випадку у MacOS 10.5.x був якийсь баг, через який бібліотека LWJGL не працювала як треба, тому довелось скачувати пропатчену версію. #### Ліба для системи Деякі бібліотеки потрібна тільки для однієї з ОС. У цьому випадку структура виглядає трошки складнішою, але все що воно робить, це вибирає яку бібліотеку на якій операційній системі скачувати. ![](https://i.imgur.com/gW9yrQ4.png) :::info **Завдання:** дістати список назв бібліотек (ключ `name`) з пакетного індексу. ::: :::info **Завдання:** скачати програмно будь-яку бібліотеку з цього списку. Лінк на закачку вказаний в ключі `url`. Як скачувати файли через Python: https://www.tutorialspoint.com/downloading-files-from-web-using-python ::: :::info **Завдання:** для складних варіантів (де є ключ `downloads.natives`) потрібно скачати бібліотеку для правильної операційної системи (windows якщо у вас вінда, osx якщо MacOS). ::: ## Індекс ассетів :::info Він вказаний як лінк на ассети в пакетному індексі, наприклад: https://launchermeta.mojang.com/v1/packages/4759bad2824e419da9db32861fcdc3a274336532/pre-1.6.json ::: ![](https://i.imgur.com/1Yu46AQ.png) Формат цього файлу доволі простий: ключ `objects` є словник об'єктів, де ключем є шлях до файлу на клієнті (куди треба скачати), а значенням є пара (hash, size): - **hash** вказує на хеш об'єкту, і по цьому хешу можна отримати лінк на закачку. Лінк будується так: `https://resources.download.minecraft.net/XX/YYYYYYYYYYYYYYYYYYYY`, де `XX` --- це перші два символи хешу, а `YYYYYYYYYYYYYYYYYYY` --- сам хеш. - **size** --- розмір файлу для закачки. Це потрібно для плавного відображення прогрес-бару при закачці. :::info **Завдання**: Написати функцію, яка по хешу отримує лінк на закачку ресурса по правилу вище. ::: :::info **Завдання**: Написати функцію, яка отримує шлях до файлу, і створює всі папки які потрібно для того, щоб цей файл можна було скачати. ::: :::info **Завдання**: (якщо зробили попередні два) Написати функцію, яка по індексу ассетів викачає всі файли по черзі і збереже їх в правильну папку. ::: :::info **Завдання**: Написати функцію, яка по індексу ассетів порахує розмір всіх файлів для закачки і виведе на екран (в мегабайтах). ::: :::info **Завдання**: Написати функцію, яка отримує на вхід два лінки на два різних індекси ассетів і виводить - скільки файлів ассетів є спільні для обох індексів - розмір файлів даних для кожного індексу - розмір даних для спільних асетів - скільки байт можна зекономити на інтернет закачці другого індексу, якщо не скачувати файли які вже були скачані по першому індексу :::