Create and enter room

This commit is contained in:
Notify-ctrl 2022-03-01 13:18:00 +08:00
parent 6fb0158d39
commit 5f175090c0
14 changed files with 232 additions and 62 deletions

View File

@ -21,5 +21,9 @@ freekill.client_callback["enter_lobby"] = function(json_data)
ClientInstance:notifyUI("enter_lobby", json_data) ClientInstance:notifyUI("enter_lobby", json_data)
end end
freekill.client_callback["enter_room"] = function(json_data)
ClientInstance:notifyUI("enter_room", json_data)
end
-- Create ClientInstance (used by Lua) -- Create ClientInstance (used by Lua)
ClientInstance = Client:new() ClientInstance = Client:new()

View File

@ -15,12 +15,30 @@ function Server:initialize()
end end
freekill.server_callback["create_room"] = function(json_data) freekill.server_callback["create_room"] = function(json_data)
-- json_data: [ int id, string name, int capacity ] -- json_data: [ int uid, string name, int capacity ]
local data = json.decode(json_data) local data = json.decode(json_data)
local owner = freekill.ServerInstance:findPlayer(data[1]) local owner = freekill.ServerInstance:findPlayer(tonumber(data[1]))
local roomName = data[2] local roomName = data[2]
local capacity = data[3] local capacity = data[3]
freekill.ServerInstance:createRoom(owner, roomName, capacity) freekill.ServerInstance:createRoom(owner, roomName, capacity)
end end
freekill.server_callback["enter_room"] = function(json_data)
-- json_data: [ int uid, int roomId ]
local data = json.decode(json_data)
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)
local player = freekill.ServerInstance:findPlayer(tonumber(data[1]))
local room = player:getRoom()
if not room:isLobby() then
room:removePlayer(player)
end
end
ServerInstance = Server:new() ServerInstance = Server:new()

View File

@ -1,8 +0,0 @@
import QtQuick 2.15
import QtQuick.Controls 2.0
import QtQuick.Window 2.0
Item {
id: root
}

63
qml/Pages/CreateRoom.qml Normal file
View File

@ -0,0 +1,63 @@
import QtQuick 2.15
import QtQuick.Controls 2.0
import QtQuick.Layouts 1.15
Item {
id: root
Frame {
anchors.centerIn: parent
Column {
x: 32
y: 20
spacing: 20
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Room Name"
}
TextField {
id: roomName
font.pixelSize: 18
text: "tmp's Room"
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Text {
text: "Player num"
}
SpinBox {
id: playerNum
from: 2
to: 8
}
}
RowLayout {
anchors.rightMargin: 8
spacing: 16
Button {
text: "OK"
onClicked: {
mainWindow.busy = true;
mainStack.pop();
Backend.notifyServer(
"create_room",
JSON.stringify([roomName.text, playerNum.value])
);
}
}
Button {
text: "Cancel"
onClicked: {
mainStack.pop();
}
}
}
}
}
}

View File

@ -1,6 +1,5 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtQuick.Window 2.0
Item { Item {
id: root id: root
@ -20,16 +19,16 @@ Item {
Button { Button {
text: "Join Server" text: "Join Server"
onClicked: { onClicked: {
mainWindow.state = "busy"; mainWindow.busy = true;
mainWindow.busyString = "Connecting to host..."; toast.show("Connecting to host...");
Backend.joinServer(server_addr.text); Backend.joinServer(server_addr.text);
} }
} }
Button { Button {
text: "Console start" text: "Console start"
onClicked: { onClicked: {
mainWindow.state = "busy"; mainWindow.busy = true;
mainWindow.busyString = "Connecting to host..."; toast.show("Connecting to host...");
Backend.startServer(9527); Backend.startServer(9527);
Backend.joinServer("127.0.0.1"); Backend.joinServer("127.0.0.1");
} }

View File

@ -40,7 +40,13 @@ Item {
hoverEnabled: true hoverEnabled: true
onEntered: { parent.color = "blue" } onEntered: { parent.color = "blue" }
onExited: { parent.color = "black" } onExited: { parent.color = "black" }
onClicked: {} onClicked: {
mainWindow.busy = true;
Backend.notifyServer(
"enter_room",
JSON.stringify([roomId])
);
}
} }
} }
} }
@ -85,7 +91,9 @@ Item {
} }
Button { Button {
text: "Create Room" text: "Create Room"
onClicked: {} onClicked: {
mainStack.push(createRoom);
}
} }
Button { Button {
text: "Generals Overview" text: "Generals Overview"
@ -101,12 +109,42 @@ Item {
} }
Button { Button {
text: "Exit Lobby" text: "Exit Lobby"
onClicked: {
toast.show("Goodbye.");
Backend.quitLobby();
mainStack.pop();
}
} }
} }
} }
Loader {
id: lobby_dialog
z: 1000
onSourceChanged: {
if (item === null)
return;
item.finished.connect(function(){
source = "";
});
item.widthChanged.connect(function(){
lobby_dialog.moveToCenter();
});
item.heightChanged.connect(function(){
lobby_dialog.moveToCenter();
});
moveToCenter();
}
function moveToCenter()
{
item.x = Math.round((root.width - item.width) / 2);
item.y = Math.round(root.height * 0.67 - item.height / 2);
}
}
Component.onCompleted: { Component.onCompleted: {
// toast.show("Welcome to FreeKill lobby!") toast.show("Welcome to FreeKill lobby!");
} }
} }

18
qml/Pages/Room.qml Normal file
View File

@ -0,0 +1,18 @@
import QtQuick 2.15
import QtQuick.Controls 2.0
Item {
id: root
Text {
anchors.centerIn: parent
text: "You are in room."
}
Button {
text: "quit"
onClicked: {
mainStack.pop();
Backend.notifyServer("quit_room", "[]");
}
}
}

View File

@ -1,6 +1,7 @@
import QtQuick 2.15 import QtQuick 2.15
import QtQuick.Controls 2.0 import QtQuick.Controls 2.0
import QtQuick.Window 2.0 import QtQuick.Window 2.0
import "Pages"
Window { Window {
id: mainWindow id: mainWindow
@ -10,46 +11,52 @@ Window {
property var callbacks: ({ property var callbacks: ({
"error_msg": function(json_data) { "error_msg": function(json_data) {
toast.show(json_data); toast.show(json_data);
if (mainWindow.state === "busy") mainWindow.busy = false;
mainWindow.state = "init";
}, },
"enter_lobby": function(json_data) { "enter_lobby": function(json_data) {
mainWindow.state = "lobby"; if (mainStack.depth === 1) {
mainStack.push(lobby);
}
mainWindow.busy = false;
},
"enter_room": function(json_data) {
mainStack.push(room);
mainWindow.busy = false;
} }
}) })
Loader { StackView {
id: mainLoader id: mainStack
source: "Page/Init.qml" visible: !mainWindow.busy
initialItem: init
anchors.fill: parent anchors.fill: parent
} }
property string state: "init" Component {
id: init
onStateChanged: { Init {}
switch (state) {
case "init":
mainLoader.source = "Page/Init.qml";
break;
case "lobby":
mainLoader.source = "Page/Lobby.qml";
break;
case "room":
mainLoader.source = "Page/Room.qml";
break;
case "busy":
mainLoader.source = "";
break;
default: break;
}
} }
property string busyString: "Busy" Component {
id: lobby
Lobby {}
}
Component {
id: room
Room {}
}
Component {
id: createRoom
CreateRoom {}
}
property bool busy: false
BusyIndicator { BusyIndicator {
running: true running: true
anchors.centerIn: parent anchors.centerIn: parent
visible: mainWindow.state === "busy" visible: mainWindow.busy === true
} }
Rectangle { Rectangle {
@ -83,14 +90,14 @@ Window {
ScriptAction { ScriptAction {
script: { script: {
toast.opacity = 0 toast.opacity = 0;
} }
} }
} }
function show(text) { function show(text) {
opacity = 1 opacity = 1;
toast_text.text = text toast_text.text = text;
} }
} }

View File

@ -23,6 +23,7 @@ Client::Client(QObject* parent)
Client::~Client() Client::~Client()
{ {
ClientInstance = nullptr; ClientInstance = nullptr;
router->getSocket()->disconnectFromHost();
router->getSocket()->deleteLater(); router->getSocket()->deleteLater();
} }
@ -39,12 +40,12 @@ void Client::requestServer(const QString& command, const QString& json_data, int
void Client::replyToServer(const QString& command, const QString& json_data) void Client::replyToServer(const QString& command, const QString& json_data)
{ {
int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER; int type = Router::TYPE_REPLY | Router::SRC_CLIENT | Router::DEST_SERVER;
router->reply(type, command, json_data); router->reply(type, command, json_data);
} }
void Client::notifyServer(const QString& command, const QString& json_data) void Client::notifyServer(const QString& command, const QString& json_data)
{ {
int type = Router::TYPE_REQUEST | Router::SRC_CLIENT | Router::DEST_SERVER; int type = Router::TYPE_NOTIFICATION | Router::SRC_CLIENT | Router::DEST_SERVER;
router->notify(type, command, json_data); router->notify(type, command, json_data);
} }

View File

@ -3,6 +3,7 @@
#include "router.h" #include "router.h"
#include "client.h" #include "client.h"
#include "server.h" #include "server.h"
#include "serverplayer.h"
Router::Router(QObject *parent, ClientSocket *socket, RouterType type) Router::Router(QObject *parent, ClientSocket *socket, RouterType type)
: QObject(parent) : QObject(parent)
@ -153,9 +154,14 @@ void Router::handlePacket(const QByteArray& rawPacket)
if (type & TYPE_NOTIFICATION) { if (type & TYPE_NOTIFICATION) {
if (type & DEST_CLIENT) { if (type & DEST_CLIENT) {
qobject_cast<Client *>(parent())->callLua(command, json_data); ClientInstance->callLua(command, json_data);
} else { } else {
qDebug() << rawPacket << Qt::endl; // Add the uid of sender to json_data
QJsonArray arr = QJsonDocument::fromJson(json_data.toUtf8()).array();
arr.prepend(
(int)qobject_cast<ServerPlayer *>(parent())->getUid()
);
ServerInstance->callLua(command, QJsonDocument(arr).toJson());
} }
} }
else if (type & TYPE_REQUEST) { else if (type & TYPE_REQUEST) {
@ -165,7 +171,8 @@ void Router::handlePacket(const QByteArray& rawPacket)
if (type & DEST_CLIENT) { if (type & DEST_CLIENT) {
qobject_cast<Client *>(parent())->callLua(command, json_data); qobject_cast<Client *>(parent())->callLua(command, json_data);
} else { } else {
qDebug() << rawPacket << Qt::endl; // requesting server is not allowed
Q_ASSERT(false);
} }
} }
else if (type & TYPE_REPLY) { else if (type & TYPE_REPLY) {

View File

@ -8,6 +8,10 @@ Room::Room(Server* server)
id = roomId; id = roomId;
roomId++; roomId++;
this->server = server; this->server = server;
if (!isLobby()) {
connect(this, &Room::playerAdded, server->lobby(), &Room::removePlayer);
connect(this, &Room::playerRemoved, server->lobby(), &Room::addPlayer);
}
} }
Room::~Room() Room::~Room()
@ -72,7 +76,15 @@ void Room::setOwner(ServerPlayer *owner)
void Room::addPlayer(ServerPlayer *player) void Room::addPlayer(ServerPlayer *player)
{ {
players.insert(player->getId(), player); if (!player) return;
players.insert(player->getUid(), player);
player->setRoom(this);
if (isLobby()) {
player->doNotify("enter_lobby", "{}");
} else {
player->doNotify("enter_room", "{}");
}
qDebug() << "Player #" << player->getUid() << " entered room";
emit playerAdded(player); emit playerAdded(player);
} }

View File

@ -22,6 +22,7 @@ Server::Server(QObject* parent)
L = CreateLuaState(); L = CreateLuaState();
DoLuaScript(L, "lua/freekill.lua"); DoLuaScript(L, "lua/freekill.lua");
DoLuaScript(L, "lua/server/server.lua");
} }
Server::~Server() Server::~Server()
@ -41,13 +42,11 @@ void Server::createRoom(ServerPlayer* owner, const QString &name, uint capacity)
room->setName(name); room->setName(name);
room->setCapacity(capacity); room->setCapacity(capacity);
room->setOwner(owner); room->setOwner(owner);
// TODO room->addPlayer(owner);
// room->addPlayer(owner);
rooms.insert(room->getId(), room); rooms.insert(room->getId(), room);
#ifdef QT_DEBUG #ifdef QT_DEBUG
qDebug() << "Room #" << room->getId() << " created."; qDebug() << "Room #" << room->getId() << " created.";
#endif #endif
emit roomCreated(room);
} }
Room *Server::findRoom(uint id) const Room *Server::findRoom(uint id) const
@ -75,13 +74,14 @@ void Server::processNewConnection(ClientSocket* client)
// version check, file check, ban IP, reconnect, etc // version check, file check, ban IP, reconnect, etc
ServerPlayer *player = new ServerPlayer(lobby()); ServerPlayer *player = new ServerPlayer(lobby());
player->setSocket(client); player->setSocket(client);
players.insert(player->getUid(), player);
#ifdef QT_DEBUG #ifdef QT_DEBUG
qDebug() << "ServerPlayer #" << player->getUid() << "connected."; qDebug() << "ServerPlayer #" << player->getUid() << "connected.";
qDebug() << "His address is " << client->peerAddress(); qDebug() << "His address is " << client->peerAddress();
#endif #endif
player->doNotify("enter_lobby", "{}"); //player->doNotify("enter_lobby", "{}");
lobby()->addPlayer(player);
} }
void Server::onRoomAbandoned() void Server::onRoomAbandoned()

View File

@ -13,10 +13,13 @@ QmlBackend::QmlBackend(QObject* parent)
void QmlBackend::startServer(ushort port) void QmlBackend::startServer(ushort port)
{ {
class Server *server = new class Server(this); if (!ServerInstance) {
if (!server->listen(QHostAddress::Any, port)) { class Server *server = new class Server(this);
server->deleteLater();
emit notifyUI("error_msg", tr("Cannot start server!")); if (!server->listen(QHostAddress::Any, port)) {
server->deleteLater();
emit notifyUI("error_msg", tr("Cannot start server!"));
}
} }
} }
@ -50,3 +53,8 @@ void QmlBackend::notifyServer(const QString& command, const QString& json_data)
{ {
ClientInstance->notifyServer(command, json_data); ClientInstance->notifyServer(command, json_data);
} }
void QmlBackend::quitLobby()
{
delete ClientInstance;
}

View File

@ -31,6 +31,9 @@ public slots:
void replyToServer(const QString &command, const QString &json_data); void replyToServer(const QString &command, const QString &json_data);
void notifyServer(const QString &command, const QString &json_data); void notifyServer(const QString &command, const QString &json_data);
// Lobby
void quitLobby();
private: private:
WindowType type; WindowType type;
}; };