frist
This commit is contained in:
@@ -0,0 +1,169 @@
|
||||
#include "NetworkManager.h"
|
||||
#include <QJsonArray>
|
||||
#include <QDateTime>
|
||||
|
||||
NetworkManager::NetworkManager(QObject* parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(&_socket, &QWebSocket::connected, this, &NetworkManager::onConnected);
|
||||
connect(&_socket, &QWebSocket::disconnected, this, &NetworkManager::onDisconnected);
|
||||
connect(&_socket, &QWebSocket::textMessageReceived, this, &NetworkManager::onTextMessageReceived);
|
||||
connect(&_socket, &QWebSocket::errorOccurred, this, &NetworkManager::onError);
|
||||
connect(&_socket, &QWebSocket::binaryMessageReceived, this, [this](const QByteArray& msg) {
|
||||
emit binaryFrameReceived(msg);
|
||||
});
|
||||
connect(&_heartbeatTimer, &QTimer::timeout, this, &NetworkManager::onHeartbeat);
|
||||
}
|
||||
|
||||
void NetworkManager::connectToServer(const QString& url) {
|
||||
_serverUrl = url;
|
||||
_socket.open(QUrl(url));
|
||||
}
|
||||
|
||||
void NetworkManager::disconnect() {
|
||||
_heartbeatTimer.stop();
|
||||
_socket.close();
|
||||
}
|
||||
|
||||
bool NetworkManager::isConnected() const {
|
||||
return _socket.state() == QAbstractSocket::ConnectedState;
|
||||
}
|
||||
|
||||
void NetworkManager::sendMessage(const QString& type, const QJsonObject& payload) {
|
||||
QJsonObject msg;
|
||||
msg["type"] = type;
|
||||
msg["seq"] = ++_seqNum;
|
||||
msg["timestamp"] = QDateTime::currentMSecsSinceEpoch();
|
||||
if (!payload.isEmpty())
|
||||
msg["payload"] = payload;
|
||||
_socket.sendTextMessage(QJsonDocument(msg).toJson(QJsonDocument::Compact));
|
||||
}
|
||||
|
||||
void NetworkManager::joinRoom(const QString& roomId, const QString& nickname) {
|
||||
QJsonObject payload;
|
||||
payload["room_id"] = roomId;
|
||||
payload["nickname"] = nickname;
|
||||
sendMessage("join_room", payload);
|
||||
}
|
||||
|
||||
void NetworkManager::createRoom(const QString& nickname, int maxPlayers) {
|
||||
QJsonObject payload;
|
||||
payload["nickname"] = nickname;
|
||||
payload["max_players"] = maxPlayers;
|
||||
sendMessage("create_room", payload);
|
||||
}
|
||||
|
||||
void NetworkManager::leaveRoom() {
|
||||
sendMessage("leave_room");
|
||||
}
|
||||
|
||||
void NetworkManager::setReady(bool ready) {
|
||||
QJsonObject payload;
|
||||
payload["ready"] = ready;
|
||||
sendMessage("set_ready", payload);
|
||||
}
|
||||
|
||||
void NetworkManager::startGame() {
|
||||
sendMessage("start_game");
|
||||
}
|
||||
|
||||
void NetworkManager::selectCard(const QString& cardUid) {
|
||||
QJsonObject payload;
|
||||
payload["card_uid"] = cardUid;
|
||||
sendMessage("select_card", payload);
|
||||
}
|
||||
|
||||
void NetworkManager::confirmAction(const QString& action, const QJsonObject& extra) {
|
||||
QJsonObject payload;
|
||||
payload["action"] = action;
|
||||
if (!extra.isEmpty()) {
|
||||
for (auto it = extra.begin(); it != extra.end(); ++it)
|
||||
payload[it.key()] = it.value();
|
||||
}
|
||||
sendMessage("confirm_action", payload);
|
||||
}
|
||||
|
||||
void NetworkManager::effectResponse(const QJsonObject& response) {
|
||||
sendMessage("effect_response", response);
|
||||
}
|
||||
|
||||
void NetworkManager::listRooms() {
|
||||
sendMessage("list_rooms");
|
||||
}
|
||||
|
||||
void NetworkManager::sendChat(const QString& text) {
|
||||
QJsonObject payload;
|
||||
payload["text"] = text;
|
||||
sendMessage("send_chat", payload);
|
||||
}
|
||||
|
||||
void NetworkManager::sendBinaryFrame(const QByteArray& data) {
|
||||
if (_socket.state() == QAbstractSocket::ConnectedState)
|
||||
_socket.sendBinaryMessage(data);
|
||||
}
|
||||
|
||||
void NetworkManager::onConnected() {
|
||||
_heartbeatTimer.start(15000);
|
||||
emit connected();
|
||||
}
|
||||
|
||||
void NetworkManager::onDisconnected() {
|
||||
_heartbeatTimer.stop();
|
||||
emit disconnected();
|
||||
}
|
||||
|
||||
void NetworkManager::onTextMessageReceived(const QString& message) {
|
||||
auto doc = QJsonDocument::fromJson(message.toUtf8());
|
||||
if (doc.isNull()) return;
|
||||
handleServerMessage(doc.object());
|
||||
}
|
||||
|
||||
void NetworkManager::onError(QAbstractSocket::SocketError error) {
|
||||
Q_UNUSED(error)
|
||||
emit connectionError(_socket.errorString());
|
||||
}
|
||||
|
||||
void NetworkManager::onHeartbeat() {
|
||||
sendMessage("heartbeat");
|
||||
}
|
||||
|
||||
void NetworkManager::handleServerMessage(const QJsonObject& msg) {
|
||||
auto type = msg["type"].toString();
|
||||
auto payload = msg["payload"].toObject();
|
||||
|
||||
if (type == "room_state") {
|
||||
emit roomStateUpdated(payload);
|
||||
} else if (type == "game_start") {
|
||||
emit gameStarted(payload);
|
||||
} else if (type == "state_snapshot") {
|
||||
emit gameStateSnapshot(payload);
|
||||
} else if (type == "card_move") {
|
||||
emit cardMoveEvent(payload);
|
||||
} else if (type == "card_flip") {
|
||||
emit cardFlipEvent(payload);
|
||||
} else if (type == "effect_trigger") {
|
||||
emit effectTriggered(payload);
|
||||
} else if (type == "request_choice") {
|
||||
emit requestChoice(payload);
|
||||
} else if (type == "player_exit") {
|
||||
emit playerExited(payload);
|
||||
} else if (type == "settlement") {
|
||||
emit settlementNotify(payload);
|
||||
} else if (type == "game_end") {
|
||||
emit gameEnded(payload);
|
||||
} else if (type == "error") {
|
||||
emit errorNotify(payload);
|
||||
} else if (type == "chat") {
|
||||
emit chatMessage(payload);
|
||||
} else if (type == "room_created") {
|
||||
emit roomCreated(payload["room_id"].toString());
|
||||
} else if (type == "room_joined") {
|
||||
emit roomJoined(payload);
|
||||
} else if (type == "room_left") {
|
||||
emit roomLeft();
|
||||
} else if (type == "room_list") {
|
||||
emit roomListReceived(payload["rooms"].toArray());
|
||||
} else if (type == "settlement_result") {
|
||||
emit settlementResult(payload);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef NETWORKMANAGER_H
|
||||
#define NETWORKMANAGER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QWebSocket>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QTimer>
|
||||
|
||||
class NetworkManager : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static NetworkManager& instance() {
|
||||
static NetworkManager mgr;
|
||||
return mgr;
|
||||
}
|
||||
|
||||
void connectToServer(const QString& url);
|
||||
void disconnect();
|
||||
bool isConnected() const;
|
||||
|
||||
void sendMessage(const QString& type, const QJsonObject& payload = {});
|
||||
|
||||
void joinRoom(const QString& roomId, const QString& nickname);
|
||||
void createRoom(const QString& nickname, int maxPlayers);
|
||||
void leaveRoom();
|
||||
void setReady(bool ready);
|
||||
void startGame();
|
||||
void selectCard(const QString& cardUid);
|
||||
void confirmAction(const QString& action, const QJsonObject& extra = {});
|
||||
void effectResponse(const QJsonObject& response);
|
||||
void listRooms();
|
||||
void sendChat(const QString& text);
|
||||
void sendBinaryFrame(const QByteArray& data);
|
||||
|
||||
signals:
|
||||
void connected();
|
||||
void disconnected();
|
||||
void connectionError(const QString& error);
|
||||
|
||||
void roomStateUpdated(const QJsonObject& roomState);
|
||||
void gameStarted(const QJsonObject& initConfig);
|
||||
void gameStateSnapshot(const QJsonObject& snapshot);
|
||||
void cardMoveEvent(const QJsonObject& event);
|
||||
void cardFlipEvent(const QJsonObject& event);
|
||||
void effectTriggered(const QJsonObject& event);
|
||||
void requestChoice(const QJsonObject& request);
|
||||
void playerExited(const QJsonObject& event);
|
||||
void settlementNotify(const QJsonObject& event);
|
||||
void gameEnded(const QJsonObject& result);
|
||||
void errorNotify(const QJsonObject& error);
|
||||
void chatMessage(const QJsonObject& msg);
|
||||
|
||||
void roomCreated(const QString& roomId);
|
||||
void roomJoined(const QJsonObject& roomInfo);
|
||||
void roomLeft();
|
||||
void roomListReceived(const QJsonArray& rooms);
|
||||
void settlementResult(const QJsonObject& data);
|
||||
void binaryFrameReceived(const QByteArray& data);
|
||||
|
||||
private slots:
|
||||
void onConnected();
|
||||
void onDisconnected();
|
||||
void onTextMessageReceived(const QString& message);
|
||||
void onError(QAbstractSocket::SocketError error);
|
||||
void onHeartbeat();
|
||||
|
||||
private:
|
||||
explicit NetworkManager(QObject* parent = nullptr);
|
||||
~NetworkManager() override = default;
|
||||
|
||||
void handleServerMessage(const QJsonObject& msg);
|
||||
|
||||
QWebSocket _socket;
|
||||
QTimer _heartbeatTimer;
|
||||
int _seqNum = 0;
|
||||
QString _serverUrl;
|
||||
};
|
||||
|
||||
#endif // NETWORKMANAGER_H
|
||||
Reference in New Issue
Block a user