From 0653b802b843eb9d6ee38af4efaa963e6199beef Mon Sep 17 00:00:00 2001 From: Quentin Bazin Date: Wed, 20 May 2020 04:47:26 +0200 Subject: [PATCH] [Scene] Added 'createEntityFromModel()'. --- external/entt | 2 +- source/common/scene/Scene.cpp | 95 +++++++++++++++++++ source/common/scene/Scene.hpp | 8 +- .../scene/component/LuaCallbackComponent.hpp | 0 source/server/lua/loader/LuaEntityLoader.cpp | 49 ++++------ 5 files changed, 119 insertions(+), 35 deletions(-) create mode 100644 source/common/scene/Scene.cpp rename source/{server => common}/scene/component/LuaCallbackComponent.hpp (100%) diff --git a/external/entt b/external/entt index 0adee56d..39baa596 160000 --- a/external/entt +++ b/external/entt @@ -1 +1 @@ -Subproject commit 0adee56d764686c16fbccfa1eee2446efdce737c +Subproject commit 39baa59625ff59cda4425721a0c52819fd715476 diff --git a/source/common/scene/Scene.cpp b/source/common/scene/Scene.cpp new file mode 100644 index 00000000..8c2d5e12 --- /dev/null +++ b/source/common/scene/Scene.cpp @@ -0,0 +1,95 @@ +/* + * ===================================================================================== + * + * OpenMiner + * + * Copyright (C) 2018-2020 Unarelith, Quentin Bazin + * 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 + +#include + +#include "Scene.hpp" + +Scene::Scene() { + registerComponents(); +} + +void Scene::update() { + for (auto &controller : m_controllers) + controller->update(m_registry); +} + +// Opaque entity stamper: https://github.com/skypjack/entt/issues/481#issuecomment-627614706 +entt::entity Scene::createEntityFromModel(entt::registry &modelRegistry, entt::entity modelEntity) { + if (!modelRegistry.valid(modelEntity)) { + gkError() << "Failed to create entity from model: Model entity with ID" << (u32)modelEntity << "doesn't exist"; + return entt::null; + } + + auto other = m_registry.create(); + 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 +Type &get(entt::registry ®istry, entt::entity entity) { + return registry.get_or_emplace(entity); +} + +template +Type &set(entt::registry ®istry, entt::entity entity, const Type &instance) { + return registry.emplace_or_replace(entity, instance); +} + +template +void extend_meta_type() { + entt::meta().type() + .template func<&get, entt::as_ref_t>("get"_hs) + .template func<&set>("set"_hs); +} + +#include + +#include "AnimationComponent.hpp" +#include "DrawableDef.hpp" +#include "ItemStack.hpp" +#include "LuaCallbackComponent.hpp" +#include "NetworkComponent.hpp" +#include "PositionComponent.hpp" +#include "RotationComponent.hpp" + +void Scene::registerComponents() { + extend_meta_type(); + extend_meta_type(); + extend_meta_type(); + extend_meta_type(); + extend_meta_type(); + extend_meta_type(); + extend_meta_type(); + extend_meta_type(); +} + diff --git a/source/common/scene/Scene.hpp b/source/common/scene/Scene.hpp index 01ad4038..cc3782dc 100644 --- a/source/common/scene/Scene.hpp +++ b/source/common/scene/Scene.hpp @@ -34,12 +34,18 @@ class Scene { public: - virtual void update() { for (auto &controller : m_controllers) controller->update(m_registry); } + Scene(); + + virtual void update(); + + entt::entity createEntityFromModel(entt::registry &modelRegistry, entt::entity modelEntity); const entt::registry ®istry() const { return m_registry; } entt::registry ®istry() { return m_registry; } protected: + void registerComponents(); + mutable entt::registry m_registry; std::deque> m_controllers; diff --git a/source/server/scene/component/LuaCallbackComponent.hpp b/source/common/scene/component/LuaCallbackComponent.hpp similarity index 100% rename from source/server/scene/component/LuaCallbackComponent.hpp rename to source/common/scene/component/LuaCallbackComponent.hpp diff --git a/source/server/lua/loader/LuaEntityLoader.cpp b/source/server/lua/loader/LuaEntityLoader.cpp index c11f7e92..d218a491 100644 --- a/source/server/lua/loader/LuaEntityLoader.cpp +++ b/source/server/lua/loader/LuaEntityLoader.cpp @@ -35,6 +35,7 @@ #include "PositionComponent.hpp" #include "Registry.hpp" #include "RotationComponent.hpp" +#include "WorldController.hpp" void LuaEntityLoader::loadEntity(const sol::table &table) const { std::string stringID = m_mod.id() + ":" + table["id"].get(); @@ -101,8 +102,6 @@ void LuaEntityLoader::loadEntity(const sol::table &table) const { } } -#include "WorldController.hpp" - void LuaEntityLoader::spawnEntity(const std::string &entityID, const sol::table &table) const { gk::Vector3f pos; u16 dim; @@ -125,43 +124,27 @@ void LuaEntityLoader::spawnEntity(const std::string &entityID, const sol::table stack.setAmount(itemStack.value()[2].get_or(1)); } - // Create entity copy here - entt::registry ®istry = Registry::getInstance().entityRegistry(); - entt::entity entityModel = Registry::getInstance().getEntityFromStringID(entityID); - if (entityModel != entt::null) { + entt::registry &modelRegistry = Registry::getInstance().entityRegistry(); + entt::entity modelEntity = Registry::getInstance().getEntityFromStringID(entityID); + if (modelEntity != entt::null) { ServerWorld &world = m_worldController.getWorld(dim); - entt::registry &sceneRegistry = world.scene().registry(); - entt::entity entity = sceneRegistry.create(); + Scene &scene = world.scene(); + entt::registry ®istry = scene.registry(); + entt::entity entity = scene.createEntityFromModel(modelRegistry, modelEntity); - sceneRegistry.emplace(entity, pos.x, pos.y, pos.z, dim); - sceneRegistry.emplace(entity, entity); + registry.emplace(entity, pos.x, pos.y, pos.z, dim); + registry.emplace(entity, entity); - if (registry.has(entityModel)) - sceneRegistry.emplace(entity); - - auto *luaCallbackComponent = registry.try_get(entityModel); - if (luaCallbackComponent) - sceneRegistry.emplace(entity, *luaCallbackComponent); - - auto *drawable = registry.try_get(entityModel); - if (drawable) { - auto &drawableDef = sceneRegistry.emplace(entity, *drawable); - if (stack.amount()) { - auto &cube = drawableDef.getInventoryCubeDef(); + // FIXME: This code is too specific to the item drop entity + if (stack.amount()) { + auto *drawable = registry.try_get(entity); + if (drawable) { + auto &cube = drawable->getInventoryCubeDef(); cube.blockID = stack.item().stringID(); } + + registry.emplace(entity, stack); } - - auto *animation = registry.try_get(entityModel); - if (animation) - sceneRegistry.emplace(entity, *animation); - - auto *hitbox = registry.try_get(entityModel); - if (hitbox) - sceneRegistry.emplace(entity, *hitbox); - - if (stack.amount()) - sceneRegistry.emplace(entity, stack); } else gkError() << "In mod '" + m_mod.id() + "': Cannot find entity with id '" + entityID + "'";