mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(gameplay): implement entity update packets
Add S2CEntityUpdate to sync entity positions from server to client, including update handling in the client entity manager and server-side AI updates.
This commit is contained in:
@@ -10,14 +10,15 @@ namespace Cubed {
|
|||||||
class ClientWorld;
|
class ClientWorld;
|
||||||
class ClientEntityManager {
|
class ClientEntityManager {
|
||||||
public:
|
public:
|
||||||
enum class Command { CREATE, DESTORY };
|
enum class Command { CREATE, DESTORY, UPDATE };
|
||||||
|
|
||||||
ClientEntityManager(ClientWorld& world);
|
ClientEntityManager(ClientWorld& world);
|
||||||
void update();
|
void update();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void receive_entity_create(S2CEntityCreate& s2c);
|
void receive_entity_create(S2CEntityCreate& msg);
|
||||||
void receive_entity_destory(EntityID id);
|
void receive_entity_destory(EntityID id);
|
||||||
|
void receive_entity_update(S2CEntityUpdate& msg);
|
||||||
|
|
||||||
void destory(EntityID id);
|
void destory(EntityID id);
|
||||||
void create(std::string_view name, const glm::vec3& pos);
|
void create(std::string_view name, const glm::vec3& pos);
|
||||||
@@ -30,11 +31,17 @@ private:
|
|||||||
std::string name;
|
std::string name;
|
||||||
glm::vec3 pos;
|
glm::vec3 pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct UpdateInfo {
|
||||||
|
EntityID id;
|
||||||
|
glm::vec3 pos;
|
||||||
|
};
|
||||||
|
|
||||||
using EntityMap = tbb::concurrent_hash_map<EntityID, entt::entity>;
|
using EntityMap = tbb::concurrent_hash_map<EntityID, entt::entity>;
|
||||||
using acc = EntityMap::accessor;
|
using acc = EntityMap::accessor;
|
||||||
using cacc = EntityMap::const_accessor;
|
using cacc = EntityMap::const_accessor;
|
||||||
using CreateFunc = std::function<void(EntityID id)>;
|
using CreateFunc = std::function<void(EntityID id)>;
|
||||||
using TaskElement = std::variant<EntityCreateElement, EntityID>;
|
using TaskElement = std::variant<EntityCreateElement, EntityID, UpdateInfo>;
|
||||||
using TaskPair = std::pair<Command, TaskElement>;
|
using TaskPair = std::pair<Command, TaskElement>;
|
||||||
|
|
||||||
ClientWorld& m_world;
|
ClientWorld& m_world;
|
||||||
@@ -48,6 +55,7 @@ private:
|
|||||||
// not thread safe
|
// not thread safe
|
||||||
void handle_entity_create(EntityID id, std::string_view name,
|
void handle_entity_create(EntityID id, std::string_view name,
|
||||||
const glm::vec3& pos);
|
const glm::vec3& pos);
|
||||||
|
void handle_entity_update(UpdateInfo& info);
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
void create_entity_in_registry(EntityID id, Args&&... args) {
|
void create_entity_in_registry(EntityID id, Args&&... args) {
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -51,10 +51,12 @@ enum class PacketEnum : uint16_t {
|
|||||||
LOGIN_RSP = 1002,
|
LOGIN_RSP = 1002,
|
||||||
LOGOUT_REQ = 1003,
|
LOGOUT_REQ = 1003,
|
||||||
LOGOUT_RSP = 1004,
|
LOGOUT_RSP = 1004,
|
||||||
|
|
||||||
PLAYER_INFO = 2001,
|
PLAYER_INFO = 2001,
|
||||||
C2S_PLAYER_INFO = 2002,
|
C2S_PLAYER_INFO = 2002,
|
||||||
PLAYER_INFO_RSP = 2003,
|
PLAYER_INFO_RSP = 2003,
|
||||||
PLAYER_WATER_SOUND = 2004,
|
PLAYER_WATER_SOUND = 2004,
|
||||||
|
|
||||||
CHUNK_DATA_REQ = 3001,
|
CHUNK_DATA_REQ = 3001,
|
||||||
CHUNK_DATA_RSP = 3002,
|
CHUNK_DATA_RSP = 3002,
|
||||||
BLOCK_CHANGE_REQ = 3003,
|
BLOCK_CHANGE_REQ = 3003,
|
||||||
@@ -65,8 +67,11 @@ enum class PacketEnum : uint16_t {
|
|||||||
S2C_ENTITY_DESTORY = 3008,
|
S2C_ENTITY_DESTORY = 3008,
|
||||||
C2S_ENTITY_CREATE_REQUEST = 3009,
|
C2S_ENTITY_CREATE_REQUEST = 3009,
|
||||||
C2S_ENTITY_DESTORY_REQUEST = 3010,
|
C2S_ENTITY_DESTORY_REQUEST = 3010,
|
||||||
|
S2C_ENTITY_UPDATE = 3011,
|
||||||
|
|
||||||
CHAT_MSG = 4001,
|
CHAT_MSG = 4001,
|
||||||
VOICE_MSG = 4002,
|
VOICE_MSG = 4002,
|
||||||
|
|
||||||
PING = 9001,
|
PING = 9001,
|
||||||
PONG = 9002
|
PONG = 9002
|
||||||
|
|
||||||
@@ -145,6 +150,9 @@ template <> constexpr uint16_t get_packet_id<ChatMsg>() {
|
|||||||
template <> constexpr uint16_t get_packet_id<VoiceMsg>() {
|
template <> constexpr uint16_t get_packet_id<VoiceMsg>() {
|
||||||
return std::to_underlying(PacketEnum::VOICE_MSG);
|
return std::to_underlying(PacketEnum::VOICE_MSG);
|
||||||
}
|
}
|
||||||
|
template <> constexpr uint16_t get_packet_id<S2CEntityUpdate>() {
|
||||||
|
return std::to_underlying(PacketEnum::S2C_ENTITY_UPDATE);
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::derived_from<T, google::protobuf::Message>
|
requires std::derived_from<T, google::protobuf::Message>
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ private:
|
|||||||
void handle_entity_destory(EntityID id);
|
void handle_entity_destory(EntityID id);
|
||||||
void handle_task();
|
void handle_task();
|
||||||
void send_all_entities(std::shared_ptr<Session>& session);
|
void send_all_entities(std::shared_ptr<Session>& session);
|
||||||
|
void update_ai();
|
||||||
template <typename... Args>
|
template <typename... Args>
|
||||||
EntityID create_entity_in_factory(Args&&... args) {
|
EntityID create_entity_in_factory(Args&&... args) {
|
||||||
auto entity = m_registry.create();
|
auto entity = m_registry.create();
|
||||||
|
|||||||
@@ -36,8 +36,23 @@ void ClientEntityManager::handle_entity_create(EntityID id,
|
|||||||
c->transform.position.value = pos;
|
c->transform.position.value = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientEntityManager::handle_entity_update(UpdateInfo& info) {
|
||||||
|
entt::entity e;
|
||||||
|
{
|
||||||
|
cacc a;
|
||||||
|
if (m_entities.find(a, info.id)) {
|
||||||
|
e = a->second;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
auto creature = m_registry.try_get<BaseClientCreature>(e);
|
||||||
|
ASSERT(creature);
|
||||||
|
creature->transform.position.value = info.pos;
|
||||||
|
}
|
||||||
|
|
||||||
void ClientEntityManager::receive_entity_create(S2CEntityCreate& s2c) {
|
void ClientEntityManager::receive_entity_create(S2CEntityCreate& s2c) {
|
||||||
EntityCreateElement c;
|
EntityCreateElement c{};
|
||||||
c.id = s2c.id();
|
c.id = s2c.id();
|
||||||
c.name = s2c.name();
|
c.name = s2c.name();
|
||||||
c.pos = {s2c.pos().x(), s2c.pos().y(), s2c.pos().z()};
|
c.pos = {s2c.pos().x(), s2c.pos().y(), s2c.pos().z()};
|
||||||
@@ -48,6 +63,13 @@ void ClientEntityManager::receive_entity_destory(EntityID id) {
|
|||||||
m_tasks.emplace(Command::DESTORY, id);
|
m_tasks.emplace(Command::DESTORY, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ClientEntityManager::receive_entity_update(S2CEntityUpdate& msg) {
|
||||||
|
UpdateInfo e;
|
||||||
|
e.id = msg.id();
|
||||||
|
e.pos = Tools::get_net_pos(msg.pos());
|
||||||
|
m_tasks.emplace(Command::UPDATE, std::move(e));
|
||||||
|
}
|
||||||
|
|
||||||
void ClientEntityManager::destory(EntityID id) {
|
void ClientEntityManager::destory(EntityID id) {
|
||||||
auto client = m_world.get_client();
|
auto client = m_world.get_client();
|
||||||
Arena arena;
|
Arena arena;
|
||||||
@@ -81,6 +103,11 @@ void ClientEntityManager::handle_task() {
|
|||||||
ASSERT(p);
|
ASSERT(p);
|
||||||
handle_entity_destory(*p);
|
handle_entity_destory(*p);
|
||||||
} break;
|
} break;
|
||||||
|
case Command::UPDATE: {
|
||||||
|
auto* p = std::get_if<UpdateInfo>(&pair.second);
|
||||||
|
ASSERT(p);
|
||||||
|
handle_entity_update(*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,6 +156,12 @@ asio::awaitable<void> NetworkClient::read_loop() {
|
|||||||
m_world.entity_manager().receive_entity_destory(msg->id());
|
m_world.entity_manager().receive_entity_destory(msg->id());
|
||||||
}
|
}
|
||||||
} break;
|
} break;
|
||||||
|
case std::to_underlying(PacketEnum::S2C_ENTITY_UPDATE): {
|
||||||
|
auto* msg = Arena::Create<S2CEntityUpdate>(&arena);
|
||||||
|
if (decode_packet(*msg, body_data, header)) {
|
||||||
|
m_world.entity_manager().receive_entity_update(*msg);
|
||||||
|
}
|
||||||
|
} break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (const asio::system_error& e) {
|
} catch (const asio::system_error& e) {
|
||||||
|
|||||||
@@ -22,7 +22,10 @@ void ServerEntityManager::init() {
|
|||||||
std::move(c), PigTag{});
|
std::move(c), PigTag{});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
void ServerEntityManager::update() { handle_task(); }
|
void ServerEntityManager::update() {
|
||||||
|
handle_task();
|
||||||
|
update_ai();
|
||||||
|
}
|
||||||
|
|
||||||
void ServerEntityManager::handle_task() {
|
void ServerEntityManager::handle_task() {
|
||||||
TaskPair pair;
|
TaskPair pair;
|
||||||
|
|||||||
@@ -21,4 +21,9 @@ message C2SEntityCreateRequest {
|
|||||||
string uuid = 1;
|
string uuid = 1;
|
||||||
string name = 2;
|
string name = 2;
|
||||||
Vec3 pos = 3;
|
Vec3 pos = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message S2CEntityUpdate {
|
||||||
|
uint64 id = 1;
|
||||||
|
Vec3 pos = 2;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user