--- a/qmlfrontend/CMakeLists.txt Sat May 11 20:43:12 2019 +0200
+++ b/qmlfrontend/CMakeLists.txt Sat May 11 22:39:55 2019 +0200
@@ -17,6 +17,7 @@
"preview_image_provider.cpp" "preview_image_provider.h"
"engine_interface.h"
"preview_acceptor.cpp" "preview_acceptor.h"
+ "net_session.cpp" "net_session.h"
)
-target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Quick)
+target_link_libraries(${PROJECT_NAME} Qt5::Core Qt5::Network Qt5::Quick)
--- a/qmlfrontend/Page1.qml Sat May 11 20:43:12 2019 +0200
+++ b/qmlfrontend/Page1.qml Sat May 11 22:39:55 2019 +0200
@@ -5,6 +5,7 @@
focus: true
property HWEngine hwEngine
+ property NetSession netSession
Component {
id: hwEngineComponent
@@ -17,6 +18,15 @@
}
}
+ Component {
+ id: netSessionComponent
+
+ NetSession {
+ nickname: "test0272"
+ url: "hwnet://gameserver.hedgewars.org:46632"
+ }
+ }
+
Component.onCompleted: {
hwEngine = hwEngineComponent.createObject()
}
@@ -40,6 +50,10 @@
hwEngine.getPreview()
}
}
+ netButton.onClicked: {
+ netSession = netSessionComponent.createObject()
+ netSession.open()
+ }
Keys.onPressed: {
if (event.key === Qt.Key_Enter)
--- a/qmlfrontend/Page1Form.ui.qml Sat May 11 20:43:12 2019 +0200
+++ b/qmlfrontend/Page1Form.ui.qml Sat May 11 22:39:55 2019 +0200
@@ -5,11 +5,13 @@
import Hedgewars.Engine 1.0
Item {
+ id: element
property alias button1: button1
property alias previewImage: previewImage
property alias gameButton: gameButton
width: 1024
height: 800
+ property alias netButton: netButton
property alias tickButton: tickButton
property alias gameView: gameView
@@ -80,4 +82,13 @@
Layout.fillHeight: true
}
}
+
+ Button {
+ id: netButton
+ text: qsTr("Net")
+ anchors.bottom: parent.bottom
+ anchors.bottomMargin: 8
+ anchors.left: parent.left
+ anchors.leftMargin: 8
+ }
}
--- a/qmlfrontend/main.cpp Sat May 11 20:43:12 2019 +0200
+++ b/qmlfrontend/main.cpp Sat May 11 22:39:55 2019 +0200
@@ -6,6 +6,7 @@
#include "engine_interface.h"
#include "game_view.h"
#include "hwengine.h"
+#include "net_session.h"
#include "preview_acceptor.h"
static QObject* previewacceptor_singletontype_provider(
@@ -32,6 +33,7 @@
previewacceptor_singletontype_provider);
qmlRegisterType<HWEngine>("Hedgewars.Engine", 1, 0, "HWEngine");
qmlRegisterType<GameView>("Hedgewars.Engine", 1, 0, "GameView");
+ qmlRegisterType<NetSession>("Hedgewars.Engine", 1, 0, "NetSession");
qmlRegisterUncreatableType<EngineInstance>("Hedgewars.Engine", 1, 0,
"EngineInstance",
"Create by HWEngine run methods");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlfrontend/net_session.cpp Sat May 11 22:39:55 2019 +0200
@@ -0,0 +1,137 @@
+#include "net_session.h"
+
+NetSession::NetSession(QObject *parent) : QObject(parent) {}
+
+QUrl NetSession::url() const { return m_url; }
+
+QAbstractSocket::SocketState NetSession::state() const {
+ if (m_socket)
+ return m_socket->state();
+ else
+ return QAbstractSocket::UnconnectedState;
+}
+
+void NetSession::open() {
+ m_socket.reset(new QTcpSocket());
+
+ connect(m_socket.data(), &QAbstractSocket::stateChanged, this,
+ &NetSession::stateChanged);
+ connect(m_socket.data(), &QTcpSocket::readyRead, this,
+ &NetSession::onReadyRead);
+
+ m_socket->connectToHost(m_url.host(),
+ static_cast<quint16>(m_url.port(46631)));
+}
+
+QString NetSession::nickname() const { return m_nickname; }
+
+QString NetSession::password() const { return m_password; }
+
+NetSession::SessionState NetSession::sessionState() const {
+ return m_sessionState;
+}
+
+void NetSession::setUrl(const QUrl &url) {
+ if (m_url == url) return;
+
+ m_url = url;
+ emit urlChanged(m_url);
+}
+
+void NetSession::setNickname(const QString &nickname) {
+ if (m_nickname == nickname) return;
+
+ m_nickname = nickname;
+ emit nicknameChanged(m_nickname);
+}
+
+void NetSession::setPassword(const QString &password) {
+ if (m_password == password) return;
+
+ m_password = password;
+ emit passwordChanged(m_password);
+}
+
+void NetSession::close() {
+ if (!m_socket.isNull()) {
+ m_socket->disconnectFromHost();
+ m_socket.clear();
+
+ setSessionState(NotConnected);
+ }
+}
+
+void NetSession::onReadyRead() {
+ while (m_socket->canReadLine()) {
+ auto line = QString::fromUtf8(m_socket->readLine().simplified());
+
+ if (line.isEmpty()) {
+ parseNetMessage(m_buffer);
+ m_buffer.clear();
+ } else {
+ m_buffer.append(line);
+ }
+ }
+}
+
+void NetSession::parseNetMessage(const QStringList &message) {
+ if (message.isEmpty()) {
+ qWarning() << "Empty net message received";
+ return;
+ }
+
+ qDebug() << "[SERVER]" << message;
+
+ using Handler = std::function<void(NetSession *, const QStringList &)>;
+ static QMap<QString, Handler> commandsMap{
+ {"CONNECTED", &NetSession::handleConnected},
+ {"PING", &NetSession::handlePing},
+ {"BYE", &NetSession::handleBye}};
+
+ auto handler =
+ commandsMap.value(message[0], &NetSession::handleUnknownCommand);
+
+ handler(this, message.mid(1));
+}
+
+void NetSession::handleConnected(const QStringList ¶meters) {
+ setSessionState(Login);
+}
+
+void NetSession::handlePing(const QStringList ¶meters) {
+ send("PONG", parameters);
+}
+
+void NetSession::handleBye(const QStringList ¶meters) { close(); }
+
+void NetSession::handleUnknownCommand(const QStringList ¶meters) {
+ Q_UNUSED(parameters);
+
+ qWarning() << "Command is not recognized";
+}
+
+void NetSession::send(const QString &message) { send(QStringList(message)); }
+
+void NetSession::send(const QString &message, const QString ¶m) {
+ send(QStringList{message, param});
+}
+
+void NetSession::send(const QString &message, const QStringList ¶meters) {
+ send(QStringList(message) + parameters);
+}
+
+void NetSession::send(const QStringList &message) {
+ Q_ASSERT(!m_socket.isNull());
+
+ qDebug() << "[CLIENT]" << message;
+
+ m_socket->write(message.join('\n').toUtf8() + "\n\n");
+}
+
+void NetSession::setSessionState(NetSession::SessionState sessionState) {
+ if (m_sessionState == sessionState) return;
+
+ m_sessionState = sessionState;
+
+ emit sessionStateChanged(sessionState);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/qmlfrontend/net_session.h Sat May 11 22:39:55 2019 +0200
@@ -0,0 +1,70 @@
+#ifndef NET_SESSION_H
+#define NET_SESSION_H
+
+#include <QSharedPointer>
+#include <QSslSocket>
+#include <QStringList>
+#include <QUrl>
+
+class NetSession : public QObject {
+ Q_OBJECT
+
+ // clang-format off
+ Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
+ Q_PROPERTY(QAbstractSocket::SocketState state READ state NOTIFY stateChanged)
+ Q_PROPERTY(QString nickname READ nickname WRITE setNickname NOTIFY nicknameChanged)
+ Q_PROPERTY(QString password READ password WRITE setPassword NOTIFY passwordChanged)
+ Q_PROPERTY(SessionState sessionState READ sessionState NOTIFY sessionStateChanged)
+ // clang-format on
+
+ public:
+ enum SessionState { NotConnected, Login, Lobby, Room, Game };
+ Q_ENUMS(SessionState)
+
+ explicit NetSession(QObject *parent = nullptr);
+
+ QUrl url() const;
+ QAbstractSocket::SocketState state() const;
+
+ Q_INVOKABLE void open();
+
+ QString nickname() const;
+ QString password() const;
+ SessionState sessionState() const;
+
+ public slots:
+ void setUrl(const QUrl &url);
+ void setNickname(const QString &nickname);
+ void setPassword(const QString &password);
+ void close();
+
+ signals:
+ void urlChanged(const QUrl url);
+ void stateChanged(QAbstractSocket::SocketState state);
+ void nicknameChanged(const QString &nickname);
+ void passwordChanged(const QString &password);
+ void sessionStateChanged(SessionState sessionState);
+
+ private slots:
+ void onReadyRead();
+ void parseNetMessage(const QStringList &message);
+ void handleConnected(const QStringList ¶meters);
+ void handlePing(const QStringList ¶meters);
+ void handleBye(const QStringList ¶meters);
+ void handleUnknownCommand(const QStringList ¶meters);
+ void send(const QString &message);
+ void send(const QString &message, const QString ¶m);
+ void send(const QString &message, const QStringList ¶meters);
+ void send(const QStringList &message);
+ void setSessionState(SessionState sessionState);
+
+ private:
+ QUrl m_url;
+ QSharedPointer<QTcpSocket> m_socket;
+ QString m_nickname;
+ QString m_password;
+ QStringList m_buffer;
+ SessionState m_sessionState;
+};
+
+#endif // NET_SESSION_H