Commit 4787a387 authored by Matěj Toul's avatar Matěj Toul
Browse files

Merge branch 'xtoul/lowlevel-audio-final' of...

Merge branch 'xtoul/lowlevel-audio-final' of https://gitlab.fi.muni.cz/gamedev/age/libraries into xtoul/lowlevel-audio-final
parents 007ad073 9657b767
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
#pragma once
#include <com/runner.hpp>
#include <net/types.hpp>
#include <net/socket/isocket.hpp>
#include <span>


namespace net
{
    struct Driver final : public com::Runner
    {
        const ConnectionId SERVER_ID = 0;
        static inline std::string self_name() { return "driver"; }

        Driver();
        ~Driver() override;

        void next_round() override;

        bool start_server(int port, int max_connections);
        bool start_client(std::string address, int port);
        SendResult send(
            ConnectionId peer, std::span<const uint8_t> data,
            ReliabilityMode reliability = ReliabilityMode::UNRELIABLE,
            OrderingMode ordering = OrderingMode::UNORDERED,
            int channel = 0);
        SendResult broadcast(
            std::span<const uint8_t> data,
            ReliabilityMode reliability = ReliabilityMode::UNRELIABLE,
            OrderingMode ordering = OrderingMode::UNORDERED,
            int channel = 0);

        void register_on_connected(const std::function<void()>& callback);
        void register_on_disconnected(const std::function<void()>& callback);
        void register_on_peer_connected(const std::function<void(ConnectionId)>& callback);
        void register_on_peer_disconnected(const std::function<void(ConnectionId)>& callback);

        SocketMode mode() const { return socket->get_mode(); }
        ConnectionStatus status() const { return socket->get_status(); }

    private:
        void initialize() override;

        void add_connection(ConnectionId connection);
        void remove_connection(ConnectionId connection);

        void handle_packet(ConnectionId from, NetworkMessage* message);

        std::unique_ptr<ISocket> socket;
        std::unordered_map<ConnectionId, Connection> connections;
    };
}
+34 −0
Original line number Diff line number Diff line
#pragma once
#include <com/context.hpp>
#include <net/driver.hpp>

namespace net
{
    struct RPCSystem;
    struct Index final
    {
        static Index const &instance();

        com::Folder* root() const { return m_root; }
        Driver* driver() const { return m_driver; }
        RPCSystem* rpc_system() const { return m_rpc_system; }

      private:
        Index();
        Index(Index const &) = delete;
        Index(Index &&) = delete;
        Index &operator=(Index const &) const = delete;
        Index &operator=(Index &&) const = delete;

        com::Folder* m_root;
        Driver* m_driver;
        RPCSystem* m_rpc_system;
    };

    inline Index const &index() { return Index::instance(); }

    inline com::Folder* root() { return index().root(); }
    inline Driver* driver() { return index().driver(); }
    inline RPCSystem* rpc_system() { return index().rpc_system(); }

}
+101 −0
Original line number Diff line number Diff line
#pragma once
#include <string>
#include <vector>
#include <com/context.hpp>
#include <com/library.hpp>
#include <net/index.hpp>
#include <net/types.hpp>
#include <utils/serialization.hpp>

namespace net
{
    struct RPCSystem : com::Library
    {
        const ConnectionId BROADCAST_ID = static_cast<uint32_t>(-1);
        static inline std::string self_name() { return "rpc_system.lib"; }

        RPCSystem();
        ~RPCSystem() override;

        /**
         * @brief Processes an incoming RPC packet, deserializes it, and calls the appropriate local function.
         * Should not be called directly, only by the NetDriver when receiving an RPC packet.
         */
        void process_packet(ConnectionId from, utils::Deserializer& deserializer);

        void call_remote(
            com::ContextItem* context_item,
            const std::string& method_name,
            ConnectionId target,
            ReliabilityMode reliability,
            const std::vector<com::Reflection::ValuePtr>& params);

        template<typename... Args>
        void call_remote(
            com::ContextItem* context_item,
            const std::string& method_name,
            ConnectionId target,
            ReliabilityMode reliability,
            Args&&... args)
        {

            std::vector<com::Reflection::ValuePtr> params;
            params.reserve(sizeof...(args));
            (params.push_back(make_reflection_value(std::forward<Args>(args))), ...); // Convert each argument to a ValuePtr and add to params vector

            call_remote(context_item, method_name, target, reliability,
                static_cast<const std::vector<com::Reflection::ValuePtr>&>(params));
        }


    private:
        void register_functions() override;

        std::vector<uint8_t> create_packet(
            com::ContextItem* context_item,
            std::string const& function_name,
            const std::vector<std::shared_ptr<com::Reflection::Value>>& params,
            int& written_bytes);

        void call_function_local(
            std::vector<std::string> const& context_item_path,
            std::string const& function_name,
            utils::Deserializer& deserializer,
            ConnectionId from_id);

        template<typename T>
        static com::Reflection::ValuePtr make_reflection_value(const T& val)
        {
            if constexpr (std::is_same_v<T, int>)
            {
                return com::make_value<com::Reflection::ValueINT>(val);
            } else if constexpr (std::is_same_v<T, float>)
            {
                return com::make_value<com::Reflection::ValueFLOAT>(val);
            } else if constexpr (std::is_same_v<T, bool>)
            {
                return com::make_value<com::Reflection::ValueBOOL>(val);
            } else if constexpr (std::is_same_v<T, std::string>)
            {
                return com::make_value<com::Reflection::ValueSTRING>(val);
            } else if constexpr (std::is_same_v<std::decay_t<T>, const char*> ||
                                 std::is_same_v<std::decay_t<T>, char*> ||
                                 std::is_array_v<std::remove_reference_t<T>>)
            {
                return com::make_value<com::Reflection::ValueSTRING>(std::string(val));
            } else if constexpr (std::is_same_v<T, vec2>)
            {
                return com::make_value<com::Reflection::ValueVEC2>(val);
            } else if constexpr (std::is_same_v<T, vec3>)
            {
                return com::make_value<com::Reflection::ValueVEC3>(val);
            } else if constexpr (std::is_same_v<T, vec2i>)
            {
                return com::make_value<com::Reflection::ValueVEC2I>(val);
            } else
            {
                throw std::runtime_error("Unsupported type for reflection value creation");
            }
        }
    };
}
+1 −1
Original line number Diff line number Diff line
@@ -3,7 +3,7 @@
#include <string>
#include <span>
#include <vector>
#include <net/network_types.hpp>
#include <net/types.hpp>

namespace net
{
+17 −1
Original line number Diff line number Diff line
@@ -5,6 +5,16 @@ namespace net
{
    typedef uint32_t ConnectionId;

    struct Connection
    {
        ConnectionId id = 0;
        bool active = false;
        double rtt = 0.0;

        Connection() = default;
        explicit Connection(const ConnectionId id) : id(id) {}
    };

    struct NetworkMessage
    {
        ConnectionId sender;
@@ -12,6 +22,11 @@ namespace net
        int channel;
    };

    enum class PacketType : uint8_t
    {
        RPC
    };

    enum class SocketMode : uint8_t
    {
        SERVER,
@@ -25,7 +40,8 @@ namespace net
        NOT_CONNECTED,
        MESSAGE_TOO_LARGE,
        BUFFER_FULL,
        PEER_NOT_FOUND
        PEER_NOT_FOUND,
        BROADCAST_INCOMPLETE
    };

    enum class ReliabilityMode : uint8_t
Loading