mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-09 02:07:04 +08:00
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:
@@ -158,6 +158,7 @@ protobuf_generate(
|
|||||||
TARGET ${PROJECT_NAME}
|
TARGET ${PROJECT_NAME}
|
||||||
LANGUAGE cpp
|
LANGUAGE cpp
|
||||||
PROTOS ${PROTO_FILES}
|
PROTOS ${PROTO_FILES}
|
||||||
|
IMPORT_DIRS ${CMAKE_CURRENT_SOURCE_DIR}/src/proto
|
||||||
)
|
)
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||||
message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}")
|
message(STATUS "Building with AddressSanitizer enabled for target: ${PROJECT_NAME}")
|
||||||
@@ -190,7 +191,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||||
|
target_include_directories(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
||||||
ASIO_STANDALONE
|
ASIO_STANDALONE
|
||||||
ASIO_NO_DEPRECATED
|
ASIO_NO_DEPRECATED
|
||||||
|
|||||||
59
include/Cubed/gameplay/packet.hpp
Normal file
59
include/Cubed/gameplay/packet.hpp
Normal 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
|
||||||
@@ -7,15 +7,16 @@
|
|||||||
#include "Cubed/gameplay/server_chunk.hpp"
|
#include "Cubed/gameplay/server_chunk.hpp"
|
||||||
#include "Cubed/gameplay/server_player.hpp"
|
#include "Cubed/gameplay/server_player.hpp"
|
||||||
#include "Cubed/tools/thread_pool.hpp"
|
#include "Cubed/tools/thread_pool.hpp"
|
||||||
#include "proto/player_request.pb.h"
|
|
||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <shared_mutex>
|
#include <shared_mutex>
|
||||||
|
#include <tbb/concurrent_hash_map.h>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
class Session;
|
||||||
class ServerWorld {
|
class ServerWorld {
|
||||||
public:
|
public:
|
||||||
ServerWorld();
|
ServerWorld();
|
||||||
@@ -64,7 +65,8 @@ public:
|
|||||||
void set_block(const glm::ivec3& block_pos, unsigned id);
|
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 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;
|
glm::vec3 get_player_pos(const std::string& name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -119,6 +121,9 @@ private:
|
|||||||
|
|
||||||
std::optional<std::string> m_request_gen_name = std::nullopt;
|
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 init_chunks();
|
||||||
|
|
||||||
void gen_chunks_internal();
|
void gen_chunks_internal();
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "Cubed/gameplay/packet.hpp"
|
||||||
|
|
||||||
#include <asio.hpp>
|
#include <asio.hpp>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
|
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
class ServerWorld;
|
class ServerWorld;
|
||||||
class Session : public std::enable_shared_from_this<Session> {
|
class Session : public std::enable_shared_from_this<Session> {
|
||||||
@@ -13,16 +16,15 @@ public:
|
|||||||
Session(tcp::socket socket, ServerWorld& server_world);
|
Session(tcp::socket socket, ServerWorld& server_world);
|
||||||
~Session();
|
~Session();
|
||||||
void start();
|
void start();
|
||||||
void send(std::shared_ptr<std::vector<uint8_t>> packet);
|
void send(Packet packet);
|
||||||
void close();
|
void close();
|
||||||
const std::string& uuid() const;
|
const std::string& uuid() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static constexpr int HEADER_LEN = 8;
|
|
||||||
static constexpr uint32_t MAX_PACKET_SIZE = 4 * 1024 * 1024;
|
static constexpr uint32_t MAX_PACKET_SIZE = 4 * 1024 * 1024;
|
||||||
tcp::socket m_socket;
|
tcp::socket m_socket;
|
||||||
std::vector<char> m_read_buffer;
|
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;
|
asio::strand<asio::io_context::executor_type> m_strand;
|
||||||
std::string m_uuid;
|
std::string m_uuid;
|
||||||
ServerWorld& m_server_world;
|
ServerWorld& m_server_world;
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "Cubed/gameplay/server_world.hpp"
|
#include "Cubed/gameplay/server_world.hpp"
|
||||||
|
|
||||||
#include "Cubed/config.hpp"
|
#include "Cubed/config.hpp"
|
||||||
|
#include "Cubed/gameplay/packet.hpp"
|
||||||
|
#include "Cubed/gameplay/session.hpp"
|
||||||
#include "Cubed/tools/cubed_assert.hpp"
|
#include "Cubed/tools/cubed_assert.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
|
|
||||||
@@ -357,17 +359,14 @@ void ServerWorld::sync_player_pos(const std::string& name, float x, float y,
|
|||||||
it->second.update_pos(x, y, z);
|
it->second.update_pos(x, y, z);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerWorld::handle_player_request(const PlayerRequest& request) {
|
void ServerWorld::handle_player_login(const std::string& name,
|
||||||
if (request.join()) {
|
std::shared_ptr<Session> session) {
|
||||||
player_join(request.name());
|
player_join(name);
|
||||||
}
|
m_player_session.emplace(name, session);
|
||||||
if (request.exit()) {
|
LoginRsp rsp;
|
||||||
player_exit(request.name());
|
rsp.set_success(true);
|
||||||
}
|
rsp.set_uuid(name);
|
||||||
if (request.chunk_send()) {
|
session->send(make_packet(name));
|
||||||
m_request_gen_name = request.name();
|
|
||||||
need_gen();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerWorld::player_join(const std::string& name) {
|
void ServerWorld::player_join(const std::string& name) {
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
#include "Cubed/gameplay/server_world.hpp"
|
#include "Cubed/gameplay/server_world.hpp"
|
||||||
#include "Cubed/tools/log.hpp"
|
#include "Cubed/tools/log.hpp"
|
||||||
#include "Cubed/tools/uuid.hpp"
|
#include "Cubed/tools/uuid.hpp"
|
||||||
#include "proto/player_pos.pb.h"
|
|
||||||
#include "proto/player_request.pb.h"
|
|
||||||
using asio::ip::tcp;
|
using asio::ip::tcp;
|
||||||
|
|
||||||
namespace Cubed {
|
namespace Cubed {
|
||||||
@@ -61,20 +59,8 @@ asio::awaitable<void> Session::read_loop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmd_id == 1001) {
|
if (cmd_id == 1001) {
|
||||||
PlayerRequest player_request;
|
|
||||||
if (player_request.ParseFromArray(body_data.data(),
|
|
||||||
body_data.size())) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (cmd_id == 1002) {
|
if (cmd_id == 1002) {
|
||||||
PlayerPos player_pos;
|
|
||||||
if (player_pos.ParseFromArray(body_data.data(),
|
|
||||||
body_data.size())) {
|
|
||||||
m_server_world.sync_player_pos(
|
|
||||||
player_pos.name(), player_pos.x(), player_pos.y(),
|
|
||||||
player_pos.z());
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const asio::system_error& e) {
|
} catch (const asio::system_error& e) {
|
||||||
|
|||||||
11
src/proto/packet.proto
Normal file
11
src/proto/packet.proto
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
import "common/chunk_pos.proto";
|
||||||
|
import "common/error.proto";
|
||||||
|
import "common/player_info.proto";
|
||||||
|
import "common/vector3.proto";
|
||||||
|
import "player/player.proto";
|
||||||
|
import "auth/auth.proto";
|
||||||
|
import "system/ping.proto";
|
||||||
|
import "system/pong.proto";
|
||||||
|
import "world/chunk_data.proto";
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "common/vector3.proto"
|
import "common/vector3.proto";
|
||||||
|
|
||||||
message PlayerPos {
|
message PlayerPos {
|
||||||
string uuid = 1;
|
string uuid = 1;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
import "common/chunk_pos.proto"
|
import "common/chunk_pos.proto";
|
||||||
|
|
||||||
message ChunkData {
|
message ChunkData {
|
||||||
ChunkPos pos = 1;
|
ChunkPos pos = 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user