From 6bf6c1634a1c876eeca09c0ef7728d3d1d250e57 Mon Sep 17 00:00:00 2001 From: Sashegdev Date: Mon, 20 Apr 2026 19:30:17 +0000 Subject: [PATCH] =?UTF-8?q?=D0=A4=D0=B8=D0=BA=D1=81=D1=8B=20=D0=BF=D1=80?= =?UTF-8?q?=D0=BE=D1=85=D0=BE=D0=B4=D0=BE=D0=BA=20(=D0=BD=D0=BE=D1=80?= =?UTF-8?q?=D0=BC=D0=B0=D0=BB=D1=8C=D0=BD=D0=BE,=20=D0=B2=20=D0=BE=D1=82?= =?UTF-8?q?=D0=BB=D0=B8=D1=87=D0=B8=D0=B8=20=D0=BE=D1=82=20main=20=D0=B2?= =?UTF-8?q?=D0=B5=D1=82=D0=BA=D0=B8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ОНО РАБОТАЕТ СУКАААА --- launcher/dependency-reduced-pom.xml | 18 + launcher/pom.xml | 25 + .../me/sashegdev/zernmc/launcher/Main.java | 73 +- .../zernmc/launcher/auth/AuthManager.java | 28 +- .../zernmc/launcher/menu/LaunchMenu.java | 754 ++++++++++-------- .../zernmc/launcher/menu/LoginMenu.java | 46 +- .../zernmc/launcher/menu/ServerCheckMenu.java | 100 ++- .../zernmc/launcher/utils/Config.java | 10 + .../zernmc/launcher/utils/Input.java | 15 + .../zernmc/launcher/utils/ZHttpClient.java | 32 +- server/main.py | 338 ++++++++ 11 files changed, 1025 insertions(+), 414 deletions(-) diff --git a/launcher/dependency-reduced-pom.xml b/launcher/dependency-reduced-pom.xml index 41197c7..477027c 100644 --- a/launcher/dependency-reduced-pom.xml +++ b/launcher/dependency-reduced-pom.xml @@ -91,6 +91,24 @@ + + + global + + ZernMC Launcher + global + http://87.120.187.36:1582 + + + + zernmc + + ZernMC Private Launcher + zernmc + http://87.120.187.36:1582 + + + 21 me.sashegdev.zernmc.launcher.Main diff --git a/launcher/pom.xml b/launcher/pom.xml index e51e2fa..870a7f7 100644 --- a/launcher/pom.xml +++ b/launcher/pom.xml @@ -153,4 +153,29 @@ + + + + global + + true + + + global + ZernMC Launcher + http://87.120.187.36:1582 + + + + + + + zernmc + + zernmc + ZernMC Private Launcher + http://87.120.187.36:1582 + + + \ No newline at end of file diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/Main.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/Main.java index fb73deb..8e97e0a 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/Main.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/Main.java @@ -4,7 +4,6 @@ import me.sashegdev.zernmc.launcher.auth.AuthManager; import me.sashegdev.zernmc.launcher.menu.*; import me.sashegdev.zernmc.launcher.ui.ArrowMenu; import me.sashegdev.zernmc.launcher.utils.*; - import java.io.IOException; import java.net.http.HttpClient; import java.net.http.HttpRequest; @@ -23,13 +22,12 @@ public class Main { System.setProperty("file.encoding", "UTF-8"); System.setProperty("sun.err.encoding", "UTF-8"); System.setProperty("sun.stdout.encoding", "UTF-8"); - java.nio.charset.Charset.defaultCharset(); - ZAnsi.install(); + ZAnsi.install(); System.out.print("\033[H\033[2J"); System.out.println(ZAnsi.brightGreen("Добро пожаловать в ZernMC Launcher " + CURRENT_VERSION)); - //проверка всех сервисов при старте + // Проверка всех сервисов при старте ZHttpClient.checkAllServicesOnStartup(); checkAndAutoUpdateLauncher(); @@ -49,8 +47,8 @@ public class Main { } else { System.out.println(ZAnsi.brightGreen("Добро пожаловать обратно, " + AuthManager.getUsername() + "!")); } - // === КОНЕЦ АВТОРИЗАЦИИ === + // === ГЛАВНЫЙ ЦИКЛ === try { mainLoop(); } catch (Exception e) { @@ -63,7 +61,6 @@ public class Main { private static void checkAndAutoUpdateLauncher() { System.out.println(ZAnsi.cyan("Проверка обновлений лаунчера...")); - try { String json = ZHttpClient.getLauncherVersionInfo(); String serverVersion = extractVersion(json); @@ -74,13 +71,11 @@ public class Main { if (Version.isNewer(CURRENT_VERSION, serverVersion)) { System.out.println(ZAnsi.brightYellow("\nДоступна новая версия лаунчера! (" + serverVersion + ")")); System.out.println(ZAnsi.cyan("Начинается автоматическое обновление...\n")); - performAutoUpdate(serverVersion); restartLauncher(); } else { System.out.println(ZAnsi.brightGreen("Лаунчер актуален.")); } - } catch (Exception e) { System.out.println(ZAnsi.yellow("Не удалось проверить обновления лаунчера.")); System.out.println(ZAnsi.white("Ошибка: ") + e.getMessage()); @@ -109,9 +104,7 @@ public class Main { long size = Files.size(tempJar); System.out.println(ZAnsi.brightGreen("Скачано успешно (" + (size / 1024) + " KB)")); - // Заменяем текущий jar Files.move(tempJar, currentJar, StandardCopyOption.REPLACE_EXISTING); - System.out.println(ZAnsi.brightGreen("Обновление успешно установлено!")); } @@ -152,27 +145,73 @@ public class Main { } } + // ====================== ГЛАВНЫЙ ЦИКЛ ====================== private static void mainLoop() throws Exception { + if (Config.isZernMCBuild()) { + zernMCFlow(); + } else { + globalFlow(); + } + } + + // ====================== ZERNMC FLOW ====================== + private static void zernMCFlow() throws Exception { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.header("=== ZernMC Private Launcher ===")); + + // 1. Проверка подключения к серверу + System.out.println(ZAnsi.cyan("Проверка подключения к ZernMC серверу...")); + try { + String response = ZHttpClient.get("/health"); + System.out.println(ZAnsi.brightGreen("✓ Сервер доступен")); + } catch (Exception e) { + System.out.println(ZAnsi.brightRed("✗ Не удалось подключиться к ZernMC серверу")); + System.out.println(ZAnsi.white("Ошибка: " + e.getMessage())); + ConsoleUtils.pause(); + System.exit(1); + } + + // 2. Авторизация + boolean sessionRestored = AuthManager.loadSavedSession(); + if (!sessionRestored) { + LoginMenu loginMenu = new LoginMenu(); + boolean loggedIn = loginMenu.show(); + if (!loggedIn) { + System.exit(0); + } + } else { + System.out.println(ZAnsi.brightGreen("Добро пожаловать обратно, " + AuthManager.getUsername() + "!")); + } + + // 3. Запуск меню (LaunchMenu сам определит режим и вызовет нужный flow) + LaunchMenu launchMenu = new LaunchMenu(); + launchMenu.show(); // ← Здесь будет вызван showZernMCOnly() внутри + } + + // ====================== GLOBAL FLOW ====================== + private static void globalFlow() throws Exception { while (true) { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.header("=== ZernMC Launcher ===")); + List options = List.of( - "Запустить игру", - "Проверка обновлений", - "Настройки", - "Проверка подключения к серверам Zern", - "Выход" + "Запустить игру", + "Проверка обновлений", + "Настройки", + "Проверка подключения к серверам", + "Выход" ); ArrowMenu menu = new ArrowMenu("Главное меню", options); int choice = menu.show(); if (choice == -1 || choice == 4) { - System.out.print("\033[H\033[2J"); System.out.println(ZAnsi.yellow("До свидания!")); break; } switch (choice) { - case 0 -> new LaunchMenu().show(); + case 0 -> new LaunchMenu().show(); // обычный LaunchMenu case 1 -> new UpdateMenu().show(); case 2 -> new SettingsMenu().show(); case 3 -> new ServerCheckMenu().show(); diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java index f6cd5b3..82dc04f 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/auth/AuthManager.java @@ -203,31 +203,23 @@ public class AuthManager { if (!isLoggedIn()) return false; try { String response = ZHttpClient.get("/auth/pass/my"); - return response.contains("\"is_active\":true"); + JsonObject json = JsonParser.parseString(response).getAsJsonObject(); + return json.has("has_active") && json.get("has_active").getAsBoolean(); } catch (Exception e) { - System.err.println("Не удалось проверить проходки: " + e.getMessage()); + System.err.println(ZAnsi.red("Не удалось проверить проходки: ") + e.getMessage()); return false; } } - public static String activatePass(String passCode) { + public static String getPassStatus() { + if (!isLoggedIn()) return "Не авторизован"; try { - String json = "{\"pass_code\":\"" + passCode.toUpperCase() + "\"}"; - SimpleHttpResponse resp = post("/auth/pass/activate", json); - - System.out.println(ZAnsi.cyan("[AUTH] Активация проходки: HTTP " + resp.statusCode())); - - if (resp.statusCode() == 200) { - return "Проходка успешно активирована!"; - } else if (resp.statusCode() == 401) { - return "Ошибка: Требуется авторизация. Перезайдите в аккаунт."; - } else { - String error = extractError(resp.body()); - return "Ошибка: " + error; - } + String response = ZHttpClient.get("/auth/pass/my"); + JsonObject json = JsonParser.parseString(response).getAsJsonObject(); + boolean hasActive = json.has("has_active") && json.get("has_active").getAsBoolean(); + return hasActive ? "Есть активная проходка" : "Проходка отсутствует"; } catch (Exception e) { - e.printStackTrace(); - return "Ошибка соединения: " + e.getMessage(); + return "Ошибка проверки"; } } diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LaunchMenu.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LaunchMenu.java index 8c22af4..17d28e7 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LaunchMenu.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LaunchMenu.java @@ -10,12 +10,15 @@ import me.sashegdev.zernmc.launcher.minecraft.installer.VersionInstaller; import me.sashegdev.zernmc.launcher.minecraft.model.LaunchOptions; import me.sashegdev.zernmc.launcher.minecraft.model.MinecraftVersion; import me.sashegdev.zernmc.launcher.ui.ArrowMenu; +import me.sashegdev.zernmc.launcher.utils.Config; import me.sashegdev.zernmc.launcher.utils.ConsoleUtils; import me.sashegdev.zernmc.launcher.utils.Input; import me.sashegdev.zernmc.launcher.utils.ZAnsi; import me.sashegdev.zernmc.launcher.utils.ZHttpClient; +import java.awt.*; import java.io.IOException; +import java.net.URI; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -23,6 +26,151 @@ import java.util.stream.Collectors; public class LaunchMenu { public void show() throws Exception { + if (Config.isZernMCBuild()) { + showZernMCOnly(); + } else { + showGlobal(); + } + } + + // ====================== ZERNMC BUILD ====================== + private void showZernMCOnly() throws Exception { + while (true) { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.header("=== ZernMC Private Launcher ===")); + System.out.println(ZAnsi.cyan("Доступны только серверные сборки")); + + if (!awaitActivePass()) { + return; + } + + PackDownloader tempDownloader = new PackDownloader(null); + List availablePacks = tempDownloader.getAvailablePacks(); + + if (availablePacks.isEmpty()) { + System.out.println(ZAnsi.yellow("На данный момент нет доступных сборок на сервере.")); + ConsoleUtils.pause(); + return; + } + + List options = availablePacks.stream() + .map(p -> String.format("%s [%s + %s v%d] — %d файлов", + p.getName(), + p.getMinecraftVersion(), + p.getLoaderType(), + p.getVersion(), + p.getFilesCount())) + .collect(Collectors.toList()); + + options.add("Назад в главное меню"); + + ArrowMenu menu = new ArrowMenu("Выберите сборку", options); + int choice = menu.show(); + + if (choice == -1 || choice == options.size() - 1) return; + + ServerPack selected = availablePacks.get(choice); + installAndRunServerPack(selected); + } + } + + private boolean awaitActivePass() throws Exception { + if (AuthManager.hasActivePass()) { + System.out.println(ZAnsi.brightGreen("✓ Активная проходка подтверждена")); + return true; + } + + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.brightRed("У вас нет активной проходки!")); + System.out.println(ZAnsi.white("Для доступа к сборкам ZernMC требуется активная проходка.")); + System.out.println(); + + openActivationWebsite(); + + System.out.println(ZAnsi.cyan("Ожидаем активацию проходки... (проверка каждые 10 секунд)")); + System.out.println(ZAnsi.white("Нажмите Enter для отмены")); + + for (int i = 0; i < 60; i++) { + try { + if (System.in.available() > 0) { + Input.readLine(); + System.out.println(ZAnsi.yellow("\nОжидание отменено.")); + return false; + } + } catch (Exception ignored) {} + + Thread.sleep(10000); + + if (AuthManager.hasActivePass()) { + System.out.println(ZAnsi.brightGreen("\n✓ Проходка успешно активирована!")); + return true; + } + + System.out.print(ZAnsi.cyan(".")); + if ((i + 1) % 6 == 0) System.out.println(); + } + + System.out.println(ZAnsi.brightRed("\n\nВремя ожидания истекло.")); + return false; + } + + private void openActivationWebsite() { + //String url = "https://launcher.ru.zernmc.ru/activate-pass"; + String url = ZHttpClient.getBaseUrl() + "/activate-pass"; + + try { + if (Desktop.isDesktopSupported() && Desktop.getDesktop().isSupported(Desktop.Action.BROWSE)) { + Desktop.getDesktop().browse(new URI(url)); + System.out.println(ZAnsi.cyan("Браузер открыт: " + url)); + } else { + System.out.println(ZAnsi.yellow("Не удалось открыть браузер автоматически.")); + System.out.println(ZAnsi.white("Откройте вручную: " + url)); + } + } catch (Exception e) { + System.out.println(ZAnsi.brightRed("Ошибка открытия браузера: " + e.getMessage())); + System.out.println(ZAnsi.white("Ссылка: " + url)); + } + } + + private void installAndRunServerPack(ServerPack selected) throws Exception { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.header("Установка сборки: " + selected.getName())); + + System.out.println(ZAnsi.white(" Minecraft: ") + selected.getMinecraftVersion()); + System.out.println(ZAnsi.white(" Лоадер: ") + selected.getLoaderType() + + (selected.getLoaderVersion() != null ? " " + selected.getLoaderVersion() : "")); + System.out.println(ZAnsi.white(" Версия: v") + selected.getVersion()); + System.out.println(ZAnsi.white(" Файлов: ") + selected.getFilesCount()); + + String localName = askPackName(); + if (localName == null) return; + + if (InstanceManager.getInstance(localName) != null) { + System.out.println(ZAnsi.brightRed("Сборка с таким именем уже существует!")); + ConsoleUtils.pause(); + return; + } + + InstanceManager.createInstanceFolder(localName); + Instance newInstance = InstanceManager.getInstance(localName); + + PackDownloader packDownloader = new PackDownloader(newInstance); + boolean success = packDownloader.installOrUpdatePack(selected.getName(), selected); + + if (!success) { + System.out.println(ZAnsi.brightRed("\n[FAIL] Не удалось установить сборку.")); + ConsoleUtils.pause(); + return; + } + + System.out.println(ZAnsi.brightGreen("\n[OK] Сборка '" + localName + "' успешно установлена!")); + ConsoleUtils.pause(); + + launchExistingInstance(newInstance); + } + + // ====================== GLOBAL BUILD ====================== + private void showGlobal() throws Exception { while (true) { ConsoleUtils.clearScreen(); List instances = InstanceManager.getAllInstances(); @@ -37,11 +185,10 @@ public class LaunchMenu { ArrowMenu menu = new ArrowMenu("Управление сборками", options); int choice = menu.show(); - if (choice == -1) break; - if (choice == options.size() - 1) break; + if (choice == -1 || choice == options.size() - 1) break; if (choice == instances.size()) { - installNewPack(); + installNewPackGlobal(); continue; } @@ -50,289 +197,101 @@ public class LaunchMenu { } } - private void installNewPack() throws Exception { + private void installNewPackGlobal() throws Exception { ConsoleUtils.clearScreen(); - + List options = List.of( - "Установить сборку с сервера ZernMC", - "Установить Vanilla Minecraft", - "Создать сборку вручную (Fabric/Forge)", - "Назад" + "Установить сборку с сервера ZernMC", + "Установить Vanilla Minecraft", + "Создать сборку вручную (Fabric/Forge)", + "Назад" ); - + ArrowMenu menu = new ArrowMenu("Установка новой сборки", options); int choice = menu.show(); - + if (choice == -1 || choice == 3) return; - + switch (choice) { - case 0 -> { - try { - installServerPack(); - } catch (Exception e) { - System.out.println(ZAnsi.brightRed("Ошибка: " + e.getMessage())); - e.printStackTrace(); - ConsoleUtils.pause(); - } - } + case 0 -> installServerPackGlobal(); case 1 -> createVanillaInstance(); case 2 -> createCustomInstance(); } } - private void installServerPack() throws Exception { - if (!AuthManager.hasActivePass()) { - ConsoleUtils.clearScreen(); - System.out.println(ZAnsi.brightRed("У вас нет активной проходки!")); - System.out.println(ZAnsi.white("Чтобы скачивать сборки с сервера ZernMC, необходимо активировать проходку.")); - System.out.println(); - System.out.print(ZAnsi.white("Введите код проходки (ZERN-XXXXXXX) или Enter для отмены: ")); - - String code = Input.readLine(); - if (code.isEmpty()) return; - - String result = AuthManager.activatePass(code); - System.out.println(ZAnsi.cyan(result)); - - if (!result.contains("успешно")) { - ConsoleUtils.pause(); - return; - } - - // Повторная проверка - if (!AuthManager.hasActivePass()) { - System.out.println(ZAnsi.brightRed("Не удалось активировать проходку.")); - ConsoleUtils.pause(); - return; - } - } + private void installServerPackGlobal() throws Exception { + if (!awaitActivePass()) return; ConsoleUtils.clearScreen(); - System.out.println(ZAnsi.cyan("Получение списка доступных сборок с сервера...")); - + System.out.println(ZAnsi.cyan("Получение списка доступных сборок...")); + PackDownloader tempDownloader = new PackDownloader(null); List availablePacks = tempDownloader.getAvailablePacks(); - + if (availablePacks.isEmpty()) { System.out.println(ZAnsi.yellow("Нет доступных сборок на сервере.")); ConsoleUtils.pause(); return; } - - // Исправлено: убраны спецсимволы для Windows + List options = availablePacks.stream() - .map(p -> String.format("%s [%s + %s v%d] - %d файлов", - p.getName(), - p.getMinecraftVersion(), - p.getLoaderType(), - p.getVersion(), - p.getFilesCount())) - .collect(Collectors.toList()); + .map(p -> String.format("%s [%s + %s v%d] — %d файлов", + p.getName(), + p.getMinecraftVersion(), + p.getLoaderType(), + p.getVersion(), + p.getFilesCount())) + .collect(Collectors.toList()); options.add("Назад"); - + ArrowMenu menu = new ArrowMenu("Выберите сборку для установки", options); int choice = menu.show(); - + if (choice == -1 || choice == options.size() - 1) return; - + ServerPack selected = availablePacks.get(choice); - - // Запрашиваем имя для локальной сборки + ConsoleUtils.clearScreen(); System.out.println(ZAnsi.header("Установка сборки: " + selected.getName())); - System.out.println(ZAnsi.white(" Minecraft: ") + selected.getMinecraftVersion()); - System.out.println(ZAnsi.white(" Лоадер: ") + selected.getLoaderType() + " " + selected.getLoaderVersion()); - System.out.println(ZAnsi.white(" Версия: v") + selected.getVersion()); - System.out.println(ZAnsi.white(" Файлов: ") + selected.getFilesCount()); - System.out.println(); - - System.out.print(ZAnsi.white("Введите название локальной сборки (Enter = использовать имя пака): ")); - String localName = Input.readLine(); - if (localName.isEmpty()) { - localName = selected.getName(); - } - - // Проверяем, существует ли уже такая сборка + + System.out.print(ZAnsi.white("\nВведите название локальной сборки (Enter = имя пака): ")); + String localName = Input.readLine().trim(); + if (localName.isEmpty()) localName = selected.getName(); + if (InstanceManager.getInstance(localName) != null) { System.out.println(ZAnsi.brightRed("Сборка с таким именем уже существует!")); ConsoleUtils.pause(); return; } - - // Создаем инстанс + InstanceManager.createInstanceFolder(localName); Instance newInstance = InstanceManager.getInstance(localName); - - // Устанавливаем сборку + PackDownloader packDownloader = new PackDownloader(newInstance); boolean success = packDownloader.installOrUpdatePack(selected.getName(), selected); - + if (success) { System.out.println(ZAnsi.brightGreen("\n[OK] Сборка '" + localName + "' успешно установлена!")); } else { System.out.println(ZAnsi.brightRed("\n[FAIL] Не удалось установить сборку.")); } - + ConsoleUtils.pause(); } - private void createVanillaInstance() throws Exception { - ConsoleUtils.clearScreen(); - System.out.println(ZAnsi.cyan("Получение списка версий Minecraft...")); - - VersionInstaller versionInstaller = new VersionInstaller(null); - List allVersions = versionInstaller.getAvailableVersions(); - - List versionOptions = allVersions.stream() - .map(v -> v.getId() + " (" + v.getType() + ")") - .collect(Collectors.toList()); - versionOptions.add("Назад"); - - ArrowMenu versionMenu = new ArrowMenu("Выбор версии Minecraft", versionOptions); - int versionChoice = versionMenu.show(); - - if (versionChoice == -1 || versionChoice == versionOptions.size() - 1) return; - - MinecraftVersion selectedMc = allVersions.get(versionChoice); - String mcVersion = selectedMc.getId(); - - String packName = askPackName(); - if (packName == null) return; - - if (InstanceManager.getInstance(packName) != null) { - System.out.println(ZAnsi.brightRed("Сборка с таким именем уже существует!")); - ConsoleUtils.pause(); - return; - } - - InstanceManager.createInstanceFolder(packName); - Instance newInstance = InstanceManager.getInstance(packName); - - MinecraftLib lib = new MinecraftLib(newInstance); - boolean success = lib.installMinecraft(mcVersion); - - if (success) { - System.out.println(ZAnsi.brightGreen("\n[OK] Vanilla сборка '" + packName + "' успешно создана!")); - } else { - System.out.println(ZAnsi.brightRed("\n[FAIL] Не удалось создать сборку.")); - } - - ConsoleUtils.pause(); - } - - private void createCustomInstance() throws Exception { - ConsoleUtils.clearScreen(); - System.out.println(ZAnsi.cyan("Получение списка версий Minecraft...")); - - VersionInstaller versionInstaller = new VersionInstaller(null); - List allVersions = versionInstaller.getAvailableVersions(); - - List versionOptions = allVersions.stream() - .map(v -> v.getId() + " (" + v.getType() + ")") - .collect(Collectors.toList()); - versionOptions.add("Назад"); - - ArrowMenu versionMenu = new ArrowMenu("Выбор версии Minecraft", versionOptions); - int versionChoice = versionMenu.show(); - - if (versionChoice == -1 || versionChoice == versionOptions.size() - 1) return; - - MinecraftVersion selectedMc = allVersions.get(versionChoice); - String mcVersion = selectedMc.getId(); - - // === Выбор лоадера с правильной проверкой поддержки === - List loaderOptions = buildLoaderOptions(mcVersion); - ArrowMenu loaderMenu = new ArrowMenu("Выбор модлоадера для " + mcVersion, loaderOptions); - int loaderChoice = loaderMenu.show(); - - if (loaderChoice == -1 || loaderChoice == loaderOptions.size() - 1) return; - - String selectedLoader = loaderOptions.get(loaderChoice); - - if (selectedLoader.contains("Vanilla")) { - createVanillaInstance(); - return; - } - - String loaderType = selectedLoader.contains("Fabric") ? "fabric" : "forge"; - - String loaderVersion; - if (loaderType.equals("fabric")) { - loaderVersion = askFabricLoaderVersion(); - } else { - loaderVersion = askForgeVersion(mcVersion); - } - - if (loaderVersion == null) return; - - String packName = askPackName(); - if (packName == null) return; - - if (InstanceManager.getInstance(packName) != null) { - System.out.println(ZAnsi.brightRed("Сборка с таким именем уже существует!")); - ConsoleUtils.pause(); - return; - } - - InstanceManager.createInstanceFolder(packName); - Instance newInstance = InstanceManager.getInstance(packName); - - MinecraftLib lib = new MinecraftLib(newInstance); - - boolean success = loaderType.equals("fabric") - ? lib.installFabric(mcVersion, loaderVersion) - : lib.installForge(mcVersion, loaderVersion); - - if (success) { - System.out.println(ZAnsi.brightGreen("\n[OK] Сборка '" + packName + "' успешно установлена!")); - } else { - System.out.println(ZAnsi.brightRed("\n[FAIL] Не удалось установить сборку.")); - } - - ConsoleUtils.pause(); - } - - // ====================== Вспомогательные методы ====================== - - private List buildLoaderOptions(String mcVersion) { - List options = new ArrayList<>(); - - if (isFabricSupported(mcVersion)) { - options.add("Fabric"); - } - if (isForgeSupported(mcVersion)) { - options.add("Forge"); - } - options.add("Vanilla"); - options.add("Назад"); - - return options; - } - - private boolean isFabricSupported(String version) { - return version.matches("^1\\.(1[4-9]|[2-9]\\d).*"); - } - - private boolean isForgeSupported(String version) { - if (version.matches("^1\\.2[2-9].*") || version.matches("^\\d{2}.*")) { - return false; - } - return version.matches("^1\\.(1[2-9]|[2-9]\\d).*") || - version.matches("^1\\.20.*") || version.matches("^1\\.21.*"); - } - + // ====================== manageInstance — полностью восстановлен ====================== private void manageInstance(Instance instance) throws Exception { while (true) { ConsoleUtils.clearScreen(); System.out.println(ZAnsi.header("Управление сборкой: " + instance.getName())); System.out.println(ZAnsi.white("Версия: " + instance.getMinecraftVersion())); - System.out.println(ZAnsi.white("Лоадер: " + instance.getLoaderType() + + System.out.println(ZAnsi.white("Лоадер: " + instance.getLoaderType() + (instance.getLoaderVersion() != null ? " " + instance.getLoaderVersion() : ""))); - + if (instance.isServerPack()) { System.out.println(ZAnsi.green("Серверная сборка: v" + instance.getServerVersion())); } - + List options = new ArrayList<>(); options.add("Запустить сборку"); if (instance.isServerPack()) { @@ -341,12 +300,12 @@ public class LaunchMenu { options.add("Изменить версию лоадера"); options.add("Удалить сборку"); options.add("Назад"); - + ArrowMenu menu = new ArrowMenu("Действия", options); int choice = menu.show(); - + if (choice == -1 || choice == options.size() - 1) return; - + switch (choice) { case 0 -> launchExistingInstance(instance); case 1 -> { @@ -367,20 +326,20 @@ public class LaunchMenu { } } } - + private void checkAndUpdateServerPack(Instance instance) throws Exception { ConsoleUtils.clearScreen(); System.out.println(ZAnsi.cyan("Проверка обновлений для " + instance.getName())); - + PackDownloader downloader = new PackDownloader(instance); boolean hasUpdate = downloader.checkForUpdates(instance.getServerPackName()); - + if (!hasUpdate) { System.out.println(ZAnsi.green("Сборка актуальна (v" + instance.getServerVersion() + ")")); ConsoleUtils.pause(); return; } - + System.out.println(ZAnsi.brightYellow("Доступно обновление!")); if (Input.confirm("Обновить сборку")) { boolean success = downloader.updatePack(instance.getServerPackName()); @@ -392,44 +351,43 @@ public class LaunchMenu { } else { System.out.println(ZAnsi.yellow("Обновление отменено.")); } - ConsoleUtils.pause(); } - + private void changeLoaderVersion(Instance instance) throws Exception { ConsoleUtils.clearScreen(); System.out.println(ZAnsi.cyan("Изменение версии лоадера для " + instance.getName())); - + String currentLoader = instance.getLoaderType(); String mcVersion = instance.getMinecraftVersion(); - + if ("vanilla".equalsIgnoreCase(currentLoader)) { System.out.println(ZAnsi.yellow("Это vanilla сборка. Нельзя изменить лоадер.")); ConsoleUtils.pause(); return; } - + String newLoaderVersion; if ("fabric".equalsIgnoreCase(currentLoader)) { newLoaderVersion = askFabricLoaderVersion(); } else { newLoaderVersion = askForgeVersion(mcVersion); } - + if (newLoaderVersion == null) return; - + System.out.println(ZAnsi.cyan("Переустановка лоадера " + currentLoader + " -> " + newLoaderVersion + "...")); - + MinecraftLib lib = new MinecraftLib(instance); boolean success; - + try { if ("fabric".equalsIgnoreCase(currentLoader)) { success = lib.installFabric(mcVersion, newLoaderVersion); } else { success = lib.installForge(mcVersion, newLoaderVersion); } - + if (success) { System.out.println(ZAnsi.brightGreen("Версия лоадера успешно изменена!")); } else { @@ -438,25 +396,25 @@ public class LaunchMenu { } catch (Exception e) { System.out.println(ZAnsi.brightRed("Ошибка при смене лоадера: " + e.getMessage())); } - + ConsoleUtils.pause(); } - + private void deleteInstance(Instance instance) throws IOException { ConsoleUtils.clearScreen(); - + List confirmOptions = List.of( - "Да, удалить сборку", - "Нет, отменить" + "Да, удалить сборку", + "Нет, отменить" ); - + ArrowMenu confirmMenu = new ArrowMenu( - "Вы действительно хотите удалить сборку '" + instance.getName() + "'?", - confirmOptions + "Вы действительно хотите удалить сборку '" + instance.getName() + "'?", + confirmOptions ); - + int choice = confirmMenu.show(); - + if (choice == 0) { boolean deleted = InstanceManager.deleteInstance(instance.getName()); if (deleted) { @@ -467,67 +425,10 @@ public class LaunchMenu { } else { System.out.println(ZAnsi.yellow("Удаление отменено.")); } - + ConsoleUtils.pause(); } - - private String askFabricLoaderVersion() throws Exception { - System.out.println(ZAnsi.cyan("Получение списка версий Fabric Loader...")); - List versions = ZHttpClient.getFabricLoaderVersions(); - - List options = versions.stream() - .limit(30) - .map(v -> "Fabric Loader " + v) - .collect(Collectors.toList()); - options.add("Назад"); - - ArrowMenu menu = new ArrowMenu("Выбор версии Fabric Loader", options); - int choice = menu.show(); - - if (choice == -1 || choice == options.size() - 1) return null; - return versions.get(choice); - } - - private String askForgeVersion(String mcVersion) throws Exception { - System.out.println(ZAnsi.cyan("Получение списка версий Forge для " + mcVersion + "...")); - - List allForgeVersions = getAllForgeVersions(); - - List compatibleVersions = allForgeVersions.stream() - .filter(v -> v.startsWith(mcVersion + "-")) - .map(v -> v.substring(mcVersion.length() + 1)) - .collect(Collectors.toList()); - - if (compatibleVersions.isEmpty()) { - System.out.println(ZAnsi.yellow("Не найдено совместимых версий Forge для " + mcVersion)); - ConsoleUtils.pause(); - return null; - } - - List options = compatibleVersions.stream() - .limit(30) - .map(v -> "Forge " + v) - .collect(Collectors.toList()); - options.add("Назад"); - - ArrowMenu menu = new ArrowMenu("Выбор версии Forge для " + mcVersion, options); - int choice = menu.show(); - - if (choice == -1 || choice == options.size() - 1) return null; - - return compatibleVersions.get(choice); - } - - private String askPackName() { - System.out.print(ZAnsi.white("\nВведите название новой сборки: ")); - String name = Input.readLine(); - if (name.isEmpty()) { - System.out.println(ZAnsi.yellow("Отменено.")); - return null; - } - return name; - } - + private void launchExistingInstance(Instance instance) { if (instance.isServerPack() && !AuthManager.hasActivePass()) { ConsoleUtils.clearScreen(); @@ -535,47 +436,236 @@ public class LaunchMenu { ConsoleUtils.pause(); return; } + ConsoleUtils.clearScreen(); System.out.println(ZAnsi.brightGreen("Запуск сборки: " + instance.getName())); - + MinecraftLib lib = new MinecraftLib(instance); - LaunchOptions options = new LaunchOptions(); - - // Авторизация Minecraft + LaunchOptions options = new LaunchOptions(); + options.setUsername(AuthManager.getUsername()); options.setUuid(AuthManager.getUuid()); options.setAccessToken(AuthManager.getAccessToken()); - + try { lib.launch(options); } catch (Exception e) { System.out.println(ZAnsi.brightRed("Ошибка при запуске: " + e.getMessage())); e.printStackTrace(); } - + ConsoleUtils.pause(); } - + + // ====================== Остальные вспомогательные методы ====================== + + private String askPackName() { + System.out.print(ZAnsi.white("\nВведите название новой сборки: ")); + String name = Input.readLine().trim(); + if (name.isEmpty()) { + System.out.println(ZAnsi.yellow("Отменено.")); + return null; + } + return name; + } + + private void createVanillaInstance() throws Exception { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.cyan("Получение списка версий Minecraft...")); + + VersionInstaller versionInstaller = new VersionInstaller(null); + List allVersions = versionInstaller.getAvailableVersions(); + + List versionOptions = allVersions.stream() + .map(v -> v.getId() + " (" + v.getType() + ")") + .collect(Collectors.toList()); + versionOptions.add("Назад"); + + ArrowMenu versionMenu = new ArrowMenu("Выбор версии Minecraft", versionOptions); + int versionChoice = versionMenu.show(); + + if (versionChoice == -1 || versionChoice == versionOptions.size() - 1) return; + + MinecraftVersion selectedMc = allVersions.get(versionChoice); + String mcVersion = selectedMc.getId(); + + String packName = askPackName(); + if (packName == null) return; + + if (InstanceManager.getInstance(packName) != null) { + System.out.println(ZAnsi.brightRed("Сборка с таким именем уже существует!")); + ConsoleUtils.pause(); + return; + } + + InstanceManager.createInstanceFolder(packName); + Instance newInstance = InstanceManager.getInstance(packName); + + MinecraftLib lib = new MinecraftLib(newInstance); + boolean success = lib.installMinecraft(mcVersion); + + if (success) { + System.out.println(ZAnsi.brightGreen("\n[OK] Vanilla сборка '" + packName + "' успешно создана!")); + } else { + System.out.println(ZAnsi.brightRed("\n[FAIL] Не удалось создать сборку.")); + } + + ConsoleUtils.pause(); + } + + private void createCustomInstance() throws Exception { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.cyan("Получение списка версий Minecraft...")); + + VersionInstaller versionInstaller = new VersionInstaller(null); + List allVersions = versionInstaller.getAvailableVersions(); + + List versionOptions = allVersions.stream() + .map(v -> v.getId() + " (" + v.getType() + ")") + .collect(Collectors.toList()); + versionOptions.add("Назад"); + + ArrowMenu versionMenu = new ArrowMenu("Выбор версии Minecraft", versionOptions); + int versionChoice = versionMenu.show(); + + if (versionChoice == -1 || versionChoice == versionOptions.size() - 1) return; + + MinecraftVersion selectedMc = allVersions.get(versionChoice); + String mcVersion = selectedMc.getId(); + + List loaderOptions = buildLoaderOptions(mcVersion); + ArrowMenu loaderMenu = new ArrowMenu("Выбор модлоадера для " + mcVersion, loaderOptions); + int loaderChoice = loaderMenu.show(); + + if (loaderChoice == -1 || loaderChoice == loaderOptions.size() - 1) return; + + String selectedLoader = loaderOptions.get(loaderChoice); + + if (selectedLoader.contains("Vanilla")) { + createVanillaInstance(); + return; + } + + String loaderType = selectedLoader.contains("Fabric") ? "fabric" : "forge"; + + String loaderVersion = loaderType.equals("fabric") + ? askFabricLoaderVersion() + : askForgeVersion(mcVersion); + + if (loaderVersion == null) return; + + String packName = askPackName(); + if (packName == null) return; + + if (InstanceManager.getInstance(packName) != null) { + System.out.println(ZAnsi.brightRed("Сборка с таким именем уже существует!")); + ConsoleUtils.pause(); + return; + } + + InstanceManager.createInstanceFolder(packName); + Instance newInstance = InstanceManager.getInstance(packName); + + MinecraftLib lib = new MinecraftLib(newInstance); + + boolean success = loaderType.equals("fabric") + ? lib.installFabric(mcVersion, loaderVersion) + : lib.installForge(mcVersion, loaderVersion); + + if (success) { + System.out.println(ZAnsi.brightGreen("\n[OK] Сборка '" + packName + "' успешно установлена!")); + } else { + System.out.println(ZAnsi.brightRed("\n[FAIL] Не удалось установить сборку.")); + } + + ConsoleUtils.pause(); + } + + private List buildLoaderOptions(String mcVersion) { + List options = new ArrayList<>(); + + if (isFabricSupported(mcVersion)) options.add("Fabric"); + if (isForgeSupported(mcVersion)) options.add("Forge"); + options.add("Vanilla"); + options.add("Назад"); + + return options; + } + + private boolean isFabricSupported(String version) { + return version.matches("^1\\.(1[4-9]|[2-9]\\d).*"); + } + + private boolean isForgeSupported(String version) { + if (version.matches("^1\\.2[2-9].*") || version.matches("^\\d{2}.*")) return false; + return version.matches("^1\\.(1[2-9]|[2-9]\\d).*") || + version.matches("^1\\.20.*") || version.matches("^1\\.21.*"); + } + + private String askFabricLoaderVersion() throws Exception { + System.out.println(ZAnsi.cyan("Получение списка версий Fabric Loader...")); + List versions = ZHttpClient.getFabricLoaderVersions(); + + List options = versions.stream() + .limit(30) + .map(v -> "Fabric Loader " + v) + .collect(Collectors.toList()); + options.add("Назад"); + + ArrowMenu menu = new ArrowMenu("Выбор версии Fabric Loader", options); + int choice = menu.show(); + + if (choice == -1 || choice == options.size() - 1) return null; + return versions.get(choice); + } + + private String askForgeVersion(String mcVersion) throws Exception { + System.out.println(ZAnsi.cyan("Получение списка версий Forge для " + mcVersion + "...")); + + List allForgeVersions = getAllForgeVersions(); + + List compatibleVersions = allForgeVersions.stream() + .filter(v -> v.startsWith(mcVersion + "-")) + .map(v -> v.substring(mcVersion.length() + 1)) + .collect(Collectors.toList()); + + if (compatibleVersions.isEmpty()) { + System.out.println(ZAnsi.yellow("Не найдено совместимых версий Forge для " + mcVersion)); + ConsoleUtils.pause(); + return null; + } + + List options = compatibleVersions.stream() + .limit(30) + .map(v -> "Forge " + v) + .collect(Collectors.toList()); + options.add("Назад"); + + ArrowMenu menu = new ArrowMenu("Выбор версии Forge для " + mcVersion, options); + int choice = menu.show(); + + if (choice == -1 || choice == options.size() - 1) return null; + + return compatibleVersions.get(choice); + } + private List getAllForgeVersions() throws Exception { - String metadataUrl = "https://maven.minecraftforge.net/net/minecraftforge/forge/maven-metadata.xml"; - - String xml = ZHttpClient.downloadString(metadataUrl); - + String xml = ZHttpClient.downloadString("https://maven.minecraftforge.net/net/minecraftforge/forge/maven-metadata.xml"); + List versions = new ArrayList<>(); int index = 0; - + while ((index = xml.indexOf("", index)) != -1) { int start = index + 9; int end = xml.indexOf("", start); if (end == -1) break; - + String version = xml.substring(start, end).trim(); versions.add(version); index = end; } - + versions.sort((a, b) -> b.compareTo(a)); - return versions; } } \ No newline at end of file diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java index 20482a0..ebdff19 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/LoginMenu.java @@ -148,14 +148,46 @@ public class LoginMenu { * Читаем пароль — стараемся скрыть вывод через Console, * если недоступно (IDE/терминал без TTY) — читаем обычным способом. */ - private String readPassword(String prompt) { - java.io.Console console = System.console(); - if (console != null) { - char[] chars = console.readPassword(prompt); - return chars != null ? new String(chars) : ""; + private String readPassword(String prompt) throws IOException { + // Создаём временный терминал для ввода пароля + org.jline.terminal.Terminal passTerminal = org.jline.terminal.TerminalBuilder.builder() + .system(true) + .jna(true) + .build(); + + passTerminal.enterRawMode(); + passTerminal.writer().print(prompt); + passTerminal.writer().flush(); + + StringBuilder password = new StringBuilder(); + + try { + while (true) { + int key = passTerminal.reader().read(); + + if (key == 13 || key == 10) { // Enter + passTerminal.writer().println(); + break; + } else if (key == 127 || key == 8) { // Backspace + if (password.length() > 0) { + password.setLength(password.length() - 1); + passTerminal.writer().print("\b \b"); + passTerminal.writer().flush(); + } + } else if (key == 3) { // Ctrl+C + passTerminal.writer().println(); + System.exit(0); + } else if (key >= 32 && key < 127) { // Печатные символы + password.append((char) key); + passTerminal.writer().print('*'); + passTerminal.writer().flush(); + } + } + } finally { + passTerminal.close(); } - // Fallback: в IDE пароль будет виден - return Input.readLine(prompt); + + return password.toString(); } private void printBanner() { diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/ServerCheckMenu.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/ServerCheckMenu.java index 68bd045..51e113b 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/ServerCheckMenu.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/menu/ServerCheckMenu.java @@ -16,71 +16,83 @@ import java.util.List; public class ServerCheckMenu { public void show() throws IOException { - List options = List.of( - "Проверить подключение к ZernMC серверу", - "Проверить доступ к Mojang (Minecraft)", - "Проверить доступ к Fabric Meta", - "Назад в главное меню" - ); + while (true) { + ConsoleUtils.clearScreen(); + System.out.println(ZAnsi.header("Диагностика подключения")); - ArrowMenu menu = new ArrowMenu("Диагностика подключения", options); - int choice = menu.show(); + List options = List.of( + "Проверить подключение к ZernMC серверу", + "Проверить доступ к Mojang (Minecraft)", + "Проверить доступ к Fabric Meta", + "Проверить доступ к Forge Maven", + "Назад в главное меню" + ); - if (choice == -1 || choice == 4) return; + ArrowMenu menu = new ArrowMenu("Выберите проверку", options); + int choice = menu.show(); - ConsoleUtils.clearScreen(); + if (choice == -1 || choice == 4) { + return; + } - switch (choice) { - case 0 -> checkZernServer(); - case 1 -> checkMojang(); - case 2 -> checkFabric(); + ConsoleUtils.clearScreen(); + + switch (choice) { + case 0 -> checkZernServer(); + case 1 -> checkMojang(); + case 2 -> checkFabric(); + case 3 -> checkForge(); + } + + ConsoleUtils.pause(); } - - ConsoleUtils.pause(); } private void checkZernServer() { System.out.println(ZAnsi.cyan("Проверка подключения к ZernMC серверу...")); + try { String response = ZHttpClient.get("/health"); - System.out.println(ZAnsi.brightGreen("Сервер успешно подключён!")); - System.out.println("Ответ: " + response); + System.out.println(ZAnsi.brightGreen("[OK] ZernMC сервер успешно подключён!")); + System.out.println(ZAnsi.white("Ответ сервера: ") + response); } catch (Exception e) { - System.out.println(ZAnsi.brightRed("Не удалось подключиться к ZernMC серверу")); - System.out.println("Ошибка: " + e.getMessage()); + System.out.println(ZAnsi.brightRed("[FAIL] Не удалось подключиться к ZernMC серверу")); + System.out.println(ZAnsi.white("Ошибка: ") + e.getMessage()); } } private void checkMojang() { System.out.println(ZAnsi.cyan("Проверка доступа к Mojang...")); + try { HttpClient client = HttpClient.newBuilder() - .connectTimeout(Duration.ofSeconds(8)) + .connectTimeout(Duration.ofSeconds(10)) .build(); HttpRequest request = HttpRequest.newBuilder() - .uri(URI.create("https://launchermeta.mojang.com/mc/game/version_manifest_v2.json")) + .uri(URI.create("https://piston-meta.mojang.com/mc/game/version_manifest_v2.json")) .GET() .build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { - System.out.println(ZAnsi.brightGreen("Mojang доступен")); + System.out.println(ZAnsi.brightGreen("[OK] Mojang доступен")); } else { - System.out.println(ZAnsi.brightRed("Mojang вернул код " + response.statusCode())); + System.out.println(ZAnsi.brightRed("[FAIL] Mojang вернул код " + response.statusCode())); } } catch (Exception e) { - System.out.println(ZAnsi.brightRed("Нет доступа к Mojang")); - System.out.println("Ошибка: " + e.getMessage()); + System.out.println(ZAnsi.brightRed("[FAIL] Нет доступа к Mojang")); + System.out.println(ZAnsi.white("Ошибка: ") + e.getMessage()); } } private void checkFabric() { System.out.println(ZAnsi.cyan("Проверка доступа к Fabric Meta...")); + try { HttpClient client = HttpClient.newBuilder() - .connectTimeout(Duration.ofSeconds(8)) + .connectTimeout(Duration.ofSeconds(10)) .build(); HttpRequest request = HttpRequest.newBuilder() @@ -91,13 +103,39 @@ public class ServerCheckMenu { HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() == 200) { - System.out.println(ZAnsi.brightGreen("Fabric Meta доступен")); + System.out.println(ZAnsi.brightGreen("[OK] Fabric Meta доступен")); } else { - System.out.println(ZAnsi.brightRed("Fabric Meta вернул код " + response.statusCode())); + System.out.println(ZAnsi.brightRed("[FAIL] Fabric Meta вернул код " + response.statusCode())); } } catch (Exception e) { - System.out.println(ZAnsi.brightRed("Нет доступа к Fabric Meta")); - System.out.println("Ошибка: " + e.getMessage()); + System.out.println(ZAnsi.brightRed("[FAIL] Нет доступа к Fabric Meta")); + System.out.println(ZAnsi.white("Ошибка: ") + e.getMessage()); + } + } + + private void checkForge() { + System.out.println(ZAnsi.cyan("Проверка доступа к Forge Maven...")); + + try { + HttpClient client = HttpClient.newBuilder() + .connectTimeout(Duration.ofSeconds(10)) + .build(); + + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create("https://maven.minecraftforge.net/net/minecraftforge/forge/maven-metadata.xml")) + .GET() + .build(); + + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); + + if (response.statusCode() == 200) { + System.out.println(ZAnsi.brightGreen("[OK] Forge Maven доступен")); + } else { + System.out.println(ZAnsi.brightRed("[FAIL] Forge Maven вернул код " + response.statusCode())); + } + } catch (Exception e) { + System.out.println(ZAnsi.brightRed("[FAIL] Нет доступа к Forge Maven")); + System.out.println(ZAnsi.white("Ошибка: ") + e.getMessage()); } } } \ No newline at end of file diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Config.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Config.java index 942fc16..c22793e 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Config.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Config.java @@ -10,6 +10,8 @@ public class Config { private static final Path CONFIG_DIR = Path.of(System.getProperty("user.home"), ".zernmc"); private static final Path CONFIG_FILE = CONFIG_DIR.resolve("launcher.properties"); + private static final String BUILD_PROFILE = System.getProperty("build.profile", "global"); + private static final Properties props = new Properties(); // Настройки @@ -83,6 +85,14 @@ public class Config { return maxMemory; } + public static boolean isZernMCBuild() { + return "zernmc".equalsIgnoreCase(BUILD_PROFILE); + } + + public static boolean isGlobalBuild() { + return !isZernMCBuild(); + } + public static void setMaxMemory(int memory) { // Защита от слишком маленьких/больших значений if (memory < 1024) memory = 1536; diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Input.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Input.java index 7ece5e6..988505e 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Input.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/Input.java @@ -19,6 +19,7 @@ public class Input { } public static String readLine(String prompt) { + flushInput(); // Очищаем буфер System.out.print(prompt); return scanner.nextLine().trim(); } @@ -79,4 +80,18 @@ public class Input { public static void close() { scanner.close(); } + + + /** + * Очищает буфер ввода от оставшихся символов + */ + public static void flushInput() { + try { + while (System.in.available() > 0) { + System.in.read(); + } + } catch (IOException e) { + // Игнорируем + } + } } \ No newline at end of file diff --git a/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/ZHttpClient.java b/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/ZHttpClient.java index 3e0bff0..292e6e4 100644 --- a/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/ZHttpClient.java +++ b/launcher/src/main/java/me/sashegdev/zernmc/launcher/utils/ZHttpClient.java @@ -3,6 +3,8 @@ package me.sashegdev.zernmc.launcher.utils; import org.json.JSONArray; import org.json.JSONObject; +import me.sashegdev.zernmc.launcher.auth.AuthManager; + import java.io.IOException; import java.net.URI; import java.net.URLEncoder; @@ -380,13 +382,19 @@ public class ZHttpClient { } try { - HttpRequest request = HttpRequest.newBuilder() + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() .uri(URI.create(BASE_URL + endpoint)) .timeout(Duration.ofSeconds(15)) .header("User-Agent", "ZernMC-Launcher/1.0") - .GET() - .build(); + .GET(); + // ===== ДОБАВИТЬ ТОКЕН АВТОРИЗАЦИИ ===== + String accessToken = AuthManager.getAccessToken(); + if (accessToken != null && !accessToken.equals("0")) { + requestBuilder.header("Authorization", "Bearer " + accessToken); + } + + HttpRequest request = requestBuilder.build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); if (response.statusCode() != 200) { @@ -401,19 +409,25 @@ public class ZHttpClient { private static String proxyGet(String endpoint) throws IOException { try { - HttpRequest request = HttpRequest.newBuilder() + HttpRequest.Builder requestBuilder = HttpRequest.newBuilder() .uri(URI.create(BASE_URL + "/proxy" + endpoint)) .timeout(Duration.ofSeconds(30)) .header("User-Agent", "ZernMC-Launcher/1.0") - .GET() - .build(); - + .GET(); + + // ===== ДОБАВИТЬ ТОКЕН АВТОРИЗАЦИИ ===== + String accessToken = AuthManager.getAccessToken(); + if (accessToken != null && !accessToken.equals("0")) { + requestBuilder.header("Authorization", "Bearer " + accessToken); + } + + HttpRequest request = requestBuilder.build(); HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString()); - + if (response.statusCode() != 200) { throw new IOException("HTTP " + response.statusCode()); } - + proxySuccessCount++; return response.body(); } catch (Exception e) { diff --git a/server/main.py b/server/main.py index 0e4b013..d6466a5 100644 --- a/server/main.py +++ b/server/main.py @@ -15,6 +15,8 @@ from middleware import LoggingMiddleware from cli import parse_args, run_test_mode, run_production_mode, run_development_mode from log_manager import init_logging +from fastapi.responses import Response + import httpx import base64 from fastapi.responses import StreamingResponse @@ -80,6 +82,331 @@ async def lifespan(app: FastAPI): logger.info("Server shutting down...") + +# ====================== ШАБЛОН СТРАНИЦЫ АКТИВАЦИИ ====================== +ACTIVATE_PASS_HTML = """ + + + + + + Активация проходки | ZernMC + + + +
+ + +
+
+ + +
+ +
+ + +
+ + +
+ +
+ + +
+ + + + +""" + + + # Create app with lifespan app = FastAPI(title="ZernMC Launcher Server", lifespan=lifespan) @@ -144,6 +471,17 @@ async def health(): return {"status": "healthy", "timestamp": datetime.utcnow().isoformat()} +# ====================== WEB ИНТЕРФЕЙС ДЛЯ АКТИВАЦИИ ПРОХОДКИ ====================== + +@app.get("/activate-pass") +async def activate_pass_page(): + """Веб-интерфейс для активации проходки""" + return Response( + content=ACTIVATE_PASS_HTML, + media_type="text/html" + ) + + # ====================== ЭНДПОИНТЫ ДЛЯ ПАКОВ ====================== @app.get("/packs")