@startuml
'skinparam classAttributeIconSize 0
set namespaceSeparator ::

'Classes

'-Exceptions

class std::exception

class b12software::exception::B12SoftwareException {
    + B12SoftwareException(const std::string &what, const std::string &where)
    + ~B12SoftwareException()
    + const char *what() const noexcept
    + const char *where() const noexcept

    - std::string _what
    - std::string _where
}

class b12software::exception::CircularBufferException {
    + CircularBufferException(const std::string &what, const std::string &where): B12SoftwareException(what, where)
}

class b12software::exception::NetworkException {
    + NetworkException(const std::string &what, const std::string &where)
}

class b12software::exception::NullPointerException {
    + NullPointerException(const std::string &what, const std::string &where)
}

class b12software::exception::NotEnoughDataInCircularBufferException {
    + NotEnoughDataInCircularBufferException(const std::string &what, const std::string &where)
}

class rtype::exception::DatagramErrorException {
    + DatagramErrorException(const std::string &what, const std::string &where)
}

class rtype::exception::DatagramMalformedException {
    + DatagramMalformedException(const std::string &what, const std::string &where)
}

'-Containers

class b12software::containers::CircularBuffer {
    + explicit CircularBuffer(size_t size)
    + CircularBuffer(const CircularBuffer &other)
    + ~CircularBuffer()
    + CircularBuffer &operator=(const CircularBuffer &rhs)
    + bool write(const void *data, size_t size)
    + size_t read(void *toWrite, size_t size)
    + size_t read(std::string &str, const char *delim, size_t size)
    + void clear()
    + bool isFull() const
    + size_t getNbBufferedBytes() const
    + size_t getBufferSize() const

    - size_t _bufferSize
    - size_t _readIdx
    - size_t _writeIdx
    - std::uint8_t *_buffer
    - bool _full
    - size_t _nbBufferedBytes
}

class b12software::containers::ThreadSafeCircularBuffer {
    + ThreadSafeCircularBuffer(int size)
    + ThreadSafeCircularBuffer(const ThreadSafeCircularBuffer &other)
    + ~ThreadSafeCircularBuffer()
    + ThreadSafeCircularBuffer &operator=(const ThreadSafeCircularBuffer &rhs)
    + void lock()
    + void unlock()
    + void try_lock()
    - ThreadSafeCircularBuffer(const ThreadSafeCircularBuffer &other, const std::lock_guard<std::recursive_mutex> &)
    - mutable std::recursive_mutex _mutex
}

class b12software::containers::ThreadSafeQueue<T : queue elements type> {
    + ThreadSafeQueue()
    + ThreadSafeQueue(const ThreadSafeQueue<T> &other)
    + ThreadSafeQueue<T> &operator=(const ThreadSafeQueue<T> &rhs)
    + T &front()
    + T &back()
    + bool empty() const
    + size_t size() const
    + void push(const T &elem)
    + void push(T &&elem)
    + void emplace<class... Args>(Args&&... args)
    + void pop()
    + void lock()
    + void unlock()
    + void try_lock()

    - mutable std::recursive_mutex _mutex
    - std::condition_variable_any _variable
    - std::queue<T> _queue
}

class b12software::containers::ThreadSafeList<T : list elements type> {
    + ThreadSafeList()
    + ThreadSafeList(const ThreadSafeList<T> &other)
    + ThreadSafeList<T> &operator=(const ThreadSafeList<T> &rhs)
    + T &front()
    + T &back()
    + bool empty() const
    + size_t size() const
    + typename std::list<T>::iterator begin()
    + typename std::list<T>::const_iterator begin() const
    + typename std::list<T>::iterator end()
    + typename std::list<T>::const_iterator end() const
    + void clear()
    + void push_back(const T &elem)
    + void push_back(T &&elem)
    + void remove(const T &value)
    + template<class UnaryPredicate> void remove_if(UnaryPredicate p)
    + void lock()
    + void unlock()
    + void try_lock()
    - std::recursive_mutex _mutex
    - std::list<T> _list
}

'-Logger

enum b12software::logger::LogLevel {
    LogLevelDebug
    LogLevelInfo
    LogLevelWarn
    LogLevelError
    LogLevelFatal
    LogLevelNone
}

interface b12software::logger::ILogger {
    + {abstract} void setLogLevel(LogLevel level)
    + {abstract} LogLevel getLogLevel() const
    + {abstract} void log(LogLevel messageLevel, const std::string &message)
}

class b12software::logger::StandardLogger {
    + StandardLogger(LogLevel defaultLevel = LogLevelError)
    + ~StandardLogger()
    + StandardLogger(const StandardLogger &other)
    + StandardLogger &operator=(const StandardLogger &rhs)

    - LogLevel _currentLevel
}

class b12software::logger::DefaultLogger {
    - DefaultLogger()
    + {static} void SetDefaultLogger(const std::shared_ptr<ILogger> &logger)
    + {static} const std::shared_ptr<ILogger> &GetCurrentLogger()
    + {static} void ClearDefautLogger()
    + {static} void SetLogLevel(LogLevel level)
    + {static} LogLevel GetLogLevel()
    + {static} void Log(LogLevel messageLevel, const std::string &message)
    - {static} std::shared_ptr<ILogger> currentLogger
}

'-Network

class b12software::network::HostInfos << (S, orchid) >> {
    + std::string host
    + unsigned short port
}

interface b12software::network::INetworkManager {
    + {abstract} void start()
    + {abstract} void stop()
    + {abstract} std::weak_ptr<udp::IUdpSocket> createNewUdpSocket()
    + {abstract} std::weak_ptr<tcp::ITcpClient> createNewTcpClient()
    + {abstract} std::weak_ptr<tcp::ITcpServer> createNewTcpServer()
    + {abstract} void destroyUdpSocket(const std::weak_ptr<udp::IUdpSocket> &socket)
    + {abstract} void destroyTcpClient(const std::weak_ptr<tcp::ITcpClient> &client)
    + {abstract} void destroyTcpServer(const std::weak_ptr<tcp::ITcpServer> &server)
}

class b12software::network::udp::Datagram {
    + Datagram()
    + Datagram(const HostInfos &destination)
    + Datagram(const void *data, size_t size)
    + Datagram(const HostInfos &destination, const void *data, size_t size)
    + Datagram(const Datagram &other)
    + ~Datagram()
    + Datagram &operator=(const Datagram &rhs)
    + void setData(const void *data, size_t size)
    + void setDestination(const HostInfos &infos)
    + const void *getData() const
    + size_t getDatagramSize() const
    + const HostInfos &getHostInfos() const
    + bool isValid() const
    + void clear()

    # byte *_data
    # size_t _size
    # HostInfos _infos
}

interface b12software::network::udp::IUdpSocket {
    + {abstract} void bind(int port)
    + {abstract} void unbind()
    + {abstract} void registerHost(const HostInfos &infos)
    + {abstract} void unregisterHost()
    + {abstract} void send(const void *data, size_t size, const HostInfos &infos)
    + {abstract} void send(const Datagram &datagram)
    + {abstract} Datagram receive()
    + {abstract} bool hasPendingDatagrams() const
    + {abstract} unsigned short getPort() const
    + {abstract} std::string getAddress() const
}

interface b12software::network::tcp::IPacket {
    + {abstract} size_t getSize() const
    + {abstract} const void *getData() const
    + {abstract} size_t setData(const void *data, size_t size)
    + {abstract} void clear()
    + {abstract} bool isValid() const
}

interface b12software::network::tcp::ITcpClient {
    + {abstract} void connect(const HostInfos &infos)
    + {abstract} void disconnect()
    + {abstract} bool isConnected() const
    + {abstract} const HostInfos &getHostInfos() const
    + {abstract} const HostInfos &getSelfInfos() const
    + {abstract} size_t send(const void *data, size_t size)
    + {abstract} void send(const IPacket &packet)
    + {abstract} size_t receive(void *data, size_t size)
    + {abstract} void receive(IPacket &packet)
    + {abstract} size_t getAvailableBytesSize() const
}

interface b12software::network::tcp::ITcpServer {
    + {abstract} void bind(int port)
    + {abstract} void unbind()
    + {abstract} void disconnect(int clientId)
    + {abstract} void sendToAll(const void *data, size_t size)
    + {abstract} void sendToAll(const IPacket &packet)
    + {abstract} void sendToClient(int clientId, const void *data, size_t size)
    + {abstract} void sendToClient(int clientId, const IPacket &packet)
    + {abstract} void sendToClients(const std::vector<int> &clientIds, const void *data, size_t size)
    + {abstract} void sendToClients(const std::vector<int> &clientIds, const IPacket &packet)
    + {abstract} void sendExceptClients(const std::vector<int> &exceptIds, const void *data, size_t size)
    + {abstract} void sendExceptClients(const std::vector<int> &exceptIds, const IPacket &packet)
    + {abstract} std::vector<int> getConnectedClientIds()
    + {abstract} std::vector<int> getNewConnectedClientIds()
    + {abstract} std::vector<int> getDisconnectedClientIds()
    + {abstract} std::weak_ptr<ITcpClient> getClientById(int clientId)
}

class b12software::network::asio::AsioNetworkManager {
    + AsioNetworkManager()
    + ~AsioNetworkManager()
    - {static} void networkingThreadFunc(AsioNetworkManager *manager)
    - boost::asio::io_context _ioContext
    - boost::asio::io_context::work *_worker
    - std::vector<std::shared_ptr<udp::IUdpSocket>> _udpSockets
    - std::vector<std::shared_ptr<tcp::ITcpClient>> _tcpClients
    - std::vector<std::shared_ptr<tcp::ITcpServer>> _tcpServers
    - std::thread _networkThread
    - bool _started
}

class b12software::network::asio::AsioUdpSocket {
    + AsioUdpSocket(boost::asio::io_context &context)
    + ~AsioUdpSocket()
    - void startReceiving()
    - void sendHandler(const std::shared_ptr<udp::Datagram> &message, const boost::system::error_code &error, size_t byteTransferred)
    - void receiveHandler(const std::shared_ptr<std::array<char, maxReceiveDatagramSize>> &array, const std::shared_ptr<AsioUdpSocket::endpoint> &endpoint, const boost::system::error_code &error, size_t byteReceived)
    - boost::asio::io_context &_context
    - socket _socket
    - containers::ThreadSafeQueue<udp::Datagram> _datagrams
    - HostInfos _defaultHost
    - {static} static constexpr size_t maxReceiveDatagramSize
}

note left
using socket = boost::asio::ip::udp::socket;
using endpoint = boost::asio::ip::udp::endpoint;
end note

class b12software::network::asio::AsioTcpServer {
    + AsioTcpServer(boost::asio::io_context &context)
    + ~AsioTcpServer()
    - void recomputeDisconnected()
    - void startAccept()
    - void handleAccept(boost::shared_ptr<AsioTcpClient> client, const boost::system::error_code& error)
    - boost::asio::io_context &_context
    - acceptor _acceptor
    - std::map<int, std::shared_ptr<AsioTcpClient>> _clients
    - mutex _clientMapMutex
    - mutex _idVectorMutex
    - std::vector<int> _newIds
    - std::queue<int> _freeIds
    - std::vector<int> _disconnectedIds
    - int _maxId
}

note left
using acceptor = boost::asio::ip::tcp::acceptor;
using endpoint = boost::asio::ip::tcp::endpoint;
using mutex = std::recursive_mutex;
using lock = std::scoped_lock<mutex>;
end note

class b12software::network::asio::AsioTcpClient {
    + AsioTcpClient(boost::asio::io_context &context)
    + ~AsioTcpClient()
    + socket &getSocket()
    + void recompute()
    - void startReceive()
    - void handleConnect(const boost::system::error_code &error, boost::asio::ip::tcp::resolver::iterator endpointIterator)
    - void handleSend(const std::shared_ptr<byte[]> &message, const boost::system::error_code &error, size_t byteTransferred)
    - void handleReceive(const std::shared_ptr<byte[]> &message, const boost::system::error_code &error, size_t byteTransferred)
    - {static} constexpr size_t bufferSizeInBytes
    - boost::asio::io_context &_context
    - socket _socket
    - HostInfos _distantInfos
    - HostInfos _selfInfos
    - containers::ThreadSafeCircularBuffer _buffer
}

note left
using socket = boost::asio::ip::tcp::socket;
using endpoint = boost::asio::ip::tcp::endpoint;
using byte = unsigned char;
end note

'-Rtype datagram

class rtype::network::RTypeDatagram {
    + RTypeDatagram()
    + RTypeDatagram(const RTypeDatagram &other)
    + RTypeDatagram(const Datagram &other)
    + RTypeDatagram(const HostInfos &destination)
    + RTypeDatagram(const void *data, size_t size)
    + RTypeDatagram(const HostInfos &destination, const void *data, size_t size)
    + ~RTypeDatagram()
    + RTypeDatagram &operator=(const RTypeDatagram &rhs)
    + RTypeDatagram &operator=(const Datagram &rhs)
    + void initSingleOpCodeDatagram(RTypeDatagramType type)
    + void init100ConnectDatagram(const std::string &username)
    + void init106ClientDisconnectedDatagram(const std::string &username)
    + void init108NewClientConnectedDatagram(const std::string &username)
    + void init111RoomListDatagram(const std::vector<RTypeDatagramRoom> &rooms)
    + void init112CreateRoomDatagram(const RTypeDatagramRoom &room)
    + void init116JoinRoomDatagram(const RTypeDatagramRoom &room)
    + void init117RoomJoinedDatagram(const std::vector<std::string> &users)
    + void init200ActionDatagram(const RTypeDatagramAction &action)
    + void init210DisplayDatagram(const RTypeDatagramDisplay &entity)
    + void init220LivingDatagram(const RTypeDatagramLiving &data)
    + void init230ChargeDatagram(unsigned char charge)
    + void init240ScoreDatagram(const RTypeDatagramScore &score)
    + void init250EndGameDatagram(const RTypeDatagramScore &score)
    + unsigned short getType() const
    + void extract100ConnectDatagram(std::string &username)
    + void extract106ClientDisconnectedDatagram(std::string &username)
    + void extract108NewClientConnectedDatagram(std::string &username)
    + void extract111RoomListDatagram(std::vector<RTypeDatagramRoom> &rooms)
    + void extract112CreateRoomDatagram(RTypeDatagramRoom &room)
    + void extract116JoinRoomDatagram(RTypeDatagramRoom &room)
    + void extract117RoomJoinedDatagram(std::vector<std::string> &users)
    + void extract200ActionDatagram(RTypeDatagramAction &action)
    + void extract210DisplayDatagram(RTypeDatagramDisplay &entity)
    + void extract220LivingDatagram(RTypeDatagramLiving &data)
    + void extract230ChargeDatagram(unsigned char &charge)
    + void extract240ScoreDatagram(RTypeDatagramScore &score)
    + void extract250EndGameDatagram(RTypeDatagramScore &score)
}

class rtype::network::RTypeDatagramAction << (S, orchid) >> {
    + bool shot
    + bool up
    + bool down
    + bool left
    + bool right
}

class rtype::network::RTypeDatagramDisplay::Vector2 << (S, orchid) >> {
    + int x
    + int y
}

class rtype::network::RTypeDatagramDisplay::Vector3 << (S, orchid) >> {
    + int x
    + int y
    + int z
}

class rtype::network::RTypeDatagramDisplay << (S, orchid) >> {
    + uint64_t entityId
    + Vector3 position
    + Vector2 rotation
    + Vector2 scale
    + uint32_t type
}

class rtype::network::RTypeDatagramLiving << (S, orchid) >> {
    + uint64_t entityId
    + int life
}

class rtype::network::RTypeDatagramRoom << (S, orchid) >> {
    + std::string name
    + unsigned char capacity
    + unsigned char slotUsed
    + bool hasPassword
    + std::string password
}

class rtype::network::RTypeDatagramScore << (S, orchid) >> {
    + unsigned int p1Score
    + unsigned int p2Score
    + unsigned int p3Score
    + unsigned int p4Score
}

enum rtype::network::RTypeDatagramType {
    T_100_CONNECT = 100
    T_101_CONNECTED = 101
    T_102_PING = 102
    T_103_PONG = 103
    T_104_DISCONNECT = 104
    T_105_DISCONNECTED = 105
    T_106_CLIENT_DISCONNECTED = 106
    T_107_OK_CLIENT_DISCONNECTED = 107
    T_108_NEW_CLIENT_CONNECTED = 108
    T_109_OK_NEW_CLIENT_CONNECTED = 109
    T_110_GET_ROOMS = 110
    T_111_ROOM_LIST = 111
    T_112_CREATE_ROOM = 112
    T_113_ROOM_CREATED = 113
    T_114_QUIT_ROOM = 114
    T_115_ROOM_QUITTED = 115
    T_116_JOIN_ROOM = 116
    T_117_ROOM_JOINED = 117
    T_200_ACTION = 200
    T_210_DISPLAY = 210
    T_220_LIVING = 220
    T_230_CHARGE = 230
    T_240_SCORE = 240
    T_250_END_GAME = 250
    T_260_GAME_ENDED = 260
    T_270_GAME_STARTING = 270
    T_280_GAME_STARTED = 280
    T_300_UNKNOWN_PACKET = 300
    T_301_INVALID_PACKET = 301
    T_302_INVALID_PARAM = 302
    T_303_USERNAME_ALREADY_USED = 303
    T_304_ROOM_NAME_ALREADY_USED = 304
    T_305_NOT_IN_A_ROOM = 305
    T_306_UNKNOWN_ROOM = 306
    T_307_INVALID_PASSWORD = 307
    T_308_ROOM_FULL = 308
    T_309_OPERATION_NOT_PERMITTED = 309
}

'Extension

'-Exceptions

std::exception <|-- b12software::exception::B12SoftwareException

b12software::exception::B12SoftwareException <|-- b12software::exception::CircularBufferException
b12software::exception::CircularBufferException <|-- b12software::exception::NotEnoughDataInCircularBufferException

b12software::exception::B12SoftwareException <|-- b12software::exception::NetworkException

b12software::exception::B12SoftwareException <|-- b12software::exception::NullPointerException

b12software::exception::B12SoftwareException <|-- rtype::exception::DatagramErrorException

rtype::exception::DatagramErrorException <|-- rtype::exception::DatagramMalformedException

'-Containers
b12software::containers::CircularBuffer <|-- b12software::containers::ThreadSafeCircularBuffer

'-Logger

b12software::logger::ILogger <|- b12software::logger::StandardLogger

'-Network

b12software::network::INetworkManager <|-- b12software::network::asio::AsioNetworkManager
b12software::network::udp::IUdpSocket <|-- b12software::network::asio::AsioUdpSocket
b12software::network::tcp::ITcpClient <|-- b12software::network::asio::AsioTcpClient
b12software::network::tcp::ITcpServer <|-- b12software::network::asio::AsioTcpServer

'-Rtype datagram

class rtype::FsNotifier {
    + typedef std::function<bool (std::filesystem::path)> Handler
    + FsNotifier(const std::filesystem::path &folderPath)
    + void update()
    + void addCreateListener(const Handler &createHandler)
    + void addDeletedListener(const Handler &deleteHandle)
    - int computeSet(const std::map<int, Handler> &map, fd_set *set, fd_set *errorSet)
    - int computeSet(int notifyFd, fd_set *set, fd_set *errorSet)
    - void checkNotifier(int fdNotifier, const std::map<int, Handler> &map, int mask)
    - std::filesystem::path _folderPath
    - int _notifierFdCreate
    - int _notifierFdDelete
    - std::map<int, Handler> _mapCreatedEvents
    - std::map<int, Handler> _mapDeletedEvents
    - std::map<std::filesystem::path, bool> _indexedPaths
}

class rtype::LibLoader {
    + template <typename TypeAPI> MapType = std::map<std::filesystem::path, rtype::LibLoader::LibLoaded<TypeAPI>>
    + LibLoader(std::unique_ptr<ecs::IECS> &ecs, std::shared_ptr<ecs::IWorld> &world, const std::string &libFolder)
    + void checkForChanges()
    - template <typename TypeAPI> std::string getEntryPoint()
    - template <typename TypeAPI> std::string getlibFolder()
    - template <typename TypeAPI> void loadLib(const std::filesystem::path &libPath, MapType <TypeAPI> &libs)
    - template <typename TypeAPI> void unloadLib(const std::filesystem::path &libPath, MapType <TypeAPI> &libs)
    - void firstLibrariesLoad()
    - std::unique_ptr<ecs::IECS> &_ecs
    - std::shared_ptr<ecs::IWorld> &_world
    - const std::filesystem::path _entitiesPath
    - const std::filesystem::path _systemsPath
    - MapType<ecs::IEntityAPI> _entities
    - MapType<ecs::ISystemAPI> _systems
    - rtype::FsNotifier _notifierEntities
    - rtype::FsNotifier _notifierSystems
}

b12software::network::udp::Datagram <|-- rtype::network::RTypeDatagram

title R-Type - Class Diagram

abstract ecs::ASystem {
    + ASystem()
    + ~ASystem() = default
    + bool isRunning() const
    + void start()
    + void stop()
    - bool isRunning
}

class ecs::DLLoader {
    + explicit DLLoader(const std::string &libraryPath)
    + ~DLLoader()
    + template<typename API> std::shared_ptr<API> loadAPI(const std::string &entryPoint) const
    - HandlerType _instance
}

class ecs::DLLoaderException  {
    + DLLoaderException(const std::string &msg, const std::string &where)
    - std::string _what
    - std::string _where
}

class ecs::ECSException {
    + ECSException(const std::string &what, const std::string &where)
}

interface ecs::IComponent {
    + {abstract} ~IComponent() = default
    + {abstract} setEntity(const std::weak_ptr<IEntity> &entity)
    + {abstract} std::weak_ptr<IEntity> &getEntity() const
    + {abstract} const Version &getVersion() const
}

abstract ecs::AComponent {
    + setEntity(const std::weak_ptr<IEntity> &entity)
    + std::weak_ptr<IEntity> &getEntity() const

    - std::weak_ptr<IEntity> _entity
}

class ecs::components::TransformComponent {
    + TransformComponent(const Vector3 &position, const Vector2 &rotation, const Vector2 &scale)
    + TransformComponent(const TransformComponent &other)
    + TransformComponent &operator=(const TransformComponent &rhs)
    + const Vector3 &getPosition() const
    + void setPosition(const Vector3 &position)
    + const Vector2 &getRotation() const
    + void setRotation(const Vector2 &rotation)
    + const Vector2 &getScale() const
    + void setScale(const Vector2 &scale)

    - Vector3 _position
    - Vector2 _rotation
    - Vector2 _scale
}

interface ecs::IECS {
    + {abstract} ~IECS() = default
    + {abstract} std::shared_ptr<IWorld> createWorld()
    + {abstract} std::shared_ptr<IEntity> createEntityFromAPI(const Version &version)
    + {abstract} std::shared_ptr<ISystem> createSystemFromAPI(const Version &version)
    + {abstract} bool knowSystem(const Version &version)
    + {abstract} bool knowEntity(const Version &version)
    + {abstract} bool knowSystems(const std::vector<Version> &versions)
    + {abstract} bool knowEntities(const std::vector<Version> &versions)
    + {abstract} void learnSystem(const std::shared_ptr<ISystemAPI> &api)
    + {abstract} void learnEntity(const std::shared_ptr<IEntityAPI> &api)
    + {abstract} std::shared_ptr<ISystemAPI> forgetSystem(const Version &version)
    + {abstract} std::shared_ptr<IEntityAPI> forgetEntity(const Version &version)
    + {abstract} virtual std::vector<std::shared_ptr<ecs::IEntityAPI>> getKnownEntities() const
}

interface ecs::IEntity {
    + {abstract} ~IEntity() = default
    + {abstract} std::weak_ptr<IComponent> getComponent(const Version &componentType)
    + {abstract} std::vector<std::weak_ptr<IComponent>> getComponents(const std::vector<Version> &componentTypes)
    + {abstract} bool hasComponent(const Version &componentType) const
    + {abstract} bool hasComponents(const std::vector<Version> &componentTypes)
    + {abstract} int getId() const
    + {abstract} const std::string &getName() const
    + {abstract} void addComponent(const std::shared_ptr<IComponent> &component)
    + {abstract} std::shared_ptr<IComponent> removeComponent(const Version &version)
}

interface ecs::IEntityAPI {
    + {abstract} ~IEntityAPI() = default
    + {abstract} [[nodiscard]] const Version &getVersion() const
    + {abstract} [[nodiscard]] std::shared_ptr<IEntity> createNewEntity()
}

interface ecs::ISystem {
    + {abstract} ~ISystem() = default
    + {abstract} void tick(long deltatime)
    + {abstract} void start()
    + {abstract} void stop()
    + {abstract} const Version &getType() const
    + {abstract} bool isRunning() const
    + {abstract} void setWorld(const std::weak_ptr<IWorld> &world)
}

interface ecs::ISystemAPI {
    + {abstract} ~ISystemAPI() = default
    + {abstract} [[nodiscard]] const Version &getVersion() const
    + {abstract} [[nodiscard]] std::shared_ptr<ISystem> createNewSystem() const
}

interface ecs::IWorld {
    + {abstract} ~IWorld() = default
    + {abstract} tick(long deltatime)
    + {abstract} std::weak_ptr<IEntity> pushEntity(const std::shared_ptr<IEntity> &entity)
    + {abstract} std::shared_ptr<IEntity> popEntity(int id)
    + {abstract} std::weak_ptr<IEntity> getEntityById(int id) const
    + {abstract} std::vector<std::weak_ptr<IEntity>> getEntitiesWith(const std::vector<Version> &components)
    + {abstract} void applyToEach(const std::vector<Version> &componentTypes, std::function<void (std::weak_ptr<IEntity>, std::vector<std::weak_ptr<IComponent>>)> toApply)
    + {abstract} std::weak_ptr<ISystem> addSystem(const std::shared_ptr<ISystem> &system)
    + {abstract} void removeSystem(const Version &system)
    + {abstract} std::weak_ptr<ISystem> getSystem(const Version &system)
}

class ecs::Version {
    + Version(const std::string, int lilianVersion, int titouanVersion, int julianVersion, int etienneVersion)
    + ~Version() = default
    + const std::vector<int> &getVersions() const
    + const std::string &getType() const
    + bool operator<(const Version &rhs) const
    + bool operator>(const Version &rhs) const
    + bool operator<=(const Version &rhs) const
    + bool operator>=(const Version &rhs) const
    + bool operator==(const Version &rhs) const
    + bool operator!=(const Version &rhs) const
    - std::string _type
    - std::vector<int> _versions
}

class ecs::IDGenerator {
    + IDGenerator()
    + IDGenerator(const IDGenerator &other)
    + ~IDGenerator()
    + IDGenerator &operator=(const IDGenerator &rhs)
    + int generateNewID()
    + void freeId(int id)
    - int _maxID
    - std::queue<int> _freeIds
}

class ecs::ECS {
    + ECS()
    + ~ECS()
    - std::vector<std::shared_ptr<ISystemAPI>> _systemsAPI
    - std::vector<std::shared_ptr<IEntityAPI>> _entitysAPI
}

class ecs::Entity {
    + Entity(const std::string &name)
    + ~Entity()
    - {static} IDGenerator Generator
    - int _id
    - std::string _name
    - std::vector<std::shared_ptr<IComponent>> _components
}

class ecs::World {
    + World()
    + ~World()
    - std::vector<std::shared_ptr<IEntity>> _entities
    - std::vector<std::shared_ptr<ISystem>> _systems
}

class b12software::maths::Vector2D {
    + Vector2D()
    + Vector2D(float value)
    + Vector2D(float x, float y)
    + float &operator[](int i)
    + const float &operator[](int i) const
    + float magnitude() const
    + float magnitudeSq() const
    + void normalize()
    + Vector2D normalized() const

    + {static} float Dot(const Vector2D &lhs, const Vector2D &rhs)
    + {static} float Magnitude(const Vector2D &vec)
    + {static} float MagnitudeSq(const Vector2D &vec)
    + {static} float Distance(const Vector2D &p1, const Vector2D &p2)
    + {static} void Normalize(Vector2D &vec)
    + {static} Vector2D Normalized(const Vector2D &vec)
    + {static} float Angle(const Vector2D &lhs, const Vector2D &rhs)
    + {static} Vector2D Project(const Vector2D &len, const Vector2D &dir)
    + {static} Vector2D Perpendicular(const Vector2D &len, const Vector2D &dir)
    + {static} Vector2D Reflection(const Vector2D &vec, const Vector2D &normal)

    + Vector2D operator+(const Vector2D &rhs) const
    + Vector2D operator-(const Vector2D &rhs) const
    + Vector2D operator*(const Vector2D &rhs) const
    + Vector2D operator*(float rhs) const
    + bool operator==(const Vector2D &rhs) const
    + bool operator!=(const Vector2D &rhs) const
}

class b12software::maths::Vector3D {
    + Vector3D()
    + Vector3D(float value)
    + Vector3D(float x, float y)
    + float &operator[](int i)
    + const float &operator[](int i) const
    + float magnitude() const
    + float magnitudeSq() const
    + void normalize()
    + Vector3D normalized() const

    + {static} float Dot(const Vector3D &lhs, const Vector3D &rhs)
    + {static} float Magnitude(const Vector3D &vec)
    + {static} float MagnitudeSq(const Vector3D &vec)
    + {static} float Distance(const Vector3D &p1, const Vector3D &p2)
    + {static} void Normalize(Vector3D &vec)
    + {static} Vector3D Normalized(const Vector3D &vec)
    + {static} float Angle(const Vector3D &lhs, const Vector3D &rhs)
    + {static} Vector3D Project(const Vector3D &len, const Vector3D &dir)
    + {static} Vector3D Perpendicular(const Vector3D &len, const Vector3D &dir)
    + {static} Vector3D Reflection(const Vector3D &vec, const Vector3D &normal)

    + Vector3D operator+(const Vector3D &rhs) const
    + Vector3D operator-(const Vector3D &rhs) const
    + Vector3D operator*(const Vector3D &rhs) const
    + Vector3D operator*(float rhs) const
    + bool operator==(const Vector3D &rhs) const
    + bool operator!=(const Vector3D &rhs) const
}

ecs::ISystem <|-down- ecs::ASystem: Inheritance

std::exception <|-- ecs::DLLoaderException

b12software::exception::B12SoftwareException <|-- ecs::ECSException

ecs::IECS <|-- ecs::ECS

ecs::IComponent <|-- ecs::AComponent

ecs::AComponent <|-- ecs::components::TransformComponent

ecs::IEntity <|-- ecs::Entity

ecs::IWorld <|-- ecs::World

std::enable_shared_from_this <|-- ecs::World

class rtype::RTypeServer {
    + RTypeServer(unsigned short port = 54321, const std::string libsFolder = "./server")
    + ~RTypeServer()
    + void run()
    - void handleDatagrams()
    - void handleLiveness()
    - void handleLooping()
    - Client &getClientByHost(const b12software::network::HostInfos &host)
    - Client &getClientByUsername(const std::string &username)
    - int isInvalidUsername(const std::string &username)
    - void addNewClient(const Client &client)
    - void updateClientLiveness(const b12software::network::HostInfos &host)
    - void disconnectClient(const Client &client)
    - int isInvalidRoomName(const std::string &name)
    - void createRoom(const std::string &name, unsigned char capacity, bool hasPassword, const std::string &password)
    - void joinRoom(const std::string &roomName, Client &client, const std::string &password = "")
    - void exitRoom(Client &client)
    - void handleRooms()
    - void updateRooms()
    - void cleanRooms()
    - void protocol100ConnectDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol102PingDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol104DisconnectDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol107ClientDisconnectedDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol109NewClientConnectedDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol110GetRoomsDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol112CreateRoomsDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol114QuitRoomsDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol116JoinRoomsDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol200ActionDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol260OkGameEndedDatagramHandler(rtype::network::RTypeDatagram dg)
    - void protocol280OkGameStartedDatagramHandler(rtype::network::RTypeDatagram dg)
    - void unknownDatagramHandler(rtype::network::RTypeDatagram dg)
    - void invalidDatagramHandler(rtype::network::RTypeDatagram dg)
    - void emptyDatagramHandler(rtype::network::RTypeDatagram dg)
    - std::unique_ptr<b12software::network::INetworkManager> _networkManager
    - std::weak_ptr<b12software::network::udp::IUdpSocket> _socket
    - b12software::containers::ThreadSafeList<rtype::Client> _clients
    - std::list<std::shared_ptr<rtype::Room>> _rooms
}

class rtype::exception::RTypeServerException {
    + RTypeServerException(const std::string &what, const std::string &where)
}

class rtype::exception::RTypeUnknownRoomException {
    + RTypeUnknownRoomException(const std::string &what, const std::string &where)
}

class rtype::exception::RTypeRoomAlreadyFullException {
    + RTypeRoomAlreadyFullException(const std::string &what, const std::string &where)
}

class rtype::exception::RTypeInvalidPasswordException {
    + RTypeInvalidPasswordException(const std::string &what, const std::string &where)
}

class rtype::Configuration {
    + Configuration(int nbArgs, char * const *args)
    + Configuration(const Configuration &other)
    + ~Configuration()
    + Configuration &operator=(const Configuration &rhs)
    + bool shouldDisplayHelp() const
    + unsigned short getPort() const
    + std::string &getLibsFolder() const
    + void displayHelp(bool onError = false) const
    + bool hasError() const
    + void displayErrors() const
    - std::string _binaryName
    - std::string _libsFolder
    - bool _help
    - unsigned short _port
    - std::vector<std::string> _errors
}

class rtype::Client {
    + Client()
    + Client(const b12software::network::HostInfos &host, const std::string &username, ClientState state = CS_IN_LOBBY)
    + ~Client()
    + Client(const Client &other)
    + Client &operator=(const Client &rhs)
    + bool operator==(const Client &rhs) const
    + bool operator!=(const Client &rhs) const
    + void setHost(const b12software::network::HostInfos &host)
    + const b12software::network::HostInfos &getHost() const
    + const std::string &getUsername() const
    + void setUsername(const std::string &username)
    + ClientState getClientState() const
    + void setClientState(ClientState state)
    + const TimePoint &getLastReached() const
    + void setLastReached(const TimePoint &lastReached)
    + const TimePoint &getClock(rtype::network::RTypeDatagramType type) const
    + void setClock(rtype::network::RTypeDatagramType type, const TimePoint &clock)
    + const rtype::network::RTypeDatagram &getDatagram(rtype::network::RTypeDatagramType type) const
    + void setDatagram(rtype::network::RTypeDatagramType type, const rtype::network::RTypeDatagram &datagram)
    + std::vector<rtype::network::RTypeDatagramType> getDatagramTypes() const
    + const std::weak_ptr<rtype::Room> &getRoom() const
    + void setRoom(const std::weak_ptr<rtype::Room> &room)
    + void removeRoom()
    - b12software::network::HostInfos _host
    - std::string _username
    - ClientState _state
    - TimePoint _lastReached
    - std::map<rtype::network::RTypeDatagramType, TimePoint> _clocks
    - std::map<rtype::network::RTypeDatagramType, rtype::network::RTypeDatagram> _datagrams
    - std::weak_ptr<rtype::Room> _room
}

enum rtype::ClientState {
    CS_IN_LOBBY
    CS_IN_ROOM
    CS_IN_GAME
}

class rtype::Room {
    + Room(const std::string libsFolder)
    + ~Room()
    + const std::string &getName() const
    + void setName(const std::string &name)
    + unsigned char getCapacity() const
    + void setCapacity(unsigned char capacity)
    + unsigned char getSlotUsed() const
    + void setSlotUsed(unsigned char slotUsed)
    + bool hasPassword() const
    + void setHasPassword(bool hasPassword)
    + const std::string &getPassword() const
    + void setPassword(const std::string &password)
    + bool isGameRunning() const
    + void setGameRunning(bool gameRunning)
    + void addClient(Client &client)
    + void removeClient(const Client &client)
    + void applyToClients(std::function<void(Client &)> func)
    + bool shouldGameRun() const
    + void startGame()
    + void syncGame(std::weak_ptr<b12software::network::udp::IUdpSocket> socket)
    + void setUsernameInputs(const std::string &username, const rtype::network::RTypeDatagramAction &inputs)
    - void endGame()
    - void syncGameOnNetwork(const std::weak_ptr<b12software::network::udp::IUdpSocket>& socket)
    - void syncDisplayLiving(Client &client, const std::weak_ptr<b12software::network::udp::IUdpSocket>& socket, bool living, bool display)
    - void syncScore(Client &client, const std::weak_ptr<b12software::network::udp::IUdpSocket>& socket)
    - void syncCharge(Client &client, const std::weak_ptr<b12software::network::udp::IUdpSocket>& socket)
    - {static} void gameThreadFunc(const std::atomic_bool &shouldGameBeRunning, std::atomic_bool &threadRunning, GameInfos &infos, const std::string libsFolder)
    - std::string _name
    - unsigned char _capacity
    - unsigned char _slotUsed
    - bool _hasPassword
    - std::string _password
    - bool _gameRunning
    - std::vector<std::reference_wrapper<Client>> _clients
    - std::atomic_bool _shouldGameBeRunning
    - GameInfos _gameInfos
    - std::map<std::string, int> _clientPlayerMap
    - std::atomic_bool _threadRunning
    - std::unique_ptr<std::thread> _thread
    - const std::string _libsFolder
}

enum rtype::RTypeEntityType {
    ET_UNKNOWN = 0
    ET_PLAYER_1 = 1
    ET_PLAYER_2 = 2
    ET_PLAYER_3 = 3
    ET_PLAYER_4 = 4
    /*!< Anywhere from 100 - 199 is a basic shot the value indicate its size */
    ET_SHOOT_TYPE_BASIC_BASE = 100
    ET_SHOOT_TYPE_BASIC_MAX = 199
    ET_BONUS_SHOOTING_SPEED_UP = 1000
    ET_BONUS_SHOOTING_SPEED_DOWN = 1001
    ET_BONUS_MOVING_SPEED_UP = 1000
    ET_BONUS_MOVING_SPEED_DOWN = 1001
    /*!< Above this value should be the monsters types */
    ET_MONSTER_TYPE_BASE = 100000
}

class rtype::EntityInfos {
    + EntityInfos(bool hasDisplay = true, bool hasHp = true)
    + ~EntityInfos()
    + EntityInfos(const EntityInfos &other)
    + EntityInfos &operator=(const EntityInfos &rhs)
    + b12software::maths::Vector3D getPosition() const
    + void setPosition(const b12software::maths::Vector3D &position)
    + void setPosition(int x, int y, int z)
    + b12software::maths::Vector2D getRotation() const
    + void setRotation(const b12software::maths::Vector2D &rotation)
    + void setRotation(int x, int y)
    + b12software::maths::Vector2D getScale() const
    + void setScale(const b12software::maths::Vector2D &scale)
    + void setScale(int x, int y)
    + uint32_t getType() const
    + void setType(uint32_t type)
    + uint32_t getHp() const
    + void setHp(uint32_t hp)
    + uint32_t getId() const
    + void setId(uint32_t id)
    # std::atomic_bool _hasDisplay
    # std::atomic_bool _hasHp
    # std::atomic_uint32_t _posX
    # std::atomic_uint32_t _posY
    # std::atomic_uint32_t _posZ
    # std::atomic_uint32_t _rotX
    # std::atomic_uint32_t _rotY
    # std::atomic_uint32_t _scaleX
    # std::atomic_uint32_t _scaleY
    # std::atomic_uint32_t _type
    # std::atomic_uint32_t _hp
    # std::atomic_uint64_t _id
}

class rtype::GameInfos {
    + GameInfos()
    +  ~GameInfos()
    + GameInfos(const GameInfos &other)
    + GameInfos &operator=(const GameInfos &rhs)
    + void reset()
    + int getNbPlayers() const
    + void setNbPlayers(int nbPlayer)
    + PlayerInfos &getPlayer(int nb)
    + const PlayerInfos &getPlayer(int nb) const
    + void setPlayer(int nb, const PlayerInfos &infos)
    + b12software::containers::ThreadSafeList<rtype::EntityInfos> &getEntities()
    + const b12software::containers::ThreadSafeList<rtype::EntityInfos> &getEntities() const
    + void setEntities(const b12software::containers::ThreadSafeList<rtype::EntityInfos> &entities)
    + void addEntity(const rtype::EntityInfos &entity)
    + void removeEntity(uint32_t id)
    + void removeEntity(const rtype::EntityInfos &entity)
    + void removeEntities(const std::function<bool(const rtype::EntityInfos &)> &func)
    + std::weak_ptr<GameInfos> getWeak()
    - std::atomic_int _nbPlayers
    - PlayerInfos _players[4]
    - b12software::containers::ThreadSafeList<rtype::EntityInfos> _entities
}

class rtype::PlayerInfos {
    + PlayerInfos()
    + ~PlayerInfos()
    + PlayerInfos(const PlayerInfos &other)
    + PlayerInfos &operator=(const PlayerInfos &rhs)
    + bool isUsed() const
    + void setIsUsed(bool used)
    + bool isShooting() const
    + void setIsShooting(bool shooting)
    + bool isMovingUp() const
    + void setIsMovingUp(bool movingUp)
    + bool isMovingDown() const
    + void setIsMovingDown(bool movingDown)
    + bool isMovingLeft() const
    + void setIsMovingLeft(bool movingLeft)
    + bool isMovingRight() const
    + void setIsMovingRight(bool movingRight)
    + char getCharge() const
    + void setCharge(char charge)
    + uint32_t getScore() const
    + void setScore(uint32_t score)
    - std::atomic_bool _used
    - std::atomic_bool _shooting
    - std::atomic_bool _movingUp
    - std::atomic_bool _movingDown
    - std::atomic_bool _movingLeft
    - std::atomic_bool _movingRight
    - std::atomic_char _charge
    - std::atomic_uint32_t _score
}

rtype::EntityInfos <|-- rtype::PlayerInfos

b12software::exception::B12SoftwareException <|-- rtype::exception::RTypeServerException

rtype::exception::RTypeServerException <|-- rtype::exception::RTypeInvalidPasswordException
rtype::exception::RTypeServerException <|-- rtype::exception::RTypeRoomAlreadyFullException
rtype::exception::RTypeServerException <|-- rtype::exception::RTypeUnknownRoomException

class ecs::components::DamageableComponent {
    + {static} const ecs::Version Version
    + DamageableComponent(int hp = 3, int maxHp = 3)
    + ~DamageableComponent()
    + DamageableComponent(const DamageableComponent &other)
    + DamageableComponent &operator=(const DamageableComponent &rhs)
    + void setHp(int hp)
    + void setMaxHp(int maxHp)
    + void heal(int amount)
    + void damage(int amount)
    + int getHp() const
    + bool isAlive() const
    + int getMaxHp() const
    + long getInvulnerabilityPeriodAfterDamage() const
    + void setInvulnerabilityPeriodAfterDamage(long invulnerabilityPeriodAfterDamage)
    + long getInvulnerabilityRemaining() const
    + void setInvulnerabilityRemaining(long invulnerabilityRemaining)
    + bool isInvulnerable() const
    + int getDamageLayer() const
    + void setDamageLayer(int damageLayer)
    + int getLastHitOwner() const
    + void setLastHitOwner(int lastHitOwner)
    - int _hp
    - int _maxHp
    - long _invulnerabilityPeriodAfterDamage
    - long _invulnerabilityRemaining
    - int _damageLayer
    - int _lastHitOwner
}

ecs::AComponent <|-- ecs::components::DamageableComponent

class ecs::components::NetworkIdentityComponent {
    + {static} const ecs::Version Version
    + NetworkIdentityComponent(uint32_t id = 0)
    + ~NetworkIdentityComponent()
    + NetworkIdentityComponent(const NetworkIdentityComponent &other)
    + NetworkIdentityComponent &operator=(const NetworkIdentityComponent &rhs)
    + void setNetworkId(uint32_t id)
    + uint32_t getNetworkId() const
    - uint32_t _id
}

ecs::AComponent <|-- ecs::components::NetworkIdentityComponent

class ecs::components::WeaponComponent {
    + {static} const ecs::Version Version
    + WeaponComponent(WeaponType type = WEAPON_TYPE_STANDARD_WAVE_CANON, uint32_t rps = 1)
    + ~WeaponComponent()
    + WeaponComponent(const WeaponComponent &other)
    + WeaponComponent &operator=(const WeaponComponent &rhs)
    + WeaponType getType() const
    + void setType(WeaponType type)
    + uint32_t getRps() const
    + void setRps(uint32_t rps)
    - WeaponType _type
    - uint32_t _rps
}

ecs::AComponent <|-- ecs::components::WeaponComponent

enum ecs::components::WeaponComponent::WeaponType {
    WEAPON_TYPE_STANDARD_WAVE_CANON
}

class ecs::components::ColliderComponent {
    + {static} const ecs::Version Version
    + ColliderComponent(const b12software::maths::Vector2D &size = b12software::maths::Vector2D(1, 1), const b12software::maths::Vector2D &offset = b12software::maths::Vector2D())
    + ~ColliderComponent()
    + ColliderComponent(const ColliderComponent &other)
    + ColliderComponent &operator=(const ColliderComponent &rhs)
    + const b12software::maths::Vector2D &getSize() const
    + void setSize(const b12software::maths::Vector2D &size)
    + const b12software::maths::Vector2D &getOffset() const
    + void setOffset(const b12software::maths::Vector2D &offset)
    - b12software::maths::Vector2D _size
    - b12software::maths::Vector2D _offset
}

ecs::AComponent <|-- ecs::components::ColliderComponent

class ecs::components::RigidbodyComponent {
    + {static} const ecs::Version Version
    + RigidbodyComponent(float ups = 1, const b12software::maths::Vector2D &direction = b12software::maths::Vector2D())
    + ~RigidbodyComponent()
    + RigidbodyComponent(const RigidbodyComponent &other)
    + RigidbodyComponent &operator=(const RigidbodyComponent &other)
    + const b12software::maths::Vector2D &getDirection() const
    + void setDirection(const b12software::maths::Vector2D &direction)
    + float getUps() const
    + void setUps(float ups)
    + bool shouldLookTowardsDirection() const
    + void setLookTowardsDirection(bool lookTowardsDirection)
    - b12software::maths::Vector2D _direction
    - float _ups
    - bool _lookTowardsDirection
}

ecs::AComponent <|-- ecs::components::RigidbodyComponent

class ecs::components::PlayerComponent {
    + {static} const ecs::Version Version
    + PlayerComponent(uint32_t score = 0, uint8_t charge = 0)
    + ~PlayerComponent()
    + PlayerComponent(const PlayerComponent &other)
    + PlayerComponent &operator=(const PlayerComponent &rhs)
    + uint32_t getScore() const
    + void setScore(uint32_t score)
    + float getCharge() const
    + void setCharge(float charge)
    + bool isShotPressed() const
    + void setShotPressed(bool shotPressed)
    + bool isReleased() const
    + void setReleased(bool released)
    - uint32_t _score
    - float _charge
    - bool _shotPressed
    - bool _released
}

ecs::AComponent <|-- ecs::components::PlayerComponent

class ecs::components::DamagerComponent {
    + {static} const ecs::Version Version
    + DamagerComponent(uint32_t damages = 1, bool destroyOnHit = true)
    + ~DamagerComponent()
    + DamagerComponent(const DamagerComponent &other)
    + DamagerComponent &operator=(const DamagerComponent &rhs)
    + uint32_t getDamages() const
    + void setDamages(uint32_t damages)
    + bool isDestroyOnHit() const
    + void setDestroyOnHit(bool destroyOnHit)
    + int getDamageLayer() const
    + void setDamageLayer(int damageLayer)
    + int getOwner() const
    + void setOwner(int owner)
    - uint32_t _damages
    - bool _destroyOnHit
    - int _damageLayer
    - int _owner
}

ecs::AComponent <|-- ecs::components::DamagerComponent

class ecs::components::DisplayableComponent {
    + {static} const ecs::Version Version
    + DisplayableComponent(uint32_t type = rtype::ET_UNKNOWN)
    + ~DisplayableComponent()
    + DisplayableComponent(const DisplayableComponent &other)
    + DisplayableComponent &operator=(const DisplayableComponent &rhs)
    + uint32_t getType() const
    + void setType(uint32_t type)
    - uint32_t _type
}

ecs::AComponent <|-- ecs::components::DisplayableComponent

class ecs::components::PointAwarderComponent {
    + {static} const ecs::Version Version
    + PointAwarderComponent(int points = 500)
    + ~PointAwarderComponent()
    + PointAwarderComponent(const PointAwarderComponent &other)
    + PointAwarderComponent &operator=(const PointAwarderComponent &rhs)
    + int getPoints() const
    + void setPoints(int points)
    - int _points
}

ecs::AComponent <|-- ecs::components::PointAwarderComponent

class systems::MovementSystem {
    + MovementSystem()
    + ~MovementSystem()
    + MovementSystem(const MovementSystem &other)
    + MovementSystem &operator=(const MovementSystem &rhs)
    + {static} const ecs::Version Version
}

ecs::ASystem <|-- systems::MovementSystem

class systems::MovementSystemApi {
    + MovementSystemApi()
    + ~MovementSystemApi()
    + MovementSystemApi(const MovementSystemApi &other)
    + MovementSystemApi &operator=(const MovementSystemApi &rhs)
    + {static} const ecs::Version Version
}

ecs::ISystemAPI <|-- systems::MovementSystemApi

class systems::DamageSystem {
    + DamageSystem()
    + ~DamageSystem()
    + DamageSystem(const DamageSystem &other)
    + DamageSystem &operator=(const DamageSystem &rhs)
    + {static} const ecs::Version Version
    - void computeDamages() const
    - {static} bool collide(const b12software::maths::Vector2D &colAPos, const b12software::maths::Vector2D &colASize, const b12software::maths::Vector2D &colBPos, const b12software::maths::Vector2D &colBSize)
    - long _elapsedTime
    - long _computeEvery
}

ecs::ASystem <|-- systems::DamageSystem

class systems::DamageSystemApi {
    + DamageSystemApi()
    + ~DamageSystemApi()
    + DamageSystemApi(const DamageSystemApi &other)
    + DamageSystemApi &operator=(const DamageSystemApi &rhs)
    + {static} const ecs::Version Version
}

ecs::ISystemAPI <|-- systems::DamageSystemApi

class systems::LifeSystem {
    + LifeSystem()
    + ~LifeSystem()
    + LifeSystem(const LifeSystem &other)
    + LifeSystem &operator=(const LifeSystem &rhs)
    + {static} const ecs::Version Version
}

ecs::ASystem <|-- systems::LifeSystem

class systems::LifeSystemApi {
    + LifeSystemApi()
    + ~LifeSystemApi()
    + LifeSystemApi(const LifeSystemApi &other)
    + LifeSystemApi &operator=(const LifeSystemApi &rhs)
    + {static} const ecs::Version Version
}

ecs::ISystemAPI <|-- systems::LifeSystemApi

class systems::NetworkSyncSystem {
    + NetworkSyncSystem()
    + ~NetworkSyncSystem()
    + NetworkSyncSystem(const NetworkSyncSystem &other)
    + NetworkSyncSystem &operator=(const NetworkSyncSystem &rhs)
    + {static} const ecs::Version Version
    + void setGameInfosPtr(std::weak_ptr<rtype::GameInfos> ptr)
    + bool areGameInfosSet() const
    - std::weak_ptr<rtype::GameInfos> _ptr
    - bool _valid
    - long _elapsedTime
    - long _timeBetweenSync
}

ecs::ASystem <|-- systems::NetworkSyncSystem

class systems::NetworkSyncSystemApi {
    + NetworkSyncSystemApi()
    + ~NetworkSyncSystemApi()
    + NetworkSyncSystemApi(const NetworkSyncSystemApi &other)
    + NetworkSyncSystemApi &operator=(const NetworkSyncSystemApi &rhs)
    + {static} const ecs::Version Version
}

ecs::ISystemAPI <|-- systems::NetworkSyncSystemApi

class systems::WeaponSystem {
    + WeaponSystem()
    + ~WeaponSystem()
    + WeaponSystem(const WeaponSystem &other)
    + WeaponSystem &operator=(const WeaponSystem &rhs)
    + {static} const ecs::Version Version
}

ecs::ASystem <|-- systems::WeaponSystem

class systems::WeaponSystemApi {
    + WeaponSystemApi()
    + ~WeaponSystemApi()
    + WeaponSystemApi(const WeaponSystemApi &other)
    + WeaponSystemApi &operator=(const WeaponSystemApi &rhs)
    + {static} const ecs::Version Version
}

ecs::ISystemAPI <|-- systems::WeaponSystemApi

@enduml
