feat(gameplay): add Session class and UUID generation utility

This commit is contained in:
2026-06-23 15:54:01 +08:00
parent 27e3cd6851
commit 1acfeef9e6
4 changed files with 135 additions and 0 deletions

View File

@@ -147,6 +147,7 @@ add_executable(${PROJECT_NAME}
src/gameplay/client_chunk.cpp
src/gameplay/server_player.cpp
src/gameplay/client_player.cpp
src/gameplay/session.cpp
)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")

View File

@@ -0,0 +1,33 @@
#pragma once
#include <asio.hpp>
#include <deque>
#include <memory>
#include <string>
namespace Cubed {
using asio::ip::tcp;
class Session : public std::enable_shared_from_this<Session> {
public:
Session(tcp::socket socket);
~Session();
void start();
void send();
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::vector<char>> m_write_queue;
std::mutex m_write_mutex;
std::string m_uuid;
asio::awaitable<void> read();
asio::awaitable<void> write();
};
} // namespace Cubed

View File

@@ -0,0 +1,42 @@
#pragma once
#include <array>
#include <chrono>
#include <cstdint>
#include <iomanip>
#include <iostream>
#include <random>
#include <sstream>
#include <string>
namespace Cubed {
inline std::string generate_uuid() {
static std::mt19937_64 rng(
std::chrono::steady_clock::now().time_since_epoch().count() ^
(std::random_device{}()));
std::uniform_int_distribution<uint64_t> dist(0, UINT64_MAX);
uint64_t a = dist(rng);
uint64_t b = dist(rng);
std::array<uint8_t, 16> bytes{};
for (int i = 0; i < 8; ++i) {
bytes[i] = (a >> (56 - 8 * i)) & 0xFF;
bytes[8 + i] = (b >> (56 - 8 * i)) & 0xFF;
}
bytes[6] = (bytes[6] & 0x0F) | 0x40;
bytes[8] = (bytes[8] & 0x3F) | 0x80;
std::ostringstream ss;
ss << std::hex << std::setfill('0');
for (size_t i = 0; i < bytes.size(); ++i) {
if (i == 4 || i == 6 || i == 8 || i == 10) {
ss << '-';
}
ss << std::setw(2) << static_cast<int>(bytes[i]);
}
return ss.str();
}
} // namespace Cubed

59
src/gameplay/session.cpp Normal file
View File

@@ -0,0 +1,59 @@
#include "Cubed/gameplay/session.hpp"
#include "Cubed/tools/log.hpp"
#include "Cubed/tools/uuid.hpp"
using asio::ip::tcp;
namespace Cubed {
Session::Session(tcp::socket socket)
: m_socket(std::move(socket)), m_uuid(generate_uuid()) {}
Session::~Session() {}
void Session::start() {
auto self = shared_from_this();
asio::co_spawn(
m_socket.get_executor(),
[self]() -> asio::awaitable<void> { co_await self->read(); },
asio::detached);
}
const std::string& Session::uuid() const { return m_uuid; }
asio::awaitable<void> Session::read() {
try {
while (true) {
std::array<char, HEADER_LEN> header;
co_await asio::async_read(m_socket, asio::buffer(header),
asio::use_awaitable);
uint32_t total_len_net;
std::memcpy(&total_len_net, header.data(), sizeof(total_len_net));
uint32_t total_len = ntohl(total_len_net);
uint16_t cmd_id_net;
std::memcpy(&cmd_id_net, header.data() + 4, sizeof(cmd_id_net));
uint16_t cmd_id = ntohs(cmd_id_net);
if (total_len < HEADER_LEN || total_len > MAX_PACKET_SIZE) {
throw std::runtime_error("invalid packet length");
}
uint32_t body_len = total_len - HEADER_LEN;
std::vector<char> body_data(body_len);
if (body_len > 0) {
co_await asio::async_read(m_socket, asio::buffer(body_data),
asio::use_awaitable);
}
if (cmd_id == 1001) {
}
}
} catch (const asio::system_error& e) {
Logger::warn("Catch Asio Error {}", e.what());
close();
} catch (...) {
Logger::error("Unknow Error");
}
}
} // namespace Cubed