diff --git a/lua/server/room.lua b/lua/server/room.lua index ea729181..6195068d 100644 --- a/lua/server/room.lua +++ b/lua/server/room.lua @@ -256,6 +256,31 @@ fk.room_callback["QuitRoom"] = function(jsonData) end end +fk.room_callback["AddRobot"] = function(jsonData) + -- jsonData: [ int uid ] + local data = json.decode(jsonData) + local player = fk.ServerInstance:findPlayer(tonumber(data[1])) + local room = player:getRoom() + + if not room:isLobby() then + room:addRobot(player) + end +end + +fk.room_callback["PlayerRunned"] = function(jsonData) + -- jsonData: [ int runner_id, int robot_id ] + -- note: this function is not called by Router. + -- note: when this function is called, the room must be started + local data = json.decode(jsonData) + local runner = data[1] + local robot = data[2] + for _, p in ipairs(RoomInstance.players) do + if p:getId() == runner then + p.serverplayer = RoomInstance:findPlayerById(robot) + end + end +end + fk.room_callback["PlayerStateChanged"] = function(jsonData) -- jsonData: [ int uid, string stateString ] -- note: this function is not called by Router. diff --git a/qml/Pages/Room.qml b/qml/Pages/Room.qml index 205c42ae..06f41943 100644 --- a/qml/Pages/Room.qml +++ b/qml/Pages/Room.qml @@ -27,9 +27,12 @@ Item { } } Button { - text: "start game" + text: "add robot" visible: dashboardModel.isOwner && !isStarted anchors.centerIn: parent + onClicked: { + ClientInstance.notifyServer("AddRobot", "[]"); + } } states: [ diff --git a/qml/Pages/RoomLogic.js b/qml/Pages/RoomLogic.js index 680e7d9e..ac4066d6 100644 --- a/qml/Pages/RoomLogic.js +++ b/qml/Pages/RoomLogic.js @@ -187,6 +187,21 @@ callbacks["MoveFocus"] = function(jsonData) { } } +callbacks["PlayerRunned"] = function(jsonData) { + // jsonData: int runner, int robot + let data = JSON.parse(jsonData); + let runner = data[0]; + let robot = data[1]; + + let model; + for (let i = 0; i < playerNum - 1; i++) { + model = photoModel.get(i); + if (model.id === runner) { + model.id = robot; + } + } +} + callbacks["AskForGeneral"] = function(jsonData) { // jsonData: string[] Generals // TODO: choose multiple generals diff --git a/src/core/player.cpp b/src/core/player.cpp index beb95f13..e77c5aa5 100644 --- a/src/core/player.cpp +++ b/src/core/player.cpp @@ -56,6 +56,8 @@ QString Player::getStateString() const return QStringLiteral("online"); case Trust: return QStringLiteral("trust"); + case Robot: + return QStringLiteral("robot"); case Offline: return QStringLiteral("offline"); default: @@ -75,6 +77,8 @@ void Player::setStateString(const QString &state) setState(Online); else if (state == QStringLiteral("trust")) setState(Trust); + else if (state == QStringLiteral("robot")) + setState(Robot); else if (state == QStringLiteral("offline")) setState(Offline); else diff --git a/src/core/player.h b/src/core/player.h index 6476616d..b0cb0657 100644 --- a/src/core/player.h +++ b/src/core/player.h @@ -10,7 +10,8 @@ public: enum State{ Invalid, Online, - Trust, + Trust, // Trust or run + Robot, // only for real robot Offline }; diff --git a/src/server/room.cpp b/src/server/room.cpp index 1f0393bf..f013d924 100644 --- a/src/server/room.cpp +++ b/src/server/room.cpp @@ -11,6 +11,7 @@ Room::Room(Server* server) setParent(server); owner = nullptr; gameStarted = false; + robot_id = -1; timeout = 15; if (!isLobby()) { connect(this, &Room::playerAdded, server->lobby(), &Room::removePlayer); @@ -80,7 +81,14 @@ bool Room::isFull() const bool Room::isAbandoned() const { - return players.isEmpty(); + if (players.isEmpty()) + return true; + + foreach (ServerPlayer *p, players) { + if (p->getState() == Player::Online) + return false; + } + return true; } ServerPlayer *Room::getOwner() const @@ -149,6 +157,20 @@ void Room::addPlayer(ServerPlayer *player) emit playerAdded(player); } +void Room::addRobot(ServerPlayer *player) +{ + if (player != owner || isFull()) return; + + ServerPlayer *robot = new ServerPlayer(this); + robot->setState(Player::Robot); + robot->setId(robot_id); + robot->setAvatar("guanyu"); + robot->setScreenName(QString("COMP-%1").arg(robot_id)); + robot_id--; + + addPlayer(robot); +} + void Room::removePlayer(ServerPlayer *player) { players.removeOne(player); @@ -157,12 +179,22 @@ void Room::removePlayer(ServerPlayer *player) if (isLobby()) return; if (gameStarted) { + // TODO: if the player is died.. + // create robot first + ServerPlayer *robot = new ServerPlayer(this); + robot->setState(Player::Robot); + robot->setId(robot_id); + robot->setAvatar(player->getAvatar()); + robot->setScreenName(QString("COMP-%1").arg(robot_id)); + robot_id--; + + // tell lua & clients QJsonArray jsonData; jsonData << player->getId(); + jsonData << robot->getId(); + callLua("PlayerRunned", QJsonDocument(jsonData).toJson()); doBroadcastNotify(getPlayers(), "PlayerRunned", QJsonDocument(jsonData).toJson()); runned_players << player->getId(); - - // TODO: create a robot for runned player. } else { QJsonArray jsonData; jsonData << player->getId(); @@ -190,7 +222,11 @@ QList Room::getOtherPlayers(ServerPlayer* expect) const ServerPlayer *Room::findPlayer(int id) const { - return server->findPlayer(id); + foreach (ServerPlayer *p, players) { + if (p->getId() == id) + return p; + } + return nullptr; } int Room::getTimeout() const @@ -230,9 +266,9 @@ void Room::gameOver() { gameStarted = false; runned_players.clear(); - // clean offline players + // clean not online players foreach (ServerPlayer *p, players) { - if (p->getState() == Player::Offline) { + if (p->getState() != Player::Online) { p->deleteLater(); } } diff --git a/src/server/room.h b/src/server/room.h index 111c4dbb..5a652607 100644 --- a/src/server/room.h +++ b/src/server/room.h @@ -26,6 +26,7 @@ public: void setOwner(ServerPlayer *owner); void addPlayer(ServerPlayer *player); + void addRobot(ServerPlayer *player); void removePlayer(ServerPlayer *player); QList getPlayers() const; QList getOtherPlayers(ServerPlayer *expect) const; @@ -76,6 +77,7 @@ private: ServerPlayer *owner; // who created this room? QList players; QList runned_players; + int robot_id; bool gameStarted; int timeout; diff --git a/src/server/server.cpp b/src/server/server.cpp index c2428229..eea3c2a4 100644 --- a/src/server/server.cpp +++ b/src/server/server.cpp @@ -232,6 +232,7 @@ void Server::handleNameAndPassword(ClientSocket *client, const QString& name, co void Server::onRoomAbandoned() { Room *room = qobject_cast(sender()); + room->gameOver(); rooms.remove(room->getId()); updateRoomList(); room->deleteLater(); diff --git a/src/server/serverplayer.cpp b/src/server/serverplayer.cpp index d124764f..e558e7a9 100644 --- a/src/server/serverplayer.cpp +++ b/src/server/serverplayer.cpp @@ -64,22 +64,32 @@ void ServerPlayer::speak(const QString& message) void ServerPlayer::doRequest(const QString& command, const QString& jsonData, int timeout) { + if (getState() != Player::Online) return; int type = Router::TYPE_REQUEST | Router::SRC_SERVER | Router::DEST_CLIENT; router->request(type, command, jsonData, timeout); } QString ServerPlayer::waitForReply() { + if (getState() != Player::Online) { + QThread::sleep(1); + return ""; + } return router->waitForReply(); } QString ServerPlayer::waitForReply(int timeout) { + if (getState() != Player::Online) { + QThread::sleep(1); + return ""; + } return router->waitForReply(timeout); } void ServerPlayer::doNotify(const QString& command, const QString& jsonData) { + if (getState() != Player::Online) return; int type = Router::TYPE_NOTIFICATION | Router::SRC_SERVER | Router::DEST_CLIENT; router->notify(type, command, jsonData); } diff --git a/src/swig/server.i b/src/swig/server.i index 9e96f4b6..c2494d6e 100644 --- a/src/swig/server.i +++ b/src/swig/server.i @@ -32,6 +32,7 @@ public: void setOwner(ServerPlayer *owner); void addPlayer(ServerPlayer *player); + void addRobot(ServerPlayer *player); void removePlayer(ServerPlayer *player); QList getPlayers() const; ServerPlayer *findPlayer(int id) const;