#include #include #include #include // Для system() #include // C++17 для работы с файловой системой #include // Для работы с файлами конфигурации // Пространство имен для удобства работы с файловой системой namespace fs = std::filesystem; // Имя файла конфигурации для хранения URL репозитория const std::string CONFIG_FILE = "launcher_config.txt"; // --- Функции для работы с конфигурацией --- // Функция для сохранения URL Git-репозитория в файл void saveGitRepository(const std::string& repoUrl) { std::ofstream configFile(CONFIG_FILE); if (configFile.is_open()) { configFile << repoUrl; configFile.close(); } else { std::cerr << "Ошибка: Не удалось открыть файл конфигурации для записи." << std::endl; } } // Функция для загрузки URL Git-репозитория из файла std::string loadGitRepository() { std::ifstream configFile(CONFIG_FILE); std::string repoUrl; if (configFile.is_open()) { std::getline(configFile, repoUrl); configFile.close(); } return repoUrl; } // --- Кроссплатформенные функции --- // Функция для получения пути к папке .minecraft в зависимости от ОС fs::path getMinecraftPath() { fs::path minecraftPath; #if defined(_WIN32) // Для Windows путь обычно находится в %APPDATA%\.minecraft char* appdata = nullptr; size_t len; _dupenv_s(&appdata, &len, "APPDATA"); if (appdata != nullptr) { minecraftPath = fs::path(appdata) / ".minecraft"; free(appdata); } #elif defined(__linux__) // Для Linux путь обычно находится в ~/.minecraft char* home = getenv("HOME"); if (home != nullptr) { minecraftPath = fs::path(home) / ".minecraft"; } #elif defined(__APPLE__) // Для macOS путь находится в ~/Library/Application Support/minecraft char* home = getenv("HOME"); if (home != nullptr) { minecraftPath = fs::path(home) / "Library" / "Application Support" / "minecraft"; } #else std::cerr << "Неизвестная операционная система!" << std::endl; #endif return minecraftPath; } // Функция для открытия папки в файловом менеджере по умолчанию void openFolder(const fs::path& folderPath) { if (!fs::exists(folderPath)) { std::cout << "Папка не существует. Создание папки: " << folderPath.string() << std::endl; try { fs::create_directories(folderPath); } catch (const fs::filesystem_error& e) { std::cerr << "Ошибка при создании папки: " << e.what() << std::endl; return; } } std::string command; #if defined(_WIN32) command = "explorer \"" + folderPath.string() + "\""; #elif defined(__linux__) command = "xdg-open \"" + folderPath.string() + "\""; #elif defined(__APPLE__) command = "open \"" + folderPath.string() + "\""; #else std::cerr << "Команда для открытия папки на данной ОС не поддерживается." << std::endl; return; #endif // Выполнение системной команды system(command.c_str()); } // Функция для очистки содержимого папки void clearFolder(const fs::path& folderPath) { if (!fs::exists(folderPath) || !fs::is_directory(folderPath)) { return; // Если папки нет, ничего не делаем } for (const auto& entry : fs::directory_iterator(folderPath)) { try { fs::remove_all(entry.path()); } catch (const fs::filesystem_error& e) { std::cerr << "Не удалось удалить " << entry.path() << ": " << e.what() << std::endl; } } } // --- Функции меню --- // Функция для открытия папки с модами void openModsFolderAction() { fs::path minecraftPath = getMinecraftPath(); if (minecraftPath.empty()) { std::cerr << "Не удалось определить путь к папке Minecraft." << std::endl; return; } fs::path modsPath = minecraftPath / "mods"; std::cout << "Путь к папке модов: " << modsPath.string() << std::endl; openFolder(modsPath); } // Функция для установки URL репозитория void setGitRepositoryAction() { std::string repoUrl; std::cout << "\nВведите URL Git-репозитория (например, https://github.com/user/repo.git):" << std::endl; std::getline(std::cin >> std::ws, repoUrl); // std::ws для очистки буфера от пробельных символов if (repoUrl.empty()) { std::cout << "URL не может быть пустым." << std::endl; return; } saveGitRepository(repoUrl); std::cout << "URL репозитория успешно сохранен." << std::endl; } // Функция для загрузки модов из Git void downloadModsAction() { std::string repoUrl = loadGitRepository(); if (repoUrl.empty()) { std::cout << "URL Git-репозитория не настроен. Пожалуйста, сначала установите его (пункт 2)." << std::endl; return; } fs::path modsPath = getMinecraftPath() / "mods"; std::cout << "Папка для модов: " << modsPath.string() << std::endl; // Убедимся, что папка существует if (!fs::exists(modsPath)) { try { fs::create_directories(modsPath); } catch (const fs::filesystem_error& e) { std::cerr << "Ошибка при создании папки mods: " << e.what() << std::endl; return; } } // Запрос подтверждения перед очисткой char confirmation; std::cout << "\nВНИМАНИЕ! Все существующие файлы в папке 'mods' будут удалены." << std::endl; std::cout << "Продолжить? (y/n): "; std::cin >> confirmation; // Проверка, что пользователь ввел 'y' или 'Y' if (confirmation != 'y' && confirmation != 'Y') { std::cout << "Загрузка отменена." << std::endl; // Очистка буфера ввода после чтения символа std::cin.ignore(std::numeric_limits::max(), '\n'); return; } // Очистка буфера ввода std::cin.ignore(std::numeric_limits::max(), '\n'); std::cout << "Очистка папки mods..." << std::endl; clearFolder(modsPath); std::cout << "Папка очищена." << std::endl; // Формирование команды для клонирования репозитория // Клонируем содержимое репозитория прямо в папку mods std::string command = "git clone " + repoUrl + " \"" + modsPath.string() + "\""; std::cout << "\nВыполнение команды: " << command << std::endl; std::cout << "Начинается загрузка модов. Это может занять некоторое время..." << std::endl; int result = system(command.c_str()); if (result == 0) { std::cout << "Моды успешно загружены!" << std::endl; } else { std::cerr << "Произошла ошибка при загрузке модов. Убедитесь, что Git установлен и URL репозитория верный." << std::endl; } } // Отображение главного меню void printMenu() { std::cout << "\n--- Minecraft Mod Launcher ---" << std::endl; std::cout << "1. Открыть папку с модами (.minecraft/mods)" << std::endl; std::cout << "2. Указать/изменить URL Git-репозитория с модами" << std::endl; std::cout << "3. Загрузить/обновить моды из Git-репозитория" << std::endl; std::cout << "4. Выход" << std::endl; std::cout << "-----------------------------" << std::endl; std::string currentRepo = loadGitRepository(); if (currentRepo.empty()) { std::cout << "Текущий репозиторий: не задан" << std::endl; } else { std::cout << "Текущий репозиторий: " << currentRepo << std::endl; } std::cout << "\nВведите ваш выбор: "; } // --- Главная функция программы --- int main() { // Установка кодировки консоли для корректного отображения кириллицы в Windows #if defined(_WIN32) system("chcp 65001 > nul"); #endif int choice; while (true) { printMenu(); std::cin >> choice; // Проверка на корректность ввода if (std::cin.fail()) { std::cout << "Ошибка: введите число." << std::endl; std::cin.clear(); // Сброс флага ошибки // Очистка буфера ввода до следующей новой строки std::cin.ignore(std::numeric_limits::max(), '\n'); continue; } switch (choice) { case 1: openModsFolderAction(); break; case 2: setGitRepositoryAction(); break; case 3: downloadModsAction(); break; case 4: std::cout << "Выход из программы." << std::endl; return 0; default: std::cout << "Неверный выбор. Пожалуйста, попробуйте снова." << std::endl; break; } std::cout << "\nНажмите Enter для продолжения..."; // Очистка буфера перед ожиданием Enter if (choice != 3 && choice !=2) { std::cin.ignore(std::numeric_limits::max(), '\n'); } std::cin.get(); } return 0; }