#1 - quicr module
This commit is contained in:
@@ -24,6 +24,7 @@ target_link_libraries(${PROJECT_NAME}
|
||||
PUBLIC
|
||||
glm::glm
|
||||
protobuf::libprotobuf
|
||||
tw::message_protocol
|
||||
)
|
||||
|
||||
target_include_directories(${PROJECT_NAME}
|
||||
|
||||
@@ -11,3 +11,7 @@ message EntitySpawnMessage {
|
||||
message EntityDespawnMessage {
|
||||
uint32 entity_id = 1;
|
||||
}
|
||||
|
||||
message SetControlledEntity {
|
||||
uint32 entity_id = 1;
|
||||
}
|
||||
|
||||
@@ -7,10 +7,17 @@
|
||||
#include "PlayerMove.pb.h"
|
||||
#include "Entity.pb.h"
|
||||
|
||||
#include "message_protocol/MessageType.hpp"
|
||||
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
#include <string_view>
|
||||
|
||||
enum PacketType {
|
||||
namespace tw {
|
||||
|
||||
/**
|
||||
* Every address this application assigns, and the message that travels to it.
|
||||
*/
|
||||
enum MessageType : msg::MessageType {
|
||||
MESSAGE_PACKET,
|
||||
LOGIN_REQUEST_MSG,
|
||||
LOGIN_RESPONSE_PACKET,
|
||||
@@ -33,9 +40,11 @@ enum PacketType {
|
||||
|
||||
CLUSTER_ZONE_HELLO,
|
||||
CLUSTER_ZONE_BYE,
|
||||
|
||||
SET_CONTROLLED_ENTITY_MSG,
|
||||
};
|
||||
|
||||
namespace tw {
|
||||
|
||||
template<typename Msg>
|
||||
class Message;
|
||||
|
||||
@@ -43,99 +52,107 @@ class Message;
|
||||
template<>
|
||||
class Message<mmo::LoginRequest> {
|
||||
public:
|
||||
static constexpr PacketType value = LOGIN_REQUEST_MSG;
|
||||
static constexpr MessageType value = LOGIN_REQUEST_MSG;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::LoginResponse> {
|
||||
public:
|
||||
static constexpr PacketType value = LOGIN_RESPONSE_PACKET;
|
||||
static constexpr MessageType value = LOGIN_RESPONSE_PACKET;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::WorldStateMessage> {
|
||||
public:
|
||||
static constexpr PacketType value = WORLD_STATE_PACKET;
|
||||
static constexpr MessageType value = WORLD_STATE_PACKET;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::PlayerMoveMessage> {
|
||||
public:
|
||||
static constexpr PacketType value = PLAYER_UPDATE_MSG;
|
||||
static constexpr MessageType value = PLAYER_UPDATE_MSG;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::EntitySpawnMessage> {
|
||||
public:
|
||||
static constexpr PacketType value = ENTITY_SPAWN_MSG;
|
||||
static constexpr MessageType value = ENTITY_SPAWN_MSG;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::EntityDespawnMessage> {
|
||||
public:
|
||||
static constexpr PacketType value = ENTITY_DESPAWN_MSG;
|
||||
static constexpr MessageType value = ENTITY_DESPAWN_MSG;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::SetControlledEntity> {
|
||||
public:
|
||||
static constexpr MessageType value = SET_CONTROLLED_ENTITY_MSG;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::SendChatMessageRequest> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_SEND_MESSAGE_REQUEST;
|
||||
static constexpr MessageType value = CHAT_SEND_MESSAGE_REQUEST;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::SendChatMessageResponse> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_SEND_MESSAGE_RESPONSE;
|
||||
static constexpr MessageType value = CHAT_SEND_MESSAGE_RESPONSE;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::JoinChannelRequest> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_JOIN_CHANNEL_REQUEST;
|
||||
static constexpr MessageType value = CHAT_JOIN_CHANNEL_REQUEST;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::JoinChannelResponse> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_JOIN_CHANNEL_RESPONSE;
|
||||
static constexpr MessageType value = CHAT_JOIN_CHANNEL_RESPONSE;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::LeaveChannelRequest> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_LEAVE_CHANNEL_REQUEST;
|
||||
static constexpr MessageType value = CHAT_LEAVE_CHANNEL_REQUEST;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::LeaveChannelResponse> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_LEAVE_CHANNEL_RESPONSE;
|
||||
static constexpr MessageType value = CHAT_LEAVE_CHANNEL_RESPONSE;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::chat::ChatMessageBroadcastRequest> {
|
||||
public:
|
||||
static constexpr PacketType value = CHAT_MESSAGE_BROADCAST_REQUEST;
|
||||
static constexpr MessageType value = CHAT_MESSAGE_BROADCAST_REQUEST;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::cluster::ZoneHello> {
|
||||
public:
|
||||
static constexpr PacketType value = CLUSTER_ZONE_HELLO;
|
||||
static constexpr MessageType value = CLUSTER_ZONE_HELLO;
|
||||
};
|
||||
|
||||
template<>
|
||||
class Message<mmo::cluster::ZoneBye> {
|
||||
public:
|
||||
static constexpr PacketType value = CLUSTER_ZONE_BYE;
|
||||
static constexpr MessageType value = CLUSTER_ZONE_BYE;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
struct fmt::formatter<PacketType> : fmt::formatter<std::string_view> {
|
||||
auto format(PacketType type, fmt::format_context& ctx) const {
|
||||
struct fmt::formatter<tw::MessageType> : fmt::formatter<std::string_view> {
|
||||
auto format(tw::MessageType type, fmt::format_context& ctx) const {
|
||||
using enum tw::MessageType;
|
||||
|
||||
std::string_view name;
|
||||
switch (type) {
|
||||
case MESSAGE_PACKET: name = "MESSAGE_PACKET"; break;
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#pragma once
|
||||
|
||||
#include "MessageRegistry.hpp"
|
||||
|
||||
#include "message_protocol/MessageConnection.hpp"
|
||||
#include "message_protocol/MessageEndpoint.hpp"
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <functional>
|
||||
#include <span>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace tw {
|
||||
|
||||
/**
|
||||
* Sends and receives protobuf messages over an endpoint.
|
||||
*
|
||||
* A view rather than an owner: several of these may share one endpoint, and
|
||||
* messages encoded some other way can travel over it at the same time.
|
||||
*/
|
||||
class ProtobufMessages {
|
||||
msg::MessageEndpoint* m_endpoint;
|
||||
|
||||
// Reused between sends so a steady stream of messages does not allocate.
|
||||
std::vector<std::byte> m_buffer;
|
||||
|
||||
template<typename T>
|
||||
bool serialize(const T& message) {
|
||||
m_buffer.resize(message.ByteSizeLong());
|
||||
return message.SerializeToArray(m_buffer.data(), static_cast<int>(m_buffer.size()));
|
||||
}
|
||||
|
||||
public:
|
||||
explicit ProtobufMessages(msg::MessageEndpoint* endpoint) :
|
||||
m_endpoint(endpoint) {
|
||||
}
|
||||
|
||||
/** Calls `handler` for every T that arrives from any peer. */
|
||||
template<typename T>
|
||||
void set_handler(std::function<void(msg::PeerId, const T&)> handler) {
|
||||
m_endpoint->set_handler(
|
||||
Message<T>::value,
|
||||
[handler = std::move(handler), message = T{}](msg::PeerId peer,
|
||||
std::span<const std::byte> body) mutable {
|
||||
if(!message.ParseFromArray(body.data(), static_cast<int>(body.size()))) {
|
||||
spdlog::warn("Failed to parse a {} of {} bytes", Message<T>::value, body.size());
|
||||
return;
|
||||
}
|
||||
|
||||
handler(peer, message);
|
||||
});
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
tl::expected<void, msg::MessageError> send(msg::MessageConnection* peer,
|
||||
const T& message,
|
||||
bool reliable = true) {
|
||||
if(!serialize(message)) {
|
||||
return tl::make_unexpected(
|
||||
msg::MessageError(msg::MessageErrorType::SendFailed, "failed to serialize the message"));
|
||||
}
|
||||
|
||||
return peer->send(Message<T>::value, m_buffer, reliable);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
tl::expected<void, msg::MessageError> send_to(msg::PeerId id, const T& message, bool reliable = true) {
|
||||
auto* peer = m_endpoint->peer(id);
|
||||
if(peer == nullptr) {
|
||||
return tl::make_unexpected(msg::MessageError(msg::MessageErrorType::NotConnected));
|
||||
}
|
||||
|
||||
return send(peer, message, reliable);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void broadcast(const T& message, bool reliable = false) {
|
||||
if(!serialize(message)) {
|
||||
spdlog::error("Failed to serialize a {} for broadcast", Message<T>::value);
|
||||
return;
|
||||
}
|
||||
|
||||
for(auto* peer : m_endpoint->peers()) {
|
||||
auto send_r = peer->send(Message<T>::value, m_buffer, reliable);
|
||||
if(!send_r) {
|
||||
spdlog::error("Failed to send to peer {}: {}", peer->peer_id(), send_r.error().message());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include "Serialization.hpp"
|
||||
#include "packets/Packet.hpp"
|
||||
#include "Serializers.hpp"
|
||||
#include "GlmSerializers.hpp"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Serializers.hpp"
|
||||
#include "packets/Packet.hpp"
|
||||
|
||||
struct PlayerUpdate {
|
||||
uint32_t id;
|
||||
|
||||
Reference in New Issue
Block a user