Entity serialization is almost complete, only rendering data left.

This commit is contained in:
Quentin Bazin 2020-04-05 18:58:25 +02:00
parent a361f9e01b
commit 2f4188bf4a
23 changed files with 292 additions and 62 deletions

View File

@ -31,6 +31,7 @@
#include "ClientPlayer.hpp"
#include "ClientWorld.hpp"
#include "ClientCommandHandler.hpp"
#include "DrawableComponent.hpp"
#include "LuaGUIState.hpp"
#include "Registry.hpp"
@ -241,5 +242,19 @@ void ClientCommandHandler::setupCallbacks() {
}
}
});
m_client.setCommandCallback(Network::Command::SceneState, [this](sf::Packet &packet) {
u16 dimensionID;
packet >> dimensionID;
// FIXME: Check dimension and only apply changes if it's the same as the current one
packet >> m_world.scene();
// FIXME: Move this elsewhere
m_world.scene().registry().view<DrawableComponent>().each([](auto, auto &drawableComponent) {
if (!drawableComponent.drawable() && drawableComponent.drawableDef()) {
}
});
});
}

View File

@ -30,29 +30,12 @@
#include "CollisionController.hpp"
#include "RenderingController.hpp"
ClientScene::ClientScene(ClientPlayer &player) : m_player(player) {
ClientScene::ClientScene(ClientPlayer &player) {
m_controllers.emplace_back(new AnimationController);
m_controllers.emplace_back(new CollisionController(player));
m_controllers.emplace_back(new RenderingController);
}
void ClientScene::update() {
for (auto &controller : m_controllers)
controller->update(m_registry);
static bool test = false;
if (!test && m_registry.alive() > 2) {
gkDebug() << "serializing...";
sf::Packet packet;
serialize(packet);
gkDebug() << "deserializing...";
deserialize(packet);
gkDebug() << "serializing...";
serialize(packet);
test = true;
}
}
void ClientScene::draw(gk::RenderTarget &target, gk::RenderStates states) const {
if (!m_camera) return;

View File

@ -35,7 +35,6 @@
#include <entt/entt.hpp>
#include "AbstractController.hpp"
#include "Scene.hpp"
class ClientPlayer;
@ -44,18 +43,12 @@ class ClientScene : public Scene, public gk::Drawable {
public:
ClientScene(ClientPlayer &player);
void update();
void setCamera(gk::Camera &camera) { m_camera = &camera; }
private:
void draw(gk::RenderTarget &target, gk::RenderStates states) const override;
ClientPlayer &m_player;
gk::Camera *m_camera = nullptr;
std::deque<std::unique_ptr<AbstractController>> m_controllers;
};
#endif // CLIENTSCENE_HPP_

View File

@ -0,0 +1,36 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#include "DrawableFactory.hpp"
#include "InventoryCube.hpp"
#include "Registry.hpp"
void DrawableFactory::createInventoryCube(DrawableComponent &component, const InventoryCubeDef &def) {
auto &cube = component.setDrawable<InventoryCube>(def.size, true);
cube.setOrigin(def.origin);
cube.updateVertexBuffer(Registry::getInstance().getBlockFromStringID(def.block));
}

View File

@ -0,0 +1,38 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#ifndef DRAWABLEFACTORY_HPP_
#define DRAWABLEFACTORY_HPP_
#include "DrawableComponent.hpp"
#include "DrawableDefinitions.hpp"
class DrawableFactory {
public:
static void createInventoryCube(DrawableComponent &component, const InventoryCubeDef &def);
};
#endif // DRAWABLEFACTORY_HPP_

View File

@ -101,11 +101,6 @@ void ClientWorld::checkPlayerChunk(double playerX, double playerY, double player
}
}
void ClientWorld::onBlockDestroyed(int x, int y, int z, const Block &block) {
if (Config::useItemDrops)
ItemDropFactory::create(m_scene.registry(), x, y, z, block.getItemDrop().item().stringID(), block.getItemDrop().amount());
}
void ClientWorld::clear() {
m_chunks.clear();
}

View File

@ -51,8 +51,6 @@ class ClientWorld : public World, public gk::Drawable {
void sendChunkRequests();
void checkPlayerChunk(double playerX, double playerY, double playerZ);
void onBlockDestroyed(int x, int y, int z, const Block &block) override;
void clear();
void updateSky(u16 dimensionID);

View File

@ -59,8 +59,11 @@ std::string Network::commandToString(Network::Command command) {
{Network::Command::RegistryData, "RegistryData"},
{Network::Command::ChatMessage, "ChatMessage"}
{Network::Command::ChatMessage, "ChatMessage"},
{Network::Command::SceneState, "SceneState"},
};
return commandNames[command];
}

View File

@ -66,6 +66,9 @@ namespace Network {
// Chat commands
ChatMessage = 21, // <TCP> [NetworkCommand][u16 client id][std::string message] (both)
// Scene commands
SceneState = 22, // <TCP> [NetworkCommand][u16 dimension id][Scene scene] (from Server only)
};
std::string commandToString(Command command);

View File

@ -31,12 +31,20 @@
#include <gk/gl/Drawable.hpp>
class DrawableComponent {
#include "ISerializable.hpp"
class DrawableComponent : public ISerializable {
public:
template<typename T, typename... Args>
auto setDrawable(Args &&...args) -> typename std::enable_if<std::is_base_of<gk::Drawable, T>::value, T &>::type {
m_drawable.reset(new T(std::forward<Args>(args)...));
return *static_cast<T*>(m_drawable.get());
m_drawable = std::make_shared<T>(std::forward<Args>(args)...);
return *std::static_pointer_cast<T>(m_drawable);
}
template<typename T, typename... Args>
auto setDrawableDef(Args &&...args) -> typename std::enable_if<std::is_base_of<ISerializable, T>::value, T &>::type {
m_drawableDef = std::make_shared<T>(std::forward<Args>(args)...);
return *std::static_pointer_cast<T>(m_drawableDef);
}
void draw(gk::RenderTarget &target, gk::RenderStates states) {
@ -44,8 +52,15 @@ class DrawableComponent {
target.draw(*m_drawable, states);
}
void serialize(sf::Packet &packet) const override { m_drawableDef->serialize(packet); }
void deserialize(sf::Packet &packet) override { m_drawableDef->deserialize(packet); }
const gk::Drawable *drawable() const { return m_drawable.get(); }
const ISerializable *drawableDef() const { return m_drawableDef.get(); }
private:
std::unique_ptr<gk::Drawable> m_drawable;
std::shared_ptr<gk::Drawable> m_drawable;
std::shared_ptr<ISerializable> m_drawableDef;
};
#endif // DRAWABLECOMPONENT_HPP_

View File

@ -0,0 +1,46 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#ifndef DRAWABLEDEFINITIONS_HPP_
#define DRAWABLEDEFINITIONS_HPP_
#include <string>
#include <gk/core/Vector3.hpp>
#include "ISerializable.hpp"
#include "NetworkUtils.hpp"
struct InventoryCubeDef : public ISerializable {
float size = 1.f;
gk::Vector3f origin{0, 0, 0};
std::string block{"_:air"};
void serialize(sf::Packet &packet) const override { packet << size << origin << block; }
void deserialize(sf::Packet &packet) override { packet >> size >> origin >> block; }
};
#endif // DRAWABLEDEFINITIONS_HPP_

View File

@ -27,21 +27,27 @@
#ifndef SCENE_HPP_
#define SCENE_HPP_
#include "AbstractController.hpp"
#include "ISerializable.hpp"
#include "SceneSerializer.hpp"
class Scene : public ISerializable {
public:
void serialize(sf::Packet &packet) const override { m_serializer.serialize(packet); }
void deserialize(sf::Packet &packet) override { m_serializer.deserialize(packet); }
virtual void update() { for (auto &controller : m_controllers) controller->update(m_registry); }
void serialize(sf::Packet &packet) const override { m_serializer.serialize(packet, *this); }
void deserialize(sf::Packet &packet) override { m_serializer.deserialize(packet, *this); }
const entt::DefaultRegistry &registry() const { return m_registry; }
entt::DefaultRegistry &registry() { return m_registry; }
protected:
mutable entt::DefaultRegistry m_registry;
std::deque<std::unique_ptr<AbstractController>> m_controllers;
private:
SceneSerializer m_serializer{*this};
SceneSerializer m_serializer;
};
#endif // SCENE_HPP_

View File

@ -25,18 +25,19 @@
* =====================================================================================
*/
#include "AnimationComponent.hpp"
#include "DrawableComponent.hpp"
#include "ItemStack.hpp"
#include "Scene.hpp"
#include "SceneSerializer.hpp"
void SceneSerializer::serialize(sf::Packet &packet) const {
void SceneSerializer::serialize(sf::Packet &packet, const Scene &scene) const {
m_outputArchive.setPacket(packet);
m_scene.registry().snapshot().component<AnimationComponent, gk::DoubleBox, ItemStack, gk::Transformable>(m_outputArchive);
scene.registry().snapshot().component<AnimationComponent, gk::DoubleBox, ItemStack, gk::Transformable>(m_outputArchive);
}
void SceneSerializer::deserialize(sf::Packet &packet) {
void SceneSerializer::deserialize(sf::Packet &packet, Scene &scene) {
m_inputArchive.setPacket(packet);
m_scene.registry().restore().component<AnimationComponent, gk::DoubleBox, ItemStack, gk::Transformable>(m_inputArchive);
scene.registry().restore().component<AnimationComponent, gk::DoubleBox, ItemStack, gk::Transformable>(m_inputArchive);
}
void SceneSerializer::OutputArchive::operator()(Entity entity) {

View File

@ -31,19 +31,16 @@
#include <entt/entt.hpp>
#include "ISerializable.hpp"
#include "NetworkUtils.hpp"
class Scene;
class SceneSerializer : public ISerializable {
class SceneSerializer {
using Entity = entt::DefaultRegistry::entity_type;
public:
SceneSerializer(Scene &scene) : m_scene(scene) {}
void serialize(sf::Packet &packet) const;
void deserialize(sf::Packet &packet);
void serialize(sf::Packet &packet, const Scene &scene) const;
void deserialize(sf::Packet &packet, Scene &scene);
private:
class OutputArchive {
@ -52,7 +49,7 @@ class SceneSerializer : public ISerializable {
template<typename T>
void operator()(Entity entity, const T &value) {
// gkDebug() << entity << value;
gkDebug() << entity << (void *)&value;
(*m_packet) << entity << value;
}
@ -69,7 +66,7 @@ class SceneSerializer : public ISerializable {
template<typename T>
void operator()(Entity &entity, T &value) {
(*m_packet) >> entity >> value;
// gkDebug() << entity << value;
gkDebug() << entity << (void *)&value;
}
void setPacket(sf::Packet &packet) { m_packet = &packet; }
@ -78,8 +75,6 @@ class SceneSerializer : public ISerializable {
sf::Packet *m_packet = nullptr;
};
Scene &m_scene;
mutable OutputArchive m_outputArchive;
mutable InputArchive m_inputArchive;
};

View File

@ -173,8 +173,8 @@ void Server::disconnectClient(ClientInfo &client) {
}
}
void Server::sendToAllClients(sf::Packet &packet) {
for (ClientInfo &client : m_info.clients()) {
void Server::sendToAllClients(sf::Packet &packet) const {
for (const ClientInfo &client : m_info.clients()) {
client.tcpSocket->send(packet);
}
}

View File

@ -48,7 +48,7 @@ class Server {
void handleGameEvents();
void sendToAllClients(sf::Packet &packet);
void sendToAllClients(sf::Packet &packet) const;
bool isRunning() const { return m_isRunning; }

View File

@ -26,7 +26,7 @@
*/
#include "AnimationComponent.hpp"
#include "DrawableComponent.hpp"
#include "InventoryCube.hpp"
#include "DrawableDefinitions.hpp"
#include "ItemDropFactory.hpp"
#include "ItemStack.hpp"
#include "Registry.hpp"
@ -35,9 +35,10 @@ void ItemDropFactory::create(entt::DefaultRegistry &registry, double x, double y
auto entity = registry.create();
auto &drawableComponent = registry.assign<DrawableComponent>(entity);
auto &cube = drawableComponent.setDrawable<InventoryCube>(0.25f, true);
cube.setOrigin(cube.size() / 2.f, cube.size() / 2.f, cube.size() / 2.f);
cube.updateVertexBuffer(Registry::getInstance().getBlockFromStringID(itemID));
auto &cube = drawableComponent.setDrawableDef<InventoryCubeDef>();
cube.size = 0.25f;
cube.origin = gk::Vector3f{cube.size / 2.f, cube.size / 2.f, cube.size / 2.f};
cube.block = itemID;
auto &transformable = registry.assign<gk::Transformable>(entity);
transformable.setPosition(x + 0.5, y + 0.5, z + 0.5);
@ -46,7 +47,7 @@ void ItemDropFactory::create(entt::DefaultRegistry &registry, double x, double y
animationComponent.addRotation(0.f, 0.f, 1.f, 0.5f);
animationComponent.addTranslation(0.f, 0.f, -0.0005f, -0.2f, 0.f, true);
registry.assign<gk::DoubleBox>(entity, 0., 0., 0., cube.size(), cube.size(), cube.size());
registry.assign<gk::DoubleBox>(entity, 0., 0., 0., cube.size, cube.size, cube.size);
registry.assign<ItemStack>(entity, itemID, amount);
}

View File

@ -0,0 +1,37 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#include <gk/core/Debug.hpp>
#include <gk/core/GameClock.hpp>
#include "ServerScene.hpp"
ServerScene::ServerScene() {
}
void ServerScene::update() {
}

View File

@ -0,0 +1,39 @@
/*
* =====================================================================================
*
* OpenMiner
*
* Copyright (C) 2018-2020 Unarelith, Quentin Bazin <openminer@unarelith.net>
* Copyright (C) 2019-2020 the OpenMiner contributors (see CONTRIBUTORS.md)
*
* This file is part of OpenMiner.
*
* OpenMiner is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* OpenMiner is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with OpenMiner; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* =====================================================================================
*/
#ifndef SERVERSCENE_HPP_
#define SERVERSCENE_HPP_
#include "Scene.hpp"
class ServerScene : public Scene {
public:
ServerScene();
void update() override;
};
#endif // SERVERSCENE_HPP_

View File

@ -33,6 +33,8 @@
#include "ServerPlayer.hpp"
#include "ServerWorld.hpp"
#include "Dimension.hpp" // FIXME
void ServerWorld::update() {
if (m_lastTick < m_clock.getTicks() / 50) {
m_lastTick = m_clock.getTicks() / 50;
@ -51,6 +53,18 @@ void ServerWorld::update() {
}
}
}
m_scene.update();
// FIXME: Should be placed somewhere else
// FIXME: Shouldn't send that often
if (m_clock.getTicks() % 100 < 12) {
sf::Packet packet;
packet << Network::Command::SceneState; // FIXME
packet << m_dimension.id();
packet << m_scene;
m_server->server().sendToAllClients(packet);
}
}
void ServerWorld::createChunkNeighbours(ServerChunk &chunk) {
@ -146,6 +160,13 @@ void ServerWorld::sendRequestedData(ClientInfo &client, int cx, int cy, int cz)
sendChunkData(client, chunk);
}
#include "ItemDropFactory.hpp" // FIXME
void ServerWorld::onBlockDestroyed(int x, int y, int z, const Block &block) {
// FIXME if (Config::useItemDrops)
ItemDropFactory::create(m_scene.registry(), x, y, z, block.getItemDrop().item().stringID(), block.getItemDrop().amount());
}
ServerChunk &ServerWorld::createChunk(s32 cx, s32 cy, s32 cz) {
ServerChunk *chunk = (ServerChunk *)getChunk(cx, cy, cz);
if (!chunk) {

View File

@ -30,6 +30,7 @@
#include <unordered_map>
#include "ServerChunk.hpp"
#include "ServerScene.hpp"
#include "TerrainGenerator.hpp"
#include "World.hpp"
@ -55,6 +56,8 @@ class ServerWorld : public World {
void sendChunkData(const ClientInfo &client, ServerChunk &chunk);
void sendRequestedData(ClientInfo &client, s32 cx, s32 cy, s32 cz);
void onBlockDestroyed(int x, int y, int z, const Block &block) override;
ServerChunk &createChunk(s32 cx, s32 cy, s32 cz);
Chunk *getChunk(int cx, int cy, int cz) const override;
@ -79,6 +82,8 @@ class ServerWorld : public World {
ServerCommandHandler *m_server = nullptr;
gk::GameClock &m_clock;
ServerScene m_scene;
};
#endif // SERVERWORLD_HPP_