Skip to content

Commit

Permalink
MP player handling and "dedicated server"
Browse files Browse the repository at this point in the history
  • Loading branch information
vos committed May 20, 2012
1 parent 0eae0d6 commit 1785d63
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 17 deletions.
49 changes: 45 additions & 4 deletions main.cpp
Expand Up @@ -2,10 +2,26 @@
#include <QDesktopWidget>

#include "mainwindow.h"

#include "randomutil.h"
#include "canvas.h"
#include "playerintelligence.h"
#include "multiplayerserver.h"

const quint16 DEFAULT_PORT = 54321;

quint16 readUShort(const QStringList &arguments, const QString &name, quint16 defaultValue = 0)
{
if (arguments.isEmpty())
return defaultValue;

int index = arguments.indexOf(name);
if (index < 0 || index + 1 >= arguments.count())
return defaultValue;

bool ok;
quint16 value = arguments.at(index + 1).toUShort(&ok);
return ok ? value : defaultValue;
}

int main(int argc, char *argv[])
{
Expand All @@ -20,12 +36,37 @@ int main(int argc, char *argv[])
qRegisterMetaType<PlayerIntelligence*>("PlayerIntelligence*");

RandomUtil::init();
QStringList arguments = a.arguments();

#ifdef DEBUG
qDebug() << "PlanetAttack started with arguments:" << arguments;
#endif

QWidget *w;
if (a.arguments().contains("-noui")) {
w = new Canvas;
if (arguments.contains("-server")) {
QHostAddress adress = QHostAddress::Any;
quint16 port = readUShort(arguments, "-port", DEFAULT_PORT);

w = new QWidget; // TODO: replace with dedicated server class
w->setWindowTitle("Dedicated Server (placeholder)");

Game *game = new Game(w);
MultiplayerServer *server = new MultiplayerServer(game, game);
if (server->listen(adress, port)) {
qDebug("The server is listening on interface %s, port %i",
qPrintable(server->serverAddress().toString()), server->serverPort());
// game->startGameLoop();
} else {
qCritical("Failed to start the server on interface %s, port %i: %s (error code %i)",
qPrintable(adress.toString()), port, qPrintable(server->errorString()), server->serverError());
return 1;
}
} else {
w = new MainWindow;
if (arguments.contains("-noui")) {
w = new Canvas;
} else {
w = new MainWindow;
}
}

w->resize(1024, 768);
Expand Down
32 changes: 30 additions & 2 deletions multiplayerclient.cpp
Expand Up @@ -7,7 +7,8 @@ MultiplayerClient::MultiplayerClient(Game *game, Player *player, QObject *parent
QTcpSocket(parent),
m_game(game),
m_player(player),
m_packetSize(0)
m_packetSize(0),
m_playerId(-1)
{
connect(this, SIGNAL(connected()), SLOT(socket_connected()));
connect(this, SIGNAL(disconnected()), SLOT(socket_disconnected()));
Expand Down Expand Up @@ -60,14 +61,41 @@ void MultiplayerClient::socket_readyRead()
// read and handle packet data
switch ((MultiplayerPacket::PacketType)packetType) {
case MultiplayerPacket::ConnectionAccepted: {
MultiplayerPacket packet(MultiplayerPacket::PlayerJoin);
MultiplayerPacket packet(MultiplayerPacket::PlayerConnect);
packet.stream() << *m_player;
packet.send(this);
break;
}
case MultiplayerPacket::ConnectionRefused:
// TODO
break;
case MultiplayerPacket::PlayerConnectAccepted: {
in >> m_playerId;
qDebug("playerId = %d", m_playerId);
break;
}
case MultiplayerPacket::PlayerConnectDenied:
// TODO
break;
case MultiplayerPacket::PlayerConnected: {
PlayerID playerId;
Player *player = new Player;
in >> playerId >> *player;
if (m_game->addPlayer(player)) {
m_idPlayerMap.insert(playerId, player);
qDebug("playerId = %d, name = %s", playerId, qPrintable(player->name()));
}
break;
}
case MultiplayerPacket::PlayerDisconnected: {
PlayerID playerId;
in >> playerId;
Player *player = m_idPlayerMap.value(playerId);
m_idPlayerMap.remove(playerId);
m_game->removePlayer(player);
qDebug("playerId = %d, name = %s", playerId, qPrintable(player->name()));
break;
}
case MultiplayerPacket::PlanetAdded: {
Planet *planet = new Planet;
in >> *planet;
Expand Down
6 changes: 6 additions & 0 deletions multiplayerclient.h
Expand Up @@ -2,11 +2,14 @@
#define MULTIPLAYERCLIENT_H

#include <QTcpSocket>
#include <QHash>

class Game;
class Player;
class Planet;

typedef quint8 PlayerID;

class MultiplayerClient : public QTcpSocket
{
Q_OBJECT
Expand All @@ -27,6 +30,9 @@ private slots:
Player *m_player;
quint32 m_packetSize;

PlayerID m_playerId;
QHash<PlayerID, Player*> m_idPlayerMap;

};

#endif // MULTIPLAYERCLIENT_H
6 changes: 5 additions & 1 deletion multiplayerpacket.cpp
Expand Up @@ -5,8 +5,12 @@
const char* MultiplayerPacket::PacketTypeNames[] = {
"ConnectionAccepted",
"ConnectionRefused",
"PlayerJoin",
"PlayerConnect",
"PlayerConnectAccepted",
"PlayerConnectDenied",
"PlayerConnected",
"PlayerDisconnect",
"PlayerDisconnected",
"PlanetAdded",
"IllegalPacketType"
};
Expand Down
6 changes: 5 additions & 1 deletion multiplayerpacket.h
Expand Up @@ -12,8 +12,12 @@ class MultiplayerPacket
enum PacketType {
ConnectionAccepted, // server -> client
ConnectionRefused, // server -> client
PlayerJoin, // client -> server
PlayerConnect, // client -> server
PlayerConnectAccepted, // server -> client
PlayerConnectDenied, // server -> client
PlayerConnected, // server -> other clients
PlayerDisconnect, // client -> server
PlayerDisconnected, // server -> other clients
PlanetAdded, // client -> server -> other clients
IllegalPacketType
};
Expand Down
44 changes: 36 additions & 8 deletions multiplayerserver.cpp
Expand Up @@ -6,7 +6,8 @@

MultiplayerServer::MultiplayerServer(Game *game, QObject *parent) :
QTcpServer(parent),
m_game(game)
m_game(game),
m_nextPlayerId(1)
{
}

Expand Down Expand Up @@ -56,8 +57,12 @@ void MultiplayerServer::client_disconnected()
qPrintable(socket->peerAddress().toString()), socket->peerPort());
#endif

if (player != NULL) {
if (client->isConnected()) {
m_game->removePlayer(player);

MultiplayerPacket playerDisconnectedPacket(MultiplayerPacket::PlayerDisconnected);
playerDisconnectedPacket.stream() << client->id;
sendPacketToOtherClients(playerDisconnectedPacket, socket);
}
m_clients.remove(socket);
delete client;
Expand Down Expand Up @@ -99,11 +104,33 @@ void MultiplayerServer::client_readyRead()

// read and handle packet data
switch ((MultiplayerPacket::PacketType)packetType) {
case MultiplayerPacket::PlayerJoin: {
case MultiplayerPacket::PlayerConnect: {
Player *player = new Player;
in >> *player;
if (m_game->addPlayer(player)) {
client->player = player;
client->id = m_nextPlayerId++;

// accept the player
MultiplayerPacket connectAcceptedPacket(MultiplayerPacket::PlayerConnectAccepted);
connectAcceptedPacket.stream() << client->id;
connectAcceptedPacket.send(socket);

// send the client the other players data
foreach (Client *otherClient, m_clients.values()) {
if (otherClient != client && otherClient->isConnected()) {
MultiplayerPacket otherPlayerPacket(MultiplayerPacket::PlayerConnected); // send PlayerList in one packet?
otherPlayerPacket.stream() << otherClient->id << *otherClient->player;
otherPlayerPacket.send(socket);
}
}

// inform the other clients about the new player
MultiplayerPacket playerConnectedPacket(MultiplayerPacket::PlayerConnected);
playerConnectedPacket.stream() << client->id << *player;
sendPacketToOtherClients(playerConnectedPacket, socket);
} else {
MultiplayerPacket(MultiplayerPacket::PlayerConnectDenied).send(socket);
}
break;
}
Expand All @@ -113,11 +140,12 @@ void MultiplayerServer::client_readyRead()
case MultiplayerPacket::PlanetAdded: {
Planet *planet = new Planet;
in >> *planet;
m_game->addPlanet(planet);
// resend packet to all other clients
MultiplayerPacket packet(MultiplayerPacket::PlanetAdded);
packet.stream() << *planet;
sendPacketToOtherClients(packet, socket);
if (m_game->addPlanet(planet)) {
// resend packet to all other clients
MultiplayerPacket packet(MultiplayerPacket::PlanetAdded);
packet.stream() << *planet;
sendPacketToOtherClients(packet, socket);
}
break;
}
default:
Expand Down
8 changes: 7 additions & 1 deletion multiplayerserver.h
Expand Up @@ -9,6 +9,8 @@
class Game;
class Player;

typedef quint8 PlayerID; // uint8 enough?

class MultiplayerServer : public QTcpServer
{
Q_OBJECT
Expand All @@ -26,12 +28,16 @@ private slots:
Game *m_game;

struct Client {
explicit inline Client(Player *p = NULL) : player(p), packetSize(0) { }
explicit inline Client(Player *p = NULL) : player(p), id(-1), packetSize(0) { }
Player *player;
PlayerID id;
quint32 packetSize;
inline bool isConnected() const { return player != NULL; }
};
QHash<QTcpSocket*, Client*> m_clients;

PlayerID m_nextPlayerId;

void incomingConnection(int socketDescriptor);
void sendPacketToOtherClients(MultiplayerPacket &packet, const QTcpSocket *sender);

Expand Down

0 comments on commit 1785d63

Please sign in to comment.