diff --git a/Ui-TEMP/MinecraftUI.qml b/Ui-TEMP/MinecraftUI.qml deleted file mode 100644 index 3cdb676..0000000 --- a/Ui-TEMP/MinecraftUI.qml +++ /dev/null @@ -1,177 +0,0 @@ - - -/* -This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only. -It is supposed to be strictly declarative and only uses a subset of QML. If you edit -this file manually, you might introduce QML code that is not supported by Qt Design Studio. -Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files. -*/ -import QtQuick -import QtQuick.Controls -import UntitledProject1 - -Rectangle { - id: rectangle - width: Constants.width - height: Constants.height - color: "#2e2e2e" - radius: 0 - border.color: "#1a1a1a" - - Image { - id: kishkaProfileIdle - x: 40 - y: 239 - source: "Profile Box/Kishka Profile Idle.svg" - fillMode: Image.PreserveAspectFit - } - - Image { - id: kishkaVerIdle - x: 165 - y: 239 - source: "Version box/Kishka Ver idle.svg" - fillMode: Image.PreserveAspectFit - } - - Button { - id: folderbutt - x: 130 - y: 304 - width: 70 - height: 40 - visible: true - text: qsTr("Button") - topPadding: 0 - rightPadding: 0 - leftPadding: 0 - icon.width: 335 - icon.source: "Folder/Folder Idle.svg" - icon.height: 170 - icon.color: "#0026282a" - flat: true - display: AbstractButton.IconOnly - bottomPadding: 0 - } - - Button { - id: playbutt - x: 40 - y: 57 - width: 335 - height: 170 - visible: true - text: qsTr("Button") - icon.cache: false - rightPadding: 0 - bottomPadding: 0 - leftPadding: 0 - topPadding: 0 - flat: true - icon.height: 170 - icon.width: 335 - display: AbstractButton.IconOnly - icon.color: "#0026282a" - icon.source: "Play Button/Play Idle.svg" - } - - Button { - id: optionsbut - x: 215 - y: 304 - width: 70 - height: 40 - visible: true - text: qsTr("Button") - topPadding: 0 - rightPadding: 0 - leftPadding: 0 - icon.width: 335 - icon.source: "Options/Options Idle.svg" - icon.height: 170 - icon.color: "#0026282a" - icon.cache: false - flat: true - display: AbstractButton.IconOnly - bottomPadding: 0 - } - - states: [ - State { - name: "clicked" - when: playbutt.pressed - - PropertyChanges { - target: playbutt - x: 40 - y: 55 - rightPadding: 0 - bottomPadding: 0 - leftPadding: 0 - topPadding: 0 - icon.source: "Play Button/Play pressed.svg" - } - }, - - State { - name: "Hover" - when: playbutt.hovered - - PropertyChanges { - target: playbutt - flat: true - icon.source: "Play Button/Play Active.svg" - } - }, - State { - name: "Folder Pressed" - when: folderbutt.pressed - - PropertyChanges { - target: folderbutt - icon.source: "Folder/Folder Pressed.svg" - icon.height: 170 - icon.width: 335 - icon.color: "#0026282a" - } - }, - - State { - name: "Folder Hover" - when: folderbutt.hovered - - PropertyChanges { - target: rectangle - color: "#2e2e2e" - } - - PropertyChanges { - target: folderbutt - x: 130 - y: 304 - icon.height: 170 - icon.width: 335 - icon.color: "#0026282a" - icon.source: "Folder/Folder Active.svg" - } - }, - State { - name: "Option Pressed" - when: optionsbut.pressed - - PropertyChanges { - target: optionsbut - icon.source: "Options/Options active.svg" - } - }, - State { - name: "OptionHover" - when: optionsbut.hovered - - PropertyChanges { - target: optionsbut - icon.source: "Options/Options Pressed.svg" - } - } - ] -} diff --git a/Ui-TEMP/MinecraftUI.ui.qml b/Ui-TEMP/MinecraftUI.ui.qml deleted file mode 100644 index 3cdb676..0000000 --- a/Ui-TEMP/MinecraftUI.ui.qml +++ /dev/null @@ -1,177 +0,0 @@ - - -/* -This is a UI file (.ui.qml) that is intended to be edited in Qt Design Studio only. -It is supposed to be strictly declarative and only uses a subset of QML. If you edit -this file manually, you might introduce QML code that is not supported by Qt Design Studio. -Check out https://doc.qt.io/qtcreator/creator-quick-ui-forms.html for details on .ui.qml files. -*/ -import QtQuick -import QtQuick.Controls -import UntitledProject1 - -Rectangle { - id: rectangle - width: Constants.width - height: Constants.height - color: "#2e2e2e" - radius: 0 - border.color: "#1a1a1a" - - Image { - id: kishkaProfileIdle - x: 40 - y: 239 - source: "Profile Box/Kishka Profile Idle.svg" - fillMode: Image.PreserveAspectFit - } - - Image { - id: kishkaVerIdle - x: 165 - y: 239 - source: "Version box/Kishka Ver idle.svg" - fillMode: Image.PreserveAspectFit - } - - Button { - id: folderbutt - x: 130 - y: 304 - width: 70 - height: 40 - visible: true - text: qsTr("Button") - topPadding: 0 - rightPadding: 0 - leftPadding: 0 - icon.width: 335 - icon.source: "Folder/Folder Idle.svg" - icon.height: 170 - icon.color: "#0026282a" - flat: true - display: AbstractButton.IconOnly - bottomPadding: 0 - } - - Button { - id: playbutt - x: 40 - y: 57 - width: 335 - height: 170 - visible: true - text: qsTr("Button") - icon.cache: false - rightPadding: 0 - bottomPadding: 0 - leftPadding: 0 - topPadding: 0 - flat: true - icon.height: 170 - icon.width: 335 - display: AbstractButton.IconOnly - icon.color: "#0026282a" - icon.source: "Play Button/Play Idle.svg" - } - - Button { - id: optionsbut - x: 215 - y: 304 - width: 70 - height: 40 - visible: true - text: qsTr("Button") - topPadding: 0 - rightPadding: 0 - leftPadding: 0 - icon.width: 335 - icon.source: "Options/Options Idle.svg" - icon.height: 170 - icon.color: "#0026282a" - icon.cache: false - flat: true - display: AbstractButton.IconOnly - bottomPadding: 0 - } - - states: [ - State { - name: "clicked" - when: playbutt.pressed - - PropertyChanges { - target: playbutt - x: 40 - y: 55 - rightPadding: 0 - bottomPadding: 0 - leftPadding: 0 - topPadding: 0 - icon.source: "Play Button/Play pressed.svg" - } - }, - - State { - name: "Hover" - when: playbutt.hovered - - PropertyChanges { - target: playbutt - flat: true - icon.source: "Play Button/Play Active.svg" - } - }, - State { - name: "Folder Pressed" - when: folderbutt.pressed - - PropertyChanges { - target: folderbutt - icon.source: "Folder/Folder Pressed.svg" - icon.height: 170 - icon.width: 335 - icon.color: "#0026282a" - } - }, - - State { - name: "Folder Hover" - when: folderbutt.hovered - - PropertyChanges { - target: rectangle - color: "#2e2e2e" - } - - PropertyChanges { - target: folderbutt - x: 130 - y: 304 - icon.height: 170 - icon.width: 335 - icon.color: "#0026282a" - icon.source: "Folder/Folder Active.svg" - } - }, - State { - name: "Option Pressed" - when: optionsbut.pressed - - PropertyChanges { - target: optionsbut - icon.source: "Options/Options active.svg" - } - }, - State { - name: "OptionHover" - when: optionsbut.hovered - - PropertyChanges { - target: optionsbut - icon.source: "Options/Options Pressed.svg" - } - } - ] -} diff --git a/assets/Folder/Folder Active.svg b/assets/Folder/Folder Active.svg deleted file mode 100644 index b12cf09..0000000 --- a/assets/Folder/Folder Active.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/Folder/Folder Idle.svg b/assets/Folder/Folder Idle.svg deleted file mode 100644 index 0b82a40..0000000 --- a/assets/Folder/Folder Idle.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/Folder/Folder Pressed.svg b/assets/Folder/Folder Pressed.svg deleted file mode 100644 index 8c71b1e..0000000 --- a/assets/Folder/Folder Pressed.svg +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/options/Options Idle.svg b/assets/options/Options Idle.svg deleted file mode 100644 index e2e9317..0000000 --- a/assets/options/Options Idle.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/options/Options Pressed.svg b/assets/options/Options Pressed.svg deleted file mode 100644 index 9c37a69..0000000 --- a/assets/options/Options Pressed.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/options/Options active.svg b/assets/options/Options active.svg deleted file mode 100644 index c56f406..0000000 --- a/assets/options/Options active.svg +++ /dev/null @@ -1,26 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/play button/Play Active.svg b/assets/play button/Play Active.svg deleted file mode 100644 index 39f605d..0000000 --- a/assets/play button/Play Active.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/play button/Play Idle.svg b/assets/play button/Play Idle.svg deleted file mode 100644 index f386539..0000000 --- a/assets/play button/Play Idle.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/play button/Play pressed.svg b/assets/play button/Play pressed.svg deleted file mode 100644 index 1dd3f4b..0000000 --- a/assets/play button/Play pressed.svg +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/assets/profile box/Kishka Profile Active.svg b/assets/profile box/Kishka Profile Active.svg deleted file mode 100644 index f513773..0000000 --- a/assets/profile box/Kishka Profile Active.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/profile box/Kishka Profile Idle.svg b/assets/profile box/Kishka Profile Idle.svg deleted file mode 100644 index e8c7e2d..0000000 --- a/assets/profile box/Kishka Profile Idle.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/profile box/Kishka Profile open.svg b/assets/profile box/Kishka Profile open.svg deleted file mode 100644 index d7900bf..0000000 --- a/assets/profile box/Kishka Profile open.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/scroll/Scroll Lever.svg b/assets/scroll/Scroll Lever.svg deleted file mode 100644 index 845f36f..0000000 --- a/assets/scroll/Scroll Lever.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/assets/scroll/Scroll palka.svg b/assets/scroll/Scroll palka.svg deleted file mode 100644 index d80f052..0000000 --- a/assets/scroll/Scroll palka.svg +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - \ No newline at end of file diff --git a/assets/version box/Kishka Profile Open.svg b/assets/version box/Kishka Profile Open.svg deleted file mode 100644 index 2a52892..0000000 --- a/assets/version box/Kishka Profile Open.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/version box/Kishka Ver Active.svg b/assets/version box/Kishka Ver Active.svg deleted file mode 100644 index 537d7ff..0000000 --- a/assets/version box/Kishka Ver Active.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/assets/version box/Kishka Ver idle.svg b/assets/version box/Kishka Ver idle.svg deleted file mode 100644 index 361ffe8..0000000 --- a/assets/version box/Kishka Ver idle.svg +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/mainwindow.cpp b/mainwindow.cpp deleted file mode 100644 index 11a6fdb..0000000 --- a/mainwindow.cpp +++ /dev/null @@ -1,467 +0,0 @@ -#include "mainwindow.h" -#include "ui_mainwindow.h" // Подключаем сгенерированный заголовочный файл -#include "settingsdialog.h" -#include "profiledialog.h" // Подключаем новый диалог - -#include -#include -#include -#include -#include // Для диалога выбора -#include // Для проверки файла -#include // Для работы с JSON -#include // Для работы с JSON -#include // Для работы с JSON -#include // Для работы с JSON -#include // Для генерации ID профиля -#include // Для поиска папки с данными - -MainWindow::MainWindow(QWidget *parent) - : QMainWindow(parent) - , ui(new Ui::MainWindow) // Инициализируем указатель на UI -{ - ui->setupUi(this); // Загружаем интерфейс из .ui файла - - // Начальная настройка виджетов - ui->progressBar->setRange(0, 0); // Неопределенный прогресс-бар - ui->progressBar->setVisible(false); - - // Инициализация логики - settings = new QSettings("GaleonDev", "MinecraftLauncher", this); - process = new QProcess(this); - - // Подключаем сигналы от процесса (это делается вручную) - connect(process, &QProcess::readyReadStandardOutput, this, &MainWindow::readProcessOutput); - connect(process, &QProcess::readyReadStandardError, this, &MainWindow::readProcessOutput); - connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onProcessFinished(int, QProcess::ExitStatus))); - connect(process, SIGNAL(errorOccurred(QProcess::ProcessError)), this, SLOT(onProcessError(QProcess::ProcessError))); - // Загружаем профили при старте - profilesPath = "/launcher_profiles.json"; - loadProfiles(); -} - -MainWindow::~MainWindow() -{ - delete ui; // Освобождаем память от объекта UI -} - -// Вспомогательная функция для проверки правил OS -bool checkRules(const QJsonObject &item) { - if (!item.contains("rules")) { - return true; // Нет правил - разрешено для всех. - } - - // Если правила есть, по умолчанию запрещаем, пока не найдем разрешающее правило. - bool isAllowed = false; - - QString currentOs; -#if defined(Q_OS_WIN) - currentOs = "windows"; -#elif defined(Q_OS_MAC) - currentOs = "osx"; -#elif defined(Q_OS_LINUX) - currentOs = "linux"; -#endif - - QJsonArray rules = item["rules"].toArray(); - - for (const QJsonValue &value : rules) { - QJsonObject rule = value.toObject(); - QString action = rule["action"].toString(); - - bool conditionMet = false; - if (rule.contains("os")) { - QJsonObject osRule = rule["os"].toObject(); - if (osRule.contains("name") && osRule["name"].toString() == currentOs) { - conditionMet = true; - } - } else { - // Правило без указания ОС применяется ко всем системам. - conditionMet = true; - } - - if (conditionMet) { - if (action == "allow") { - isAllowed = true; - } else if (action == "disallow") { - isAllowed = false; - } - } - } - - return isAllowed; -} - -void MainWindow::loadProfiles() -{ - QFile profilesFile(profilesPath); - if (profilesFile.exists() && profilesFile.open(QIODevice::ReadOnly)) { - QJsonDocument doc = QJsonDocument::fromJson(profilesFile.readAll()); - profilesData = doc.object(); - profilesFile.close(); - } else { - // Создаем базовую структуру, если файла нет - profilesData = QJsonObject({{"profiles", QJsonObject()}}); - } - - QJsonObject profiles = profilesData["profiles"].toObject(); - ui->profileComboBox->clear(); - - if (profiles.isEmpty()) { - // Если профилей нет, принудительно открываем диалог создания - QMessageBox::information(this, "Настройка", "Не найдено ни одного профиля. Давайте создадим новый."); - createNewProfile(); - return; // createNewProfile вызовет loadProfiles() повторно - } - - // Заполняем ComboBox - for (const QString &key : profiles.keys()) { - QJsonObject profile = profiles[key].toObject(); - ui->profileComboBox->addItem(profile["name"].toString(), key); // Имя и UUID - } -} - -void MainWindow::saveProfiles() -{ - QFile profilesFile(profilesPath); - if (profilesFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - QJsonDocument doc(profilesData); - profilesFile.write(doc.toJson(QJsonDocument::Indented)); - profilesFile.close(); - } else { - QMessageBox::critical(this, "Ошибка", "Не удалось сохранить файл профилей: " + profilesFile.errorString()); - } -} - -void MainWindow::on_editProfileButton_clicked() -{ - // 1. Проверяем, выбран ли профиль - QString currentProfileId = ui->profileComboBox->currentData().toString(); - if (currentProfileId.isEmpty()) { - QMessageBox::warning(this, "Нет профиля", "Пожалуйста, выберите профиль для редактирования."); - return; - } - - // 2. Получаем данные текущего профиля - QJsonObject profiles = profilesData["profiles"].toObject(); - QJsonObject currentProfile = profiles[currentProfileId].toObject(); - - // 3. Создаем диалог и заполняем его данными - ProfileDialog dialog(this); - dialog.setWindowTitle("Редактирование профиля"); - dialog.setProfileName(currentProfile["name"].toString()); - dialog.setJavaPath(currentProfile["javaDir"].toString()); - - // 4. Показываем диалог и обрабатываем результат - if (dialog.exec() == QDialog::Accepted) { - if (dialog.profileName().isEmpty() || dialog.javaPath().isEmpty()) { - QMessageBox::warning(this, "Ошибка", "Имя профиля и путь к Java не могут быть пустыми."); - return; - } - - // 5. Обновляем данные в нашем JSON объекте - currentProfile["name"] = dialog.profileName(); - currentProfile["javaDir"] = dialog.javaPath(); - - // 6. Записываем обновленный профиль обратно - profiles[currentProfileId] = currentProfile; - profilesData["profiles"] = profiles; - - // 7. Сохраняем и перезагружаем список - saveProfiles(); - - // Сохраняем ID, чтобы восстановить выбор после перезагрузки - QString previouslySelectedId = currentProfileId; - loadProfiles(); - int indexToSelect = ui->profileComboBox->findData(previouslySelectedId); - if (indexToSelect != -1) { - ui->profileComboBox->setCurrentIndex(indexToSelect); - } - } -} - -void MainWindow::createNewProfile() -{ - ProfileDialog dialog(this); - if (dialog.exec() == QDialog::Accepted) { - if (dialog.profileName().isEmpty() || dialog.javaPath().isEmpty()) { - QMessageBox::warning(this, "Ошибка", "Имя профиля и путь к Java не могут быть пустыми."); - return; - } - - QString uuid = QUuid::createUuid().toString(QUuid::WithoutBraces); - QJsonObject newProfile; - newProfile["name"] = dialog.profileName(); - newProfile["javaDir"] = dialog.javaPath(); - newProfile["lastVersionId"] = ""; - newProfile["created"] = QDateTime::currentDateTime().toString(Qt::ISODate); - newProfile["lastUsed"] = QDateTime::currentDateTime().toString(Qt::ISODate); - newProfile["icon"] = "Bedrock"; - newProfile["type"] = "custom"; - - QJsonObject profiles = profilesData["profiles"].toObject(); - profiles[uuid] = newProfile; - profilesData["profiles"] = profiles; - - saveProfiles(); - loadProfiles(); // Перезагружаем список профилей - } -} - -void MainWindow::on_addProfileButton_clicked() -{ - createNewProfile(); -} - -void MainWindow::on_profileComboBox_currentIndexChanged(int index) -{ - // Пока ничего не делаем, но слот полезен для будущего - Q_UNUSED(index); -} - -void MainWindow::on_launchButton_clicked() -{ - QString currentProfileId = ui->profileComboBox->currentData().toString(); - if (currentProfileId.isEmpty()) { - QMessageBox::critical(this, "Ошибка", "Не выбран профиль для запуска!"); - return; - } - QJsonObject profile = profilesData["profiles"].toObject()[currentProfileId].toObject(); - QString javaPath = profile["javaDir"].toString(); - if (!QFileInfo::exists(javaPath)) { - QMessageBox::critical(this, "Ошибка", "Не найден исполняемый файл Java, указанный в профиле:\n" + javaPath); - return; - } - // --- 1. Выбор версии (остается без изменений) --- - QString minecraftPath = getMinecraftPath(); - if (minecraftPath.isEmpty()) { - QMessageBox::warning(this, "Ошибка", "Не удалось найти директорию .minecraft."); - return; - } - QString versionsPath = QDir::toNativeSeparators(minecraftPath + "/versions"); - QDir versionsDir(versionsPath); - if (!versionsDir.exists()) { - QMessageBox::warning(this, "Ошибка", "Папка 'versions' не найдена!"); - return; - } - QStringList versionList = versionsDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot); - if (versionList.isEmpty()) { - QMessageBox::warning(this, "Ошибка", "Не найдено ни одной установленной версии Minecraft."); - return; - } - bool ok; - QString selectedVersion = QInputDialog::getItem(this, "Выбор версии", - "Выберите версию Minecraft для запуска:", - versionList, 0, false, &ok); - if (!ok || selectedVersion.isEmpty()) { - return; // Пользователь отменил выбор - } - - // --- 2. Чтение и парсинг JSON файла версии --- - QString jsonPath = QDir::toNativeSeparators(versionsPath + "/" + selectedVersion + "/" + selectedVersion + ".json"); - QFile jsonFile(jsonPath); - if (!jsonFile.open(QIODevice::ReadOnly)) { - QMessageBox::critical(this, "Ошибка", "Не удалось открыть .json файл для версии " + selectedVersion); - return; - } - QByteArray jsonData = jsonFile.readAll(); - jsonFile.close(); - QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData); - if (jsonDoc.isNull()) { - QMessageBox::critical(this, "Ошибка", "Некорректный .json файл для версии " + selectedVersion); - return; - } - QJsonObject rootObj = jsonDoc.object(); - - // --- 3. Формирование Classpath --- - QStringList classpathEntries; - QString librariesPath = QDir::toNativeSeparators(minecraftPath + "/libraries"); - QJsonArray libraries = rootObj["libraries"].toArray(); - - for (const QJsonValue &value : libraries) { - QJsonObject library = value.toObject(); - - if (!checkRules(library)) { - continue; // Пропускаем библиотеку, если она не для этой ОС - } - - QJsonObject downloads = library["downloads"].toObject(); - if(downloads.isEmpty()){ // Для Fabric Loader и некоторых других - QString name = library["name"].toString(); - QStringList parts = name.split(':'); - QString path = parts[0].replace('.', '/') + "/" + parts[1] + "/" + parts[2] + "/" + parts[1] + "-" + parts[2] + ".jar"; - classpathEntries << QDir::toNativeSeparators(librariesPath + "/" + path); - - } else { - QJsonObject artifact = downloads["artifact"].toObject(); - QString path = artifact["path"].toString(); - classpathEntries << QDir::toNativeSeparators(librariesPath + "/" + path); - } - } - // Добавляем сам .jar файл игры в classpath - classpathEntries << QDir::toNativeSeparators(versionsPath + "/" + selectedVersion + "/" + selectedVersion + ".jar"); - - // Определяем разделитель для classpath в зависимости от ОС - QString pathSeparator; -#if defined(Q_OS_WIN) - pathSeparator = ";"; -#else - pathSeparator = ":"; -#endif - QString classpath = classpathEntries.join(pathSeparator); - - // --- 4. Сборка аргументов --- - QStringList jvmArgs; - QStringList gameArgs; - - // Аргументы для JVM - QJsonObject argumentsObj = rootObj["arguments"].toObject(); - QJsonArray jvmArgsArray = argumentsObj["jvm"].toArray(); - for (const QJsonValue &value : jvmArgsArray) { - if (value.isString()) { - jvmArgs << value.toString(); - } else if (value.isObject()) { - if (checkRules(value.toObject())) { - QJsonArray values = value.toObject()["values"].toArray(); - for(const QJsonValue &v : values){ - jvmArgs << v.toString(); - } - } - } - } - - // Аргументы для игры - QJsonArray gameArgsArray = argumentsObj["game"].toArray(); - for (const QJsonValue &value : gameArgsArray) { - if (value.isString()) { - gameArgs << value.toString(); - } else if (value.isObject()) { - if (checkRules(value.toObject())) { - QJsonArray values = value.toObject()["values"].toArray(); - for(const QJsonValue &v : values){ - gameArgs << v.toString(); - } - } - } - } - - // --- 5. Подстановка значений в плейсхолдеры --- - QString nativesPath = QDir::toNativeSeparators(versionsPath + "/" + selectedVersion + "/natives"); - QDir(nativesPath).mkpath("."); // Создаем папку для нативных библиотек, если ее нет - - // Заменители для JVM аргументов - for (QString &arg : jvmArgs) { - arg.replace("${natives_directory}", nativesPath); - arg.replace("${launcher_name}", "CustomLauncher"); - arg.replace("${launcher_version}", "1.0"); - arg.replace("${classpath}", classpath); - } - // Заменители для игровых аргументов (используем базовые значения) - for (QString &arg : gameArgs) { - arg.replace("${auth_player_name}", "Player"); - arg.replace("${version_name}", selectedVersion); - arg.replace("${game_directory}", minecraftPath); - arg.replace("${assets_root}", QDir::toNativeSeparators(minecraftPath + "/assets")); - arg.replace("${assets_index_name}", rootObj["assetIndex"].toObject()["id"].toString()); - arg.replace("${auth_uuid}", "00000000-0000-0000-0000-000000000000"); - arg.replace("${auth_access_token}", "0"); - arg.replace("${clientid}", "N/A"); - arg.replace("${auth_xuid}", "N/A"); - arg.replace("${user_type}", "msa"); - arg.replace("${version_type}", rootObj["type"].toString()); - } - - // --- 6. Финальная сборка и запуск --- - QString mainClass = rootObj["mainClass"].toString(); - //QString javaPath = "java"; - - QStringList finalArguments; - finalArguments << jvmArgs << mainClass << gameArgs; - - ui->logOutput->appendPlainText("Запуск Minecraft версии: " + selectedVersion); - ui->logOutput->appendPlainText("Главный класс: " + mainClass); - // Для отладки можно вывести всю команду - ui->logOutput->appendPlainText("Команда: " + javaPath + " " + finalArguments.join(" ")); - - process->start(javaPath, finalArguments); - ui->progressBar->setVisible(true); -} - -void MainWindow::on_modsFolderButton_clicked() -{ - QString minecraftPath = getMinecraftPath(); - if (minecraftPath.isEmpty()) { - QMessageBox::warning(this, "Ошибка", "Не удалось найти директорию .minecraft."); - return; - } - QString modsPath = minecraftPath + "/mods"; - QDesktopServices::openUrl(QUrl::fromLocalFile(modsPath)); -} - -void MainWindow::on_settingsButton_clicked() -{ - SettingsDialog dialog(this); - dialog.exec(); -} - -void MainWindow::on_updateModsButton_clicked() -{ - QString gitRepoUrl = settings->value("gitRepoUrl").toString(); - if (gitRepoUrl.isEmpty()) { - QMessageBox::information(this, "Настройки", "Пожалуйста, укажите URL Git-репозитория в настройках."); - return; - } - - QString minecraftPath = getMinecraftPath(); - if (minecraftPath.isEmpty()) { - QMessageBox::warning(this, "Ошибка", "Не удалось найти директорию .minecraft."); - return; - } - QString modsPath = minecraftPath + "/mods"; - QDir modsDir(modsPath); - - if (!modsDir.exists(".git")) { - ui->logOutput->appendPlainText("Клонирование модов из " + gitRepoUrl); - process->start("git", QStringList() << "clone" << gitRepoUrl << modsPath); - } else { - ui->logOutput->appendPlainText("Обновление модов..."); - process->setWorkingDirectory(modsPath); - process->start("git", QStringList() << "pull"); - } - ui->progressBar->setVisible(true); -} - -void MainWindow::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) -{ - ui->progressBar->setVisible(false); - if (exitStatus == QProcess::CrashExit) { - ui->logOutput->appendPlainText("Процесс завершился с ошибкой."); - } else { - ui->logOutput->appendPlainText("Процесс успешно завершен с кодом " + QString::number(exitCode)); - } -} - -void MainWindow::onProcessError(QProcess::ProcessError error) -{ - ui->progressBar->setVisible(false); - ui->logOutput->appendPlainText("Ошибка запуска процесса: " + process->errorString()); -} - -void MainWindow::readProcessOutput() -{ - ui->logOutput->appendPlainText(process->readAllStandardOutput()); - ui->logOutput->appendPlainText(process->readAllStandardError()); -} - -QString MainWindow::getMinecraftPath() -{ - QString path; -#if defined(Q_OS_WIN) - path = QDir::homePath() + "/AppData/Roaming/.minecraft"; -#elif defined(Q_OS_MAC) - path = QDir::homePath() + "/Library/Application Support/minecraft"; -#else - path = QDir::homePath() + "/.minecraft"; -#endif - return path; -} diff --git a/mainwindow.h b/mainwindow.h deleted file mode 100644 index fcf731e..0000000 --- a/mainwindow.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include -#include -#include -#include // Важно: добавить для хранения данных профилей - -// Предварительное объявление класса, сгенерированного из mainwindow.ui -QT_BEGIN_NAMESPACE -namespace Ui { class MainWindow; } -QT_END_NAMESPACE - -class MainWindow : public QMainWindow -{ - Q_OBJECT - -public: - MainWindow(QWidget *parent = nullptr); - ~MainWindow(); - -private slots: - // Слоты для кнопок (автоматически подключаются по имени: on_<имя_объекта>_<сигнал>) - void on_launchButton_clicked(); - void on_modsFolderButton_clicked(); - void on_updateModsButton_clicked(); - void on_settingsButton_clicked(); - void on_addProfileButton_clicked(); // Слот для кнопки "Новый..." - void on_editProfileButton_clicked(); // <-- ДОБАВЬТЕ ЭТОТ СЛОТ - void on_profileComboBox_currentIndexChanged(int index); // Слот для смены профиля - - // Слоты для QProcess (подключаются вручную) - void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); - void onProcessError(QProcess::ProcessError error); - void readProcessOutput(); - -private: - QString getMinecraftPath(); - - // Новые методы для работы с профилями - void loadProfiles(); - void saveProfiles(); - void createNewProfile(); - QString profilesPath; // Путь к launcher_profiles.json - QJsonObject profilesData; // JSON данные из файла - - Ui::MainWindow *ui; // Указатель на объект интерфейса - QProcess *process; - QSettings *settings; -}; - -#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui deleted file mode 100644 index 0e95b55..0000000 --- a/mainwindow.ui +++ /dev/null @@ -1,96 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 600 - 400 - - - - Minecraft Лаунчер - - - - - - - - - Профиль: - - - - - - - - - - Новый... - - - - - - - Редактировать... - - - - - - - - - Запустить Minecraft - - - - - - - Открыть папку с модами - - - - - - - Обновить моды из Git - - - - - - - Настройки - - - - - - - 0 - - - false - - - - - - - true - - - - - - - - - diff --git a/profiledialog.cpp b/profiledialog.cpp deleted file mode 100644 index e5fd062..0000000 --- a/profiledialog.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "profiledialog.h" -#include "ui_profiledialog.h" -#include - -ProfileDialog::ProfileDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::ProfileDialog) -{ - ui->setupUi(this); -} - -ProfileDialog::~ProfileDialog() -{ - delete ui; -} - -QString ProfileDialog::profileName() const -{ - return ui->profileNameEdit->text(); -} - -QString ProfileDialog::javaPath() const -{ - return ui->javaPathEdit->text(); -} -// === РЕАЛИЗАЦИЯ НОВЫХ ФУНКЦИЙ === -void ProfileDialog::setProfileName(const QString &name) -{ - ui->profileNameEdit->setText(name); -} - -void ProfileDialog::setJavaPath(const QString &path) -{ - ui->javaPathEdit->setText(path); -} -// =============================== - -void ProfileDialog::on_browseButton_clicked() -{ - QString filter = "Исполняемый файл (java.exe)"; -#if !defined(Q_OS_WIN) - filter = "Все файлы (*)"; -#endif - QString path = QFileDialog::getOpenFileName(this, "Выберите java.exe", QDir::homePath(), filter); - if (!path.isEmpty()) { - ui->javaPathEdit->setText(QDir::toNativeSeparators(path)); - } -} diff --git a/profiledialog.h b/profiledialog.h deleted file mode 100644 index ea6368e..0000000 --- a/profiledialog.h +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef PROFILEDIALOG_H -#define PROFILEDIALOG_H - -#include - -namespace Ui { -class ProfileDialog; -} - -class ProfileDialog : public QDialog -{ - Q_OBJECT - -public: - explicit ProfileDialog(QWidget *parent = nullptr); - ~ProfileDialog(); - - QString profileName() const; - QString javaPath() const; - // === НОВЫЕ ФУНКЦИИ === - void setProfileName(const QString &name); - void setJavaPath(const QString &path); - - -private slots: - void on_browseButton_clicked(); - -private: - Ui::ProfileDialog *ui; -}; - -#endif // PROFILEDIALOG_H diff --git a/profiledialog.ui b/profiledialog.ui deleted file mode 100644 index 0b923a5..0000000 --- a/profiledialog.ui +++ /dev/null @@ -1,99 +0,0 @@ - - - ProfileDialog - - - - 0 - 0 - 450 - 150 - - - - Настройка профиля - - - - - - - - Имя профиля: - - - - - - - - - - Путь к Java: - - - - - - - - - - - - ... - - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - ProfileDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - ProfileDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - \ No newline at end of file diff --git a/settingsdialog.cpp b/settingsdialog.cpp deleted file mode 100644 index d32c6f3..0000000 --- a/settingsdialog.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "settingsdialog.h" -#include "ui_settingsdialog.h" - -SettingsDialog::SettingsDialog(QWidget *parent) : - QDialog(parent), - ui(new Ui::SettingsDialog) -{ - ui->setupUi(this); - - settings = new QSettings("MyCompany", "MinecraftLauncher", this); - ui->gitRepoEdit->setText(settings->value("gitRepoUrl").toString()); - - // Сигналы от кнопок (OK, Cancel) автоматически подключены к слотам accept() и reject() - // благодаря QDialogButtonBox и .ui файлу -} - -SettingsDialog::~SettingsDialog() -{ - delete ui; -} - -// Эта функция будет вызвана при нажатии кнопки "OK" -void SettingsDialog::accept() -{ - settings->setValue("gitRepoUrl", ui->gitRepoEdit->text()); - QDialog::accept(); // Вызываем базовую реализацию, которая закрывает диалог -} diff --git a/settingsdialog.h b/settingsdialog.h deleted file mode 100644 index a72cfca..0000000 --- a/settingsdialog.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef SETTINGSDIALOG_H -#define SETTINGSDIALOG_H - -#include -#include - -namespace Ui { -class SettingsDialog; -} - -class SettingsDialog : public QDialog -{ - Q_OBJECT - -public: - explicit SettingsDialog(QWidget *parent = nullptr); - ~SettingsDialog(); - -private slots: - void accept(); // Переопределяем слот, чтобы сохранить настройки - -private: - Ui::SettingsDialog *ui; - QSettings *settings; -}; - -#endif // SETTINGSDIALOG_H diff --git a/settingsdialog.ui b/settingsdialog.ui deleted file mode 100644 index 8965f66..0000000 --- a/settingsdialog.ui +++ /dev/null @@ -1,74 +0,0 @@ - - - SettingsDialog - - - - 0 - 0 - 400 - 120 - - - - Настройки - - - - - - URL Git-репозитория с модами: - - - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - - buttonBox - accepted() - SettingsDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - SettingsDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - \ No newline at end of file