diff --git a/room.cpp b/room.cpp index cc86858..5d9c525 100644 --- a/room.cpp +++ b/room.cpp @@ -25,6 +25,7 @@ namespace Yc { _type = (RoomType)roomParams["type"].asInt(); _roundLength = roomParams["roundlength"].asInt(); _lastRoundEnd = std::time(NULL); + mutexQueue.unlock(); thread = new std::thread(&Room::run, this); } @@ -34,6 +35,7 @@ namespace Yc { void Room::run() { while (!_stop) { + mutexQueue.lock(); if (_msgQueue.size() > 0 && !_blocked) { _blocked = true; while (_msgQueue.size() > 0) { @@ -45,10 +47,11 @@ namespace Yc { } _blocked = false; } - std::this_thread::sleep_for(std::chrono::milliseconds(50)); if ((_type & dice) == dice) { _handleDice(); } + mutexQueue.unlock(); + std::this_thread::sleep_for(std::chrono::milliseconds(50)); } } @@ -82,10 +85,25 @@ namespace Yc { return false; } - void Room::removeUser(std::string _token) { + void Room::removeUser(std::string _token, bool silent) { for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { if ((*user)->validateToken(_token)) { _users.erase(user); + if (!silent) { + addMessage(User::system, "room_exit", (*user)->name(), (*user)->color()); + } + break; + } + } + } + + void Room::removeUser(User *userToRemove, bool silent) { + for (std::vector::iterator user = _users.begin(); user != _users.end(); ++user) { + if (*user == userToRemove) { + _users.erase(user); + if (!silent) { + addMessage(User::system, "room_exit", (*user)->name(), (*user)->color()); + } break; } } @@ -99,8 +117,7 @@ namespace Yc { addMessage(type, messageText, userName, color); } - void Room::addMessage(User::MsgType type, std::string messageText, std::string userName, std::string color) - { + void Room::addMessage(User::MsgType type, std::string messageText, std::string userName, std::string color) { Message message; message.type = type; message.messageTr = messageText; @@ -113,6 +130,24 @@ namespace Yc { addMessage(type, getJsonString(messageText), userName, color); } + void Room::addUserWhenQueueEmpty(User *user) { + mutexQueue.lock(); + _users.push_back(user); + mutexQueue.unlock(); + } + + bool Room::userToNewRoom(User *user, std::string newRoom, std::string password) { + return _parent->changeRoom(user, newRoom, password); + } + + unsigned int Room::flags() { + unsigned int value = (unsigned int)_type; + if (_password != "") { + value += (unsigned int)Room::password; + } + return value; + } + Room::RoomType Room::type() { return _type; } @@ -144,6 +179,15 @@ namespace Yc { return (_allowedUsers.size() == 0 || _password == "" || _password == password || std::find(_allowedUsers.begin(), _allowedUsers.end(), userName) != _allowedUsers.end()); } + bool Room::userIsInRoom(std::string userName) { + for (auto &user: _users) { + if (userName == user->name()) { + return true; + } + } + return false; + } + void Room::_handleDice() { if (((_type & rounds) == rounds)) { if ((_users.size() < 2 && _roundRunning) || (!_roundRunning && _roundStart + _roundLength >= time(NULL))) { diff --git a/room.h b/room.h index f4e293a..d9bf4b4 100644 --- a/room.h +++ b/room.h @@ -22,7 +22,8 @@ namespace Yc { none = 0, dice = 1, poker = 2, - rounds = 4 + rounds = 4, + password = 8 }; Room(Server *parent, Json::Value roomParams); @@ -32,7 +33,8 @@ namespace Yc { bool addUser(std::string userName, std::string color, std::string password, int socket); bool addUser(User *user, std::string password); bool userNameExists(std::string userName); - void removeUser(std::string _token); + void removeUser(std::string _token, bool silent = false); + void removeUser(User *user, bool silent = false); void setStop(); void addMessage(User::MsgType type, const char* messageText, std::string userName = "", std::string color = ""); void addMessage(User::MsgType type, std::string messageText, std::string userName = "", std::string color = ""); @@ -42,6 +44,10 @@ namespace Yc { bool canDice(); unsigned int addDice(User *user, int diceValue); bool accessAllowed(std::string userName, std::string password); + bool userIsInRoom(std::string userName); + void addUserWhenQueueEmpty(User *user); + bool userToNewRoom(User *user, std::string newRoom, std::string password); + unsigned int flags(); private: struct Message { User::MsgType type; @@ -65,6 +71,7 @@ namespace Yc { time_t _lastRoundEnd; int _roundLength; std::vector> _diceValues; + std::mutex mutexQueue; void _handleDice(); void _startDiceRound(); void _endDiceRound(); diff --git a/server.cpp b/server.cpp index 9738850..dbfb21c 100644 --- a/server.cpp +++ b/server.cpp @@ -65,7 +65,10 @@ namespace Yc { Json::Value Server::jsonRoomList() { Json::Value list; for (auto &room: _rooms) { - list.append(room->name()); + Json::Value roomJson = Json::objectValue; + roomJson["name"] = room->name(); + roomJson["flags"] = room->flags(); + list.append(roomJson); } return list; } @@ -79,6 +82,35 @@ namespace Yc { return false; } + bool Server::changeRoom(User *user, std::string newRoom, std::string password) { + if (!roomAllowed(newRoom, user->name(), password)) { + return false; + } + Json::Value userMsg = Json::objectValue; + userMsg["tr"] = "room_change_user"; + userMsg["to"] = newRoom; + for (auto &room: _rooms) { + if (room->userIsInRoom(user->name())) { + Json::Value msg = Json::objectValue; + msg["tr"] = "room_change_to"; + msg["to"] = newRoom; + userMsg["from"] = room->name(); + room->addMessage(User::system, msg, user->name(), user->color()); + } + } + user->sendMsg(User::system, userMsg, "", ""); + for (auto &room: _rooms) { + if (room->name() == newRoom) { + Json::Value msg = Json::objectValue; + msg["tr"] = "room_change_to"; + msg["from"] = userMsg["from"]; + room->addMessage(User::system, msg, user->name(), user->color()); + room->addUserWhenQueueEmpty(user); + } + } + return true; + } + void Server::createRooms(Json::Value roomList) { for (auto &room: roomList) { Room *newRoom = new Room(this, room); diff --git a/server.h b/server.h index 7dec82a..27253b8 100644 --- a/server.h +++ b/server.h @@ -18,6 +18,7 @@ namespace Yc { std::vector roomList(); Json::Value jsonRoomList(); bool roomAllowed(std::string roomName, std::string userName, std::string password); + bool changeRoom(User *user, std::string newRoom, std::string password); private: int _socket; Yc::Lib::Config *_config; diff --git a/user.cpp b/user.cpp index 21feb8a..7eb882d 100644 --- a/user.cpp +++ b/user.cpp @@ -77,6 +77,8 @@ namespace Yc { if (selectResult == 1 && FD_ISSET(_socket, &readSd) == 1) { _parent->removeUser(_token); _stop = true; + delete this; + return; } std::string msg = readSocket(_socket); if (msg == "") { @@ -113,6 +115,8 @@ namespace Yc { _parent->addMessage(User::scream, jsonTree["message"].asString(), _name, _color); } else if (jsonTree["type"].asString() == "do") { _parent->addMessage(User::dosomething, jsonTree["message"].asString(), _name, _color); + } else if (jsonTree["type"].asString() == "join") { + changeRoom(jsonTree["newroom"].asString(), jsonTree["password"].asString()); } } @@ -128,5 +132,11 @@ namespace Yc { break; } } + + void User::changeRoom(std::string newRoom, std::string password) { + if (!_parent->userToNewRoom(this, newRoom, password)) { + sendMsg(User::system, "room_not_possible", "", ""); + } + } } // namespace Lib } // namespace Yc diff --git a/user.h b/user.h index 97fa154..2106088 100644 --- a/user.h +++ b/user.h @@ -49,6 +49,7 @@ namespace Yc { void send(Json::Value out); void handleMessage(std::string message); void doDice(); + void changeRoom(std::string newRoom, std::string password); }; } // namespace Lib