From d3cebb29c2ea4f4ebf3879324502f4d60efee2b7 Mon Sep 17 00:00:00 2001 From: Daid Date: Thu, 27 Oct 2022 23:11:49 +0200 Subject: [PATCH] WIP --- src/ecs/entity.cpp | 23 ++++++++++++++++++++++- src/ecs/entity.h | 9 +++++++++ src/multiplayer.cpp | 14 ++++++++++++++ src/multiplayer.h | 21 +++++++++------------ src/multiplayer_client.cpp | 26 ++++++++++++++++---------- src/multiplayer_client.h | 3 +++ src/multiplayer_internal.h | 7 ++++--- src/multiplayer_server.cpp | 7 +++++-- 8 files changed, 82 insertions(+), 28 deletions(-) diff --git a/src/ecs/entity.cpp b/src/ecs/entity.cpp index 941a7d41..b138cbf4 100644 --- a/src/ecs/entity.cpp +++ b/src/ecs/entity.cpp @@ -17,6 +17,7 @@ Entity Entity::create() } else { e.index = free_list.back(); free_list.pop_back(); + entity_version[e.index] &=~destroyed_flag; e.version = entity_version[e.index]; } return e; @@ -37,6 +38,26 @@ Entity::operator bool() const return entity_version[index] == version; } +bool Entity::operator==(const Entity& other) const { + auto bt = bool(*this); + auto bo = bool(*this); + if (bt != bo) + return false; + if (!bt) + return true; + return index == other.index; +} + +bool Entity::operator!=(const Entity& other) const { + auto bt = bool(*this); + auto bo = bool(*this); + if (bt != bo) + return true; + if (!bt) + return false; + return index != other.index; +} + void Entity::destroy() { if (!*this) @@ -44,7 +65,7 @@ void Entity::destroy() ComponentStorageBase::destroyAll(index); // By increasing the version number, everything else will know this entity no longer exists. - entity_version[index] += 1; + entity_version[index] = (entity_version[index] + 1) | destroyed_flag; free_list.push_back(index); } diff --git a/src/ecs/entity.h b/src/ecs/entity.h index 150e80e0..6ff54a4b 100644 --- a/src/ecs/entity.h +++ b/src/ecs/entity.h @@ -42,8 +42,17 @@ class Entity final { { return ComponentStorage::storage.sparseset.has(index); } + template void removeComponent() + { + ComponentStorage::storage.sparseset.remove(index); + } + + bool operator==(const Entity& other) const; + bool operator!=(const Entity& other) const; + uint32_t getIndex() { return index; } // You should never need this, but the multiplayer code does need it. private: + static constexpr uint32_t destroyed_flag = 1 << 31; uint32_t index = std::numeric_limits::max(); uint32_t version = std::numeric_limits::max(); diff --git a/src/multiplayer.cpp b/src/multiplayer.cpp index 9ddd9415..c30cb76a 100644 --- a/src/multiplayer.cpp +++ b/src/multiplayer.cpp @@ -62,6 +62,20 @@ template <> bool multiplayerReplicationFunctions::isChanged(void* data, return false; } +template <> void multiplayerReplicationFunctions::sendData(void* data, sp::io::DataBuffer& packet) +{ + auto e = (sp::ecs::Entity*)data; + if (*e) { + packet << e->getIndex(); + } else { + packet << std::numeric_limits::max(); + } +} + +template <> void multiplayerReplicationFunctions::receiveData(void* data, sp::io::DataBuffer& packet) +{ +} + static bool collisionable_isChanged(void* data, void* prev_data_ptr) { CollisionableReplicationData* rep_data = *(CollisionableReplicationData**)prev_data_ptr; diff --git a/src/multiplayer.h b/src/multiplayer.h index 0c8f125e..b82b7687 100644 --- a/src/multiplayer.h +++ b/src/multiplayer.h @@ -126,6 +126,9 @@ bool multiplayerReplicationFunctions::isChanged(void* data, void* prev_data_p template <> bool multiplayerReplicationFunctions::isChanged(void* data, void* prev_data_ptr); +template <> void multiplayerReplicationFunctions::sendData(void* data, sp::io::DataBuffer& packet); +template <> void multiplayerReplicationFunctions::receiveData(void* data, sp::io::DataBuffer& packet); + //In between class that handles all the nasty synchronization of objects between server and client. //I'm assuming that it should be a pure virtual class though. class MultiplayerObject : public virtual PObject @@ -226,12 +229,6 @@ class MultiplayerObject : public virtual PObject registerMemberReplication(&member->z, update_delay); } - void registerMemberReplication_(F_PARAM sp::ecs::Entity* member, float update_delay = 0.0f) - { - registerMemberReplication(&member->index, update_delay); - registerMemberReplication(&member->version, update_delay); - } - void updateMemberReplicationUpdateDelay(void* data, float update_delay) { for(unsigned int n=0; n class MultiplayerECSComponentReplication : public MultiplayerECSComponentReplicationBase { @@ -340,15 +337,15 @@ template class MultiplayerECSComponentReplication : public Multiplay } } - void receive(uint32_t index, sp::io::DataBuffer& packet) override + void receive(sp::ecs::Entity entity, sp::io::DataBuffer& packet) override { T data; packet >> data; - sp::ecs::ComponentStorage::storage.sparseset.set(index, data); + entity.addComponent(data); } - void remove(uint32_t index) override + void remove(sp::ecs::Entity entity) override { - sp::ecs::ComponentStorage::storage.sparseset.remove(index); + entity.removeComponent(); } }; diff --git a/src/multiplayer_client.cpp b/src/multiplayer_client.cpp index 7e8d453b..b5926a9e 100644 --- a/src/multiplayer_client.cpp +++ b/src/multiplayer_client.cpp @@ -254,15 +254,21 @@ void GameClient::update(float /*delta*/) packet >> ecs_cmd; switch(ecs_cmd) { - case CMD_ECS_ENTITY_VERSION: + case CMD_ECS_ENTITY_CREATE: { - uint32_t index, version; - packet >> index >> version; - if (index >= sp::ecs::Entity::entity_version.size()) { - sp::ecs::Entity::entity_version.push_back(version); - } else if (sp::ecs::Entity::entity_version[index] != version) { - sp::ecs::Entity::entity_version[index] = version; - } + uint32_t index; + packet >> index; + if (index >= entity_mapping.size()) + entity_mapping.resize(index + 1); + entity_mapping[index] = sp::ecs::Entity::create(); + } + break; + case CMD_ECS_ENTITY_DESTROY: + { + uint32_t index; + packet >> index; + if (index < entity_mapping.size()) + entity_mapping[index].destroy(); } break; case CMD_ECS_SET_COMPONENT: @@ -272,7 +278,7 @@ void GameClient::update(float /*delta*/) packet >> component_index >> index; for(auto ecsrb = MultiplayerECSComponentReplicationBase::first; ecsrb; ecsrb=ecsrb->next) { if (ecsrb->component_index == component_index) - ecsrb->receive(index, packet); + ecsrb->receive(entity_mapping[index], packet); } } break; @@ -283,7 +289,7 @@ void GameClient::update(float /*delta*/) packet >> component_index >> index; for(auto ecsrb = MultiplayerECSComponentReplicationBase::first; ecsrb; ecsrb=ecsrb->next) { if (ecsrb->component_index == component_index) - ecsrb->remove(index); + ecsrb->remove(entity_mapping[index]); } } break; diff --git a/src/multiplayer_client.h b/src/multiplayer_client.h index 664121fd..ea4b6474 100644 --- a/src/multiplayer_client.h +++ b/src/multiplayer_client.h @@ -6,6 +6,7 @@ #include "multiplayer_server.h" #include "networkAudioStream.h" #include "timer.h" +#include "ecs/entity.h" #include #include @@ -20,6 +21,8 @@ class GameClient : public Updatable { constexpr static float no_data_disconnect_time = 20; public: + std::vector entity_mapping; + enum Status { Connecting, diff --git a/src/multiplayer_internal.h b/src/multiplayer_internal.h index b0ae5c2f..a5d700b4 100644 --- a/src/multiplayer_internal.h +++ b/src/multiplayer_internal.h @@ -26,8 +26,9 @@ static const command_t CMD_AUDIO_COMM_DATA = 0x0021; static const command_t CMD_AUDIO_COMM_STOP = 0x0022; static constexpr command_t CMD_ECS_UPDATE = 0x0030; -static constexpr uint8_t CMD_ECS_ENTITY_VERSION = 0x00; -static constexpr uint8_t CMD_ECS_SET_COMPONENT = 0x01; -static constexpr uint8_t CMD_ECS_DEL_COMPONENT = 0x02; +static constexpr uint8_t CMD_ECS_ENTITY_CREATE = 0x00; +static constexpr uint8_t CMD_ECS_ENTITY_DESTROY = 0x01; +static constexpr uint8_t CMD_ECS_SET_COMPONENT = 0x02; +static constexpr uint8_t CMD_ECS_DEL_COMPONENT = 0x03; #endif//MULTIPLAYER_INTERNAL_H diff --git a/src/multiplayer_server.cpp b/src/multiplayer_server.cpp index 407499e0..bd4e5b6d 100644 --- a/src/multiplayer_server.cpp +++ b/src/multiplayer_server.cpp @@ -147,12 +147,15 @@ void GameServer::update(float /*gameDelta*/) //Replicate ECS data, we send this as one big packet so ECS state is always consistent on the client. sp::io::DataBuffer ecs_packet; ecs_packet << CMD_ECS_UPDATE; - // For each entity, check which version number we last transmitted and if it is changed, transmit the new version number. + // For each entity, check which version number we last transmitted and if it is changed, transmit creation/deletion of entities. ecs_entity_version.resize(sp::ecs::Entity::entity_version.size(), std::numeric_limits::max()); for(uint32_t index; index