mirror of
https://github.com/zhenyan121/Cubed.git
synced 2026-08-08 17:57:02 +08:00
feat(gameplay): add entity destruction support
This commit is contained in:
@@ -10,7 +10,7 @@ namespace Cubed {
|
||||
class ClientWorld;
|
||||
class ClientEntityManager {
|
||||
public:
|
||||
enum class Command { CREATE };
|
||||
enum class Command { CREATE, DESTORY };
|
||||
|
||||
ClientEntityManager(ClientWorld& world);
|
||||
void update();
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
void add_entity(EntityID id, std::string_view name, const glm::vec3& pos);
|
||||
|
||||
void receive_entity_create(S2CEntityCreate& s2c);
|
||||
|
||||
void destory(EntityID id);
|
||||
const entt::registry& get_registry() const;
|
||||
|
||||
private:
|
||||
@@ -32,7 +32,7 @@ private:
|
||||
using acc = EntityMap::accessor;
|
||||
using cacc = EntityMap::const_accessor;
|
||||
using CreateFunc = std::function<void(EntityID id)>;
|
||||
using TaskElement = std::variant<EntityCreateElement>;
|
||||
using TaskElement = std::variant<EntityCreateElement, EntityID>;
|
||||
using TaskPair = std::pair<Command, TaskElement>;
|
||||
|
||||
ClientWorld& m_world;
|
||||
@@ -42,7 +42,7 @@ private:
|
||||
tbb::concurrent_queue<TaskPair> m_tasks;
|
||||
|
||||
void handle_task();
|
||||
|
||||
void handle_entity_destory(EntityID id);
|
||||
template <typename... Args>
|
||||
void create_entity_in_registry(EntityID id, Args&&... args) {
|
||||
{
|
||||
|
||||
@@ -62,6 +62,7 @@ enum class PacketEnum : uint16_t {
|
||||
S2C_CLEAR_ALL_CHUNKS = 3005,
|
||||
UPDATE_TIME = 3006,
|
||||
S2C_ENTITY_CREATE = 3007,
|
||||
S2C_ENTITY_DESTORY = 3008,
|
||||
CHAT_MSG = 4001,
|
||||
VOICE_MSG = 4002,
|
||||
PING = 9001,
|
||||
@@ -115,6 +116,9 @@ template <> constexpr uint16_t get_packet_id<S2C_ClearAllChunks>() {
|
||||
template <> constexpr uint16_t get_packet_id<S2CEntityCreate>() {
|
||||
return std::to_underlying(PacketEnum::S2C_ENTITY_CREATE);
|
||||
}
|
||||
template <> constexpr uint16_t get_packet_id<S2CEntityDestory>() {
|
||||
return std::to_underlying(PacketEnum::S2C_ENTITY_DESTORY);
|
||||
}
|
||||
template <> constexpr uint16_t get_packet_id<UpdateTime>() {
|
||||
return std::to_underlying(PacketEnum::UPDATE_TIME);
|
||||
}
|
||||
|
||||
@@ -16,11 +16,11 @@ public:
|
||||
void update();
|
||||
// not thread safe
|
||||
void add_entity(std::string_view name, const glm::vec3& pos);
|
||||
|
||||
void destory(EntityID id);
|
||||
void handle_player_login(std::shared_ptr<Session> session);
|
||||
|
||||
private:
|
||||
enum class Command { CREATE, SEND_ALL_ENTITIES };
|
||||
enum class Command { CREATE, SEND_ALL_ENTITIES, DESTORY };
|
||||
struct EntityCreateElement {
|
||||
std::string name;
|
||||
glm::vec3 pos;
|
||||
@@ -30,7 +30,7 @@ private:
|
||||
using cacc = EntityMap::const_accessor;
|
||||
using CreateFunc = std::function<EntityID()>;
|
||||
using TaskElement =
|
||||
std::variant<std::shared_ptr<Session>, EntityCreateElement>;
|
||||
std::variant<std::shared_ptr<Session>, EntityCreateElement, EntityID>;
|
||||
using TaskPair = std::pair<Command, TaskElement>;
|
||||
ServerWorld& m_world;
|
||||
tbb::concurrent_queue<TaskPair> m_tasks;
|
||||
@@ -39,8 +39,9 @@ private:
|
||||
EntityMap m_entities;
|
||||
std::unordered_map<std::string_view, CreateFunc> m_factories;
|
||||
void create_entity(std::string_view name, const glm::vec3& pos);
|
||||
void send_entity_create(EntityID id, std::string_view name,
|
||||
void handle_entity_create(EntityID id, std::string_view name,
|
||||
const glm::vec3& pos);
|
||||
void handle_entity_destory(EntityID id);
|
||||
void handle_task();
|
||||
void send_all_entities(std::shared_ptr<Session>& session);
|
||||
template <typename... Args> EntityID add_entity(Args&&... args) {
|
||||
|
||||
@@ -39,19 +39,38 @@ void ClientEntityManager::receive_entity_create(S2CEntityCreate& s2c) {
|
||||
m_tasks.emplace(Command::CREATE, std::move(c));
|
||||
}
|
||||
|
||||
void ClientEntityManager::destory(EntityID id) {
|
||||
m_tasks.emplace(Command::DESTORY, id);
|
||||
}
|
||||
|
||||
void ClientEntityManager::handle_task() {
|
||||
TaskPair pair;
|
||||
while (m_tasks.try_pop(pair)) {
|
||||
switch (pair.first) {
|
||||
case Command::CREATE:
|
||||
case Command::CREATE: {
|
||||
auto* p = std::get_if<EntityCreateElement>(&pair.second);
|
||||
ASSERT(p);
|
||||
add_entity(p->id, p->name, p->pos);
|
||||
break;
|
||||
|
||||
} break;
|
||||
case Command::DESTORY: {
|
||||
auto* p = std::get_if<EntityID>(&pair.second);
|
||||
ASSERT(p);
|
||||
handle_entity_destory(*p);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ClientEntityManager::handle_entity_destory(EntityID id) {
|
||||
acc a;
|
||||
if (!m_entities.find(a, id)) {
|
||||
return;
|
||||
}
|
||||
m_registry.destroy(a->second);
|
||||
m_entities.erase(a);
|
||||
}
|
||||
|
||||
const entt::registry& ClientEntityManager::get_registry() const {
|
||||
return m_registry;
|
||||
}
|
||||
|
||||
@@ -150,6 +150,12 @@ asio::awaitable<void> NetworkClient::read_loop() {
|
||||
}
|
||||
|
||||
} break;
|
||||
case std::to_underlying(PacketEnum::S2C_ENTITY_DESTORY): {
|
||||
auto* msg = Arena::Create<S2CEntityDestory>(&arena);
|
||||
if (decode_packet(*msg, body_data, header)) {
|
||||
m_world.entity_manager().destory(msg->id());
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
} catch (const asio::system_error& e) {
|
||||
|
||||
@@ -37,6 +37,11 @@ void ServerEntityManager::handle_task() {
|
||||
ASSERT(c);
|
||||
send_all_entities(*c);
|
||||
} break;
|
||||
case Command::DESTORY: {
|
||||
auto* c = std::get_if<EntityID>(&pair.second);
|
||||
ASSERT(c);
|
||||
handle_entity_destory(*c);
|
||||
} break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,6 +52,10 @@ void ServerEntityManager::add_entity(std::string_view name,
|
||||
EntityCreateElement{std::string(name), pos});
|
||||
}
|
||||
|
||||
void ServerEntityManager::destory(EntityID id) {
|
||||
m_tasks.emplace(Command::DESTORY, id);
|
||||
}
|
||||
|
||||
void ServerEntityManager::handle_player_login(
|
||||
std::shared_ptr<Session> session) {
|
||||
m_tasks.emplace(Command::SEND_ALL_ENTITIES, std::move(session));
|
||||
@@ -62,7 +71,7 @@ void ServerEntityManager::create_entity(std::string_view name,
|
||||
ASSERT(t);
|
||||
t->transform.position.value = pos;
|
||||
}
|
||||
send_entity_create(e, name, pos);
|
||||
handle_entity_create(e, name, pos);
|
||||
}
|
||||
|
||||
void ServerEntityManager::send_all_entities(std::shared_ptr<Session>& session) {
|
||||
@@ -79,7 +88,8 @@ void ServerEntityManager::send_all_entities(std::shared_ptr<Session>& session) {
|
||||
}
|
||||
}
|
||||
|
||||
void ServerEntityManager::send_entity_create(EntityID id, std::string_view name,
|
||||
void ServerEntityManager::handle_entity_create(EntityID id,
|
||||
std::string_view name,
|
||||
const glm::vec3& pos) {
|
||||
auto sessions = m_world.get_all_session();
|
||||
|
||||
@@ -94,4 +104,20 @@ void ServerEntityManager::send_entity_create(EntityID id, std::string_view name,
|
||||
}
|
||||
}
|
||||
|
||||
void ServerEntityManager::handle_entity_destory(EntityID id) {
|
||||
acc a;
|
||||
if (!m_entities.find(a, id)) {
|
||||
return;
|
||||
}
|
||||
m_registry.destroy(a->second);
|
||||
m_entities.erase(a);
|
||||
auto sessions = m_world.get_all_session();
|
||||
Arena arena;
|
||||
auto* s2c = Arena::Create<S2CEntityDestory>(&arena);
|
||||
s2c->set_id(id);
|
||||
for (auto& s : sessions) {
|
||||
s->send(make_packet(*s2c));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Cubed
|
||||
@@ -7,3 +7,7 @@ message S2CEntityCreate {
|
||||
string name = 2;
|
||||
Vec3 pos = 3;
|
||||
}
|
||||
|
||||
message S2CEntityDestory {
|
||||
uint64 id = 1;
|
||||
}
|
||||
Reference in New Issue
Block a user