feat(protocol): add packet serialization and login handling

Introduce packet header and ID mapping for protobuf messages.
Refactor session and server_world to use new packet wrapper.
Fix missing semicolons in proto files.
This commit is contained in:
2026-06-23 21:58:35 +08:00
parent 678fc02998
commit 2953e8a233
9 changed files with 96 additions and 33 deletions

View File

@@ -0,0 +1,59 @@
#pragma once
#include "packet.pb.h"
#include <netinet/in.h>
#include <type_traits>
namespace Cubed {
constexpr int HEADER_LEN = 8;
using Packet = std::shared_ptr<std::vector<uint8_t>>;
template <typename> struct always_false : std::false_type {}; // NOLINT
template <typename T> constexpr uint16_t get_packet_id() {
using std::is_same_v;
using U = std::decay_t<T>;
if constexpr (is_same_v<U, LoginReq>) {
return 1001;
} else if constexpr (is_same_v<U, LoginRsp>) {
return 1002;
} else if constexpr (is_same_v<U, PlayerInfo>) {
return 2001;
} else if constexpr (is_same_v<U, PlayerPos>) {
return 2002;
} else if constexpr (is_same_v<U, ChunkData>) {
return 3001;
} else if constexpr (is_same_v<U, Ping>) {
return 9001;
} else if (is_same_v<U, Pong>) {
return 9002;
} else {
static_assert(always_false<U>::value, "Unkonw Type");
}
}
template <typename T> Packet make_packet(const T& msg) {
std::string body;
if (!msg.SerializeToString(&body)) {
return {};
}
uint16_t cmd = get_packet_id<T>();
uint32_t total_len = HEADER_LEN + body.size();
auto packet = std::make_shared<std::vector<uint8_t>>(total_len);
uint32_t total_len_net = htonl(total_len);
uint16_t cmd_net = htons(cmd);
std::memcpy(packet->data(), &total_len_net, sizeof(total_len_net));
std::memcpy(packet->data() + sizeof(total_len_net), &cmd_net,
sizeof(cmd_net));
std::memcpy(packet->data() + HEADER_LEN, body.data(), body.size());
return packet;
}
} // namespace Cubed

View File

@@ -7,15 +7,16 @@
#include "Cubed/gameplay/server_chunk.hpp"
#include "Cubed/gameplay/server_player.hpp"
#include "Cubed/tools/thread_pool.hpp"
#include "proto/player_request.pb.h"
#include <future>
#include <shared_mutex>
#include <tbb/concurrent_hash_map.h>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>
namespace Cubed {
class Session;
class ServerWorld {
public:
ServerWorld();
@@ -64,7 +65,8 @@ public:
void set_block(const glm::ivec3& block_pos, unsigned id);
void sync_player_pos(const std::string& name, float x, float y, float z);
void handle_player_request(const PlayerRequest& request);
void handle_player_login(const std::string& player_name,
std::shared_ptr<Session> session);
glm::vec3 get_player_pos(const std::string& name) const;
private:
@@ -119,6 +121,9 @@ private:
std::optional<std::string> m_request_gen_name = std::nullopt;
tbb::concurrent_hash_map<std::string, std::shared_ptr<Session>>
m_player_session;
void init_chunks();
void gen_chunks_internal();

View File

@@ -1,10 +1,13 @@
#pragma once
#include "Cubed/gameplay/packet.hpp"
#include <asio.hpp>
#include <deque>
#include <memory>
#include <string>
namespace Cubed {
using asio::ip::tcp;
class ServerWorld;
class Session : public std::enable_shared_from_this<Session> {
@@ -13,16 +16,15 @@ public:
Session(tcp::socket socket, ServerWorld& server_world);
~Session();
void start();
void send(std::shared_ptr<std::vector<uint8_t>> packet);
void send(Packet packet);
void close();
const std::string& uuid() const;
private:
static constexpr int HEADER_LEN = 8;
static constexpr uint32_t MAX_PACKET_SIZE = 4 * 1024 * 1024;
tcp::socket m_socket;
std::vector<char> m_read_buffer;
std::deque<std::shared_ptr<std::vector<uint8_t>>> m_write_queue;
std::deque<Packet> m_write_queue;
asio::strand<asio::io_context::executor_type> m_strand;
std::string m_uuid;
ServerWorld& m_server_world;