changed code style, doc
This commit is contained in:
parent
9ed3f1bf3f
commit
8fb08a8ece
|
@ -1,5 +1,6 @@
|
|||
build/
|
||||
.kdev4/
|
||||
.vscode/
|
||||
*.user
|
||||
*-swp
|
||||
*.kdev4
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# FreeKill
|
||||
|
||||
___
|
||||
|
||||
试图打造一个最适合diy玩家游玩的民间三国杀,所有的一切都是为了更好的制作diy而设计的。
|
||||
|
||||
项目仍处于啥都没有的阶段。不过我为了整理思路,也写了点[文档](./doc/index.md)。
|
|
@ -0,0 +1,9 @@
|
|||
# FreeKill 开发文档
|
||||
|
||||
> dev
|
||||
|
||||
___
|
||||
|
||||
FreeKill采用Qt框架提供底层支持,在上层使用lua语言开发。在UI方面使用的是Qt Quick。
|
||||
|
||||
- [通信](./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 <port>
|
||||
```
|
||||
|
||||
`<port>`是服务器运行的端口号,如果不带任何参数则启动GUI界面,在GUI界面里面只能加入服务器或者单机游戏。
|
||||
|
||||
服务器以TCP方式监听。在默认情况下(比如单机启动),服务器的端口号是9527。
|
||||
|
||||
每当任何一个客户端连接上了之后,客户端进入大厅。
|
|
@ -0,0 +1,5 @@
|
|||
# 如何用FreeKill实现diy武将
|
||||
|
||||
> diy
|
||||
|
||||
___
|
|
@ -0,0 +1,6 @@
|
|||
# FreeKill 文档
|
||||
|
||||
___
|
||||
|
||||
- [开发者文档](./dev/index.md)
|
||||
- [DIY玩家文档](./diy/index.md)
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -46,7 +46,7 @@ Item {
|
|||
mainWindow.busy = true;
|
||||
mainStack.pop();
|
||||
Backend.notifyServer(
|
||||
"create_room",
|
||||
"CreateRoom",
|
||||
JSON.stringify([roomName.text, playerNum.value])
|
||||
);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ Item {
|
|||
text: "quit"
|
||||
onClicked: {
|
||||
mainStack.pop();
|
||||
Backend.notifyServer("quit_room", "[]");
|
||||
Backend.notifyServer("QuitRoom", "[]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
26
qml/main.qml
26
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 + "!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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<ServerPlayer *>(parent())->getUid()
|
||||
);
|
||||
|
@ -169,7 +169,7 @@ void Router::handlePacket(const QByteArray& rawPacket)
|
|||
this->requestTimeout = packet[4].toInt();
|
||||
|
||||
if (type & DEST_CLIENT) {
|
||||
qobject_cast<Client *>(parent())->callLua(command, json_data);
|
||||
qobject_cast<Client *>(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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<ServerPlayer *> targets, int timeout)
|
|||
}
|
||||
|
||||
void Room::doBroadcastNotify(const QList<ServerPlayer *> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@ public:
|
|||
void doBroadcastNotify(
|
||||
const QList<ServerPlayer *> targets,
|
||||
const QString &command,
|
||||
const QString &json_data
|
||||
const QString &jsonData
|
||||
);
|
||||
|
||||
signals:
|
||||
|
|
|
@ -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<ServerPlayer *>(sender())->setStateString("offline");
|
||||
}
|
||||
|
||||
void Server::onUserStateChanged()
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue