diff --git a/.gitignore b/.gitignore index 0c585e1d..3a29e8a4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ build/ .kdev4/ +.vscode/ *.user *-swp *.kdev4 diff --git a/README.md b/README.md new file mode 100644 index 00000000..e0138286 --- /dev/null +++ b/README.md @@ -0,0 +1,7 @@ +# FreeKill + +___ + +试图打造一个最适合diy玩家游玩的民间三国杀,所有的一切都是为了更好的制作diy而设计的。 + +项目仍处于啥都没有的阶段。不过我为了整理思路,也写了点[文档](./doc/index.md)。 diff --git a/doc/dev/index.md b/doc/dev/index.md new file mode 100644 index 00000000..80a8cd84 --- /dev/null +++ b/doc/dev/index.md @@ -0,0 +1,9 @@ +# FreeKill 开发文档 + +> dev + +___ + +FreeKill采用Qt框架提供底层支持,在上层使用lua语言开发。在UI方面使用的是Qt Quick。 + +- [通信](./protocol.md) diff --git a/doc/dev/protocol.md b/doc/dev/protocol.md new file mode 100644 index 00000000..5822be6e --- /dev/null +++ b/doc/dev/protocol.md @@ -0,0 +1,36 @@ +# FreeKill 的通信 + +> [dev](./index.md) > 通信 + +___ + +## 概述 + +FreeKill使用UTF-8文本进行通信。基本的通信格式为JSON数组: + +`[requestId, packetType, command, jsonData]` + +其中: + +- requestId用来在request型通信使用,用来确保收到的回复和发出的请求相对应。 +- packetType用来确定这条消息的类型以及发送的目的地。 +- command用来表示消息的类型。使用首字母大写的驼峰式命名,因为下划线命名会造成额外的网络开销。 +- jsonData保存着这个消息的额外信息,必须是一个JSON数组。数组中的具体内容详见源码及注释。 + +FreeKill通信有三大类型:请求(Request)、回复(Reply)和通知(Notification)。 + +___ + +## 从连接上到进入大厅 + +想要启动服务器,需要通过命令行终端: + +```sh +$ ./FreeKill -s +``` + +``是服务器运行的端口号,如果不带任何参数则启动GUI界面,在GUI界面里面只能加入服务器或者单机游戏。 + +服务器以TCP方式监听。在默认情况下(比如单机启动),服务器的端口号是9527。 + +每当任何一个客户端连接上了之后,客户端进入大厅。 \ No newline at end of file diff --git a/doc/diy/index.md b/doc/diy/index.md new file mode 100644 index 00000000..ecb2c1a1 --- /dev/null +++ b/doc/diy/index.md @@ -0,0 +1,5 @@ +# 如何用FreeKill实现diy武将 + +> diy + +___ diff --git a/doc/index.md b/doc/index.md new file mode 100644 index 00000000..50906e52 --- /dev/null +++ b/doc/index.md @@ -0,0 +1,6 @@ +# FreeKill 文档 + +___ + +- [开发者文档](./dev/index.md) +- [DIY玩家文档](./diy/index.md) diff --git a/lua/client/client.lua b/lua/client/client.lua index d46ac0d4..3d335877 100644 --- a/lua/client/client.lua +++ b/lua/client/client.lua @@ -4,15 +4,15 @@ freekill.client_callback = {} function Client:initialize() self.client = freekill.ClientInstance - self.notifyUI = function(self, command, json_data) - freekill.Backend:emitNotifyUI(command, json_data) + self.notifyUI = function(self, command, jsonData) + freekill.Backend:emitNotifyUI(command, jsonData) end - self.client.callback = function(_self, command, json_data) + self.client.callback = function(_self, command, jsonData) local cb = freekill.client_callback[command] if (type(cb) == "function") then - cb(json_data) + cb(jsonData) else - self:notifyUI(command, json_data); + self:notifyUI(command, jsonData); end end end diff --git a/lua/server/server.lua b/lua/server/server.lua index 5ea55f11..dcf3d789 100644 --- a/lua/server/server.lua +++ b/lua/server/server.lua @@ -4,36 +4,36 @@ freekill.server_callback = {} function Server:initialize() self.server = freekill.ServerInstance - self.server.callback = function(_self, command, json_data) + self.server.callback = function(_self, command, jsonData) local cb = freekill.server_callback[command] if (type(cb) == "function") then - cb(json_data) + cb(jsonData) else print("Server error: Unknown command " .. command); end end end -freekill.server_callback["create_room"] = function(json_data) - -- json_data: [ int uid, string name, int capacity ] - local data = json.decode(json_data) +freekill.server_callback["CreateRoom"] = function(jsonData) + -- jsonData: [ int uid, string name, int capacity ] + local data = json.decode(jsonData) local owner = freekill.ServerInstance:findPlayer(tonumber(data[1])) local roomName = data[2] local capacity = data[3] freekill.ServerInstance:createRoom(owner, roomName, capacity) end -freekill.server_callback["enter_room"] = function(json_data) - -- json_data: [ int uid, int roomId ] - local data = json.decode(json_data) +freekill.server_callback["EnterRoom"] = function(jsonData) + -- jsonData: [ int uid, int roomId ] + local data = json.decode(jsonData) local player = freekill.ServerInstance:findPlayer(tonumber(data[1])) local room = freekill.ServerInstance:findRoom(tonumber(data[2])) room:addPlayer(player) end -freekill.server_callback["quit_room"] = function(json_data) - -- json_data: [ int uid ] - local data = json.decode(json_data) +freekill.server_callback["QuitRoom"] = function(jsonData) + -- jsonData: [ int uid ] + local data = json.decode(jsonData) local player = freekill.ServerInstance:findPlayer(tonumber(data[1])) local room = player:getRoom() if not room:isLobby() then diff --git a/qml/Pages/CreateRoom.qml b/qml/Pages/CreateRoom.qml index fe7b0397..e404307b 100644 --- a/qml/Pages/CreateRoom.qml +++ b/qml/Pages/CreateRoom.qml @@ -46,7 +46,7 @@ Item { mainWindow.busy = true; mainStack.pop(); Backend.notifyServer( - "create_room", + "CreateRoom", JSON.stringify([roomName.text, playerNum.value]) ); } diff --git a/qml/Pages/Room.qml b/qml/Pages/Room.qml index 0c969600..e40d29e0 100644 --- a/qml/Pages/Room.qml +++ b/qml/Pages/Room.qml @@ -11,7 +11,7 @@ Item { text: "quit" onClicked: { mainStack.pop(); - Backend.notifyServer("quit_room", "[]"); + Backend.notifyServer("QuitRoom", "[]"); } } } diff --git a/qml/main.qml b/qml/main.qml index 7e971460..d3dbb7d1 100644 --- a/qml/main.qml +++ b/qml/main.qml @@ -9,25 +9,31 @@ Window { width: 720 height: 480 property var callbacks: ({ - "error_msg": function(json_data) { - toast.show(json_data); + "ErrorMsg": function(jsonData) { + toast.show(jsonData); mainWindow.busy = false; }, - "enter_lobby": function(json_data) { + "EnterLobby": function(jsonData) { if (mainStack.depth === 1) { mainStack.push(lobby); } mainWindow.busy = false; }, - "enter_room": function(json_data) { + "EnterRoom": function(jsonData) { mainStack.push(room); mainWindow.busy = false; }, - "update_room_list": function(json_data) { + "UpdateRoomList": function(jsonData) { let current = mainStack.currentItem; // should be lobby current.roomModel.clear(); - JSON.parse(json_data).forEach(function(room) { - current.roomModel.append(room); + JSON.parse(jsonData).forEach(function(room) { + current.roomModel.append({ + roomId: room[0], + roomName: room[1], + gameMode: room[2], + playerNum: room[3], + capacity: room[4], + }); }); } }) @@ -110,12 +116,12 @@ Window { Connections { target: Backend - function onNotifyUI(command, json_data) { + function onNotifyUI(command, jsonData) { let cb = callbacks[command] if (typeof(cb) === "function") { - cb(json_data); + cb(jsonData); } else { - callbacks["error_msg"]("Unknown command " + command + "!"); + callbacks["ErrorMsg"]("Unknown command " + command + "!"); } } } diff --git a/src/client/client.cpp b/src/client/client.cpp index dd27cf68..07c47aca 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -32,20 +32,20 @@ void Client::connectToHost(const QHostAddress& server, ushort port) router->getSocket()->connectToHost(server, port); } -void Client::requestServer(const QString& command, const QString& json_data, int timeout) +void Client::requestServer(const QString& command, const QString& jsonData, int timeout) { int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER; - router->request(type, command, json_data, timeout); + router->request(type, command, jsonData, timeout); } -void Client::replyToServer(const QString& command, const QString& json_data) +void Client::replyToServer(const QString& command, const QString& jsonData) { int type = Router::TYPE_REPLY | Router::SRC_CLIENT | Router::DEST_SERVER; - router->reply(type, command, json_data); + router->reply(type, command, jsonData); } -void Client::notifyServer(const QString& command, const QString& json_data) +void Client::notifyServer(const QString& command, const QString& jsonData) { int type = Router::TYPE_NOTIFICATION | Router::SRC_CLIENT | Router::DEST_SERVER; - router->notify(type, command, json_data); + router->notify(type, command, jsonData); } diff --git a/src/client/client.h b/src/client/client.h index 8bd31bac..1f25d217 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -20,11 +20,11 @@ public: // void login void requestServer(const QString &command, - const QString &json_data, int timeout = -1); - void replyToServer(const QString &command, const QString &json_data); - void notifyServer(const QString &command, const QString &json_data); + const QString &jsonData, int timeout = -1); + void replyToServer(const QString &command, const QString &jsonData); + void notifyServer(const QString &command, const QString &jsonData); - void callLua(const QString &command, const QString &json_data); + void callLua(const QString &command, const QString &jsonData); LuaFunction callback; signals: diff --git a/src/network/router.cpp b/src/network/router.cpp index bd446c95..e618a532 100644 --- a/src/network/router.cpp +++ b/src/network/router.cpp @@ -50,7 +50,7 @@ void Router::setReplyReadySemaphore(QSemaphore *semaphore) } void Router::request(int type, const QString& command, - const QString& json_data, int timeout) + const QString& jsonData, int timeout) { // In case a request is called without a following waitForReply call if (replyReadySemaphore.available() > 0) @@ -70,30 +70,30 @@ void Router::request(int type, const QString& command, body << requestId; body << type; body << command; - body << json_data; + body << jsonData; body << timeout; emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact)); } -void Router::reply(int type, const QString& command, const QString& json_data) +void Router::reply(int type, const QString& command, const QString& jsonData) { QJsonArray body; body << this->requestId; body << type; body << command; - body << json_data; + body << jsonData; emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact)); } -void Router::notify(int type, const QString& command, const QString& json_data) +void Router::notify(int type, const QString& command, const QString& jsonData) { QJsonArray body; body << -2; // requestId = -2 mean this is for notification body << type; body << command; - body << json_data; + body << jsonData; emit messageReady(QJsonDocument(body).toJson(QJsonDocument::Compact)); } @@ -150,14 +150,14 @@ void Router::handlePacket(const QByteArray& rawPacket) int requestId = packet[0].toInt(); int type = packet[1].toInt(); QString command = packet[2].toString(); - QString json_data = packet[3].toString(); + QString jsonData = packet[3].toString(); if (type & TYPE_NOTIFICATION) { if (type & DEST_CLIENT) { - ClientInstance->callLua(command, json_data); + ClientInstance->callLua(command, jsonData); } else { - // Add the uid of sender to json_data - QJsonArray arr = QJsonDocument::fromJson(json_data.toUtf8()).array(); + // Add the uid of sender to jsonData + QJsonArray arr = QJsonDocument::fromJson(jsonData.toUtf8()).array(); arr.prepend( (int)qobject_cast(parent())->getUid() ); @@ -169,7 +169,7 @@ void Router::handlePacket(const QByteArray& rawPacket) this->requestTimeout = packet[4].toInt(); if (type & DEST_CLIENT) { - qobject_cast(parent())->callLua(command, json_data); + qobject_cast(parent())->callLua(command, jsonData); } else { // requesting server is not allowed Q_ASSERT(false); @@ -187,7 +187,7 @@ void Router::handlePacket(const QByteArray& rawPacket) requestStartTime.secsTo(QDateTime::currentDateTime())) return; - m_reply = json_data; + m_reply = jsonData; // TODO: callback? qDebug() << rawPacket << Qt::endl; diff --git a/src/network/router.h b/src/network/router.h index 9e7a8ba0..3b2c987a 100644 --- a/src/network/router.h +++ b/src/network/router.h @@ -37,9 +37,9 @@ public: void setReplyReadySemaphore(QSemaphore *semaphore); void request(int type, const QString &command, - const QString &json_data, int timeout); - void reply(int type, const QString &command, const QString &json_data); - void notify(int type, const QString &command, const QString &json_data); + const QString &jsonData, int timeout); + void reply(int type, const QString &command, const QString &jsonData); + void notify(int type, const QString &command, const QString &jsonData); int getTimeout() const; diff --git a/src/server/room.cpp b/src/server/room.cpp index fca5477a..f84b4777 100644 --- a/src/server/room.cpp +++ b/src/server/room.cpp @@ -80,9 +80,9 @@ void Room::addPlayer(ServerPlayer *player) players.append(player); player->setRoom(this); if (isLobby()) { - player->doNotify("enter_lobby", "{}"); + player->doNotify("EnterLobby", "[]"); } else { - player->doNotify("enter_room", "{}"); + player->doNotify("EnterRoom", "[]"); } qDebug() << "Player #" << player->getUid() << " entered room"; emit playerAdded(player); @@ -99,7 +99,7 @@ void Room::removePlayer(ServerPlayer *player) emit abandoned(); } else if (player == owner) { setOwner(players.first()); - owner->doNotify("room_owner", "{}"); + owner->doNotify("RoomOwner", "[]"); } } @@ -143,10 +143,10 @@ void Room::doNotify(const QList targets, int timeout) } void Room::doBroadcastNotify(const QList targets, - const QString& command, const QString& json_data) + const QString& command, const QString& jsonData) { foreach (ServerPlayer *p, targets) { - p->doNotify(command, json_data); + p->doNotify(command, jsonData); } } diff --git a/src/server/room.h b/src/server/room.h index 40e366e4..8fa9b4db 100644 --- a/src/server/room.h +++ b/src/server/room.h @@ -44,7 +44,7 @@ public: void doBroadcastNotify( const QList targets, const QString &command, - const QString &json_data + const QString &jsonData ); signals: diff --git a/src/server/server.cpp b/src/server/server.cpp index 4746befe..9c28c214 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -74,17 +74,17 @@ void Server::updateRoomList() { QJsonArray arr; foreach (Room *room, rooms) { - QJsonObject obj; - obj["roomId"] = (int)room->getId(); - obj["roomName"] = room->getName(); - obj["gameMode"] = "Role"; - obj["playerNum"] = room->getPlayers().count(); - obj["capacity"] = (int)room->getCapacity(); + QJsonArray obj; + obj << (int)room->getId(); // roomId + obj << room->getName(); // roomName + obj << "Role"; // gameMode + obj << room->getPlayers().count(); // playerNum + obj << (int)room->getCapacity(); // capacity arr << obj; } lobby()->doBroadcastNotify( lobby()->getPlayers(), - "update_room_list", + "UpdateRoomList", QJsonDocument(arr).toJson() ); } @@ -100,7 +100,6 @@ void Server::processNewConnection(ClientSocket* client) qDebug() << "His address is " << client->peerAddress(); #endif - //player->doNotify("enter_lobby", "{}"); lobby()->addPlayer(player); } @@ -114,7 +113,7 @@ void Server::onRoomAbandoned() void Server::onUserDisconnected() { - // TODO + qobject_cast(sender())->setStateString("offline"); } void Server::onUserStateChanged() diff --git a/src/server/server.h b/src/server/server.h index 4df06172..347efad1 100644 --- a/src/server/server.h +++ b/src/server/server.h @@ -31,7 +31,7 @@ public: void updateRoomList(); - void callLua(const QString &command, const QString &json_data); + void callLua(const QString &command, const QString &jsonData); LuaFunction callback; signals: diff --git a/src/server/serverplayer.cpp b/src/server/serverplayer.cpp index 48ab5550..887fdb92 100644 --- a/src/server/serverplayer.cpp +++ b/src/server/serverplayer.cpp @@ -52,22 +52,22 @@ void ServerPlayer::speak(const QString& message) ; } -void ServerPlayer::doRequest(const QString& command, const QString& json_data, int timeout) +void ServerPlayer::doRequest(const QString& command, const QString& jsonData, int timeout) { int type = Router::TYPE_REQUEST | Router::SRC_SERVER | Router::DEST_CLIENT; - router->request(type, command, json_data, timeout); + router->request(type, command, jsonData, timeout); } -void ServerPlayer::doReply(const QString& command, const QString& json_data) +void ServerPlayer::doReply(const QString& command, const QString& jsonData) { int type = Router::TYPE_REPLY | Router::SRC_SERVER | Router::DEST_CLIENT; - router->reply(type, command, json_data); + router->reply(type, command, jsonData); } -void ServerPlayer::doNotify(const QString& command, const QString& json_data) +void ServerPlayer::doNotify(const QString& command, const QString& jsonData) { int type = Router::TYPE_NOTIFICATION | Router::SRC_SERVER | Router::DEST_CLIENT; - router->notify(type, command, json_data); + router->notify(type, command, jsonData); } void ServerPlayer::prepareForRequest(const QString& command, const QVariant& data) diff --git a/src/server/serverplayer.h b/src/server/serverplayer.h index af1def6b..40b01ee2 100644 --- a/src/server/serverplayer.h +++ b/src/server/serverplayer.h @@ -25,9 +25,9 @@ public: void speak(const QString &message); void doRequest(const QString &command, - const QString &json_data, int timeout = -1); - void doReply(const QString &command, const QString &json_data); - void doNotify(const QString &command, const QString &json_data); + const QString &jsonData, int timeout = -1); + void doReply(const QString &command, const QString &jsonData); + void doNotify(const QString &command, const QString &jsonData); void prepareForRequest(const QString &command, const QVariant &data = QVariant()); diff --git a/src/ui/qmlbackend.cpp b/src/ui/qmlbackend.cpp index f9a294be..b0a81f80 100644 --- a/src/ui/qmlbackend.cpp +++ b/src/ui/qmlbackend.cpp @@ -18,7 +18,7 @@ void QmlBackend::startServer(ushort port) if (!server->listen(QHostAddress::Any, port)) { server->deleteLater(); - emit notifyUI("error_msg", tr("Cannot start server!")); + emit notifyUI("ErrorMsg", tr("Cannot start server!")); } } } @@ -28,7 +28,7 @@ void QmlBackend::joinServer(QString address) class Client *client = new class Client(this); connect(client, &Client::error_message, [this, client](const QString &msg){ client->deleteLater(); - emit notifyUI("error_msg", msg); + emit notifyUI("ErrorMsg", msg); }); QString addr = "127.0.0.1"; ushort port = 9527u; @@ -44,14 +44,14 @@ void QmlBackend::joinServer(QString address) client->connectToHost(QHostAddress(addr), port); } -void QmlBackend::replyToServer(const QString& command, const QString& json_data) +void QmlBackend::replyToServer(const QString& command, const QString& jsonData) { - ClientInstance->replyToServer(command, json_data); + ClientInstance->replyToServer(command, jsonData); } -void QmlBackend::notifyServer(const QString& command, const QString& json_data) +void QmlBackend::notifyServer(const QString& command, const QString& jsonData) { - ClientInstance->notifyServer(command, json_data); + ClientInstance->notifyServer(command, jsonData); } void QmlBackend::quitLobby() diff --git a/src/ui/qmlbackend.h b/src/ui/qmlbackend.h index 0e7f5373..b00acbe1 100644 --- a/src/ui/qmlbackend.h +++ b/src/ui/qmlbackend.h @@ -18,18 +18,18 @@ public: QmlBackend(QObject *parent = nullptr); // For lua use - void emitNotifyUI(const char *command, const char *json_data) { - emit notifyUI(command, json_data); + void emitNotifyUI(const char *command, const char *jsonData) { + emit notifyUI(command, jsonData); } signals: - void notifyUI(const QString &command, const QString &json_data); + void notifyUI(const QString &command, const QString &jsonData); public slots: void startServer(ushort port); void joinServer(QString address); - void replyToServer(const QString &command, const QString &json_data); - void notifyServer(const QString &command, const QString &json_data); + void replyToServer(const QString &command, const QString &jsonData); + void notifyServer(const QString &command, const QString &jsonData); // Lobby void quitLobby();