- Баллы
- 123
I Для кого предназначена статья
Данная статья предназначена в первую очередь для Разработчиков и людей собирающихся разрабатывать собственный лаунчер.II Основные способы запуска клиента из Лаунчера
- Запуск клиента игры из Java Launcher
- Запуск клиента игры с использованием Java.exe
- Запуск клиента игры с собственной реализацией Java.exe на низкоуровневом языке С/C++
III a) Запуск клиента игры из Java Launcher
Преимущества:
- Простота разработки
- Кросс платформенный код
- Промежуточный код, позволяет любому без особых усилий посмотреть код лаунчера и изменить его.
- Невозможность интеграции серьезной защиты (вытекает из первого недостатка)
За основу к данному примеру был взят microLauncher написанный @DmitriyMX
, реализацию обертки MinecraftApplet из кода ниже можно посмотреть в исходниках
Java:
public static void main(String[] args) {
try{
//Узнаем путь до bin папки.
String mc_bin_path = getWorkPath("DmitriyMX").toString() + File.separator + "bin" + File.separator;
//Генерируем url-пути для 4х основных файлов
//(я не стал ради 4х файлов делать цикл)
URL[] urls = new URL[4];
urls[0] = new File(mc_bin_path, "minecraft.jar").toURI().toURL();
urls[1] = new File(mc_bin_path, "lwjgl.jar").toURI().toURL();
urls[2] = new File(mc_bin_path, "jinput.jar").toURI().toURL();
urls[3] = new File(mc_bin_path, "lwjgl_util.jar").toURI().toURL();
//Создаем класс-обёртку для net.minecraft.client.MinecraftApplet
MinecraftApplet mineApplet = new MinecraftApplet(mc_bin_path, urls);
//Указываем параметры(собственно из-за них и писалать обёртка)
mineApplet.customParameters.put("stand-alone", "true");
mineApplet.customParameters.put("username", "Player");
//Создаем фрейм
JFrame frame = new JFrame();
frame.setTitle("Minecraft");
frame.setSize(640, 480);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(mineApplet, BorderLayout.CENTER);
frame.validate();
frame.setVisible(true);
//Только после показа окна нужно инициализировать mineApplet
//Связано это с тем, что до того как окно нарисуется, функции getWidth() и getHeight() у mineApplet возвращают 0
mineApplet.init();
mineApplet.start();
}catch(Exception e){
e.printStackTrace();
}
}
Автор уже достаточно неплохо задокументировал main функцию, основная идея состоит в том чтобы создать Applet класс обертку над стандартным классом net.minecraft.client.MinecraftApplet из файла minecraft.jar, и в этот класс добавить собственные параметры для аплейта такие как:
Код:
mineApplet.customParameters.put("stand-alone", "true");
mineApplet.customParameters.put("username", "Player");
Все возможные параметры для minecraftApplet приведены в таблице ниже взяты из версии Minecraft 1.4.6 от 20.12.12:
Существует еще один менее гибкий метод, вместо того чтобы создавать класс обертку можно вызвать статическую функцию main из minecraft.jar она находится в классе net.minecraft.client.Minecraft и принимает масив строк.Ключ-----------------Значение----------Коментарий
"username" ----------"UserName"-------Ник пользователя
"stand-alone"---------"true"или"false"---unknown
"demo"----------------"true"или"false"---Этот параметр недавно появился
"fullscreen"------------"true"или"false"---Задает полноэкранные режим при запуске
"sessionid"-------------"-"------------------Необходим при аунтификации на сервере
"server" ---------------"127.0.0.1"---------К данному IP будет произведено подключение при запуске
"port"------------------"25555-------------и его порт
Возможные значения для main функции из net.minecraft.client.Minecraft UserName SessionId [-demo || --applet || --password]
Первый параметр Имя пользователя, второй сессия, далее идет взаимоисключающие атрибуты
За что отвечаю атрибуты [-demo || --applet || --password] мне не известно, эти атрибуты появились недавно и их еше предстоит изучить.
III б) Запуск клиента игры с использованием Java.exe
Запустить клиент из низкоуровневого языка можно с использованием Java.exe, это основной метод большинства, если не всех, лаунчеров написанных на низкоуровнивых языках
Преимущества:
- Низкоуровневые языки не позволяют с такой простотой декомпилировать их бинарные файлы как языки с промежуточным кодом, по сути дела их можно тока дисасемблировать, что гарантирует сохранность исходного кода.
- Повышенная безопасность
Недостатки
- Необходимо запускать стотонную программу Java.exe
- Сложность в разработке
- Необходимо прибегать к дополнительным усилиям для приобретения кросс платформенного кода
- Самый существенный недостаток состоит в том что нельзя задать параметры описанные в предыдущем разделе кроме тех что принимает net.minecraft.client.Minecraft в функции main
Реализация:
Весь код написан мной на С++ с использованием WinAPI
Чтобы реализовать данный метод необходимы следующие действия
- Определить где установлена Java (можно надеяться на переменную окружения PATH)
- Создать новый процесс Java.exe и передать ей параметры запуска
Строка запуска из консоли через Java.exe выглядит примерно седлающим образом
Java:
java -Djava.class.path=%APPDATA%\.minecraft\bin\lwjgl.jar;%APPDATA%\.minecraft\bin\jinput.jar;%APPDATA%\.minecraft\bin\lwjgl_util.jar;%APPDATA%\.minecraft\bin\minecraft.jar; -Djava.library.path=%APPDATA%\.minecraft\bin\natives net.minecraft.client.Minecraft UserName SessionId [-demo || --applet || --password]
В -Djava.library.path указывается путь до нативных библиотеки
Далее вызывается main функция из net.minecraft.client.Minecraft
Отсюда реализация на С/С++
Java:
#include <windows.h>
#include <tchar.h>
#define JAVA_HOME "C:\\Program Files\\Java\\jre8"
#define GAME_PATH "C:\\Users\\Алексей\\AppData\\Roaming\\.minecraft"
int _tmain(int argc, _TCHAR* argv[])
{
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
//Указываем VM где искать классы и нативные библиотеки
LPTSTR commLine =_T("-Djava.class.path=") _T(GAME_PATH) _T("\\bin\\lwjgl_util.jar;")
_T(GAME_PATH) _T("\\bin\\lwjgl.jar;")
_T(GAME_PATH) _T("\\bin\\jinput.jar;")
_T(GAME_PATH) _T("\\bin\\minecraft.jar;")
_T(" -Djava.library.path=") _T(GAME_PATH) _T("\\bin\\natives net.minecraft.client.Minecraft MyName MySessiaId");
//Создаем новый процесс
CreateProcess(TEXT(JAVA_HOME) TEXT("\\bin\\java.exe"), commLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
Sleep(100000);
return 0;
}
Можно также объединить предыдущие два способа чтобы достичь большей гибкости при реализации Лаунчера на низкоуровневом языке, однако я считаю этот метод достаточно плохим тк запуск игры все равно придется писать в java которое также без труда декомпилируется, + у вас будет целых два Лаунчера вместо одного что очень некрасиво.
В седлающем разделе описан способ снимавший основные ограничения с низкоуровневого языка
III в) Запуск клиента игры с собственной реализацией Java.exe на низкоуровневом языке С/C++
В предыдущем разделе был описан пример где вызывалась java.exe однако этот бинарник является низкоуровневым, а следовательно и мы можем реализовать свой собственный бинарник без вызова java.exe, в седлающей реализации мне удалось снять основное ограничения которое описаны в предыдущем разделе, мне удалось создать java классы в коде С++ и вызывать Java методы и классы из C++, перспектив у данного метода очень много, однако я не видел ни одного лаунчера его реализующего.http://rubukkit.org/threads/Способ-запуска-клиента-игры-из-Лаунчера-Часть-2.26970/
