235 lines
8.2 KiB
C++
235 lines
8.2 KiB
C++
#include "room.h"
|
|
|
|
#include <algorithm>
|
|
#include <server.h>
|
|
#include <unistd.h>
|
|
#include <iostream>
|
|
#include <time.h>
|
|
#include <algorithm>
|
|
#include <utility>
|
|
#include <thread>
|
|
|
|
namespace Yc {
|
|
namespace Lib {
|
|
|
|
Room::Room(Server *parent, Json::Value roomParams) :
|
|
_parent(parent),
|
|
_blocked(false),
|
|
_stop(false),
|
|
_roundRunning(false) {
|
|
_name = roomParams["name"].asString();
|
|
_password = roomParams["password"].asString();
|
|
std::vector<std::string> allowedUsers;
|
|
for (auto &user: roomParams["allowed"]) {
|
|
_allowedUsers.push_back(user.asString());
|
|
}
|
|
_type = (RoomType)roomParams["type"].asInt();
|
|
_roundLength = roomParams["roundlength"].asInt();
|
|
_lastRoundEnd = std::time(NULL);
|
|
thread = new std::thread(&Room::run, this);
|
|
}
|
|
|
|
Room::~Room() {
|
|
delete thread;
|
|
}
|
|
|
|
void Room::run() {
|
|
while (!_stop) {
|
|
if (_msgQueue.size() > 0 && !_blocked) {
|
|
_blocked = true;
|
|
while (_msgQueue.size() > 0) {
|
|
Message message = _msgQueue.front();
|
|
for (auto &user: _users) {
|
|
user->sendMsg(message.type, message.messageTr, message.userName, message.color);
|
|
}
|
|
_msgQueue.pop();
|
|
}
|
|
_blocked = false;
|
|
}
|
|
if ((_type & dice) == dice) {
|
|
_handleDice();
|
|
}
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
}
|
|
}
|
|
|
|
bool Room::addUser(std::string _userName, std::string color, std::string _password, int socket) {
|
|
if (_password != "" && _password == _password && std::find(std::begin(_allowedUsers), std::end(_allowedUsers), _userName) == std::end(_allowedUsers)) {
|
|
return false;
|
|
}
|
|
User *newUser = new User(this, _userName, color, socket);
|
|
_users.push_back(newUser);
|
|
newUser->sendMsg(User::roomList, _parent->jsonRoomList(), "", "");
|
|
addMessage(User::system, "room_entered", newUser->name(), newUser->color());
|
|
_initRound();
|
|
return true;
|
|
}
|
|
|
|
bool Room::addUser(User *user, std::string password) {
|
|
if (password == _password) {
|
|
_users.push_back(user);
|
|
user->setParent(this);
|
|
_initRound();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool Room::userNameExists(std::string userName) {
|
|
for (auto &user: _users) {
|
|
if (user->name() == userName) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Room::removeUser(std::string _token, bool silent) {
|
|
for (std::vector<User*>::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<User*>::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;
|
|
}
|
|
}
|
|
}
|
|
|
|
void Room::setStop() {
|
|
_stop = true;
|
|
}
|
|
|
|
void Room::addMessage(User::MsgType type, const char *messageText, std::string userName, std::string color) {
|
|
addMessage(type, (std::string)messageText, userName, color);
|
|
}
|
|
|
|
void Room::addMessage(User::MsgType type, std::string messageText, std::string userName, std::string color) {
|
|
Message message;
|
|
message.type = type;
|
|
message.messageTr = messageText;
|
|
message.userName = userName;
|
|
message.color = color;
|
|
_msgQueue.push(message);
|
|
}
|
|
|
|
void Room::addMessage(User::MsgType type, Json::Value messageText, std::string userName, std::string color) {
|
|
addMessage(type, getJsonString(messageText), userName, color);
|
|
}
|
|
|
|
void Room::addUserWhenQueueEmpty(User *user) {
|
|
while (_msgQueue.size() > 0) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
|
}
|
|
_users.push_back(user);
|
|
user->setParent(this);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
bool Room::isType(Room::RoomType type) {
|
|
return ((_type & type) == type);
|
|
}
|
|
|
|
bool Room::canDice() {
|
|
return (_roundRunning || (_type & rounds) == rounds) && (_type & dice) == dice;
|
|
}
|
|
|
|
unsigned int Room::addDice(User *user, int diceValue) {
|
|
if (!canDice()) {
|
|
return 1;
|
|
}
|
|
for (auto &listUser: _diceValues) {
|
|
if (listUser.first == user) {
|
|
return 2;
|
|
}
|
|
}
|
|
_diceValues.push_back(std::make_pair(user, diceValue));
|
|
addMessage(User::dice, std::to_string(diceValue), user->name(), user->color());
|
|
return 0;
|
|
|
|
}
|
|
|
|
bool Room::accessAllowed(std::string userName, std::string password) {
|
|
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 (_roundRunning && (_users.size() < 2 || _roundStart + _roundLength >= time(NULL))) {
|
|
_lastRoundEnd = time(NULL);
|
|
_roundRunning = false;
|
|
addMessage(User::system, "round_ends");
|
|
_showDiceRoundResults();
|
|
} else if (!_roundRunning && _lastRoundEnd <= time(NULL) - 15 && _users.size() >= 2) {
|
|
_roundStart = time(NULL);
|
|
_roundRunning = true;
|
|
_diceValues.clear();
|
|
addMessage(User::system, "next_round_starts_now");
|
|
}
|
|
}
|
|
}
|
|
|
|
void Room::_initRound() {
|
|
if (_users.size() == 2) {
|
|
_lastRoundEnd = time(NULL);
|
|
addMessage(User::system, "next_round_starts_soon");
|
|
}
|
|
}
|
|
|
|
void Room::_showDiceRoundResults() {
|
|
std::sort(_diceValues.begin(), _diceValues.end(), [=](std::pair<User*, int> val1, std::pair<User*, int> val2) {
|
|
return (val1.second > val2.second);
|
|
});
|
|
Json::Value userList = Json::arrayValue;
|
|
for (auto &user: _diceValues) {
|
|
Json::Value entry = Json::objectValue;
|
|
entry["name"] = user.first;
|
|
entry["value"] = user.second;
|
|
userList.append(entry);
|
|
}
|
|
addMessage(User::result, userList);
|
|
}
|
|
|
|
std::string Room::name() {
|
|
return _name;
|
|
}
|
|
|
|
} // namespace Lib
|
|
} // namespace Yc
|