initial commit of spectator code

This commit is contained in:
Max-Wilhelm Bruker 2009-09-14 18:43:47 +02:00
parent a60da5d94b
commit cdfe0e0301
8 changed files with 121 additions and 90 deletions

View file

@ -15,6 +15,7 @@ bool ReturnMessage::send(ReturnCode code)
case ReturnSyntaxError: returnCodeString = "syntax"; break;
case ReturnContextError: returnCodeString = "context"; break;
case ReturnPasswordWrong: returnCodeString = "password"; break;
case ReturnSpectatorsNotAllowed: returnCodeString = "spectators_not_allowed"; break;
}
s->msg(QString("resp|%1|%2").arg(msg_id)
.arg(returnCodeString));

View file

@ -9,7 +9,7 @@ private:
unsigned int msg_id;
QString cmd;
public:
enum ReturnCode { ReturnNothing, ReturnOk, ReturnNameNotFound, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong };
enum ReturnCode { ReturnNothing, ReturnOk, ReturnNameNotFound, ReturnLoginNeeded, ReturnSyntaxError, ReturnContextError, ReturnPasswordWrong, ReturnSpectatorsNotAllowed };
ReturnMessage(QObject *parent = 0) : QObject(parent), msg_id(0) { }
unsigned int getMsgId() const { return msg_id; }
void setMsgId(unsigned int _msg_id) { msg_id = _msg_id; }

View file

@ -85,12 +85,12 @@ bool Server::openDatabase()
return true;
}
void Server::addGame(const QString description, const QString password, const int maxPlayers, ServerSocket *creator)
void Server::addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator)
{
ServerGame *newGame = new ServerGame(creator, nextGameId++, description, password, maxPlayers, this);
ServerGame *newGame = new ServerGame(creator, nextGameId++, description, password, maxPlayers, spectatorsAllowed, this);
games << newGame;
connect(newGame, SIGNAL(gameClosing()), this, SLOT(gameClosing()));
newGame->addPlayer(creator);
newGame->addPlayer(creator, false);
broadcastGameListUpdate(newGame);
}
@ -99,8 +99,8 @@ void Server::incomingConnection(int socketId)
{
ServerSocket *socket = new ServerSocket(this);
socket->setSocketDescriptor(socketId);
connect(socket, SIGNAL(createGame(const QString, const QString, const int, ServerSocket *)), this, SLOT(addGame(const QString, const QString, const int, ServerSocket *)));
connect(socket, SIGNAL(joinGame(int, ServerSocket *)), this, SLOT(addClientToGame(int, ServerSocket *)));
connect(socket, SIGNAL(createGame(const QString, const QString, int, bool, ServerSocket *)), this, SLOT(addGame(const QString, const QString, int, bool, ServerSocket *)));
connect(socket, SIGNAL(joinGame(int, bool, ServerSocket *)), this, SLOT(addClientToGame(int, bool, ServerSocket *)));
socket->initConnection();
players << socket;
}
@ -156,16 +156,6 @@ QList<ServerGame *> Server::listOpenGames()
return result;
}
bool Server::checkGamePassword(int gameId, const QString &password)
{
ServerGame *tmp;
if ((tmp = getGame(gameId))) {
if ((!tmp->getGameStarted()) && (tmp->getPassword() == password) && (tmp->getPlayerCount() < tmp->getMaxPlayers()))
return true;
}
return false;
}
void Server::broadcastGameListUpdate(ServerGame *game)
{
qDebug(QString("broadcastGameListUpdate() to %1 players").arg(players.size()).toLatin1());
@ -183,13 +173,6 @@ void Server::broadcastChannelUpdate()
players[i]->msg(line);
}
void Server::addClientToGame(int gameId, ServerSocket *client)
{
ServerGame *game = getGame(gameId);
game->addPlayer(client);
broadcastGameListUpdate(game);
}
void Server::gameClosing()
{
qDebug("Server::gameClosing");

View file

@ -36,8 +36,7 @@ class Server : public QTcpServer
{
Q_OBJECT
private slots:
void addGame(const QString description, const QString password, const int maxPlayers, ServerSocket *creator);
void addClientToGame(int gameId, ServerSocket *client);
void addGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator);
void gameClosing();
void broadcastChannelUpdate();
public:
@ -45,7 +44,6 @@ public:
~Server();
QSettings *settings;
bool openDatabase();
bool checkGamePassword(int gameId, const QString &password);
AuthenticationResult checkUserPassword(const QString &user, const QString &password);
QList<ServerGame *> listOpenGames();
QList<ChatChannel *> getChatChannelList() { return chatChannelList; }

View file

@ -22,8 +22,8 @@
#include "serversocket.h"
#include <QSqlQuery>
ServerGame::ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, QObject *parent)
: QObject(parent), creator(_creator), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers)
ServerGame::ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent)
: QObject(parent), creator(_creator), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), spectatorsAllowed(_spectatorsAllowed)
{
}
@ -36,14 +36,16 @@ ServerGame::~ServerGame()
QString ServerGame::getGameListLine() const
{
if (players.isEmpty())
return QString("list_games|%1|||0|%2|").arg(gameId).arg(maxPlayers);
return QString("list_games|%1|||0|%2||0").arg(gameId).arg(maxPlayers);
else
return QString("list_games|%1|%2|%3|%4|%5|%6").arg(gameId)
return QString("list_games|%1|%2|%3|%4|%5|%6|%7|%8").arg(gameId)
.arg(description)
.arg(password.isEmpty() ? 0 : 1)
.arg(players.size())
.arg(maxPlayers)
.arg(creator->getPlayerName());
.arg(creator->getPlayerName())
.arg(spectatorsAllowed ? 0 : 1)
.arg(spectators.size());
}
QStringList ServerGame::getPlayerNames() const
@ -113,29 +115,53 @@ void ServerGame::startGameIfReady()
setActivePlayer(0);
}
void ServerGame::addPlayer(ServerSocket *player)
ReturnMessage::ReturnCode ServerGame::checkJoin(const QString &_password, bool spectator)
{
int max = -1;
QListIterator<ServerSocket *> i(players);
while (i.hasNext()) {
int tmp = i.next()->getPlayerId();
if (tmp > max)
max = tmp;
}
player->setPlayerId(max + 1);
if (_password != password)
return ReturnMessage::ReturnPasswordWrong;
if (spectator) {
if (!spectatorsAllowed)
return ReturnMessage::ReturnSpectatorsNotAllowed;
} else if (gameStarted || (getPlayerCount() >= getMaxPlayers()))
return ReturnMessage::ReturnContextError;
return ReturnMessage::ReturnOk;
}
void ServerGame::addPlayer(ServerSocket *player, bool spectator)
{
if (!spectator) {
int max = -1;
QListIterator<ServerSocket *> i(players);
while (i.hasNext()) {
int tmp = i.next()->getPlayerId();
if (tmp > max)
max = tmp;
}
player->setPlayerId(max + 1);
player->msg(QString("private|||player_id|%1|%2").arg(max + 1).arg(player->getPlayerName()));
} else
player->setPlayerId(-1);
player->setGame(this);
player->msg(QString("private|||player_id|%1|%2").arg(max + 1).arg(player->getPlayerName()));
broadcastEvent("join", player);
broadcastEvent(QString("join|%1").arg(spectator ? 1 : 0), player);
players << player;
if (spectator)
spectators << player;
else
players << player;
connect(player, SIGNAL(broadcastEvent(const QString &, ServerSocket *)), this, SLOT(broadcastEvent(const QString &, ServerSocket *)));
qobject_cast<Server *>(parent())->broadcastGameListUpdate(this);
}
void ServerGame::removePlayer(ServerSocket *player)
{
players.removeAt(players.indexOf(player));
if (player->getSpectator())
spectators.removeAt(spectators.indexOf(player));
else
players.removeAt(players.indexOf(player));
broadcastEvent("leave", player);
if (!players.size())
deleteLater();

View file

@ -21,6 +21,7 @@
#define SERVERGAME_H
#include <QStringList>
#include "returnmessage.h"
class ServerSocket;
@ -29,18 +30,20 @@ class ServerGame : public QObject {
private:
ServerSocket *creator;
QList<ServerSocket *> players;
QList<ServerSocket *> spectators;
bool gameStarted;
int gameId;
QString description;
QString password;
int maxPlayers;
int activePlayer, activePhase;
bool spectatorsAllowed;
signals:
void gameClosing();
public slots:
void broadcastEvent(const QString &event, ServerSocket *player);
public:
ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, QObject *parent = 0);
ServerGame(ServerSocket *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, bool _spectatorsAllowed, QObject *parent = 0);
~ServerGame();
ServerSocket *getCreator() const { return creator; }
bool getGameStarted() const { return gameStarted; }
@ -49,10 +52,12 @@ public:
QString getDescription() const { return description; }
QString getPassword() const { return password; }
int getMaxPlayers() const { return maxPlayers; }
bool getSpectatorsAllowed() const { return spectatorsAllowed; }
QString getGameListLine() const;
QStringList getPlayerNames() const;
ServerSocket *getPlayer(int player_id);
void addPlayer(ServerSocket *player);
ReturnMessage::ReturnCode checkJoin(const QString &_password, bool spectator);
void addPlayer(ServerSocket *player, bool spectator);
void removePlayer(ServerSocket *player);
void startGameIfReady();
void msg(const QString &s);

View file

@ -31,7 +31,7 @@
#include "chatchannel.h"
ServerSocket::ServerSocket(Server *_server, QObject *parent)
: QTcpSocket(parent), server(_server), game(0), PlayerStatus(StatusNormal), authState(PasswordWrong), acceptsGameListChanges(false)
: QTcpSocket(parent), server(_server), game(0), spectator(false), PlayerStatus(StatusNormal), authState(PasswordWrong), acceptsGameListChanges(false)
{
remsg = new ReturnMessage(this);
connect(this, SIGNAL(readyRead()), this, SLOT(readClient()));
@ -166,62 +166,64 @@ void ServerSocket::readClient()
}
const ServerSocket::CommandProperties ServerSocket::commandList[ServerSocket::numberCommands] = {
{"ping", false, false, false, QList<QVariant::Type>(), &ServerSocket::cmdPing},
{"login", false, false, false, QList<QVariant::Type>() << QVariant::String
{"ping", false, false, false, true, QList<QVariant::Type>(), &ServerSocket::cmdPing},
{"login", false, false, false, true, QList<QVariant::Type>() << QVariant::String
<< QVariant::String, &ServerSocket::cmdLogin},
{"chat_list_channels", true, false, false, QList<QVariant::Type>(), &ServerSocket::cmdChatListChannels},
{"chat_join_channel", true, false, false, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdChatJoinChannel},
{"chat_leave_channel", true, false, false, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdChatLeaveChannel},
{"chat_say", true, false, false, QList<QVariant::Type>() << QVariant::String
{"chat_list_channels", true, false, false, true, QList<QVariant::Type>(), &ServerSocket::cmdChatListChannels},
{"chat_join_channel", true, false, false, true, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdChatJoinChannel},
{"chat_leave_channel", true, false, false, true, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdChatLeaveChannel},
{"chat_say", true, false, false, true, QList<QVariant::Type>() << QVariant::String
<< QVariant::String, &ServerSocket::cmdChatSay},
{"list_games", true, false, false, QList<QVariant::Type>(), &ServerSocket::cmdListGames},
{"create_game", true, false, false, QList<QVariant::Type>() << QVariant::String
{"list_games", true, false, false, true, QList<QVariant::Type>(), &ServerSocket::cmdListGames},
{"create_game", true, false, false, true, QList<QVariant::Type>() << QVariant::String
<< QVariant::String
<< QVariant::Int, &ServerSocket::cmdCreateGame},
{"join_game", true, false, false, QList<QVariant::Type>() << QVariant::Int
<< QVariant::String, &ServerSocket::cmdJoinGame},
{"leave_game", true, true, false, QList<QVariant::Type>(), &ServerSocket::cmdLeaveGame},
{"list_players", true, true, false, QList<QVariant::Type>(), &ServerSocket::cmdListPlayers},
{"say", true, true, false, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdSay},
{"submit_deck", true, true, false, QList<QVariant::Type>(), &ServerSocket::cmdSubmitDeck},
{"ready_start", true, true, false, QList<QVariant::Type>(), &ServerSocket::cmdReadyStart},
{"shuffle", true, true, true, QList<QVariant::Type>(), &ServerSocket::cmdShuffle},
{"draw_cards", true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdDrawCards},
{"reveal_card", true, true, true, QList<QVariant::Type>() << QVariant::Int
<< QVariant::Int
<< QVariant::Bool, &ServerSocket::cmdCreateGame},
{"join_game", true, false, false, true, QList<QVariant::Type>() << QVariant::Int
<< QVariant::String
<< QVariant::Bool, &ServerSocket::cmdJoinGame},
{"leave_game", true, true, false, true, QList<QVariant::Type>(), &ServerSocket::cmdLeaveGame},
{"list_players", true, true, false, true, QList<QVariant::Type>(), &ServerSocket::cmdListPlayers},
{"say", true, true, false, false, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdSay},
{"submit_deck", true, true, false, false, QList<QVariant::Type>(), &ServerSocket::cmdSubmitDeck},
{"ready_start", true, true, false, false, QList<QVariant::Type>(), &ServerSocket::cmdReadyStart},
{"shuffle", true, true, true, false, QList<QVariant::Type>(), &ServerSocket::cmdShuffle},
{"draw_cards", true, true, true, false, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdDrawCards},
{"reveal_card", true, true, true, false, QList<QVariant::Type>() << QVariant::Int
<< QVariant::String, &ServerSocket::cmdRevealCard},
{"move_card", true, true, true, QList<QVariant::Type>() << QVariant::Int
{"move_card", true, true, true, false, QList<QVariant::Type>() << QVariant::Int
<< QVariant::String
<< QVariant::String
<< QVariant::Int
<< QVariant::Int
<< QVariant::Bool, &ServerSocket::cmdMoveCard},
{"create_token", true, true, true, QList<QVariant::Type>() << QVariant::String
{"create_token", true, true, true, false, QList<QVariant::Type>() << QVariant::String
<< QVariant::String
<< QVariant::String
<< QVariant::Int
<< QVariant::Int, &ServerSocket::cmdCreateToken},
{"set_card_attr", true, true, true, QList<QVariant::Type>() << QVariant::String
{"set_card_attr", true, true, true, false, QList<QVariant::Type>() << QVariant::String
<< QVariant::Int
<< QVariant::String
<< QVariant::String, &ServerSocket::cmdSetCardAttr},
{"inc_counter", true, true, true, QList<QVariant::Type>() << QVariant::String
{"inc_counter", true, true, true, false, QList<QVariant::Type>() << QVariant::String
<< QVariant::Int, &ServerSocket::cmdIncCounter},
{"add_counter", true, true, true, QList<QVariant::Type>() << QVariant::String
{"add_counter", true, true, true, false, QList<QVariant::Type>() << QVariant::String
<< QVariant::Int
<< QVariant::Int, &ServerSocket::cmdAddCounter},
{"set_counter", true, true, true, QList<QVariant::Type>() << QVariant::String
{"set_counter", true, true, true, false, QList<QVariant::Type>() << QVariant::String
<< QVariant::Int, &ServerSocket::cmdSetCounter},
{"del_counter", true, true, true, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdDelCounter},
{"list_counters", true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdListCounters},
{"list_zones", true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdListZones},
{"dump_zone", true, true, true, QList<QVariant::Type>() << QVariant::Int
{"del_counter", true, true, true, false, QList<QVariant::Type>() << QVariant::String, &ServerSocket::cmdDelCounter},
{"list_counters", true, true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdListCounters},
{"list_zones", true, true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdListZones},
{"dump_zone", true, true, true, true, QList<QVariant::Type>() << QVariant::Int
<< QVariant::String
<< QVariant::Int, &ServerSocket::cmdDumpZone},
{"stop_dump_zone", true, true, true, QList<QVariant::Type>() << QVariant::Int
{"stop_dump_zone", true, true, true, true, QList<QVariant::Type>() << QVariant::Int
<< QVariant::String, &ServerSocket::cmdStopDumpZone},
{"roll_die", true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdRollDie},
{"next_turn", true, true, true, QList<QVariant::Type>(), &ServerSocket::cmdNextTurn},
{"set_active_phase", true, true, true, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdSetActivePhase}
{"roll_die", true, true, true, false, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdRollDie},
{"next_turn", true, true, true, false, QList<QVariant::Type>(), &ServerSocket::cmdNextTurn},
{"set_active_phase", true, true, true, false, QList<QVariant::Type>() << QVariant::Int, &ServerSocket::cmdSetActivePhase}
};
ReturnMessage::ReturnCode ServerSocket::cmdPing(const QList<QVariant> &/*params*/)
@ -311,10 +313,14 @@ ReturnMessage::ReturnCode ServerSocket::cmdCreateGame(const QList<QVariant> &par
QString description = params[0].toString();
QString password = params[1].toString();
int maxPlayers = params[2].toInt();
bool spectatorsAllowed = params[3].toBool();
acceptsGameListChanges = false;
acceptsChatChannelListChanges = false;
spectator = false;
leaveGame();
emit createGame(description, password, maxPlayers, this);
emit createGame(description, password, maxPlayers, spectatorsAllowed, this);
return ReturnMessage::ReturnOk;
}
@ -322,13 +328,21 @@ ReturnMessage::ReturnCode ServerSocket::cmdJoinGame(const QList<QVariant> &param
{
int gameId = params[0].toInt();
QString password = params[1].toString();
if (!server->checkGamePassword(gameId, password))
return ReturnMessage::ReturnPasswordWrong;
acceptsGameListChanges = false;
acceptsChatChannelListChanges = false;
leaveGame();
emit joinGame(gameId, this);
return ReturnMessage::ReturnOk;
bool _spectator = params[2].toBool();
ServerGame *g = server->getGame(gameId);
if (!g)
return ReturnMessage::ReturnNameNotFound;
ReturnMessage::ReturnCode result = g->checkJoin(password, _spectator);
if (result == ReturnMessage::ReturnOk) {
acceptsGameListChanges = false;
acceptsChatChannelListChanges = false;
leaveGame();
spectator = _spectator;
g->addPlayer(this, spectator);
}
return result;
}
ReturnMessage::ReturnCode ServerSocket::cmdLeaveGame(const QList<QVariant> &/*params*/)
@ -716,6 +730,8 @@ bool ServerSocket::parseCommand(QString line)
if (commandList[i].needsLogin && (authState == PasswordWrong))
return remsg->send(ReturnMessage::ReturnLoginNeeded);
// Check context
if (!commandList[i].allowedToSpectator && spectator)
return remsg->send(ReturnMessage::ReturnContextError);
if (commandList[i].needsGame && !game)
return remsg->send(ReturnMessage::ReturnContextError);
if (commandList[i].needsStartedGame && !game->getGameStarted())

View file

@ -40,8 +40,7 @@ private slots:
void readClient();
void catchSocketError(QAbstractSocket::SocketError socketError);
signals:
void createGame(const QString description, const QString password, const int maxPlayers, ServerSocket *creator);
void joinGame(int gameId, ServerSocket *player);
void createGame(const QString description, const QString password, int maxPlayers, bool spectatorsAllowed, ServerSocket *creator);
void commandReceived(QString cmd, ServerSocket *player);
void broadcastEvent(const QString &event, ServerSocket *player);
void startGameIfReady();
@ -52,6 +51,7 @@ private:
bool needsLogin;
bool needsGame;
bool needsStartedGame;
bool allowedToSpectator;
QList<QVariant::Type> paramTypes;
CommandHandler handler;
};
@ -99,6 +99,7 @@ private:
QList<Counter *> counters;
int playerId;
QString playerName;
bool spectator;
int nextCardId;
int newCardId();
PlayerZone *getZone(const QString &name) const;
@ -121,6 +122,7 @@ public:
void initConnection();
int getPlayerId() const { return playerId; }
void setPlayerId(int _id) { playerId = _id; }
bool getSpectator() const { return spectator; }
QString getPlayerName() const { return playerName; }
bool getAcceptsGameListChanges() const { return acceptsGameListChanges; }
bool getAcceptsChatChannelListChanges() const { return acceptsChatChannelListChanges; }