settings module + ui update

This commit is contained in:
OpexHunter 2025-01-11 03:26:59 +03:00
parent f93bbc4a00
commit 0a45031868
20 changed files with 1659 additions and 330 deletions

View File

@ -12,7 +12,7 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD_REQUIRED ON)
find_package(Qt6 REQUIRED COMPONENTS Widgets) find_package(Qt6 REQUIRED COMPONENTS Widgets Network)
qt_standard_project_setup() qt_standard_project_setup()

View File

@ -1,11 +1,15 @@
qt_add_executable(PunkLauncher qt_add_executable(PunkLauncher
mainwindow.ui
mainwindow.cpp
main.cpp main.cpp
ui/mainwindow.cpp
launcher/launcher.cpp
launcher/forge1.12.2/getArgs.cpp
backend/backend.cpp
settings/settings.cpp
../resources/resources.qrc ../resources/resources.qrc
../resources/mainwindow.ui
) )
target_link_libraries(PunkLauncher PRIVATE Qt6::Widgets) target_link_libraries(PunkLauncher PRIVATE Qt6::Widgets Qt6::Network)
set_target_properties(PunkLauncher PROPERTIES set_target_properties(PunkLauncher PROPERTIES
WIN32_EXECUTABLE ON WIN32_EXECUTABLE ON

158
src/app/backend/backend.cpp Normal file
View File

@ -0,0 +1,158 @@
#include "backend.h"
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QFile>
#include <QStandardPaths>
#include <QDir>
#include <QDebug>
Backend::Backend() {}
QString Backend::getStateFilePath() {
#ifdef Q_OS_WIN
QString stateDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
#else
QString stateDir = QStandardPaths::writableLocation(QStandardPaths::StateLocation);
#endif
QDir().mkpath(stateDir);
return stateDir + "/session.json";
}
void Backend::saveToJson(const QString &uuid, const QString &access_token) {
QString filePath = getStateFilePath();
QJsonObject json;
json["uuid"] = uuid;
json["access_token"] = access_token;
QFile file(filePath);
if (file.open(QIODevice::WriteOnly)) {
file.write(QJsonDocument(json).toJson());
file.close();
qDebug() << "Данные сохранены в" << filePath;
} else {
qWarning() << "Не удалось открыть файл для записи:" << filePath;
}
}
QJsonObject Backend::loadFromJson() {
QString filePath = getStateFilePath();
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (doc.isObject()) {
return doc.object();
}
}
qWarning() << "Не удалось загрузить данные из файла:" << filePath;
return QJsonObject();
}
void Backend::sendPostRequest(const QString &url, const QJsonObject &payload, std::function<void(QJsonObject)> callback) {
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkRequest request{QUrl(url)};
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkReply* reply = manager->post(request, QJsonDocument(payload).toJson());
QObject::connect(reply, &QNetworkReply::finished, [reply, callback]() {
if (reply->error() == QNetworkReply::NoError) {
QByteArray response = reply->readAll();
QJsonDocument jsonResponse = QJsonDocument::fromJson(response);
if (jsonResponse.isObject()) {
callback(jsonResponse.object());
} else {
qWarning() << "Некорректный JSON-ответ.";
callback(QJsonObject());
}
} else {
qWarning() << "Ошибка запроса:" << reply->errorString();
callback(QJsonObject());
}
reply->deleteLater();
});
}
void Backend::authWithPassword(
QString &username, QString &password, bool &session_save_flag,
std::function<void(QString, QString, QString)> callback)
{
QString url = "http://root-kit.ru:3001/punkcraft/session/auth";
QJsonObject payload;
payload["username"] = username;
payload["password"] = password;
sendPostRequest(url, payload, [this, callback, session_save_flag](QJsonObject response) {
if (response.isEmpty()) {
qWarning() << "Ошибка авторизации: пустой ответ.";
if (callback) {
callback("", "", "");
}
return;
}
// Сохраняем пользователя в json и отправляет callback функцию
QString username = response["username"].toString();
QString uuid = response["uuid"].toString();
QString access_token = response["access_token"].toString();
if (session_save_flag) {
saveToJson(uuid, access_token);
}
if (callback) {
callback(username, uuid, access_token);
}
});
}
void Backend::authWithToken(std::function<void(QString, QString, QString)> callback) {
QJsonObject savedData = loadFromJson();
if (savedData.isEmpty()) {
qWarning() << "Нет сохранённых данных для авторизации.";
if (callback) {
callback("", "", "");
}
return;
}
QString uuid = savedData["uuid"].toString();
QString access_token = savedData["access_token"].toString();
QString url = "http://root-kit.ru:3001/punkcraft/session/auth/token";
QJsonObject payload;
payload["uuid"] = uuid;
payload["access_token"] = access_token;
sendPostRequest(url, payload, [this, callback](QJsonObject response) {
if (response.isEmpty()) {
qWarning() << "Ошибка авторизации по токену: пустой ответ.";
if (callback) {
callback("", "", "");
}
return;
}
QString username = response["username"].toString();
QString uuid = response["uuid"].toString();
QString access_token = response["access_token"].toString();
qDebug() << "Авторизация по токену успешна. Пользователь:" << username;
saveToJson(uuid, access_token);
if (callback) {
callback(username, uuid, access_token);
}
});
}

25
src/app/backend/backend.h Normal file
View File

@ -0,0 +1,25 @@
#ifndef BACKEND_H
#define BACKEND_H
#include <QString>
#include <QJsonObject>
#include <functional>
class Backend {
public:
Backend();
void authWithPassword(
QString &username, QString &password, bool &session_save_flag,
std::function<void(QString, QString, QString)> callback);
void authWithToken(std::function<void(QString, QString, QString)> callback);
QString getStateFilePath();
private:
void saveToJson(const QString &uuid, const QString &access_token);
void sendPostRequest(const QString &url, const QJsonObject &payload, std::function<void(QJsonObject)> callback);
QJsonObject loadFromJson();
};
#endif

View File

@ -0,0 +1,146 @@
#include "getArgs.h"
#include <QDebug>
#include <QObject>
#include <QWidget>
#include <QDir>
#include <QCoreApplication>
#include <QString>
#include <QList>
getArgs::getArgs() {
}
getArgs::~getArgs() {
}
QStringList getArgs::getCrossPlatformArgs(QString &RAM, QString &username, QString &uuid, QString &access_token, QString &garbarge_collector) {
QStringList arguments;
arguments
<< "-Djava.library.path=./versions/Forge_1.12.2/natives"
//<< "-Xms" + RAM + "M"
<< "-Xmx" + RAM
<< "-cp"
<< "./libraries/net/minecraftforge/forge/1.12.2-14.23.5.2860/"
"forge-1.12.2-14.23.5.2860.jar:./libraries/org/ow2/asm/asm-debug-all/"
"5.2/asm-debug-all-5.2.jar:./libraries/net/minecraft/launchwrapper/"
"1.12/launchwrapper-1.12.jar:./libraries/org/jline/jline/3.5.1/"
"jline-3.5.1.jar:./libraries/com/typesafe/akka/akka-actor_2.11/2.3.3/"
"akka-actor_2.11-2.3.3.jar:./libraries/com/typesafe/config/1.2.1/"
"config-1.2.1.jar:./libraries/org/scala-lang/"
"scala-actors-migration_2.11/1.1.0/"
"scala-actors-migration_2.11-1.1.0.jar:./libraries/org/scala-lang/"
"scala-compiler/2.11.1/scala-compiler-2.11.1.jar:./libraries/org/"
"scala-lang/plugins/scala-continuations-library_2.11/1.0.2_mc/"
"scala-continuations-library_2.11-1.0.2_mc.jar:./libraries/org/"
"scala-lang/plugins/scala-continuations-plugin_2.11.1/1.0.2_mc/"
"scala-continuations-plugin_2.11.1-1.0.2_mc.jar:./libraries/org/"
"scala-lang/scala-library/2.11.1/scala-library-2.11.1.jar:./libraries/"
"org/scala-lang/scala-parser-combinators_2.11/1.0.1/"
"scala-parser-combinators_2.11-1.0.1.jar:./libraries/org/scala-lang/"
"scala-reflect/2.11.1/scala-reflect-2.11.1.jar:./libraries/org/"
"scala-lang/scala-swing_2.11/1.0.1/scala-swing_2.11-1.0.1.jar:./"
"libraries/org/scala-lang/scala-xml_2.11/1.0.2/"
"scala-xml_2.11-1.0.2.jar:./libraries/lzma/lzma/0.0.1/"
"lzma-0.0.1.jar:./libraries/java3d/vecmath/1.5.2/vecmath-1.5.2.jar:./"
"libraries/net/sf/trove4j/trove4j/3.0.3/trove4j-3.0.3.jar:./libraries/"
"org/apache/maven/maven-artifact/3.5.3/maven-artifact-3.5.3.jar:./"
"libraries/net/sf/jopt-simple/jopt-simple/5.0.3/"
"jopt-simple-5.0.3.jar:./libraries/org/apache/logging/log4j/log4j-api/"
"2.15.0/log4j-api-2.15.0.jar:./libraries/org/apache/logging/log4j/"
"log4j-core/2.15.0/log4j-core-2.15.0.jar:./libraries/org/tlauncher/"
"patchy/1.3.9/patchy-1.3.9.jar:./libraries/oshi-project/oshi-core/1.1/"
"oshi-core-1.1.jar:./libraries/net/java/dev/jna/jna/4.4.0/"
"jna-4.4.0.jar:./libraries/net/java/dev/jna/platform/3.4.0/"
"platform-3.4.0.jar:./libraries/com/ibm/icu/icu4j-core-mojang/51.2/"
"icu4j-core-mojang-51.2.jar:./libraries/com/paulscode/codecjorbis/"
"20101023/codecjorbis-20101023.jar:./libraries/com/paulscode/codecwav/"
"20101023/codecwav-20101023.jar:./libraries/com/paulscode/"
"libraryjavasound/20101123/libraryjavasound-20101123.jar:./libraries/"
"com/paulscode/librarylwjglopenal/20100824/"
"librarylwjglopenal-20100824.jar:./libraries/com/paulscode/"
"soundsystem/20120107/soundsystem-20120107.jar:./libraries/io/netty/"
"netty-all/4.1.9.Final/netty-all-4.1.9.Final.jar:./libraries/com/"
"google/guava/guava/21.0/guava-21.0.jar:./libraries/org/apache/"
"commons/commons-lang3/3.5/commons-lang3-3.5.jar:./libraries/"
"commons-io/commons-io/2.5/commons-io-2.5.jar:./libraries/"
"commons-codec/commons-codec/1.10/commons-codec-1.10.jar:./libraries/"
"net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:./libraries/net/java/"
"jutils/jutils/1.0.0/jutils-1.0.0.jar:./libraries/com/google/code/"
"gson/gson/2.8.0/gson-2.8.0.jar:./libraries/com/mojang/authlib/"
"1.5.25/authlib-1.5.25.jar:./libraries/com/mojang/realms/1.10.22/"
"realms-1.10.22.jar:./libraries/org/apache/commons/commons-compress/"
"1.8.1/commons-compress-1.8.1.jar:./libraries/org/apache/"
"httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:./libraries/"
"commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:./"
"libraries/org/apache/httpcomponents/httpcore/4.3.2/"
"httpcore-4.3.2.jar:./libraries/it/unimi/dsi/fastutil/7.1.0/"
"fastutil-7.1.0.jar:./libraries/org/apache/logging/log4j/log4j-api/"
"2.8.1/log4j-api-2.8.1.jar:./libraries/org/apache/logging/log4j/"
"log4j-core/2.8.1/log4j-core-2.8.1.jar:./libraries/org/lwjgl/lwjgl/"
"lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar:./"
"libraries/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/"
"lwjgl_util-2.9.4-nightly-20150209.jar:./libraries/com/mojang/"
"text2speech/1.10.3/text2speech-1.10.3.jar:./versions/Forge_1.12.2/"
"Forge_1.12.2.jar"
<< "-Dfml.ignoreInvalidMinecraftCertificates=true"
<< "-Dfml.ignorePatchDiscrepancies=true"
<< "-Djava.net.preferIPv4Stack=true"
<< "-Dminecraft.applet.TargetDirectory=./"
<< "-DlibraryDirectory=./libraries"
<< "-Dlog4j.configurationFile=./assets/log_configs/client-1.12.xml"
<< "net.minecraft.launchwrapper.Launch"
<< "--username" << username
<< "--version" << "Forge_1.12.2"
<< "--assetsDir" << "./assets"
<< "--assetIndex" << "1.12"
<< "--uuid" << uuid
<< "--accessToken" << access_token
<< "--userType" << "mojang"
<< "--tweakClass" << "net.minecraftforge.fml.common.launcher.FMLTweaker"
<< "--versionType" << "Forge"
<< "--height" << "480"
<< "--width" << "854"
// Garbarge Collector общие настройки
<< "-XX:+UnlockDiagnosticVMOptions"
<< "-XX:+DisableExplicitGC"
<< "-XX:ReservedCodeCacheSize=400M"
<< "-XX:+AlwaysPreTouch"
<< "-XX:+UseNUMA"
//<< "-XX:+UseFastUnorderedTimeStamps" // Не работает
//<< "-server"
<< "-XX:+PerfDisableSharedMem"
<< "-XX:AllocatePrefetchStyle=3";
// Garbarge Collector
// CMS (Concurrent Mark-Sweep)
arguments
<< "-XX:+UseConcMarkSweepGC"
<< "-XX:CMSInitiatingOccupancyFraction=75"
<< "-XX:+UseCMSInitiatingOccupancyOnly"
<< "-XX:CMSWaitDuration=1000"
<< "-XX:+CMSConcurrentMTEnabled";
// G1GC (Garbage First Garbage Collector)
/*
<< "-XX:+UseG1GC"
<< "-XX:G1NewSizePercent=20"
<< "-XX:G1ReservePercent=20"
<< "-XX:MaxGCPauseMillis=50"
<< "-XX:G1HeapRegionSize=32M"
*/
// C4 - Не поддерживается java8
//<< "-XX:+UseC4GC"
//<< "-XX:MaxHeapSize=2G"
//<< "-XX:InitialHeapSize=1G"
return arguments;
}

View File

@ -0,0 +1,22 @@
#ifndef GETARGS_H
#define GETARGS_H
#include <QObject>
#include <QString>
#include <QStringList>
#include <QProcess>
#include <QDir>
class getArgs : public QObject {
Q_OBJECT
public:
explicit getArgs();
~getArgs();
QStringList getCrossPlatformArgs(QString &RAM, QString &username, QString &uuid, QString &access_token, QString &garbarge_collector);
};
#endif

View File

@ -0,0 +1,69 @@
#include "launcher.h"
#include <QDebug>
#include <QObject>
#include <QWidget>
#include <QDir>
#include <QCoreApplication>
#include <QString>
#include <QList>
#include "forge1.12.2/getArgs.h"
Launcher::Launcher(QObject *mainwindow) : QObject(mainwindow), process(new QProcess(this)), mainwindow(mainwindow), get_args(new getArgs()) {
// Подключение сигналов для отладки
/*
connect(process, &QProcess::readyReadStandardOutput, [this]() {
qDebug() << "Standard Output: " << process->readAllStandardOutput();
});
connect(process, &QProcess::readyReadStandardError, [this]() {
qDebug() << "Standard Error: " << process->readAllStandardError();
});
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[this](int exitCode, QProcess::ExitStatus status) {
qDebug() << "Process finished with exit code:" << exitCode
<< "and status:" << status;
});
*/
}
Launcher::~Launcher() {
delete process;
}
void Launcher::startProcess(
QString &workingDir,
QString &executablePath,
QString &RAM,
QString &username,
QString &uuid,
QString &access_token,
QString garbarge_collector) {
QStringList arguments = get_args->getCrossPlatformArgs(RAM, username, uuid, access_token, garbarge_collector);
process->setWorkingDirectory(workingDir);
process->start(executablePath, arguments);
if (!process->waitForStarted()) {
qDebug() << "Failed to start process";
qDebug() << process->errorString();
return;
}
QWidget *mainwindowWidget = qobject_cast<QWidget*>(mainwindow);
// Скрытие лаунчера при запуске
connect(process,
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[mainwindowWidget](int, QProcess::ExitStatus) { mainwindowWidget->show(); });
if (mainwindowWidget) {
mainwindowWidget->hide();
} else {
qDebug() << "Parent object is not a QWidget.";
}
qDebug() << "Process started successfully";
}

View File

@ -0,0 +1,34 @@
#ifndef LAUNCHER_H
#define LAUNCHER_H
#include <QObject>
#include <QString>
#include <QStringList>
#include <QProcess>
#include <QDir>
#include "forge1.12.2/getArgs.h"
class Launcher : public QObject {
Q_OBJECT
public:
explicit Launcher(QObject *mainwindow = nullptr);
~Launcher();
void startProcess(
QString &workingDir,
QString &executablePath,
QString &RAM,
QString &username,
QString &uuid,
QString &access_token,
QString garbarge_collector);
private:
QProcess *process;
QObject *mainwindow;
getArgs *get_args;
};
#endif

View File

@ -1,4 +1,4 @@
#include "mainwindow.h" #include "ui/mainwindow.h"
#include <QApplication> #include <QApplication>

View File

@ -1,197 +0,0 @@
#include <cstdlib>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QDir>
#include <QLineEdit>
#include <QProcess>
#include <QString>
#include <qnamespace.h>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow), process(new QProcess(this)) {
ui->setupUi(this);
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
connect(process, &QProcess::readyReadStandardOutput, this, [this]() {
qDebug() << "Standard Output: " << process->readAllStandardOutput();
});
connect(process, &QProcess::readyReadStandardError, this, [this]() {
qDebug() << "Standard Error: " << process->readAllStandardError();
});
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::mousePressEvent(QMouseEvent *event) {
if (ui->border_top->geometry().contains(event->pos())) {
isDragging = true;
ui->border_top->setCursor(Qt::SizeAllCursor);
dragStartPosition =
event->globalPosition().toPoint() - frameGeometry().topLeft();
event->accept();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event) {
if (isDragging) {
move(event->globalPosition().toPoint() - dragStartPosition);
event->accept();
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event) {
isDragging = false;
ui->border_top->setCursor(Qt::ArrowCursor);
event->accept();
}
void MainWindow::on_startBtn_clicked() {
QString RAM = "6154";
QDir exeDir(QCoreApplication::applicationDirPath());
QString workDir = exeDir.absolutePath() + "/../../../mine/hitech";
QStringList arguments;
arguments
<< "-Djava.library.path=./versions/Forge_1.12.2/natives"
//<< "-Xms" + RAM + "M"
<< "-Xmx" + RAM + "M"
<< "-cp"
<< "./libraries/net/minecraftforge/forge/1.12.2-14.23.5.2860/"
"forge-1.12.2-14.23.5.2860.jar:./libraries/org/ow2/asm/asm-debug-all/"
"5.2/asm-debug-all-5.2.jar:./libraries/net/minecraft/launchwrapper/"
"1.12/launchwrapper-1.12.jar:./libraries/org/jline/jline/3.5.1/"
"jline-3.5.1.jar:./libraries/com/typesafe/akka/akka-actor_2.11/2.3.3/"
"akka-actor_2.11-2.3.3.jar:./libraries/com/typesafe/config/1.2.1/"
"config-1.2.1.jar:./libraries/org/scala-lang/"
"scala-actors-migration_2.11/1.1.0/"
"scala-actors-migration_2.11-1.1.0.jar:./libraries/org/scala-lang/"
"scala-compiler/2.11.1/scala-compiler-2.11.1.jar:./libraries/org/"
"scala-lang/plugins/scala-continuations-library_2.11/1.0.2_mc/"
"scala-continuations-library_2.11-1.0.2_mc.jar:./libraries/org/"
"scala-lang/plugins/scala-continuations-plugin_2.11.1/1.0.2_mc/"
"scala-continuations-plugin_2.11.1-1.0.2_mc.jar:./libraries/org/"
"scala-lang/scala-library/2.11.1/scala-library-2.11.1.jar:./libraries/"
"org/scala-lang/scala-parser-combinators_2.11/1.0.1/"
"scala-parser-combinators_2.11-1.0.1.jar:./libraries/org/scala-lang/"
"scala-reflect/2.11.1/scala-reflect-2.11.1.jar:./libraries/org/"
"scala-lang/scala-swing_2.11/1.0.1/scala-swing_2.11-1.0.1.jar:./"
"libraries/org/scala-lang/scala-xml_2.11/1.0.2/"
"scala-xml_2.11-1.0.2.jar:./libraries/lzma/lzma/0.0.1/"
"lzma-0.0.1.jar:./libraries/java3d/vecmath/1.5.2/vecmath-1.5.2.jar:./"
"libraries/net/sf/trove4j/trove4j/3.0.3/trove4j-3.0.3.jar:./libraries/"
"org/apache/maven/maven-artifact/3.5.3/maven-artifact-3.5.3.jar:./"
"libraries/net/sf/jopt-simple/jopt-simple/5.0.3/"
"jopt-simple-5.0.3.jar:./libraries/org/apache/logging/log4j/log4j-api/"
"2.15.0/log4j-api-2.15.0.jar:./libraries/org/apache/logging/log4j/"
"log4j-core/2.15.0/log4j-core-2.15.0.jar:./libraries/org/tlauncher/"
"patchy/1.3.9/patchy-1.3.9.jar:./libraries/oshi-project/oshi-core/1.1/"
"oshi-core-1.1.jar:./libraries/net/java/dev/jna/jna/4.4.0/"
"jna-4.4.0.jar:./libraries/net/java/dev/jna/platform/3.4.0/"
"platform-3.4.0.jar:./libraries/com/ibm/icu/icu4j-core-mojang/51.2/"
"icu4j-core-mojang-51.2.jar:./libraries/com/paulscode/codecjorbis/"
"20101023/codecjorbis-20101023.jar:./libraries/com/paulscode/codecwav/"
"20101023/codecwav-20101023.jar:./libraries/com/paulscode/"
"libraryjavasound/20101123/libraryjavasound-20101123.jar:./libraries/"
"com/paulscode/librarylwjglopenal/20100824/"
"librarylwjglopenal-20100824.jar:./libraries/com/paulscode/"
"soundsystem/20120107/soundsystem-20120107.jar:./libraries/io/netty/"
"netty-all/4.1.9.Final/netty-all-4.1.9.Final.jar:./libraries/com/"
"google/guava/guava/21.0/guava-21.0.jar:./libraries/org/apache/"
"commons/commons-lang3/3.5/commons-lang3-3.5.jar:./libraries/"
"commons-io/commons-io/2.5/commons-io-2.5.jar:./libraries/"
"commons-codec/commons-codec/1.10/commons-codec-1.10.jar:./libraries/"
"net/java/jinput/jinput/2.0.5/jinput-2.0.5.jar:./libraries/net/java/"
"jutils/jutils/1.0.0/jutils-1.0.0.jar:./libraries/com/google/code/"
"gson/gson/2.8.0/gson-2.8.0.jar:./libraries/com/mojang/authlib/"
"1.5.25/authlib-1.5.25.jar:./libraries/com/mojang/realms/1.10.22/"
"realms-1.10.22.jar:./libraries/org/apache/commons/commons-compress/"
"1.8.1/commons-compress-1.8.1.jar:./libraries/org/apache/"
"httpcomponents/httpclient/4.3.3/httpclient-4.3.3.jar:./libraries/"
"commons-logging/commons-logging/1.1.3/commons-logging-1.1.3.jar:./"
"libraries/org/apache/httpcomponents/httpcore/4.3.2/"
"httpcore-4.3.2.jar:./libraries/it/unimi/dsi/fastutil/7.1.0/"
"fastutil-7.1.0.jar:./libraries/org/apache/logging/log4j/log4j-api/"
"2.8.1/log4j-api-2.8.1.jar:./libraries/org/apache/logging/log4j/"
"log4j-core/2.8.1/log4j-core-2.8.1.jar:./libraries/org/lwjgl/lwjgl/"
"lwjgl/2.9.4-nightly-20150209/lwjgl-2.9.4-nightly-20150209.jar:./"
"libraries/org/lwjgl/lwjgl/lwjgl_util/2.9.4-nightly-20150209/"
"lwjgl_util-2.9.4-nightly-20150209.jar:./libraries/com/mojang/"
"text2speech/1.10.3/text2speech-1.10.3.jar:./versions/Forge_1.12.2/"
"Forge_1.12.2.jar"
// Общие
<< "-XX:+UnlockDiagnosticVMOptions"
<< "-XX:+DisableExplicitGC"
<< "-XX:ReservedCodeCacheSize=400M"
<< "-XX:+AlwaysPreTouch"
<< "-XX:+UseNUMA"
//<< "-XX:+UseFastUnorderedTimeStamps" // Не работает
<< "-XX:+PerfDisableSharedMem"
<< "-XX:AllocatePrefetchStyle=3"
<< "-server"
// CMS (Concurrent Mark-Sweep)
//
<< "-XX:+UseConcMarkSweepGC"
<< "-XX:CMSInitiatingOccupancyFraction=75"
<< "-XX:+UseCMSInitiatingOccupancyOnly"
<< "-XX:CMSWaitDuration=1000"
<< "-XX:+CMSConcurrentMTEnabled"
// G1GC (Garbage First Garbage Collector)
//<< "-XX:+UseG1GC"
//<< "-XX:G1NewSizePercent=20"
//<< "-XX:G1ReservePercent=20"
//<< "-XX:MaxGCPauseMillis=50"
//<< "-XX:G1HeapRegionSize=32M"
// C4
//<< "-XX:+UseC4GC"
//<< "-XX:MaxHeapSize=2G"
//<< "-XX:InitialHeapSize=1G"
<< "-Dfml.ignoreInvalidMinecraftCertificates=true"
<< "-Dfml.ignorePatchDiscrepancies=true"
<< "-Djava.net.preferIPv4Stack=true"
<< "-Dminecraft.applet.TargetDirectory=./"
<< "-DlibraryDirectory=./libraries"
<< "-Dlog4j.configurationFile=./assets/log_configs/client-1.12.xml"
<< "net.minecraft.launchwrapper.Launch"
<< "--username" << "PIVODEVAT"
<< "--version" << "Forge_1.12.2"
<< "--gameDir" << "./"
<< "--assetsDir" << "./assets"
<< "--assetIndex" << "1.12"
<< "--uuid" << "2c175d38f2e04dcab1dcd8f8d254c130"
<< "--accessToken" << "fvTLJuNer7WUFh0AE1Xh5CZ3q2B92kTn"
<< "--userType" << "mojang"
<< "--tweakClass" << "net.minecraftforge.fml.common.launcher.FMLTweaker"
<< "--versionType" << "Forge"
<< "--height" << "480"
<< "--width" << "854";
QProcess *process = new QProcess(this);
process->setWorkingDirectory(workDir);
//process->start("/usr/lib/jvm/openjdk8/bin/java", arguments);
process->start("/home/xuy/dev/punkcraft/mine/hitech/java/zulu8.82.0.21-ca-jdk8.0.432-linux_x64/bin/java", arguments);
// Подключение сигнала finished к слоту lambda для показа окна
connect(process,
QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[this](int, QProcess::ExitStatus) { this->show(); });
// Скрытие окна перед запуском процесса
this->hide();
if (!process->waitForStarted()) {
qDebug() << "Failed to start process";
qDebug() << process->errorString();
return;
}
}

View File

@ -1,37 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMouseEvent> // Для обработки событий мыши
#include <QProcess>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private slots:
void on_startBtn_clicked();
private:
Ui::MainWindow *ui;
QProcess *process;
// Для перемещения окна
bool isDragging = false;
QPoint dragStartPosition;
};
#endif

View File

@ -0,0 +1,58 @@
#include "settings.h"
#include <QJsonDocument>
#include <QFile>
#include <QStandardPaths>
#include <QDir>
#include <QDebug>
#include <qjsonvalue.h>
#include <QJsonArray>
Settings::Settings() {}
QString Settings::getStateFilePath(QString &profile) {
#ifdef Q_OS_WIN
QString stateDir = QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation);
#else
QString stateDir = QStandardPaths::writableLocation(QStandardPaths::StateLocation);
#endif
QDir().mkpath(stateDir);
return stateDir + "/settings_" + profile + ".json";
}
void Settings::saveToJson(QString profile, QString RAM, QString java_path, QString garbarge_collector_method, QJsonArray additions_list) {
QString filePath = getStateFilePath(profile);
QJsonObject json;
json["RAM"] = RAM;
json["java_path"] = java_path;
json["garbarge_collector"] = garbarge_collector_method;
json["additions_list"] = additions_list;
QFile file(filePath);
if (file.open(QIODevice::WriteOnly)) {
file.write(QJsonDocument(json).toJson());
file.close();
qDebug() << "Данные сохранены в" << filePath;
} else {
qWarning() << "Не удалось открыть файл для записи:" << filePath;
}
}
QJsonObject Settings::loadFromJson(QString &profile) {
QString filePath = getStateFilePath(profile);
QFile file(filePath);
if (file.open(QIODevice::ReadOnly)) {
QByteArray data = file.readAll();
file.close();
QJsonDocument doc = QJsonDocument::fromJson(data);
if (doc.isObject()) {
return doc.object();
}
}
qWarning() << "Не удалось загрузить данные из файла:" << filePath;
return QJsonObject();
}

View File

@ -0,0 +1,19 @@
#ifndef SETTINGS_H
#define SETTINGS_H
#include <QString>
#include <QJsonObject>
class Settings {
public:
explicit Settings();
~Settings();
QJsonObject loadFromJson(QString &profile);
void saveToJson(QString profile, QString RAM, QString java_path, QString garbarge_collector_method, QJsonArray additions_list);
private:
QString getStateFilePath(QString &profile);
};
#endif

215
src/app/ui/mainwindow.cpp Normal file
View File

@ -0,0 +1,215 @@
#include <cstdlib>
#include <QDebug>
#include <QLineEdit>
#include <QProcess>
#include <QString>
#include <qjsonobject.h>
#include <qnamespace.h>
#include <QDir>
#include <QCoreApplication>
#include <QRegularExpression>
#include <QJsonArray>
#include "mainwindow.h"
#include "../launcher/launcher.h"
#include "../backend/backend.h"
#include "../settings/settings.h"
#include "../../resources/ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
process(new QProcess(this)),
launcher(new Launcher(this)),
backend(new Backend()),
settings(new Settings())
{
ui->setupUi(this);
// Инициализация
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
ui->StackedWidget->setCurrentWidget(ui->load); // Окно по умолчанию
on_selected_profile_currentTextChanged(ui->selected_profile->currentText()); // Обновление ui->selected_profile
backend->authWithToken([this](QString username, QString uuid, QString access_token) {
if (username.isEmpty() || uuid.isEmpty() || access_token.isEmpty()) {
ui->StackedWidget->setCurrentWidget(ui->auth);
} else {
ui->StackedWidget->setCurrentWidget(ui->main);
ui->main_nickname_label->setText(username);
this->username = username;
this->uuid = uuid;
this->access_token = access_token;
}
});
/*
connect(process, &QProcess::readyReadStandardOutput, this, [this]() {
qDebug() << "Standard Output: " << process->readAllStandardOutput();
});
connect(process, &QProcess::readyReadStandardError, this, [this]() {
qDebug() << "Standard Error: " << process->readAllStandardError();
});
*/
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::mousePressEvent(QMouseEvent *event) {
if (ui->border_top->geometry().contains(event->pos())) {
isDragging = true;
ui->border_top->setCursor(Qt::SizeAllCursor);
dragStartPosition =
event->globalPosition().toPoint() - frameGeometry().topLeft();
event->accept();
}
}
void MainWindow::mouseMoveEvent(QMouseEvent *event) {
if (isDragging) {
move(event->globalPosition().toPoint() - dragStartPosition);
event->accept();
}
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event) {
isDragging = false;
ui->border_top->setCursor(Qt::ArrowCursor);
event->accept();
}
void MainWindow::on_auth_login_btn_clicked() {
QString username = ui->auth_login_line->text();
QString password = ui->auth_pass_line->text();
bool flag = ui->auth_save_session_check_btn->isChecked();
backend->authWithPassword(
username,
password,
flag,
[this](QString username, QString uuid, QString access_token)
{
if (!username.isEmpty() && !uuid.isEmpty() && !access_token.isEmpty()) {
ui->auth_status_label->setText("");
ui->StackedWidget->setCurrentWidget(ui->main);
ui->main_nickname_label->setText(username);
this->username = username;
this->uuid = uuid;
this->access_token = access_token;
} else {
ui->auth_status_label->setText("Ошибка авторизации");
}
});
}
/*
* QComoBox не позволяет менять ориентацию текста
* В этой функции происходит его центрирование через padding-left
*/
void MainWindow::on_selected_profile_currentTextChanged(QString text) {
// Рассчёт padding-left
QFontMetrics metrics(ui->selected_profile->font());
int textWidth = metrics.horizontalAdvance(text);
int comboBoxWidth = ui->selected_profile->width();
int paddingLeft = (comboBoxWidth - textWidth) / 2;
// Обновление stylesheet заменой
QString currentStyleSheet = ui->selected_profile->styleSheet();
QString newStyleSheet = currentStyleSheet;
if (currentStyleSheet.contains("padding-left:")) {
newStyleSheet.replace(QRegularExpression("padding-left:\\s*\\d+px;?"), QString("padding-left: %1px;").arg(paddingLeft));
} else {
newStyleSheet += QString(" QComboBox { padding-left: %1px; }").arg(paddingLeft);
}
ui->selected_profile->setStyleSheet(newStyleSheet);
}
void MainWindow::on_settings_btn_clicked() {
ui->StackedWidget->setCurrentWidget(ui->settings);
// Обновление значений
QString selected_profile = ui->selected_profile->currentText();
json_settings = settings->loadFromJson(selected_profile);
ui->settings_ram->setText(json_settings["RAM"].toString());
ui->settings_java_path->setText(json_settings["java_path"].toString());
ui->settings_garbarge_collector->setCurrentText(json_settings["garbarge_collector"].toString());
}
void MainWindow::on_settings_back_btn_clicked() {
ui->StackedWidget->setCurrentWidget(ui->main);
}
void MainWindow::on_logout_btn_clicked() {
ui->StackedWidget->setCurrentWidget(ui->auth);
QString session_cache = backend->getStateFilePath();
QFile::remove(session_cache);
}
void MainWindow::on_settings_apply_btn_clicked() {
QJsonArray addition_settings;
settings->saveToJson(
ui->selected_profile->currentText(),
ui->settings_ram->text(),
ui->settings_java_path->text(),
ui->settings_garbarge_collector->currentText(),
addition_settings
);
ui->StackedWidget->setCurrentWidget(ui->main);
}
void MainWindow::on_start_btn_clicked() {
// Обновление переменных запуска клиента
QString selected_profile = ui->selected_profile->currentText();
QDir exe_dir(QCoreApplication::applicationDirPath());
client_dir = exe_dir.absolutePath() + "/../../../mine/" + selected_profile;
json_settings = settings->loadFromJson(selected_profile);
java_path = json_settings["java_path"].toString();
RAM = json_settings["RAM"].toString();
garbarge_collector = json_settings["garbarge_collector"].toString();
// Значения по умолчанию
if (selected_profile == "CyberExtrieme") {
java_path = java_path.isEmpty() ?
exe_dir.absolutePath() + "/../../../mine/CyberExtrieme/java/zing24.12.0.0-6-jre8.0.432/bin/java" : java_path;
RAM = RAM.isEmpty() ?
"4096M" : RAM;
garbarge_collector = garbarge_collector.isEmpty() ?
"default_collector" : garbarge_collector;
}
// Запуск клиента
launcher->startProcess(
this->client_dir,
this->java_path,
this->RAM,
this->username,
this->uuid,
this->access_token,
this->garbarge_collector
);
}

62
src/app/ui/mainwindow.h Normal file
View File

@ -0,0 +1,62 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QMouseEvent>
#include <QProcess>
#include "../launcher/launcher.h"
#include "../backend/backend.h"
#include "../settings/settings.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private slots:
void on_start_btn_clicked();
void on_auth_login_btn_clicked();
void on_settings_btn_clicked();
void on_settings_back_btn_clicked();
void on_logout_btn_clicked();
void on_settings_apply_btn_clicked();
void on_selected_profile_currentTextChanged(QString text);
private:
Ui::MainWindow *ui;
QProcess *process;
Launcher *launcher;
Backend *backend;
Settings *settings;
bool isDragging = false;
QPoint dragStartPosition;
QString username;
QString uuid;
QString access_token;
// Переменные для запуска клиента
QString client_dir;
QString RAM;
QString java_path;
QString garbarge_collector;
QJsonObject json_settings;
};
#endif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 54 KiB

After

Width:  |  Height:  |  Size: 172 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 B

View File

@ -0,0 +1,13 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<!-- Created using Krita: https://krita.org -->
<svg xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:krita="http://krita.org/namespaces/svg/krita"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
width="122.904pt"
height="122.904pt"
viewBox="0 0 122.904 122.904">
<defs/>
<path id="shape0" transform="translate(14.6129261015271, 28.0787413638113)" fill="#f795be" fill-rule="evenodd" stroke-opacity="0" stroke="#ffffff" stroke-width="0.72" stroke-linecap="square" stroke-linejoin="bevel" d="M0 0L96.6968 0.00281917L48.3524 84.2408Z" sodipodi:nodetypes="cccc"/>
</svg>

After

Width:  |  Height:  |  Size: 797 B

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,7 @@
<RCC> <RCC>
<qresource prefix="/"> <qresource prefix="/">
<file>auth/logo.png</file> <file>auth/logo.png</file>
<file>main/selected_profile.png</file>
<file>main/settings_pressed_32x32.png</file> <file>main/settings_pressed_32x32.png</file>
<file>main/settings_hover_32x32.png</file> <file>main/settings_hover_32x32.png</file>
<file>main/settings_32x32.png</file> <file>main/settings_32x32.png</file>