Skip to content

Commit 30b7cb0

Browse files
committed
[WorldController] Entities partially saved with the world (see #126).
1 parent 616ad0c commit 30b7cb0

File tree

7 files changed

+125
-20
lines changed

7 files changed

+125
-20
lines changed

source/client/network/ClientCommandHandler.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -130,12 +130,13 @@ void ClientCommandHandler::sendKeyPressed(u16 keyID) {
130130

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

137137
auto it = entityMap.find(entityID);
138138
if (it != entityMap.end()) {
139+
// gkDebug() << "Received component" << Network::commandToString(command);
139140
auto &component = world.scene().registry().get_or_emplace<ComponentType>(it->second);
140141
component.deserialize(packet);
141142
}
@@ -301,6 +302,7 @@ void ClientCommandHandler::setupCallbacks() {
301302
entt::entity entity = registry.create();
302303
m_entityMap.emplace(entityID, entity);
303304
registry.emplace<NetworkComponent>(entity, entityID);
305+
// gkDebug() << "Entity spawned:" << std::underlying_type_t<entt::entity>(entityID);
304306
}
305307
else if (registry.get<NetworkComponent>(it->second).entityID != entityID) {
306308
gkError() << "EntitySpawn: Entity ID" << std::underlying_type_t<entt::entity>(entityID) << "is invalid";

source/common/network/Network.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ std::string Network::commandToString(Network::Command command) {
6565
{Network::Command::EntityDespawn, "EntityDespawn"},
6666
{Network::Command::EntityPosition, "EntityPosition"},
6767
{Network::Command::EntityRotation, "EntityRotation"},
68-
{Network::Command::EntityAnimation, "EntityRotation"},
68+
{Network::Command::EntityAnimation, "EntityAnimation"},
6969
{Network::Command::EntityDrawableDef, "EntityDrawableDef"},
7070

7171
{Network::Command::KeyPressed, "KeyPressed"},

source/common/scene/Scene.cpp

+14-13
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,21 @@ T &set(entt::registry &registry, entt::entity entity, const T &instance) {
7474
}
7575

7676
template<typename T>
77-
Network::Packet serialize(entt::entity entity, T &component) {
77+
Network::Packet serialize(entt::entity entity, T &component, bool forWorldSave) {
7878
Network::Packet packet;
7979
if constexpr(std::is_base_of_v<gk::ISerializable, std::decay_t<T>>) {
80-
if (component.isUpdated) {
80+
if (forWorldSave || component.isUpdated) {
8181
packet << component.packetType << entity << component;
82-
component.isUpdated = false;
82+
if (!forWorldSave)
83+
component.isUpdated = false;
8384
}
8485
}
8586
return packet;
8687
}
8788

8889
template<typename Type>
89-
void extend_meta_type() {
90-
entt::meta<Type>().type()
90+
void extend_meta_type(const std::string &name) {
91+
entt::meta<Type>().type().prop("name"_hs, name)
9192
.template func<&get<Type>, entt::as_ref_t>("get"_hs)
9293
.template func<&set<Type>>("set"_hs)
9394
.template func<&serialize<Type>>("serialize"_hs);
@@ -104,13 +105,13 @@ void extend_meta_type() {
104105
#include "RotationComponent.hpp"
105106

106107
void Scene::registerComponents() {
107-
extend_meta_type<gk::DoubleBox>();
108-
extend_meta_type<AnimationComponent>();
109-
extend_meta_type<DrawableDef>();
110-
extend_meta_type<ItemStack>();
111-
extend_meta_type<LuaCallbackComponent>();
112-
extend_meta_type<NetworkComponent>();
113-
extend_meta_type<PositionComponent>();
114-
extend_meta_type<RotationComponent>();
108+
extend_meta_type<gk::DoubleBox>("gk::DoubleBox");
109+
extend_meta_type<AnimationComponent>("AnimationComponent");
110+
extend_meta_type<DrawableDef>("DrawableDef");
111+
extend_meta_type<ItemStack>("ItemStack");
112+
extend_meta_type<LuaCallbackComponent>("LuaCallbackComponent");
113+
extend_meta_type<NetworkComponent>("NetworkComponent");
114+
extend_meta_type<PositionComponent>("PositionComponent");
115+
extend_meta_type<RotationComponent>("RotationComponent");
115116
}
116117

source/common/scene/component/PositionComponent.hpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ struct PositionComponent : public gk::ISerializable {
4545

4646
bool isUpdated = true;
4747

48-
void serialize(sf::Packet &packet) const override { packet << x << y << z; }
49-
void deserialize(sf::Packet &packet) override { packet >> x >> y >> z; }
48+
void serialize(sf::Packet &packet) const override { packet << x << y << z << dimension; }
49+
void deserialize(sf::Packet &packet) override { packet >> x >> y >> z >> dimension; }
5050
Network::Command packetType = Network::Command::EntityPosition;
5151
};
5252

source/server/scene/controller/NetworkController.cpp

+7-3
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ void NetworkController::update(entt::registry &registry) {
4040
registry.visit(entity, [&] (const auto &component_type) {
4141
const auto &type = entt::resolve_type(component_type);
4242
const auto &component = type.func("get"_hs).invoke({}, std::ref(registry), entity);
43-
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component).template cast<Network::Packet>();
43+
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component, false).template cast<Network::Packet>();
4444
if (packet.getDataSize())
4545
m_server->server().sendToAllClients(packet);
4646
});
@@ -51,12 +51,16 @@ void NetworkController::sendEntities(entt::registry &registry, const ClientInfo
5151
registry.view<NetworkComponent>().each([&] (auto entity, auto &network) {
5252
m_server->sendEntitySpawn(network.entityID, &client);
5353

54+
// gkDebug() << "sendEntitySpawn" << std::underlying_type_t<entt::entity>(network.entityID);
55+
5456
registry.visit(entity, [&] (const auto &component_type) {
5557
const auto &type = entt::resolve_type(component_type);
5658
const auto &component = type.func("get"_hs).invoke({}, std::ref(registry), entity);
57-
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component).template cast<Network::Packet>();
58-
if (packet.getDataSize())
59+
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component, true).template cast<Network::Packet>();
60+
if (packet.getDataSize()) {
61+
// gkDebug() << "sendEntities: Serializing component" << type.prop("name"_hs).value().template cast<std::string>() << "for entity" << std::underlying_type_t<entt::entity>(entity) << "of size" << packet.getDataSize();
5962
client.tcpSocket->send(packet);
63+
}
6064
});
6165
});
6266
}

source/server/world/WorldController.cpp

+93
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include <filesystem.hpp>
3030

31+
#include "NetworkComponent.hpp"
3132
#include "Registry.hpp"
3233
#include "WorldController.hpp"
3334

@@ -109,6 +110,8 @@ void WorldController::load(const std::string &name) {
109110
chunk.setSent(false);
110111
chunk.setModified(true);
111112
}
113+
114+
loadEntities(save, world);
112115
}
113116
}
114117

@@ -155,9 +158,99 @@ void WorldController::save(const std::string &name) {
155158

156159
save << chunkCount;
157160
save.append(chunks.getData(), chunks.getDataSize());
161+
162+
saveEntities(save, world);
158163
}
159164

160165
file.write((const char *)save.getData(), save.getDataSize());
161166

162167
// gkInfo() << "Saving done.";
163168
}
169+
170+
#include "AnimationComponent.hpp"
171+
#include "DrawableDef.hpp"
172+
#include "PositionComponent.hpp"
173+
#include "RotationComponent.hpp"
174+
175+
void WorldController::loadEntities(sf::Packet &save, ServerWorld &world) {
176+
entt::registry &registry = world.scene().registry();
177+
registry.clear();
178+
179+
u32 componentCount;
180+
save >> componentCount;
181+
182+
// gkDebug() << "Loading" << componentCount << "components in dimension" << world.dimension().id();
183+
184+
for (u32 i = 0 ; i < componentCount ; ++i) {
185+
Network::Command packetID;
186+
save >> packetID;
187+
188+
entt::entity entityID;
189+
save >> entityID;
190+
191+
// gkDebug() << "Loading packet" << Network::commandToString(packetID) << "for entity" << std::underlying_type_t<entt::entity>(entityID);
192+
193+
gk::ISerializable *component = nullptr;
194+
auto it = m_entityMap.find(entityID);
195+
if (it == m_entityMap.end()) {
196+
if (packetID == Network::Command::EntitySpawn) {
197+
entt::entity entity = registry.create();
198+
m_entityMap.emplace(entityID, entity);
199+
registry.emplace<NetworkComponent>(entity, entity);
200+
}
201+
else {
202+
gkWarning() << "World load: Failed to add a component to nonexistent entity:" << std::underlying_type_t<entt::entity>(entityID);
203+
}
204+
}
205+
else {
206+
if (packetID == Network::Command::EntitySpawn) {
207+
gkWarning() << "World load: Trying to recreate an entity:" << std::underlying_type_t<entt::entity>(entityID);
208+
}
209+
else if (packetID == Network::Command::EntityPosition) {
210+
component = &registry.emplace<PositionComponent>(it->second);
211+
}
212+
else if (packetID == Network::Command::EntityRotation) {
213+
component = &registry.emplace<RotationComponent>(it->second);
214+
}
215+
else if (packetID == Network::Command::EntityAnimation) {
216+
component = &registry.emplace<AnimationComponent>(it->second);
217+
}
218+
else if (packetID == Network::Command::EntityDrawableDef) {
219+
component = &registry.emplace<DrawableDef>(it->second);
220+
}
221+
222+
if (component)
223+
component->deserialize(save);
224+
else
225+
gkWarning() << "Unknown component with packet ID" << std::hex << (int)packetID;
226+
}
227+
}
228+
}
229+
230+
void WorldController::saveEntities(sf::Packet &save, ServerWorld &world) {
231+
entt::registry &registry = world.scene().registry();
232+
233+
u32 componentCount = 0;
234+
Network::Packet entities;
235+
registry.view<NetworkComponent>().each([&] (auto entity, auto &network) {
236+
entities << Network::Command::EntitySpawn << network.entityID;
237+
++componentCount;
238+
239+
registry.visit(entity, [&] (const auto &component_type) {
240+
const auto &type = entt::resolve_type(component_type);
241+
const auto &component = type.func("get"_hs).invoke({}, std::ref(registry), entity);
242+
Network::Packet packet = type.func("serialize"_hs).invoke({}, entity, component, true).template cast<Network::Packet>();
243+
if (packet.getDataSize()) {
244+
// gkDebug() << "Serializing component" << type.prop("name"_hs).value().template cast<std::string>() << "for entity" << std::underlying_type_t<entt::entity>(entity) << "of size" << packet.getDataSize();
245+
entities.append(packet.getData(), packet.getDataSize());
246+
++componentCount;
247+
}
248+
});
249+
});
250+
251+
save << componentCount;
252+
save.append(entities.getData(), entities.getDataSize());
253+
254+
// gkDebug() << "Saving" << componentCount << "components in dimension" << world.dimension().id();
255+
}
256+

source/server/world/WorldController.hpp

+5
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,18 @@ class WorldController {
5656
void setServer(ServerCommandHandler &server) { m_server = &server; }
5757

5858
private:
59+
void loadEntities(sf::Packet &save, ServerWorld &world);
60+
void saveEntities(sf::Packet &save, ServerWorld &world);
61+
5962
std::deque<ServerWorld> m_worldList;
6063

6164
Registry &m_registry;
6265

6366
gk::GameClock &m_clock;
6467

6568
ServerCommandHandler *m_server = nullptr;
69+
70+
std::unordered_map<entt::entity, entt::entity> m_entityMap;
6671
};
6772

6873
#endif // WORLDCONTROLLER_HPP_

0 commit comments

Comments
 (0)