diff --git a/app/app.pro b/app/app.pro index 433edfa..140e5d5 100644 --- a/app/app.pro +++ b/app/app.pro @@ -16,7 +16,9 @@ SOURCES = main.cpp \ poilaumodule.cpp \ fourasmodule.cpp \ riddles.cpp \ - todomodule.cpp + todomodule.cpp \ + server.cpp \ + servermodule.cpp HEADERS += \ regismodule.h \ @@ -25,4 +27,7 @@ HEADERS += \ poilaumodule.h \ fourasmodule.h \ riddles.h \ - todomodule.h + todomodule.h \ + packet.h \ + server.h \ + servermodule.h diff --git a/app/main.cpp b/app/main.cpp index d91b456..00b6552 100644 --- a/app/main.cpp +++ b/app/main.cpp @@ -7,6 +7,7 @@ #include "poilaumodule.h" #include "fourasmodule.h" #include "todomodule.h" +#include "servermodule.h" class HelloWorldModule : public Module { @@ -38,5 +39,6 @@ int main(int argc, char *argv[]) app.addModule(new PoilAuModule()); app.addModule(new FourasModule()); app.addModule(new TodoModule()); + app.addModule(new ServerModule()); return app.exec(); } diff --git a/app/packet.h b/app/packet.h new file mode 100644 index 0000000..9fd2965 --- /dev/null +++ b/app/packet.h @@ -0,0 +1,35 @@ +#ifndef PACKET_H +#define PACKET_H + +enum PacketType +{ + INIT_CLIENT, + DELTA_CLIENT, + INIT_SERVER +}; + +struct InitClientPacket +{ + float x; + float y; + float angle; + float vforward; + float vangle; +}; + +struct DeltaClientPacket +{ + float dvforward; + float dvangle; +}; + +struct InitServerPacket +{ + unsigned int nbClients; + unsigned int idClient; + // InitClientPacket list = sizeof(InitClientPacket)*nbClients + // map ? +}; + +#endif // PACKET_H + diff --git a/app/server.cpp b/app/server.cpp new file mode 100644 index 0000000..bb9c9fb --- /dev/null +++ b/app/server.cpp @@ -0,0 +1,150 @@ +#include "server.h" +#include +#include +#include +#include +#include + +#define PI 3.1416 +#define MAX_ANGULAR_SPEED 1 +#define MAX_SPEED 3 + +Server::Server(unsigned short port, QObject *parent) : QObject(parent) +{ + server = new QTcpServer(); + timer = new QTimer(); + timer->setSingleShot(false); + std::srand(std::time(NULL)); + connect(server, SIGNAL(newConnection()), this, SLOT(on_newConnection())); + connect(timer, SIGNAL(timeout()), this, SLOT(update())); + if(server->listen(QHostAddress::Any, port)) + { + emit outMessage(QString("Listening on port %1").arg(port)); + timer->start(25); + } + else + emit errMessage(QString("Can't listen on port %1 : %2").arg(port).arg(server->errorString())); +} + +void Server::update() +{ + for(unsigned int i=0; iisOk()) + clients[i]->update(); + else + { + delete clients[i]; + clients[i--] = clients.back(); + clients.pop_back(); + } + } + + for(unsigned int i=0; isendFull(clients, i); +} + +void Server::on_newConnection() +{ + QTcpSocket* socket = server->nextPendingConnection(); + Client* client = new Client(socket); + if(client->isOk()) + { + clients.push_back(client); + connect(client, SIGNAL(outMessage(QString)), this, SIGNAL(outMessage(QString))); + connect(client, SIGNAL(errMessage(QString)), this, SIGNAL(errMessage(QString))); + } + else + delete client; +} + +Client::Client(QTcpSocket* mySocket) +{ + socket = mySocket; + ok = false; + if(socket->state() == QTcpSocket::ConnectedState) + { + ok = true; + emit outMessage(QString("New player connected : %1").arg(socket->peerAddress().toString())); + } + info.x = std::rand()%50; + info.y = std::rand()%50; + info.angle = ((float)(std::rand()%360)) / PI; + info.vforward = 0; + info.vangle = 0; + connect(socket, SIGNAL(disconnected()), this, SLOT(on_disconnected())); + connect(socket, SIGNAL(readyRead()), this, SLOT(on_readyRead())); +} + +Client::~Client() +{ + if(socket != NULL) + socket->deleteLater(); +} + +void Client::on_readyRead() +{ + while(socket->bytesAvailable()) + { + int type; + socket->read((char*)&type, sizeof(int)); + switch(type) + { + case DELTA_CLIENT: + { + DeltaClientPacket delta; + socket->read((char*)&delta, sizeof(DeltaClientPacket)); + info.vangle += delta.dvangle; + info.vforward += delta.dvforward; + if(info.vforward>3) + info.vforward = MAX_SPEED; + if(info.vforward<0) + info.vforward = 0; + float speed = info.vforward; + float maxAngularSpeed = speed <= 1 ? speed*MAX_ANGULAR_SPEED : MAX_ANGULAR_SPEED/speed; + if(info.vangle > maxAngularSpeed) + info.vangle = maxAngularSpeed; + if(info.vangle < -maxAngularSpeed) + info.vangle = -maxAngularSpeed; + } + break; + default: + emit errMessage(QString("Incorrect packet received")); + socket->close(); + break; + } + } +} + +void Client::on_disconnected() +{ + emit outMessage(QString("Player disconnected")); + disconnect(socket, SIGNAL(disconnected())); + disconnect(socket, SIGNAL(readyRead())); + ok = false; +} + +void Client::update() +{ + info.angle += info.vangle; + info.x += std::cos(info.angle)*info.vforward; + info.y += std::sin(info.angle)*info.vforward; +} + +void Client::sendDelta() +{ + // TODO +} + +void Client::sendFull(const std::vector &clients, int id) +{ + InitServerPacket packet; + packet.idClient = id; + packet.nbClients = clients.size(); + int type = INIT_SERVER; + socket->write((char*)&type, sizeof(int)); + socket->write((char*)&packet, sizeof(InitServerPacket)); + for(unsigned int i=0; iwrite((char*)&(clients[i]->info), sizeof(InitClientPacket)); + socket->flush(); +} diff --git a/app/server.h b/app/server.h new file mode 100644 index 0000000..5d6775a --- /dev/null +++ b/app/server.h @@ -0,0 +1,58 @@ +#ifndef SERVER_H +#define SERVER_H + +#include +#include +#include "packet.h" + +class QTimer; +class QTcpServer; +class QTcpSocket; +class Client; + +class Server : public QObject +{ + Q_OBJECT +public: + explicit Server(unsigned short port = 20202, QObject *parent = 0); + QTcpServer* server; + QTimer* timer; + std::vector clients; + int currentClient; + +signals: + void outMessage(QString); + void errMessage(QString); + +public slots: + void update(); + void on_newConnection(); +}; + +class Client : public QObject +{ + Q_OBJECT + +public: + Client(QTcpSocket* mySocket); + ~Client(); + bool isOk() {return ok;} + void update(); + void sendDelta(); + void sendFull(const std::vector &clients, int id); + +private: + bool ok; + QTcpSocket* socket; + InitClientPacket info; + +public slots: + void on_disconnected(); + void on_readyRead(); + +signals: + void outMessage(QString); + void errMessage(QString); +}; + +#endif // SERVER_H diff --git a/app/servermodule.cpp b/app/servermodule.cpp new file mode 100644 index 0000000..9fb7dc0 --- /dev/null +++ b/app/servermodule.cpp @@ -0,0 +1,49 @@ +#include "servermodule.h" +#include "message.h" +#include "server.h" + +ServerModule::ServerModule() : + server(NULL) +{ + +} + +bool ServerModule::messageHandler(Message msg) +{ + if(msg.command.compare(QString("PRIVMSG"), Qt::CaseInsensitive) == 0) + { + if(msg.args.compare("!server start") == 0) + { + if(server == NULL) + { + server = new Server(); + answer = QString("server started"); + return true; + } + } + else if(msg.args.compare("!server stop") == 0) + { + if(server != NULL) + { + delete server; + server = NULL; + answer = QString("server stopped"); + return true; + } + } + else if(msg.args.compare("!server") == 0) + { + if(server == NULL) + answer = QString("server is not running"); + else + answer = QString("server is running"); + return true; + } + } + return false; +} + +QString ServerModule::getName() +{ + return "server"; +} diff --git a/app/servermodule.h b/app/servermodule.h new file mode 100644 index 0000000..7520f0b --- /dev/null +++ b/app/servermodule.h @@ -0,0 +1,18 @@ +#ifndef SERVERMODULE_H +#define SERVERMODULE_H + +#include "module.h" + +class Server; + +class ServerModule : public Module +{ + Server* server; + +public: + ServerModule(); + virtual bool messageHandler(Message msg); + virtual QString getName(); +}; + +#endif // SERVERMODULE_H diff --git a/app/todomodule.cpp b/app/todomodule.cpp index ad56899..d307ad1 100644 --- a/app/todomodule.cpp +++ b/app/todomodule.cpp @@ -126,7 +126,7 @@ bool TodoModule::messageHandler(Message msg) t.description = desc; t.emitter = msg.nick; tasks.push_back(t); - answer = say(QString("todo successfully added"); + answer = say(QString("todo successfully added")); return true; } }