From 0415a41961b501116ce556626221f20df19fa0b6 Mon Sep 17 00:00:00 2001 From: Master_Laplace Date: Fri, 31 May 2024 16:59:39 +0200 Subject: [PATCH] fix(Flakkari): game directory setted by FLAKKARY_GAME_DIR env var --- CMakeLists.txt | 6 +- Flakkari/Logger/Logger.cpp | 172 +-------------------------- Flakkari/Logger/Logger.hpp | 8 +- Flakkari/Protocol/Packet.hpp | 16 +-- Flakkari/Server/Client/Client.cpp | 2 - Flakkari/Server/Game/GameManager.cpp | 26 +++- Flakkari/Server/Game/GameManager.hpp | 1 + Flakkari/core.cpp | 2 +- docs/examples/TCPServer.cpp | 74 ++++++++++++ docs/examples/UDPClient.hpp | 4 +- docs/examples/UDPServer.hpp | 5 +- 11 files changed, 120 insertions(+), 196 deletions(-) create mode 100644 docs/examples/TCPServer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 204441ea..d6a19d64 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ # Flakkari/CMakeLists.txt -cmake_minimum_required(VERSION 3.26.4) +cmake_minimum_required(VERSION 3.22.0) project(R-Type_Server) @@ -117,9 +117,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) if(MSVC) add_compile_options(/W4) elseif(WIN32) - add_compile_options(-Wall -Wextra -pedantic) + add_compile_options(-Wall -Wextra) else() - add_compile_options(-Wall -Wextra -pedantic) + add_compile_options(-Wall -Wextra) endif() # Create the executable diff --git a/Flakkari/Logger/Logger.cpp b/Flakkari/Logger/Logger.cpp index 61131576..fe1b99f5 100644 --- a/Flakkari/Logger/Logger.cpp +++ b/Flakkari/Logger/Logger.cpp @@ -9,7 +9,7 @@ using namespace Flakkari; -#if defined(DEBUG) || defined(_DEBUG) +#if defined(DEBUG) || defined(_DEBUG) || !defined(DEBUG) static Logger::Mode _mode = Logger::Mode::DEBUG; #else static Logger::Mode _mode = Logger::Mode::NORMAL; @@ -57,7 +57,7 @@ const std::string Logger::fatal_error_message() noexcept COLOR_RESET "\nPlease report this error to the developers by opening an issue on GitHub:\n" COLOR_BRIGHT_CYAN - "\thttps://github.com/MasterLaplace/Flakkari/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml&title=[Bug :: " + "\thttps://github.com/MasterLaplace/Flakkari/issues/new?assignees=&labels=bug&projects=&template=bug_report.yml&title=[Bug%20::%20" #ifdef __APPLE__ "macOS]" #elif __linux__ @@ -92,7 +92,7 @@ const std::string Logger::fatal_error_message() noexcept #endif } -void Logger::log(int level, std::string message, std::string file, int line) +void Logger::log(int level, std::string message, int line, std::string file) noexcept { if (_mode == Logger::Mode::SILENT && level != LOG_FATAL) return; @@ -174,7 +174,7 @@ void Logger::log(int level, std::string message, std::string file, int line) std::cout << fatal_error_message() << std::endl; } -void Logger::log(int level, std::string message) +void Logger::log(int level, std::string message) noexcept { if (_mode == Logger::Mode::SILENT && level != LOG_FATAL) return; @@ -255,167 +255,3 @@ void Logger::log(int level, std::string message) if (level == LOG_FATAL) std::cout << fatal_error_message() << std::endl; } - -void Logger::log(int level, std::string message, std::string file) -{ - if (_mode == Logger::Mode::SILENT && level != LOG_FATAL) - return; - - if (_mode == Logger::Mode::NORMAL && level == LOG_DEBUG) - return; - - #if !defined(_WIN32) || !defined(_WIN64) - std::string color = COLOR_RESET; - std::string levelStr = "INFO"; - - switch (level) { - case LOG_INFO: - color = COLOR_CYAN; - levelStr = "INFO"; - break; - case LOG_LOG: - color = COLOR_GREEN; - levelStr = "LOG"; - break; - case LOG_DEBUG: - color = COLOR_MAGENTA; - levelStr = "DEBUG"; - break; - case LOG_WARNING: - color = COLOR_YELLOW; - levelStr = "WARNING"; - break; - case LOG_ERROR: - color = COLOR_ORANGE; - levelStr = "ERROR"; - break; - case LOG_FATAL: - color = COLOR_BRIGHT_RED; - levelStr = "FATAL"; - break; - } - - std::cout << get_current_time(); - std::cout << color << " [" << levelStr << "] " << message << " (" << file << ")" << COLOR_RESET << std::endl; - - #else - - std::string levelStr = "INFO"; - std::cout << get_current_time(); - - switch (level) { - case LOG_INFO: - levelStr = "INFO"; - setColor(COLOR_CYAN); - break; - case LOG_LOG: - levelStr = "LOG"; - setColor(COLOR_GREEN); - break; - case LOG_DEBUG: - levelStr = "DEBUG"; - setColor(COLOR_MAGENTA); - break; - case LOG_WARNING: - levelStr = "WARNING"; - setColor(COLOR_YELLOW); - break; - case LOG_ERROR: - levelStr = "ERROR"; - setColor(COLOR_ORANGE); - break; - case LOG_FATAL: - levelStr = "FATAL"; - setColor(COLOR_BRIGHT_RED); - break; - } - - std::cout << " [" << levelStr << "] " << message << " (" << file << ")" << std::endl; - setColor(COLOR_RESET); - #endif - - if (level == LOG_FATAL) - std::cout << fatal_error_message() << std::endl; -} - -void Logger::log(int level, std::string message, int line) -{ - if (_mode == Logger::Mode::SILENT && level != LOG_FATAL) - return; - - if (_mode == Logger::Mode::NORMAL && level == LOG_DEBUG) - return; - - #if !defined(_WIN32) || !defined(_WIN64) - std::string color = COLOR_RESET; - std::string levelStr = "INFO"; - - switch (level) { - case LOG_INFO: - color = COLOR_CYAN; - levelStr = "INFO"; - break; - case LOG_LOG: - color = COLOR_GREEN; - levelStr = "LOG"; - break; - case LOG_DEBUG: - color = COLOR_MAGENTA; - levelStr = "DEBUG"; - break; - case LOG_WARNING: - color = COLOR_YELLOW; - levelStr = "WARNING"; - break; - case LOG_ERROR: - color = COLOR_ORANGE; - levelStr = "ERROR"; - break; - case LOG_FATAL: - color = COLOR_BRIGHT_RED; - levelStr = "FATAL"; - break; - } - - std::cout << get_current_time(); - std::cout << color << " [" << levelStr << "] " << message << " (" << line << ")" << COLOR_RESET << std::endl; - - #else - - std::string levelStr = "INFO"; - std::cout << get_current_time(); - - switch (level) { - case LOG_INFO: - levelStr = "INFO"; - setColor(COLOR_CYAN); - break; - case LOG_LOG: - levelStr = "LOG"; - setColor(COLOR_GREEN); - break; - case LOG_DEBUG: - levelStr = "DEBUG"; - setColor(COLOR_MAGENTA); - break; - case LOG_WARNING: - levelStr = "WARNING"; - setColor(COLOR_YELLOW); - break; - case LOG_ERROR: - levelStr = "ERROR"; - setColor(COLOR_ORANGE); - break; - case LOG_FATAL: - levelStr = "FATAL"; - setColor(COLOR_BRIGHT_RED); - break; - } - - std::cout << " [" << levelStr << "] " << message << " (" << line << ")" << std::endl; - setColor(COLOR_RESET); - #endif - - if (level == LOG_FATAL) - std::cout << fatal_error_message() << std::endl; -} diff --git a/Flakkari/Logger/Logger.hpp b/Flakkari/Logger/Logger.hpp index a969e554..0566d6cd 100644 --- a/Flakkari/Logger/Logger.hpp +++ b/Flakkari/Logger/Logger.hpp @@ -20,7 +20,7 @@ #include #include -#define FLAKKARI_LOG(level, message) Flakkari::Logger::log(level, message, __FILE__, __LINE__) +#define FLAKKARI_LOG(level, message) Flakkari::Logger::log(level, message, __LINE__, __FILE__) #define FLAKKARI_LOG_INFO(message) FLAKKARI_LOG(LOG_INFO, message) #define FLAKKARI_LOG_LOG(message) FLAKKARI_LOG(LOG_LOG, message) #define FLAKKARI_LOG_DEBUG(message) FLAKKARI_LOG(LOG_DEBUG, message) @@ -83,10 +83,8 @@ namespace Flakkari { static void setMode(Mode mode) noexcept; static const std::string get_current_time() noexcept; static const std::string fatal_error_message() noexcept; - static void log(int level, std::string message, std::string file, int line); - static void log(int level, std::string message); - static void log(int level, std::string message, std::string file); - static void log(int level, std::string message, int line); + static void log(int level, std::string message, int line, std::string file = "") noexcept; + static void log(int level, std::string message) noexcept; }; } /* namespace Flakkari */ diff --git a/Flakkari/Protocol/Packet.hpp b/Flakkari/Protocol/Packet.hpp index 3e26f44b..6609eeba 100644 --- a/Flakkari/Protocol/Packet.hpp +++ b/Flakkari/Protocol/Packet.hpp @@ -60,7 +60,7 @@ inline namespace V_0 { return str; } - friend std::ostream& operator<<(std::ostream& os, const Packet& packet) + friend std::ostream &operator<<(std::ostream &os, const Packet &packet) { os << "Packet(&intValue); + const byte *dataBytes = reinterpret_cast(&intValue); payload.insert(payload.end(), dataBytes, dataBytes + sizeof(intValue)); payload += component; header._contentLength += payload.size() + sizeof(intValue); @@ -90,15 +90,15 @@ inline namespace V_0 { * @tparam DataType Type of the data to add. * @param packet The packet to add the data to. * @param data The data to add. - * @return Packet& The packet with the data added. + * @return Packet & The packet with the data added. */ template - friend Packet& operator<<(Packet& packet, const DataType& data) + friend Packet &operator<<(Packet &packet, const DataType &data) { static_assert(std::is_trivially_copyable::value, "DataType must be trivially copyable to be used in a packet."); static_assert(std::is_standard_layout::value, "DataType must be standard layout to be used in a packet."); - const byte* dataBytes = reinterpret_cast(&data); + const byte *dataBytes = reinterpret_cast(&data); packet.payload.insert(packet.payload.end(), dataBytes, dataBytes + sizeof(data)); packet.header._contentLength += packet.payload.size() + sizeof(data); return packet; @@ -110,13 +110,13 @@ inline namespace V_0 { * @tparam DataType Type of the data to extract. * @param packet The packet to extract the data from. * @param data The data to extract. - * @return Packet& The packet with the data extracted. + * @return Packet & The packet with the data extracted. * * @deprecated This function is deprecated. Don't work with std::string. * Use the other operator>> instead. */ template - friend Packet& operator>>(Packet& packet, DataType& data) + friend Packet &operator>>(Packet &packet, DataType &data) { static_assert(std::is_trivially_copyable::value, "DataType must be trivially copyable to be used in a packet."); static_assert(std::is_standard_layout::value, "DataType must be standard layout to be used in a packet."); @@ -133,7 +133,7 @@ inline namespace V_0 { void injectString(std::string str) { int intValue = (int)str.size(); - const byte* dataBytes = reinterpret_cast(&intValue); + const byte *dataBytes = reinterpret_cast(&intValue); payload.insert(payload.end(), dataBytes, dataBytes + sizeof(intValue)); payload += str; header._contentLength += payload.size() + sizeof(intValue); diff --git a/Flakkari/Server/Client/Client.cpp b/Flakkari/Server/Client/Client.cpp index 25d87967..2abb91c5 100644 --- a/Flakkari/Server/Client/Client.cpp +++ b/Flakkari/Server/Client/Client.cpp @@ -24,8 +24,6 @@ Client::~Client() { bool Client::isConnected(float timeout) { - if (!this) - return false; if (!_isConnected) return false; return std::chrono::duration_cast(std::chrono::steady_clock::now() - _lastActivity).count() < timeout; diff --git a/Flakkari/Server/Game/GameManager.cpp b/Flakkari/Server/Game/GameManager.cpp index ece99e43..73bc9eba 100644 --- a/Flakkari/Server/Game/GameManager.cpp +++ b/Flakkari/Server/Game/GameManager.cpp @@ -21,13 +21,25 @@ std::mutex GameManager::_mutex; GameManager::GameManager() { - for (const auto & entry : std::filesystem::directory_iterator("../Games")) { - std::string gameName = entry.path().string().substr(9); +#if !defined(_WIN32) && !defined(_WIN64) && !defined( MSVC) && !defined(_MSC_VER) + _game_dir = std::getenv("FLAKKARI_GAME_DIR"); +#else + errno_t err = _dupenv_s(&_game_dir.data(), &_game_dir.size(), "FLAKKARI_GAME_DIR"); +#endif + if (_game_dir.empty()) + FLAKKARI_LOG_FATAL("No game directory set: please set \"FLAKKARI_GAME_DIR\" environment variable"); + + for (const auto & entry : std::filesystem::directory_iterator(_game_dir)) + { + std::string gameName = entry.path().string(); + gameName = gameName.substr(std::max(gameName.find_last_of("/") + 1, gameName.find_last_of("\\") + 1)); + if (_gamesStore.find(gameName) != _gamesStore.end()) { FLAKKARI_LOG_ERROR("game already loaded"); continue; } - std::ifstream configFile("../Games/" + gameName + "/config.cfg"); + + std::ifstream configFile(_game_dir + "/" + gameName + "/config.cfg"); nlohmann::json config; if (!configFile.is_open()) { @@ -57,9 +69,11 @@ std::shared_ptr GameManager::getInstance() int GameManager::addGame(std::string gameName) { auto &_gamesStore = getInstance()->_gamesStore; + auto _game_dir = getInstance()->_game_dir; + if (_gamesStore.find(gameName) != _gamesStore.end()) return FLAKKARI_LOG_ERROR("game already loaded"), 1; - std::ifstream configFile("../Games/" + gameName + "/config.cfg"); + std::ifstream configFile(_game_dir + "/" + gameName + "/config.cfg"); nlohmann::json config; if (!configFile.is_open()) @@ -95,9 +109,11 @@ std::vector> GameManager::getGamesInstances() int GameManager::updateGame(std::string gameName) { auto &_gamesStore = getInstance()->_gamesStore; + auto _game_dir = getInstance()->_game_dir; + if (_gamesStore.find(gameName) == _gamesStore.end()) return FLAKKARI_LOG_ERROR("game not found"), 1; - std::ifstream configFile("../Games/" + gameName + "/config.cfg"); + std::ifstream configFile(_game_dir + "/" + gameName + "/config.cfg"); nlohmann::json config; if (!configFile.is_open()) diff --git a/Flakkari/Server/Game/GameManager.hpp b/Flakkari/Server/Game/GameManager.hpp index 2ed62935..e163ce7a 100644 --- a/Flakkari/Server/Game/GameManager.hpp +++ b/Flakkari/Server/Game/GameManager.hpp @@ -37,6 +37,7 @@ class GameManager { std::unordered_map> /*waitingClients*/> _waitingClients; std::unordered_map> /*gamesInstances*/> _gamesInstances; std::unordered_map /*data*/> _gamesStore; + std::string _game_dir; public: GameManager(const GameManager &) = delete; diff --git a/Flakkari/core.cpp b/Flakkari/core.cpp index f6c40dc1..39735c7d 100644 --- a/Flakkari/core.cpp +++ b/Flakkari/core.cpp @@ -10,7 +10,7 @@ int main(int ac, const char *av[]) { if (ac != 2) - return FLAKKARI_LOG_FATAL("Usage: ./r-type_server "), 84; + return FLAKKARI_LOG_ERROR("Usage: ./r-type_server "), 84; try { Flakkari::UDPServer server(av[1], 8080); server.run(); diff --git a/docs/examples/TCPServer.cpp b/docs/examples/TCPServer.cpp new file mode 100644 index 00000000..f30acdf0 --- /dev/null +++ b/docs/examples/TCPServer.cpp @@ -0,0 +1,74 @@ +/************************************************************************** + * Flakkari Library v0.0.0 + * + * Flakkari Library is a C++ Library for Network. + * @file TCPServer.hpp + * @brief TCPServer is a class that represents a Basic TCP Server. + * It is used to create a TCP Server. It is a basic server that + * can only send and receive data. It is not a full fledged server. + * It is used to test the library. It is not meant to be used in + * production. + * + * Flakkari Library is under MIT License. + * https://opensource.org/licenses/MIT + * © 2023 @MasterLaplace + * @version 0.0.0 + * @date 2023-12-24 + **************************************************************************/ + +#ifndef TCPSERVER_HPP_ +#define TCPSERVER_HPP_ + +#include "Network/IOMultiplexer.hpp" + +namespace Flakkari { + +class TCPServer { + public: + TCPServer(std::string ip = "localhost", std::size_t port = 8080) : + _socket(Network::Socket(ip, port, Network::Address::IpType::IPv6, Network::Address::SocketType::TCP)) + { + std::cout << _socket << std::endl; + _socket.bind(); + _socket.listen(); + + _io = std::make_unique(); + _io->addSocket(_socket.getSocket()); + _io->addSocket(STDIN_FILENO); + } + ~TCPServer() = default; + + int run() { + while (true) + { + int result = _io->wait(); + + if (result == -1) { + FLAKKARI_LOG_FATAL("Failed to poll sockets, error: " + std::string(::strerror(errno))); + return 84; + } else if (result == 0) { + FLAKKARI_LOG_DEBUG("ppoll timed out"); + continue; + } + for (auto &fd : *_io) { + if (_io->isReady(fd)) { + auto packet = _socket.receive(); + std::cout << (*packet.value().first.get()); + std::cout << " : "; + std::cout << packet.value().second << std::endl; + _socket.send(packet.value().first, packet.value().second); + } + } + } + return 0; + } + + protected: + private: + Network::Socket _socket; + std::unique_ptr _io; +}; + +} /* namespace Flakkari */ + +#endif /* !TCPSERVER_HPP_ */ diff --git a/docs/examples/UDPClient.hpp b/docs/examples/UDPClient.hpp index 71102546..0ab6ae03 100644 --- a/docs/examples/UDPClient.hpp +++ b/docs/examples/UDPClient.hpp @@ -25,11 +25,11 @@ namespace Flakkari { class UDPClient { public: UDPClient(std::string ip = "localhost", std::size_t port = 8080) : - _socket(Flakkari::Network::Socket(ip, port, Flakkari::Network::Address::IpType::IPv4, Flakkari::Network::Address::SocketType::UDP)) + _socket(Network::Socket(ip, port, Network::Address::IpType::IPv4, Network::Address::SocketType::UDP)) { std::cout << _socket << std::endl; - _io = std::make_unique(); + _io = std::make_unique(); _io->addSocket(_socket.getSocket()); } ~UDPClient() = default; diff --git a/docs/examples/UDPServer.hpp b/docs/examples/UDPServer.hpp index 57a3eb21..7deee7de 100644 --- a/docs/examples/UDPServer.hpp +++ b/docs/examples/UDPServer.hpp @@ -26,13 +26,14 @@ namespace Flakkari { class UDPServer { public: UDPServer(std::string ip = "localhost", std::size_t port = 8080) : - _socket(Flakkari::Network::Socket(ip, port, Flakkari::Network::Address::IpType::IPv4, Flakkari::Network::Address::SocketType::UDP)) + _socket(Network::Socket(ip, port, Network::Address::IpType::IPv4, Network::Address::SocketType::UDP)) { std::cout << _socket << std::endl; _socket.bind(); - _io = std::make_unique(); + _io = std::make_unique(); _io->addSocket(_socket.getSocket()); + _io->addSocket(STDIN_FILENO); } ~UDPServer() = default;