diff --git a/docs/network/rfc/RFC.md b/docs/network/rfc/RFC.md index 02ff5a53..cabfb326 100644 --- a/docs/network/rfc/RFC.md +++ b/docs/network/rfc/RFC.md @@ -295,7 +295,8 @@ Table of Contents 2.2.2.2. READY The Client must send a ready action to enter/start the game. - The Server respond to this action with a ready action. + The Server respond to this action by sending a start wave action, only if + all the clients are ready 2.2.2.2.1. Client diff --git a/src/Nitwork/ANitwork.cpp b/src/Nitwork/ANitwork.cpp index 1864ef9a..6d3b2b97 100644 --- a/src/Nitwork/ANitwork.cpp +++ b/src/Nitwork/ANitwork.cpp @@ -188,6 +188,7 @@ namespace Nitwork { "NITWORK: packet not found: " + std::to_string(header.last_id_received - index)); continue; } + packet->setIsResend(true); addPacketToSend(*packet); } } @@ -313,11 +314,6 @@ namespace Nitwork { return lastId; } - const boost::asio::ip::udp::endpoint &ANitwork::getEndpointSender() - { - return _senderEndpoint; - } - void ANitwork::addPacketToSend(const Packet &packet) { std::lock_guard lock(_outputQueueMutex); diff --git a/src/Nitwork/ANitwork.hpp b/src/Nitwork/ANitwork.hpp index 7c01b070..24e81f35 100644 --- a/src/Nitwork/ANitwork.hpp +++ b/src/Nitwork/ANitwork.hpp @@ -26,10 +26,13 @@ namespace Nitwork { void operator=(const ANitwork &) = delete; void operator=(const ANitwork &&) = delete; + void stop() override; + + protected: + ANitwork(); // start the NitworkServer - bool start(int port, int threadNb, int tick, const std::string &ip = "") override; + bool start(int port, int threadNb, int tick, const std::string &ip = "") final; - void stop() override; // send data to the endpoint with the given data template void sendData(Packet &packet) @@ -43,17 +46,19 @@ namespace Nitwork { Logger::error("NITWORK: Package too big"); return; } - packet.id = id; - T data = std::any_cast(packet.body); - auto header = static_cast(data.header); - header = { - HEADER_CODE1, - getIdsReceived(packet.endpoint), - getLastIdsReceived(packet.endpoint), - id, - header.nb_action, - HEADER_CODE2}; - data.header = header; + T data = std::any_cast(packet.body); + if (!packet.getIsResend()) { + packet.id = id; + auto oldHeader = static_cast(data.header); + struct header_s newHeader = { + HEADER_CODE1, + getIdsReceived(packet.endpoint), + getLastIdsReceived(packet.endpoint), + id, + oldHeader.nb_action, + HEADER_CODE2}; + data.header = newHeader; + } _socket.async_send_to( boost::asio::buffer(&data, sizeof(T)), @@ -71,14 +76,10 @@ namespace Nitwork { }); } - protected: - ANitwork(); - /* Getters / Setters */ n_idsReceived_t getIdsReceived(const boost::asio::ip::udp::endpoint &endpoint); n_id_t getLastIdsReceived(const boost::asio::ip::udp::endpoint &endpoint); n_id_t getPacketId(const boost::asio::ip::udp::endpoint &endpoint); - const boost::asio::ip::udp::endpoint &getEndpointSender(); void addPacketToSend(const Packet &); void handlePacketIdsReceived(const struct header_s &header); diff --git a/src/Nitwork/INitwork.hpp b/src/Nitwork/INitwork.hpp index 8da76969..24c0bb5e 100644 --- a/src/Nitwork/INitwork.hpp +++ b/src/Nitwork/INitwork.hpp @@ -56,11 +56,22 @@ namespace Nitwork { endpoint(endpoint) { } + [[nodiscard]] bool getIsResend() const + { + return _isResend; + } + void setIsResend(bool value) + { + _isResend = value; + } n_id_t id = 0; n_actionType_t action; std::any body; boost::asio::ip::udp::endpoint endpoint; + + private: + bool _isResend = false; }; using actionSender = std::function; diff --git a/src/Nitwork/Nitwork.h b/src/Nitwork/Nitwork.h index 8153fc51..6e016e97 100644 --- a/src/Nitwork/Nitwork.h +++ b/src/Nitwork/Nitwork.h @@ -16,7 +16,6 @@ #define ONE_SECOND 1000 #define DEFAULT_THREAD_NB 4 #define MAX_NB_ACTION 16 - #define MAX_CLIENTS 4 #define HEADER_CODE1 '\x01' #define HEADER_CODE2 '\x03' diff --git a/src/Nitwork/NitworkClient.cpp b/src/Nitwork/NitworkClient.cpp index a93442f5..4c6089d0 100644 --- a/src/Nitwork/NitworkClient.cpp +++ b/src/Nitwork/NitworkClient.cpp @@ -22,7 +22,7 @@ namespace Nitwork { return _instance; } - bool NitworkClient::start(int port, int threadNb, int tick, const std::string &ip) + bool NitworkClient::startClient(int port, const std::string &ip, int threadNb, int tick) { return ANitwork::start(port, threadNb, tick, ip); } diff --git a/src/Nitwork/NitworkClient.hpp b/src/Nitwork/NitworkClient.hpp index 101feda9..4395fc74 100644 --- a/src/Nitwork/NitworkClient.hpp +++ b/src/Nitwork/NitworkClient.hpp @@ -22,11 +22,11 @@ namespace Nitwork { static NitworkClient &getInstance(); using ANitwork::start; - bool start( + bool startClient( int port, - int threadNb = DEFAULT_THREAD_NB, - int tick = TICKS_PER_SECOND, - const std::string &ip = "") final; + const std::string &ip, + int threadNb = DEFAULT_THREAD_NB, + int tick = TICKS_PER_SECOND); // Messages creation methods void addInitMsg(); diff --git a/src/Nitwork/NitworkServer.cpp b/src/Nitwork/NitworkServer.cpp index 3143dccf..36e3198c 100644 --- a/src/Nitwork/NitworkServer.cpp +++ b/src/Nitwork/NitworkServer.cpp @@ -22,9 +22,10 @@ namespace Nitwork { return _instance; } - bool NitworkServer::start(int port, int threadNb, int tick, const std::string &ip) + bool NitworkServer::startServer(int port, int nbPlayer, int threadNb, int tick) { - return ANitwork::start(port, threadNb, tick, ip); + _maxNbPlayer = nbPlayer; + return ANitwork::start(port, threadNb, tick, ""); } bool NitworkServer::startNitworkConfig(int port, const std::string & /* unused */) @@ -111,7 +112,7 @@ namespace Nitwork { void NitworkServer::handleInitMsg(const std::any & /* unused */, boost::asio::ip::udp::endpoint &endpoint) { - if (_endpoints.size() >= MAX_CLIENTS) { + if (_endpoints.size() >= _maxNbPlayer) { std::cerr << "Too many clients, can't add an other one" << std::endl; return; } @@ -130,6 +131,10 @@ namespace Nitwork { Logger::info("Client not connected"); return; } + if (_endpoints.size() < _maxNbPlayer) { + Logger::info("A new client is ready, waiting for others"); + return; + } addStarWaveMessage(endpoint, Types::Enemy::getEnemyNb()); Systems::SystemManagersDirector::getInstance().getSystemManager(0).addSystem(Systems::initWave); } diff --git a/src/Nitwork/NitworkServer.hpp b/src/Nitwork/NitworkServer.hpp index 0fa237c9..03eab7b7 100644 --- a/src/Nitwork/NitworkServer.hpp +++ b/src/Nitwork/NitworkServer.hpp @@ -21,11 +21,11 @@ namespace Nitwork { static NitworkServer &getInstance(); - bool start( + bool startServer( int port, - int threadNb = DEFAULT_THREAD_NB, - int tick = TICKS_PER_SECOND, - const std::string &ip = "") final; + int nbPlayer, + int threadNb = DEFAULT_THREAD_NB, + int tick = TICKS_PER_SECOND); /* Messages creation methods */ void addStarWaveMessage(boost::asio::ip::udp::endpoint &endpoint, n_id_t enemyId); @@ -84,6 +84,7 @@ namespace Nitwork { // NOLINTBEGIN(cppcoreguidelines-avoid-non-const-global-variables) static NitworkServer _instance; // instance of the NitworkServer (singleton) // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables) + unsigned int _maxNbPlayer = 0; // max number of players std::list _endpoints; // A vector of endpoints which will be used to send the actions to the clients // and identify them diff --git a/src/main_client.cpp b/src/main_client.cpp index 135f6786..9df8f407 100644 --- a/src/main_client.cpp +++ b/src/main_client.cpp @@ -5,23 +5,6 @@ ** main */ -// #include "NitworkClient.hpp" -// -// int main() -//{ -// const int port = 4242; -// Nitwork::NitworkClient::getInstance().start(port); -// -// Nitwork::NitworkClient::getInstance().addInitMsg(); -// Nitwork::NitworkClient::getInstance().addInitMsg(); -// Nitwork::NitworkClient::getInstance().addInitMsg(); -// Nitwork::NitworkClient::getInstance().addInitMsg(); -// Nitwork::NitworkClient::getInstance().addReadyMsg(); -// while (true) {}; -// return 0; -// } - -#include #include "Logger.hpp" #include "NitworkClient.hpp" #include "Registry.hpp" @@ -30,30 +13,30 @@ constexpr int EXIT_EPITECH = 84; -static bool checkArgs(int ac, char **av) +static bool isNumber(const std::string &str) +{ + return std::all_of(str.begin(), str.end(), ::isdigit); +} + +static bool checkArgs(int ac, const char **av) { if (ac != 3) { Logger::error("Usage: ./r-type_client "); return false; } - for (int i = 0; av[2][i] != '\0'; i++) { - if (av[2][i] < '0' || av[2][i] > '9') { - Logger::error("Invalid port"); - return false; - } - } - if (std::stoi(av[2]) < 0 || std::stoi(av[2]) > 65535) { - Logger::error("Invalid port"); + const std::vector args(av + 1, av + ac); + if (args[0].empty()) { + Logger::error("Invalid ip"); return false; } - if (av[1][0] == '\0') { - Logger::error("Invalid ip"); + if (!isNumber(args[1]) || std::stoi(args[1]) < 0 || std::stoi(args[1]) > 65535) { + Logger::error("Invalid port"); return false; } return true; } -int main(int ac, char **av) +int main(int ac, const char **av) { #ifndef NDEBUG Registry::getInstance().getLogger().setLogLevel(Logger::LogLevel::Debug); @@ -64,7 +47,7 @@ int main(int ac, char **av) } auto &sceneManager = Scene::SceneManager::getInstance(); if (!Nitwork::NitworkClient::getInstance() - .start(std::stoi(av[2]), DEFAULT_THREAD_NB, TICKS_PER_SECOND, av[1])) { + .startClient(std::stoi(av[2]), av[1], DEFAULT_THREAD_NB, TICKS_PER_SECOND)) { return EXIT_EPITECH; } Nitwork::NitworkClient::getInstance().addInitMsg(); diff --git a/src/main_server.cpp b/src/main_server.cpp index ad92f4e2..d23dac7c 100644 --- a/src/main_server.cpp +++ b/src/main_server.cpp @@ -18,24 +18,26 @@ static void signalHandler(int signum) signal(SIGINT, SIG_DFL); } +static bool isNumber(const std::string &str) +{ + return std::all_of(str.begin(), str.end(), ::isdigit); +} + static bool checkArgs(int ac, const char **av) { - if (ac != 2) { - Logger::error("Usage: ./r-type_server "); - return false; - } - if (av[1][0] == '\0') { - Logger::error("Invalid ip"); + if (ac != 3) { + Logger::error("Usage: ./r-type_server "); return false; } - for (int i = 0; av[1][i] != '\0'; i++) { - if (av[1][i] < '0' || av[1][i] > '9') { - Logger::error("Invalid port"); + const std::vector args(av + 1, av + ac); + for (const auto &arg : args) { + if (!isNumber(arg)) { + Logger::error("Invalid argument: " + arg); return false; } } - if (std::stoi(av[1]) < PORT_MIN || std::stoi(av[1]) > PORT_MAX) { - Logger::error("Invalid port"); + if (std::stoi(args[0]) < PORT_MIN || std::stoi(args[0]) > PORT_MAX || std::stoi(args[1]) < 1) { + Logger::error("Invalid port or playerNb"); return false; } return true; @@ -51,7 +53,7 @@ int main(int ac, const char **av) return EXIT_EPITECH; } Logger::info("Starting Server..."); - if (!Nitwork::NitworkServer::getInstance().start(std::stoi(av[1]))) { + if (!Nitwork::NitworkServer::getInstance().startServer(std::stoi(av[1]), std::stoi(av[2]))) { return EXIT_EPITECH; } Systems::SystemManagersDirector::getInstance().addSystemManager(Systems::getECSSystems());