Skip to content

Commit

Permalink
Now using entt::registry::visit to serialize entity. Closed #102.
Browse files Browse the repository at this point in the history
  • Loading branch information
Unarelith committed Jun 1, 2020
1 parent ac34fec commit ff9814a
Show file tree
Hide file tree
Showing 10 changed files with 89 additions and 157 deletions.
73 changes: 20 additions & 53 deletions source/client/network/ClientCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,22 @@ void ClientCommandHandler::sendChatMessage(const std::string &message) {
m_client.send(packet);
}

template<typename ComponentType>
static void addComponentCommandCallback(Network::Command command, Client &client, ClientCommandHandler::EntityMap &entityMap, ClientWorld &world) {
client.setCommandCallback(command, [&](Network::Packet &packet) {
entt::entity entityID;
packet >> entityID;

auto it = entityMap.find(entityID);
if (it != entityMap.end()) {
auto &component = world.scene().registry().get_or_emplace<ComponentType>(it->second);
component.deserialize(packet);
}
else
gkError() << Network::commandToString(command) + ": Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";
});
}

void ClientCommandHandler::setupCallbacks() {
m_client.setCommandCallback(Network::Command::ClientDisconnect, [this](Network::Packet &packet) {
u16 clientID;
Expand Down Expand Up @@ -290,58 +306,9 @@ void ClientCommandHandler::setupCallbacks() {
gkError() << "EntityDespawn: Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";
});

m_client.setCommandCallback(Network::Command::EntityPosition, [this](Network::Packet &packet) {
entt::entity entityID;
packet >> entityID;

auto it = m_entityMap.find(entityID);
if (it != m_entityMap.end()) {
auto &position = m_world.scene().registry().get_or_emplace<PositionComponent>(it->second);
packet >> position.x >> position.y >> position.z;
}
else
gkError() << "EntityPosition: Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";
});

m_client.setCommandCallback(Network::Command::EntityRotation, [this](Network::Packet &packet) {
entt::entity entityID;
packet >> entityID;

auto it = m_entityMap.find(entityID);
if (it != m_entityMap.end()) {
float w, x, y, z;
packet >> w >> x >> y >> z;

auto &rotation = m_world.scene().registry().get_or_emplace<RotationComponent>(it->second);
rotation.quat = glm::quat(w, x, y, z);
}
else
gkError() << "EntityRotation: Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";
});

m_client.setCommandCallback(Network::Command::EntityAnimation, [this](Network::Packet &packet) {
entt::entity entityID;
packet >> entityID;

auto it = m_entityMap.find(entityID);
if (it != m_entityMap.end()) {
auto &animation = m_world.scene().registry().get_or_emplace<AnimationComponent>(it->second);
animation.deserialize(packet);
}
else
gkError() << "EntityAnimation: Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";
});

m_client.setCommandCallback(Network::Command::EntityDrawableDef, [this](Network::Packet &packet) {
entt::entity entityID;
packet >> entityID;

auto it = m_entityMap.find(entityID);
if (it != m_entityMap.end()) {
packet >> m_world.scene().registry().get_or_emplace<DrawableDef>(it->second);
}
else
gkError() << "EntityDrawableDef: Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";
});
addComponentCommandCallback<PositionComponent>(Network::Command::EntityPosition, m_client, m_entityMap, m_world);
addComponentCommandCallback<RotationComponent>(Network::Command::EntityRotation, m_client, m_entityMap, m_world);
addComponentCommandCallback<AnimationComponent>(Network::Command::EntityAnimation, m_client, m_entityMap, m_world);
addComponentCommandCallback<DrawableDef>(Network::Command::EntityDrawableDef, m_client, m_entityMap, m_world);
}

8 changes: 5 additions & 3 deletions source/client/network/ClientCommandHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,14 +65,16 @@ class ClientCommandHandler {

void setSingleplayer(bool isSingleplayer) { m_isSingleplayer = isSingleplayer; }

using PlayerBoxMap = std::unordered_map<u16, PlayerBox>;
using EntityMap = std::unordered_map<entt::entity, entt::entity>;

private:
Client &m_client;
ClientWorld &m_world;
ClientPlayer &m_player;

std::unordered_map<u16, PlayerBox> &m_playerBoxes;

std::unordered_map<entt::entity, entt::entity> m_entityMap;
PlayerBoxMap &m_playerBoxes;
EntityMap m_entityMap;

bool m_isRegistryInitialized = false;

Expand Down
31 changes: 23 additions & 8 deletions source/common/scene/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include <entt/entt.hpp>

#include "Network.hpp"
#include "NetworkUtils.hpp"
#include "Scene.hpp"

static bool areComponentsRegistered = false;
Expand All @@ -52,29 +54,42 @@ entt::entity Scene::createEntityFromModel(entt::registry &modelRegistry, entt::e
}

auto other = m_registry.create();
modelRegistry.visit(modelEntity, [&](const auto component) {
modelRegistry.visit(modelEntity, [&](const auto &component) {
const auto type = entt::resolve_type(component);
const auto any = type.func("get"_hs).invoke({}, std::ref(modelRegistry), modelEntity);
type.func("set"_hs).invoke({}, std::ref(m_registry), other, any);
});
return other;
}

template<typename Type>
Type &get(entt::registry &registry, entt::entity entity) {
return registry.get_or_emplace<Type>(entity);
template<typename T>
T &get(entt::registry &registry, entt::entity entity) {
return registry.get_or_emplace<T>(entity);
}

template<typename Type>
Type &set(entt::registry &registry, entt::entity entity, const Type &instance) {
return registry.emplace_or_replace<Type>(entity, instance);
template<typename T>
T &set(entt::registry &registry, entt::entity entity, const T &instance) {
return registry.emplace_or_replace<T>(entity, instance);
}

template<typename T>
Network::Packet serialize(entt::entity entity, T &component) {
Network::Packet packet;
if constexpr(std::is_base_of_v<ISerializable, std::decay_t<T>>) {
if (component.isUpdated) {
packet << component.packetType << entity << component;
component.isUpdated = false;
}
}
return packet;
}

template<typename Type>
void extend_meta_type() {
entt::meta<Type>().type()
.template func<&get<Type>, entt::as_ref_t>("get"_hs)
.template func<&set<Type>>("set"_hs);
.template func<&set<Type>>("set"_hs)
.template func<&serialize<Type>>("serialize"_hs);
}

#include <gk/core/Box.hpp>
Expand Down
2 changes: 2 additions & 0 deletions source/common/scene/component/AnimationComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <gk/core/IntTypes.hpp>

#include "ISerializable.hpp"
#include "Network.hpp"
#include "NetworkUtils.hpp"

enum class AnimationType {
Expand Down Expand Up @@ -123,6 +124,7 @@ struct AnimationComponent : public ISerializable {

void serialize(sf::Packet &packet) const override { packet << list; }
void deserialize(sf::Packet &packet) override { packet >> list; }
Network::Command packetType = Network::Command::EntityAnimation;

std::vector<AnimationData> list;

Expand Down
2 changes: 2 additions & 0 deletions source/common/scene/component/DrawableDef.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

#include "ISerializable.hpp"
#include "InventoryCubeDef.hpp"
#include "Network.hpp"

namespace DrawableType {
enum : u8 {
Expand All @@ -49,6 +50,7 @@ class DrawableDef : public ISerializable {

void serialize(sf::Packet &packet) const override;
void deserialize(sf::Packet &packet) override;
Network::Command packetType = Network::Command::EntityDrawableDef;

bool isUpdated = true;

Expand Down
13 changes: 12 additions & 1 deletion source/common/scene/component/PositionComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,25 @@

#include <gk/core/IntTypes.hpp>

struct PositionComponent {
#include "ISerializable.hpp"
#include "Network.hpp"

struct PositionComponent : public ISerializable {
PositionComponent() = default;
PositionComponent(double x_, double y_, double z_, u16 dimension_)
: x(x_), y(y_), z(z_), dimension(dimension_) {}

double x = 0;
double y = 0;
double z = 0;

u16 dimension = 0;

bool isUpdated = true;

void serialize(sf::Packet &packet) const override { packet << x << y << z; }
void deserialize(sf::Packet &packet) override { packet >> x >> y >> z; }
Network::Command packetType = Network::Command::EntityPosition;
};

#endif // POSITIONCOMPONENT_HPP_
9 changes: 8 additions & 1 deletion source/common/scene/component/RotationComponent.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,17 @@

#include <glm/gtc/quaternion.hpp>

struct RotationComponent {
#include "ISerializable.hpp"
#include "Network.hpp"

struct RotationComponent : public ISerializable {
glm::quat quat{1, 0, 0, 0};

bool isUpdated = true;

void serialize(sf::Packet &packet) const override { packet << quat.w << quat.x << quat.y << quat.z; }
void deserialize(sf::Packet &packet) override { packet >> quat.w >> quat.x >> quat.y >> quat.z; }
Network::Command packetType = Network::Command::EntityRotation;
};

#endif // ROTATIONCOMPONENT_HPP_
40 changes: 0 additions & 40 deletions source/server/network/ServerCommandHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -148,46 +148,6 @@ void ServerCommandHandler::sendEntityDespawn(entt::entity entityID, const Client
client->tcpSocket->send(packet);
}

void ServerCommandHandler::sendEntityPosition(entt::entity entityID, double x, double y, double z, const ClientInfo *client) const {
Network::Packet packet;
packet << Network::Command::EntityPosition << entityID << x << y << z;

if (!client)
m_server.sendToAllClients(packet);
else
client->tcpSocket->send(packet);
}

void ServerCommandHandler::sendEntityRotation(entt::entity entityID, float w, float x, float y, float z, const ClientInfo *client) const {
Network::Packet packet;
packet << Network::Command::EntityRotation << entityID << w << x << y << z;

if (!client)
m_server.sendToAllClients(packet);
else
client->tcpSocket->send(packet);
}

void ServerCommandHandler::sendEntityAnimation(entt::entity entityID, const AnimationComponent &animation, const ClientInfo *client) const {
Network::Packet packet;
packet << Network::Command::EntityAnimation << entityID << animation;

if (!client)
m_server.sendToAllClients(packet);
else
client->tcpSocket->send(packet);
}

void ServerCommandHandler::sendEntityDrawableDef(entt::entity entityID, const DrawableDef &drawableDef, const ClientInfo *client) const {
Network::Packet packet;
packet << Network::Command::EntityDrawableDef << entityID << drawableDef;

if (!client)
m_server.sendToAllClients(packet);
else
client->tcpSocket->send(packet);
}

void ServerCommandHandler::setupCallbacks() {
m_server.setConnectionCallback([this](ClientInfo &client) {
Network::Packet packet;
Expand Down
4 changes: 0 additions & 4 deletions source/server/network/ServerCommandHandler.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ class ServerCommandHandler {
void sendChatMessage(u16 clientID, const std::string &message, const ClientInfo *client = nullptr) const;
void sendEntitySpawn(entt::entity entityID, const ClientInfo *client = nullptr) const;
void sendEntityDespawn(entt::entity entityID, const ClientInfo *client = nullptr) const;
void sendEntityPosition(entt::entity entityID, double x, double y, double z, const ClientInfo *client = nullptr) const;
void sendEntityRotation(entt::entity entityID, float w, float x, float y, float z, const ClientInfo *client = nullptr) const;
void sendEntityAnimation(entt::entity entityID, const AnimationComponent &animation, const ClientInfo *client = nullptr) const;
void sendEntityDrawableDef(entt::entity entityID, const DrawableDef &drawableDef, const ClientInfo *client = nullptr) const;

void setupCallbacks();

Expand Down
64 changes: 17 additions & 47 deletions source/server/scene/controller/NetworkController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,70 +24,40 @@
*
* =====================================================================================
*/
#include "AnimationComponent.hpp"
#include "DrawableDef.hpp"
#include "Network.hpp"
#include "NetworkComponent.hpp"
#include "NetworkController.hpp"
#include "PositionComponent.hpp"
#include "RotationComponent.hpp"
#include "Server.hpp"
#include "ServerCommandHandler.hpp"

void NetworkController::update(entt::registry &registry) {
registry.view<NetworkComponent>().each([this] (auto, auto &network) {
registry.view<NetworkComponent>().each([&] (auto entity, auto &network) {
if (!network.hasSpawned) {
m_server->sendEntitySpawn(network.entityID);
network.hasSpawned = true;
}
});

registry.view<NetworkComponent, PositionComponent>().each([this] (auto, auto &network, auto &position) {
if (position.isUpdated) {
m_server->sendEntityPosition(network.entityID, position.x, position.y, position.z);
position.isUpdated = false;
}
});

registry.view<NetworkComponent, RotationComponent>().each([this] (auto, auto &network, auto &rotation) {
if (rotation.isUpdated) {
m_server->sendEntityRotation(network.entityID, rotation.quat.w, rotation.quat.x, rotation.quat.y, rotation.quat.z);
rotation.isUpdated = false;
}
});

registry.view<NetworkComponent, AnimationComponent>().each([this] (auto, auto &network, auto &animation) {
if (animation.isUpdated) {
m_server->sendEntityAnimation(network.entityID, animation);
animation.isUpdated = false;
}
});

registry.view<NetworkComponent, DrawableDef>().each([this] (auto, auto &network, auto &drawableDef) {
if (drawableDef.isUpdated) {
m_server->sendEntityDrawableDef(network.entityID, drawableDef);
drawableDef.isUpdated = false;
}
registry.visit(entity, [&] (const auto &component_type) {
const auto &type = entt::resolve_type(component_type);
const auto &component = type.func("get"_hs).invoke({}, std::ref(registry), entity);
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component).template cast<Network::Packet>();
if (packet.getDataSize())
m_server->server().sendToAllClients(packet);
});
});
}

void NetworkController::sendEntities(entt::registry &registry, const ClientInfo &client) {
registry.view<NetworkComponent>().each([&] (auto entity, auto &network) {
m_server->sendEntitySpawn(network.entityID, &client);

if (auto *position = registry.try_get<PositionComponent>(entity) ; position) {
m_server->sendEntityPosition(network.entityID, position->x, position->y, position->z, &client);
}

if (auto *rotation = registry.try_get<RotationComponent>(entity) ; rotation) {
m_server->sendEntityRotation(network.entityID, rotation->quat.w, rotation->quat.x, rotation->quat.y, rotation->quat.z, &client);
}

if (auto *animation = registry.try_get<AnimationComponent>(entity) ; animation) {
m_server->sendEntityAnimation(network.entityID, *animation, &client);
}

if (auto *drawableDef = registry.try_get<DrawableDef>(entity) ; drawableDef) {
m_server->sendEntityDrawableDef(network.entityID, *drawableDef, &client);
}
registry.visit(entity, [&] (const auto &component_type) {
const auto &type = entt::resolve_type(component_type);
const auto &component = type.func("get"_hs).invoke({}, std::ref(registry), entity);
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component).template cast<Network::Packet>();
if (packet.getDataSize())
client.tcpSocket->send(packet);
});
});
}

0 comments on commit ff9814a

Please sign in to comment.