This commit is contained in:
2026-06-18 17:29:28 +08:00
commit 08a070d874
720 changed files with 41946 additions and 0 deletions
+169
View File
@@ -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);
}
}
+81
View File
@@ -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