From 1053ec29a4cf45b18c8f5a17b77e10932f2a4353 Mon Sep 17 00:00:00 2001 From: Flerp Date: Tue, 15 Jul 2025 18:11:17 -0700 Subject: [PATCH] True Initial Commit --- CMakeLists.txt | 22 +++++ README.md | 1 + main.cpp | 9 ++ mainwindow.cpp | 221 +++++++++++++++++++++++++++++++++++++++++++++++++ mainwindow.h | 54 ++++++++++++ 5 files changed, 307 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 main.cpp create mode 100644 mainwindow.cpp create mode 100644 mainwindow.h diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..aa55b13 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,22 @@ +cmake_minimum_required(VERSION 3.16) +project(7D2D-CommandUtil) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets Network) + +add_executable(7D2D-CommandUtil + main.cpp + mainwindow.cpp + mainwindow.h +) + +target_link_libraries(7D2D-CommandUtil + Qt6::Core + Qt6::Gui + Qt6::Widgets + Qt6::Network +) diff --git a/README.md b/README.md index df8e8d2..e23b33f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # 7d2d-ServerUtil +A Qt C++ Application for managing and maintainting 7 Days to Die servers diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..efdc28a --- /dev/null +++ b/main.cpp @@ -0,0 +1,9 @@ +#include +#include "mainwindow.h" + +int main(int argc, char *argv[]) { + QApplication app(argc, argv); + MainWindow window; + window.show(); + return app.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..679dec6 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,221 @@ +#include "mainwindow.h" +#include +#include + +MainWindow::MainWindow(QWidget *parent) + : QMainWindow(parent), socket(new QTcpSocket(this)) { + setupUI(); + statusTimer = new QTimer(this); + connect(statusTimer, &QTimer::timeout, this, &MainWindow::updateConnectionStatus); + statusTimer->start(1000); + connect(socket, &QTcpSocket::readyRead, this, &MainWindow::readServerOutput); +} + +MainWindow::~MainWindow() { + if (socket->state() == QAbstractSocket::ConnectedState) { + socket->write("exit\n"); + socket->disconnectFromHost(); + if (socket->state() != QAbstractSocket::UnconnectedState) { + socket->waitForDisconnected(1000); + } + } +} + +void MainWindow::attemptConnection() { + socket->abort(); + isAuthenticated = false; + socket->connectToHost(serverEdit->text(), portEdit->text().toUInt()); + if (!socket->waitForConnected(3000)) { + QMessageBox::critical(this, "Connection Failed", "Could not connect to server."); + } + updateConnectionStatus(); +} + +void MainWindow::readServerOutput() { + QByteArray response = socket->readAll(); + QString text = QString::fromUtf8(response); + serverLogTextEdit->append(text); + + if (text.contains("Please enter password:", Qt::CaseInsensitive)) { + socket->write(passwordEdit->text().toUtf8() + "\n"); + socket->waitForBytesWritten(1000); + return; + } + + if (!text.contains("Please enter password:", Qt::CaseInsensitive)) { + isAuthenticated = true; + } +} + +void MainWindow::sendTelnetCommand(const QString &command) { + if (socket->state() != QAbstractSocket::ConnectedState) { + QMessageBox::warning(this, "Not Connected", "Please connect to the server first."); + return; + } + if (!isAuthenticated) { + QMessageBox::warning(this, "Not Authenticated", "Server is waiting for a password. Please wait or reconnect."); + return; + } + socket->write(command.toUtf8() + "\n"); + socket->waitForBytesWritten(1000); + historyTextEdit->append(command); +} + +void MainWindow::sendTimeCommand() { + QString cmd = QString("st %1 %2 %3") + .arg(dayEdit->text()) + .arg(hourEdit->text()) + .arg(minuteEdit->text()); + sendTelnetCommand(cmd); +} + +void MainWindow::sendSpeedCommand() { + static const QMap values = { + {1, 1}, {2, 4}, {3, 6}, {4, 12}, {5, 500} + }; + int val = values.value(speedSlider->value(), 6); + QString cmd = QString("setgamestat TimeOfDayIncPerSec %1").arg(val); + sendTelnetCommand(cmd); +} + +void MainWindow::sendCustomCommand() { + QString cmd = customCommandEdit->text().trimmed(); + if (cmd.isEmpty()) { + QMessageBox::warning(this, "Input Error", "Please enter a custom command."); + return; + } + sendTelnetCommand(cmd); + customCommandEdit->clear(); +} + +void MainWindow::updateConnectionStatus() { + QPalette palette; + if (socket->state() == QAbstractSocket::ConnectedState) { + connectionStatusLabel->setText("Connected"); + palette.setColor(QPalette::WindowText, Qt::darkGreen); + } else { + connectionStatusLabel->setText("Disconnected"); + palette.setColor(QPalette::WindowText, Qt::red); + } + connectionStatusLabel->setPalette(palette); +} + +void MainWindow::disconnectFromServer() { + if (socket->state() == QAbstractSocket::ConnectedState) { + socket->write("exit\n"); + socket->disconnectFromHost(); + } + updateConnectionStatus(); +} + +void MainWindow::updateSliderLabel(int value) { + static const QMap labels = { + {1, "Slow-Mo"}, {2, "90"}, {3, "60"}, {4, "Double"}, {5, "Giga"} + }; + sliderLabel->setText(labels.value(value, QString::number(value))); +} + +void MainWindow::setupUI() { + tabWidget = new QTabWidget(this); + setCentralWidget(tabWidget); + + QWidget *mainTab = new QWidget; + QVBoxLayout *mainLayout = new QVBoxLayout(mainTab); + + QGroupBox *serverBox = new QGroupBox("Server Info"); + QVBoxLayout *serverVBox = new QVBoxLayout(serverBox); + QHBoxLayout *serverLayout = new QHBoxLayout(); + serverEdit = new QLineEdit(); + portEdit = new QLineEdit(); + passwordEdit = new QLineEdit(); + passwordEdit->setEchoMode(QLineEdit::Password); + serverLayout->addWidget(new QLabel("Server:")); + serverLayout->addWidget(serverEdit); + serverLayout->addWidget(new QLabel("Port:")); + serverLayout->addWidget(portEdit); + serverLayout->addWidget(new QLabel("Password:")); + serverLayout->addWidget(passwordEdit); + serverVBox->addLayout(serverLayout); + + QHBoxLayout *statusLayout = new QHBoxLayout(); + connectionStatusLabel = new QLabel("Disconnected"); + QPalette palette; + palette.setColor(QPalette::WindowText, Qt::red); + connectionStatusLabel->setPalette(palette); + statusLayout->addWidget(connectionStatusLabel); + statusLayout->addStretch(); + connectButton = new QPushButton("Connect"); + disconnectButton = new QPushButton("Disconnect"); + connect(connectButton, &QPushButton::clicked, this, &MainWindow::attemptConnection); + connect(disconnectButton, &QPushButton::clicked, this, &MainWindow::disconnectFromServer); + statusLayout->addWidget(connectButton); + statusLayout->addWidget(disconnectButton); + serverVBox->addLayout(statusLayout); + mainLayout->addWidget(serverBox); + + QGroupBox *timeBox = new QGroupBox("Set Server Time"); + QHBoxLayout *timeLayout = new QHBoxLayout(timeBox); + dayEdit = new QLineEdit(); dayEdit->setMaxLength(2); + hourEdit = new QLineEdit(); hourEdit->setMaxLength(2); + minuteEdit = new QLineEdit(); minuteEdit->setMaxLength(2); + QPushButton *timeButton = new QPushButton("Set Server Time"); + connect(timeButton, &QPushButton::clicked, this, &MainWindow::sendTimeCommand); + timeLayout->addWidget(new QLabel("Day:")); + timeLayout->addWidget(dayEdit); + timeLayout->addWidget(new QLabel("Hour:")); + timeLayout->addWidget(hourEdit); + timeLayout->addWidget(new QLabel("Minute:")); + timeLayout->addWidget(minuteEdit); + timeLayout->addStretch(); + timeLayout->addWidget(timeButton); + mainLayout->addWidget(timeBox); + + QGroupBox *speedBox = new QGroupBox("Set Game Speed"); + QVBoxLayout *speedLayout = new QVBoxLayout(speedBox); + QHBoxLayout *sliderLayout = new QHBoxLayout(); + speedSlider = new QSlider(Qt::Horizontal); + speedSlider->setMinimum(1); + speedSlider->setMaximum(5); + speedSlider->setTickInterval(1); + speedSlider->setTickPosition(QSlider::TicksBelow); + connect(speedSlider, &QSlider::valueChanged, this, &MainWindow::updateSliderLabel); + sliderLayout->addWidget(speedSlider); + QPushButton *speedButton = new QPushButton("Set Time Speed"); + connect(speedButton, &QPushButton::clicked, this, &MainWindow::sendSpeedCommand); + sliderLayout->addWidget(speedButton); + sliderLabel = new QLabel("60"); + sliderLabel->setAlignment(Qt::AlignCenter); + speedLayout->addLayout(sliderLayout); + speedLayout->addWidget(sliderLabel); + mainLayout->addWidget(speedBox); + + tabWidget->addTab(mainTab, "Time"); + + QWidget *historyTab = new QWidget; + QVBoxLayout *historyLayout = new QVBoxLayout(historyTab); + historyTextEdit = new QTextEdit(); + historyTextEdit->setReadOnly(true); + historyTextEdit->setTextInteractionFlags(Qt::TextSelectableByMouse); + historyLayout->addWidget(historyTextEdit); + tabWidget->addTab(historyTab, "History"); + + QWidget *logTab = new QWidget; + QVBoxLayout *logLayout = new QVBoxLayout(logTab); + serverLogTextEdit = new QTextEdit(); + serverLogTextEdit->setReadOnly(true); + logLayout->addWidget(serverLogTextEdit); + + QGroupBox *customBox = new QGroupBox(); + QHBoxLayout *customLayout = new QHBoxLayout(customBox); + customCommandEdit = new QLineEdit(); + QPushButton *customButton = new QPushButton("Send Command"); + connect(customButton, &QPushButton::clicked, this, &MainWindow::sendCustomCommand); + connect(customCommandEdit, &QLineEdit::returnPressed, this, &MainWindow::sendCustomCommand); + customLayout->addWidget(customCommandEdit); + customLayout->addWidget(customButton); + logLayout->addWidget(customBox); + + tabWidget->addTab(logTab, "Console"); + + updateSliderLabel(speedSlider->value()); +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..f6301b4 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,54 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +class MainWindow : public QMainWindow { + Q_OBJECT + +public: + MainWindow(QWidget *parent = nullptr); + ~MainWindow(); + +private slots: + void sendTimeCommand(); + void sendSpeedCommand(); + void updateSliderLabel(int value); + void sendCustomCommand(); + void attemptConnection(); + void updateConnectionStatus(); + void disconnectFromServer(); + void readServerOutput(); + +private: + QLineEdit *serverEdit, *portEdit, *passwordEdit; + QLineEdit *dayEdit, *hourEdit, *minuteEdit; + QLineEdit *customCommandEdit; + QSlider *speedSlider; + QLabel *sliderLabel; + QLabel *connectionStatusLabel; + QTcpSocket *socket; + QPushButton *connectButton; + QPushButton *disconnectButton; + QTimer *statusTimer; + QTextEdit *historyTextEdit; + QTextEdit *serverLogTextEdit; + QTabWidget *tabWidget; + bool isAuthenticated = false; + + void sendTelnetCommand(const QString &command); + void setupUI(); +}; + +#endif