diff --git a/src/frontend/debug_panel.cpp b/src/frontend/debug_panel.cpp index 06ab5fc8..5e238f42 100644 --- a/src/frontend/debug_panel.cpp +++ b/src/frontend/debug_panel.cpp @@ -18,6 +18,7 @@ #include "objects/Players.hpp" #include "objects/Entities.hpp" #include "objects/EntityDef.hpp" +#include "objects/Entity.hpp" #include "physics/Hitbox.hpp" #include "util/stringutil.hpp" #include "voxels/Block.hpp" diff --git a/src/graphics/render/Decorator.cpp b/src/graphics/render/Decorator.cpp index dc928b4d..4742b68f 100644 --- a/src/graphics/render/Decorator.cpp +++ b/src/graphics/render/Decorator.cpp @@ -15,6 +15,7 @@ #include "objects/Player.hpp" #include "objects/Players.hpp" #include "objects/Entities.hpp" +#include "objects/Entity.hpp" #include "logic/LevelController.hpp" #include "util/stringutil.hpp" #include "engine/Engine.hpp" diff --git a/src/graphics/render/Emitter.cpp b/src/graphics/render/Emitter.cpp index cdc883ae..483a6339 100644 --- a/src/graphics/render/Emitter.cpp +++ b/src/graphics/render/Emitter.cpp @@ -7,6 +7,7 @@ #include "window/Camera.hpp" #include "graphics/core/Texture.hpp" #include "objects/Entities.hpp" +#include "objects/Entity.hpp" #include "world/Level.hpp" Emitter::Emitter( diff --git a/src/logic/PlayerController.cpp b/src/logic/PlayerController.cpp index df471c36..f5fdea1b 100644 --- a/src/logic/PlayerController.cpp +++ b/src/logic/PlayerController.cpp @@ -13,6 +13,7 @@ #include "items/ItemStack.hpp" #include "lighting/Lighting.hpp" #include "objects/Entities.hpp" +#include "objects/Entity.hpp" #include "objects/Player.hpp" #include "objects/Players.hpp" #include "physics/Hitbox.hpp" @@ -309,16 +310,7 @@ void PlayerController::updateKeyboard(const Input& inputEvents) { } void PlayerController::resetKeyboard() { - input.zoom = false; - input.moveForward = false; - input.moveBack = false; - input.moveLeft = false; - input.moveRight = false; - input.sprint = false; - input.shift = false; - input.cheat = false; - input.jump = false; - input.delta = {}; + input = {}; } void PlayerController::updatePlayer(float delta) { @@ -338,7 +330,8 @@ static int determine_rotation( if (norm.z > 0.0f) return BLOCK_DIR_NORTH; if (norm.z < 0.0f) return BLOCK_DIR_SOUTH; } else if (name == "pane" || name == "stairs") { - int verticalBit = (name == "stairs" && (norm.y - camDir.y * 0.5f) < 0.0) ? 4 : 0; + int verticalBit = + (name == "stairs" && (norm.y - camDir.y * 0.5f) < 0.0) ? 4 : 0; if (abs(camDir.x) > abs(camDir.z)) { if (camDir.x > 0.0f) return BLOCK_DIR_EAST | verticalBit; if (camDir.x < 0.0f) return BLOCK_DIR_WEST | verticalBit; diff --git a/src/logic/scripting/lua/libs/libentity.cpp b/src/logic/scripting/lua/libs/libentity.cpp index 8e00aa1c..45e4e14e 100644 --- a/src/logic/scripting/lua/libs/libentity.cpp +++ b/src/logic/scripting/lua/libs/libentity.cpp @@ -4,6 +4,8 @@ #include "engine/Engine.hpp" #include "objects/Entities.hpp" #include "objects/EntityDef.hpp" +#include "objects/Entity.hpp" +#include "objects/Rigidbody.hpp" #include "objects/Player.hpp" #include "objects/rigging.hpp" #include "physics/Hitbox.hpp" diff --git a/src/logic/scripting/lua/libs/libentity.hpp b/src/logic/scripting/lua/libs/libentity.hpp index b7708f02..5400b449 100644 --- a/src/logic/scripting/lua/libs/libentity.hpp +++ b/src/logic/scripting/lua/libs/libentity.hpp @@ -4,6 +4,7 @@ #include "frontend/hud.hpp" #include "objects/Entities.hpp" +#include "objects/Entity.hpp" #include "world/Level.hpp" #include "logic/LevelController.hpp" #include "api_lua.hpp" diff --git a/src/logic/scripting/lua/libs/libplayer.cpp b/src/logic/scripting/lua/libs/libplayer.cpp index d4e55b77..d850231d 100644 --- a/src/logic/scripting/lua/libs/libplayer.cpp +++ b/src/logic/scripting/lua/libs/libplayer.cpp @@ -5,6 +5,7 @@ #include "objects/Entities.hpp" #include "objects/Player.hpp" #include "objects/Players.hpp" +#include "objects/Entity.hpp" #include "physics/Hitbox.hpp" #include "window/Camera.hpp" #include "world/Level.hpp" diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 56c5a17e..87044201 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -21,6 +21,7 @@ #include "maths/Heightmap.hpp" #include "objects/Entities.hpp" #include "objects/EntityDef.hpp" +#include "objects/Entity.hpp" #include "objects/Player.hpp" #include "util/stringutil.hpp" #include "util/timeutil.hpp" diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index cdf979e0..5088a70d 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -17,6 +17,7 @@ #include "maths/FrustumCulling.hpp" #include "maths/rays.hpp" #include "EntityDef.hpp" +#include "Entity.hpp" #include "rigging.hpp" #include "physics/Hitbox.hpp" #include "physics/PhysicsSolver.hpp" @@ -24,103 +25,16 @@ static debug::Logger logger("entities"); -static inline std::string COMP_TRANSFORM = "transform"; -static inline std::string COMP_RIGIDBODY = "rigidbody"; -static inline std::string COMP_SKELETON = "skeleton"; -static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA"; - -void Transform::refresh() { - combined = glm::mat4(1.0f); - combined = glm::translate(combined, pos); - combined = combined * glm::mat4(rot); - combined = glm::scale(combined, size); - displayPos = pos; - displaySize = size; - dirty = false; -} - -void Entity::setInterpolatedPosition(const glm::vec3& position) { - getSkeleton().interpolation.refresh(position); -} - -glm::vec3 Entity::getInterpolatedPosition() const { - const auto& skeleton = getSkeleton(); - if (skeleton.interpolation.isEnabled()) { - return skeleton.interpolation.getCurrent(); - } - return getTransform().pos; -} - -void Entity::destroy() { - if (isValid()) { - entities.despawn(id); - } -} - -rigging::Skeleton& Entity::getSkeleton() const { - return registry.get(entity); -} - -void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { - auto& skeleton = registry.get(entity); - skeleton.config = rigConfig; - skeleton.pose.matrices.resize( - rigConfig->getBones().size(), glm::mat4(1.0f) - ); - skeleton.calculated.matrices.resize( - rigConfig->getBones().size(), glm::mat4(1.0f) - ); -} - Entities::Entities(Level& level) : level(level), sensorsTickClock(20, 3), updateTickClock(20, 3) { } -template -static sensorcallback create_sensor_callback(Entities* entities) { - return [=](auto entityid, auto index, auto otherid) { - if (auto entity = entities->get(entityid)) { - if (entity->isValid()) { - callback(*entity, index, otherid); - } - } - }; -} - -static void initialize_body( - const EntityDef& def, Rigidbody& body, entityid_t id, Entities* entities -) { - body.sensors.resize(def.radialSensors.size() + def.boxSensors.size()); - for (auto& [i, box] : def.boxSensors) { - SensorParams params {}; - params.aabb = box; - body.sensors[i] = Sensor { - true, - SensorType::AABB, - i, - id, - params, - params, - {}, - {}, - create_sensor_callback(entities), - create_sensor_callback(entities)}; - } - for (auto& [i, radius] : def.radialSensors) { - SensorParams params {}; - params.radial = glm::vec4(radius); - body.sensors[i] = Sensor { - true, - SensorType::RADIUS, - i, - id, - params, - params, - {}, - {}, - create_sensor_callback(entities), - create_sensor_callback(entities)}; +std::optional Entities::get(entityid_t id) { + const auto& found = entities.find(id); + if (found != entities.end() && registry.valid(found->second)) { + return Entity(*this, id, registry, found->second); } + return std::nullopt; } entityid_t Entities::spawn( @@ -168,7 +82,7 @@ entityid_t Entities::spawn( Hitbox {def.bodyType, position, def.hitbox * 0.5f}, std::vector {} ); - initialize_body(def, body, id, this); + body.initialize(def, id, *this); auto& scripting = registry.emplace(entity); registry.emplace(entity, skeleton->instance()); @@ -232,8 +146,8 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { if (skeletonName != skeleton.config->getName()) { skeleton.config = level.content.getSkeleton(skeletonName); } - if (auto found = map.at(COMP_SKELETON)) { - auto& skeletonmap = *found; + if (auto foundSkeleton = map.at(COMP_SKELETON)) { + auto& skeletonmap = *foundSkeleton; if (auto found = skeletonmap.at("textures")) { auto& texturesmap = *found; for (auto& [slot, _] : texturesmap.asObject()) { @@ -284,7 +198,7 @@ std::optional Entities::rayCast( void Entities::loadEntities(dv::value root) { clean(); - auto& list = root["data"]; + const auto& list = root["data"]; for (auto& map : list) { try { loadEntity(map); @@ -298,74 +212,6 @@ void Entities::onSave(const Entity& entity) { scripting::on_entity_save(entity); } -dv::value Entities::serialize(const Entity& entity) { - auto root = dv::object(); - auto& eid = entity.getID(); - auto& def = eid.def; - root["def"] = def.name; - root["uid"] = eid.uid; - { - auto& transform = entity.getTransform(); - auto& tsfmap = root.object(COMP_TRANSFORM); - tsfmap["pos"] = dv::to_value(transform.pos); - if (transform.size != glm::vec3(1.0f)) { - tsfmap["size"] = dv::to_value(transform.size); - } - if (transform.rot != glm::mat3(1.0f)) { - tsfmap["rot"] = dv::to_value(transform.rot); - } - } - { - auto& rigidbody = entity.getRigidbody(); - auto& hitbox = rigidbody.hitbox; - auto& bodymap = root.object(COMP_RIGIDBODY); - if (!rigidbody.enabled) { - bodymap["enabled"] = false; - } - if (def.save.body.velocity) { - bodymap["vel"] = dv::to_value(rigidbody.hitbox.velocity); - } - if (def.save.body.settings) { - bodymap["damping"] = rigidbody.hitbox.linearDamping; - if (hitbox.type != def.bodyType) { - bodymap["type"] = BodyTypeMeta.getNameString(hitbox.type); - } - if (hitbox.crouching) { - bodymap["crouch"] = hitbox.crouching; - } - } - } - auto& skeleton = entity.getSkeleton(); - if (skeleton.config->getName() != def.skeletonName) { - root["skeleton"] = skeleton.config->getName(); - } - if (def.save.skeleton.pose || def.save.skeleton.textures) { - auto& skeletonmap = root.object(COMP_SKELETON); - if (def.save.skeleton.textures) { - auto& map = skeletonmap.object("textures"); - for (auto& [slot, texture] : skeleton.textures) { - map[slot] = texture; - } - } - if (def.save.skeleton.pose) { - auto& list = skeletonmap.list("pose"); - for (auto& mat : skeleton.pose.matrices) { - list.add(dv::to_value(mat)); - } - } - } - auto& scripts = entity.getScripting(); - if (!scripts.components.empty()) { - auto& compsMap = root.object("comps"); - for (auto& comp : scripts.components) { - auto data = - scripting::get_component_value(comp->env, SAVED_DATA_VARNAME); - compsMap[comp->name] = data; - } - } - return root; -} - dv::value Entities::serialize(const std::vector& entities) { auto list = dv::list(); for (auto& entity : entities) { @@ -375,7 +221,7 @@ dv::value Entities::serialize(const std::vector& entities) { } level.entities->onSave(entity); if (!eid.destroyFlag) { - list.add(level.entities->serialize(entity)); + list.add(entity.serialize()); } } return list; diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index 5bd8f955..99da0db3 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -5,108 +5,21 @@ #include #include -#include "data/dv.hpp" #include "physics/Hitbox.hpp" +#include "Transform.hpp" +#include "Rigidbody.hpp" +#include "ScriptComponents.hpp" #include "typedefs.hpp" #include "util/Clock.hpp" -#define GLM_ENABLE_EXPERIMENTAL -#include -#include -#include -struct EntityFuncsSet { - bool init; - bool on_despawn; - bool on_grounded; - bool on_fall; - bool on_sensor_enter; - bool on_sensor_exit; - bool on_save; - bool on_aim_on; - bool on_aim_off; - bool on_attacked; - bool on_used; -}; +#include +#include struct EntityDef; -struct EntityId { - entityid_t uid; - const EntityDef& def; - bool destroyFlag = false; - int64_t player = -1; -}; - -struct Transform { - static inline constexpr float EPSILON = 0.0000001f; - glm::vec3 pos; - glm::vec3 size; - glm::mat3 rot; - glm::mat4 combined; - bool dirty = true; - - glm::vec3 displayPos; - glm::vec3 displaySize; - - void refresh(); - - inline void setRot(glm::mat3 m) { - rot = m; - dirty = true; - } - - inline void setSize(glm::vec3 v) { - if (glm::distance2(displaySize, v) >= EPSILON) { - dirty = true; - } - size = v; - } - - inline void setPos(glm::vec3 v) { - if (glm::distance2(displayPos, v) >= EPSILON) { - dirty = true; - } - pos = v; - } -}; - -struct Rigidbody { - bool enabled = true; - Hitbox hitbox; - std::vector sensors; -}; - -struct UserComponent { - std::string name; - EntityFuncsSet funcsset; - scriptenv env; - dv::value params; - - UserComponent( - const std::string& name, - EntityFuncsSet funcsset, - scriptenv env, - dv::value params - ) - : name(name), - funcsset(funcsset), - env(std::move(env)), - params(std::move(params)) { - } -}; - -struct ScriptComponents { - std::vector> components; - - ScriptComponents() = default; - - ScriptComponents(ScriptComponents&& other) - : components(std::move(other.components)) { - } -}; - class Level; class Assets; +class Entity; class LineBatch; class ModelBatch; class Frustum; @@ -118,72 +31,6 @@ namespace rigging { class SkeletonConfig; } -class Entity { - Entities& entities; - entityid_t id; - entt::registry& registry; - const entt::entity entity; -public: - Entity( - Entities& entities, - entityid_t id, - entt::registry& registry, - const entt::entity entity - ) - : entities(entities), id(id), registry(registry), entity(entity) { - } - - EntityId& getID() const { - return registry.get(entity); - } - - bool isValid() const { - return registry.valid(entity); - } - - const EntityDef& getDef() const { - return registry.get(entity).def; - } - - Transform& getTransform() const { - return registry.get(entity); - } - - Rigidbody& getRigidbody() const { - return registry.get(entity); - } - - ScriptComponents& getScripting() const { - return registry.get(entity); - } - - rigging::Skeleton& getSkeleton() const; - - void setRig(const rigging::SkeletonConfig* rigConfig); - - entityid_t getUID() const { - return registry.get(entity).uid; - } - - entt::entity getHandler() const { - return entity; - } - - int64_t getPlayer() const { - return registry.get(entity).player; - } - - void setPlayer(int64_t id) { - registry.get(entity).player = id; - } - - void setInterpolatedPosition(const glm::vec3& position); - - glm::vec3 getInterpolatedPosition() const; - - void destroy(); -}; - class Entities { entt::registry registry; Level& level; @@ -229,13 +76,7 @@ public: entityid_t uid = 0 ); - std::optional get(entityid_t id) { - const auto& found = entities.find(id); - if (found != entities.end() && registry.valid(found->second)) { - return Entity(*this, id, registry, found->second); - } - return std::nullopt; - } + std::optional get(entityid_t id); /// @brief Entities raycast. No blocks check included, use combined with /// Chunks.rayCast @@ -260,7 +101,6 @@ public: std::vector getAllInRadius(glm::vec3 center, float radius); void despawn(entityid_t id); void despawn(std::vector entities); - dv::value serialize(const Entity& entity); dv::value serialize(const std::vector& entities); void setNextID(entityid_t id) { diff --git a/src/objects/Entity.cpp b/src/objects/Entity.cpp new file mode 100644 index 00000000..24aa1736 --- /dev/null +++ b/src/objects/Entity.cpp @@ -0,0 +1,119 @@ +#include "Entity.hpp" + +#include "Transform.hpp" +#include "Rigidbody.hpp" +#include "ScriptComponents.hpp" +#include "Entities.hpp" +#include "EntityDef.hpp" +#include "rigging.hpp" +#include "logic/scripting/scripting.hpp" + +#include + +static inline std::string SAVED_DATA_VARNAME = "SAVED_DATA"; + +void Entity::setInterpolatedPosition(const glm::vec3& position) { + getSkeleton().interpolation.refresh(position); +} + +glm::vec3 Entity::getInterpolatedPosition() const { + const auto& skeleton = getSkeleton(); + if (skeleton.interpolation.isEnabled()) { + return skeleton.interpolation.getCurrent(); + } + return getTransform().pos; +} + +void Entity::destroy() { + if (isValid()) { + entities.despawn(id); + } +} + +rigging::Skeleton& Entity::getSkeleton() const { + return registry.get(entity); +} + +void Entity::setRig(const rigging::SkeletonConfig* rigConfig) { + auto& skeleton = registry.get(entity); + skeleton.config = rigConfig; + skeleton.pose.matrices.resize( + rigConfig->getBones().size(), glm::mat4(1.0f) + ); + skeleton.calculated.matrices.resize( + rigConfig->getBones().size(), glm::mat4(1.0f) + ); +} + +dv::value Entity::serialize() const { + const auto& eid = getID(); + const auto& def = eid.def; + const auto& transform = getTransform(); + const auto& rigidbody = getRigidbody(); + const auto& skeleton = getSkeleton(); + const auto& scripts = getScripting(); + + auto root = dv::object(); + root["def"] = def.name; + root["uid"] = eid.uid; + + root[COMP_TRANSFORM] = transform.serialize(); + root[COMP_RIGIDBODY] = + rigidbody.serialize(def.save.body.velocity, def.save.body.settings); + + if (skeleton.config->getName() != def.skeletonName) { + root["skeleton"] = skeleton.config->getName(); + } + if (def.save.skeleton.pose || def.save.skeleton.textures) { + root[COMP_SKELETON] = skeleton.serialize( + def.save.skeleton.pose, def.save.skeleton.textures + ); + } + if (!scripts.components.empty()) { + auto& compsMap = root.object("comps"); + for (auto& comp : scripts.components) { + auto data = + scripting::get_component_value(comp->env, SAVED_DATA_VARNAME); + compsMap[comp->name] = data; + } + } + return root; +} + +EntityId& Entity::getID() const { + return registry.get(entity); +} + +bool Entity::isValid() const { + return registry.valid(entity); +} + +Transform& Entity::getTransform() const { + return registry.get(entity); +} + + +ScriptComponents& Entity::getScripting() const { + return registry.get(entity); +} + +const EntityDef& Entity::getDef() const { + return registry.get(entity).def; +} + +Rigidbody& Entity::getRigidbody() const { + return registry.get(entity); +} + +entityid_t Entity::getUID() const { + return registry.get(entity).uid; +} + +int64_t Entity::getPlayer() const { + return registry.get(entity).player; +} + +void Entity::setPlayer(int64_t id) { + registry.get(entity).player = id; +} + diff --git a/src/objects/Entity.hpp b/src/objects/Entity.hpp new file mode 100644 index 00000000..b7e8c273 --- /dev/null +++ b/src/objects/Entity.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include "typedefs.hpp" +#include "data/dv_fwd.hpp" + +#include +#include + +class Entities; +struct EntityDef; +struct Transform; +struct Rigidbody; +struct ScriptComponents; + +inline std::string COMP_TRANSFORM = "transform"; +inline std::string COMP_RIGIDBODY = "rigidbody"; +inline std::string COMP_SKELETON = "skeleton"; + +namespace rigging { + struct Skeleton; + class SkeletonConfig; +} + +struct EntityId { + entityid_t uid; + const EntityDef& def; + bool destroyFlag = false; + int64_t player = -1; +}; + +class Entity { + Entities& entities; + entityid_t id; + entt::registry& registry; + const entt::entity entity; +public: + Entity( + Entities& entities, + entityid_t id, + entt::registry& registry, + const entt::entity entity + ) + : entities(entities), id(id), registry(registry), entity(entity) { + } + + dv::value serialize() const; + + EntityId& getID() const; + + bool isValid() const; + + const EntityDef& getDef() const; + + Transform& getTransform() const; + + Rigidbody& getRigidbody() const; + + ScriptComponents& getScripting() const; + + rigging::Skeleton& getSkeleton() const; + + void setRig(const rigging::SkeletonConfig* rigConfig); + + entityid_t getUID() const; + + int64_t getPlayer() const; + + void setPlayer(int64_t id); + + void setInterpolatedPosition(const glm::vec3& position); + + glm::vec3 getInterpolatedPosition() const; + + entt::entity getHandler() const { + return entity; + } + + void destroy(); +}; diff --git a/src/objects/Player.cpp b/src/objects/Player.cpp index 21497244..8f2b0d76 100644 --- a/src/objects/Player.cpp +++ b/src/objects/Player.cpp @@ -9,6 +9,7 @@ #include "content/ContentReport.hpp" #include "items/Inventory.hpp" #include "Entities.hpp" +#include "Entity.hpp" #include "rigging.hpp" #include "physics/Hitbox.hpp" #include "physics/PhysicsSolver.hpp" @@ -137,7 +138,7 @@ void Player::updateInput(PlayerInput& input, float delta) { } if (glm::length(dir) > 0.0f) { dir = glm::normalize(dir); - hitbox->velocity += dir * speed * delta * 9.0f; + doMove(dir, speed, delta); } if (flight) { if (input.jump) { @@ -146,9 +147,22 @@ void Player::updateInput(PlayerInput& input, float delta) { if (input.shift) { hitbox->velocity.y -= speed * delta * 9; } + } else if (input.jump) { + doJump(); } - if (input.jump && hitbox->grounded) { - hitbox->velocity.y = JUMP_FORCE; +} + +void Player::doMove(const glm::vec3& dir, float speed, float delta) { + if (auto hitbox = getHitbox()) { + hitbox->velocity += dir * speed * delta * 9.0f; + } +} + +void Player::doJump() { + if (auto hitbox = getHitbox()) { + if (hitbox->grounded) { + hitbox->velocity.y = JUMP_FORCE; + } } } diff --git a/src/objects/Player.hpp b/src/objects/Player.hpp index c4d847b3..2da8ee1d 100644 --- a/src/objects/Player.hpp +++ b/src/objects/Player.hpp @@ -59,6 +59,9 @@ class Player : public Serializable { entityid_t eid = ENTITY_AUTO; entityid_t selectedEid = 0; + void doMove(const glm::vec3& dir, float speed, float delta); + void doJump(); + glm::vec3 rotation {}; public: util::VecInterpolation<3, float, true> rotationInterpolation {true}; diff --git a/src/objects/Rigidbody.cpp b/src/objects/Rigidbody.cpp new file mode 100644 index 00000000..62f88128 --- /dev/null +++ b/src/objects/Rigidbody.cpp @@ -0,0 +1,74 @@ +#define VC_ENABLE_REFLECTION + +#include "Rigidbody.hpp" + +#include "EntityDef.hpp" +#include "Entities.hpp" +#include "Entity.hpp" +#include "data/dv_util.hpp" +#include "logic/scripting/scripting.hpp" + +dv::value Rigidbody::serialize(bool saveVelocity, bool saveBodySettings) const { + auto bodymap = dv::object(); + if (!enabled) { + bodymap["enabled"] = false; + } + if (saveVelocity) { + bodymap["vel"] = dv::to_value(hitbox.velocity); + } + if (saveBodySettings) { + bodymap["damping"] = hitbox.linearDamping; + bodymap["type"] = BodyTypeMeta.getNameString(hitbox.type); + if (hitbox.crouching) { + bodymap["crouch"] = hitbox.crouching; + } + } + return bodymap; +} + +template +static sensorcallback create_sensor_callback(Entities& entities) { + return [&entities](auto entityid, auto index, auto otherid) { + if (auto entity = entities.get(entityid)) { + if (entity->isValid()) { + callback(*entity, index, otherid); + } + } + }; +} + +void Rigidbody::initialize( + const EntityDef& def, entityid_t id, Entities& entities +) { + sensors.resize(def.radialSensors.size() + def.boxSensors.size()); + for (auto& [i, box] : def.boxSensors) { + SensorParams params {}; + params.aabb = box; + sensors[i] = Sensor { + true, + SensorType::AABB, + i, + id, + params, + params, + {}, + {}, + create_sensor_callback(entities), + create_sensor_callback(entities)}; + } + for (auto& [i, radius] : def.radialSensors) { + SensorParams params {}; + params.radial = glm::vec4(radius); + sensors[i] = Sensor { + true, + SensorType::RADIUS, + i, + id, + params, + params, + {}, + {}, + create_sensor_callback(entities), + create_sensor_callback(entities)}; + } +} diff --git a/src/objects/Rigidbody.hpp b/src/objects/Rigidbody.hpp new file mode 100644 index 00000000..818329d2 --- /dev/null +++ b/src/objects/Rigidbody.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "data/dv_fwd.hpp" +#include "physics/Hitbox.hpp" + +#include +#include + +class Entities; +struct EntityDef; + +struct Rigidbody { + bool enabled = true; + Hitbox hitbox; + std::vector sensors; + + dv::value serialize(bool saveVelocity, bool saveBodySettings) const; + + void initialize( + const EntityDef& def, entityid_t id, Entities& entities + ); +}; diff --git a/src/objects/ScriptComponents.hpp b/src/objects/ScriptComponents.hpp new file mode 100644 index 00000000..2711d482 --- /dev/null +++ b/src/objects/ScriptComponents.hpp @@ -0,0 +1,49 @@ +#pragma once + +#include "typedefs.hpp" +#include "data/dv.hpp" + +#include + +struct EntityFuncsSet { + bool init; + bool on_despawn; + bool on_grounded; + bool on_fall; + bool on_sensor_enter; + bool on_sensor_exit; + bool on_save; + bool on_aim_on; + bool on_aim_off; + bool on_attacked; + bool on_used; +}; + +struct UserComponent { + std::string name; + EntityFuncsSet funcsset; + scriptenv env; + dv::value params; + + UserComponent( + const std::string& name, + EntityFuncsSet funcsset, + scriptenv env, + dv::value params + ) + : name(name), + funcsset(funcsset), + env(std::move(env)), + params(std::move(params)) { + } +}; + +struct ScriptComponents { + std::vector> components; + + ScriptComponents() = default; + + ScriptComponents(ScriptComponents&& other) + : components(std::move(other.components)) { + } +}; diff --git a/src/objects/Transform.cpp b/src/objects/Transform.cpp new file mode 100644 index 00000000..9c14353e --- /dev/null +++ b/src/objects/Transform.cpp @@ -0,0 +1,25 @@ +#include "Transform.hpp" + +#include "data/dv_util.hpp" + +void Transform::refresh() { + combined = glm::mat4(1.0f); + combined = glm::translate(combined, pos); + combined = combined * glm::mat4(rot); + combined = glm::scale(combined, size); + displayPos = pos; + displaySize = size; + dirty = false; +} + +dv::value Transform::serialize() const { + auto tsfmap = dv::object(); + tsfmap["pos"] = dv::to_value(pos); + if (size != glm::vec3(1.0f)) { + tsfmap["size"] = dv::to_value(size); + } + if (rot != glm::mat3(1.0f)) { + tsfmap["rot"] = dv::to_value(rot); + } + return tsfmap; +} diff --git a/src/objects/Transform.hpp b/src/objects/Transform.hpp new file mode 100644 index 00000000..0eb73236 --- /dev/null +++ b/src/objects/Transform.hpp @@ -0,0 +1,43 @@ +#pragma once + +#define GLM_ENABLE_EXPERIMENTAL + +#include +#include +#include +#include + +struct Transform { + static inline constexpr float EPSILON = 0.0000001f; + glm::vec3 pos; + glm::vec3 size; + glm::mat3 rot; + glm::mat4 combined; + bool dirty = true; + + glm::vec3 displayPos; + glm::vec3 displaySize; + + dv::value serialize() const; + + void refresh(); + + inline void setRot(glm::mat3 m) { + rot = m; + dirty = true; + } + + inline void setSize(glm::vec3 v) { + if (glm::distance2(displaySize, v) >= EPSILON) { + dirty = true; + } + size = v; + } + + inline void setPos(glm::vec3 v) { + if (glm::distance2(displayPos, v) >= EPSILON) { + dirty = true; + } + pos = v; + } +}; diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index 69ec5ce1..58138a48 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -23,7 +23,7 @@ Bone::Bone( std::string name, std::string model, std::vector> bones, - glm::vec3 offset + const glm::vec3& offset ) : index(index), name(std::move(name)), @@ -53,6 +53,23 @@ Skeleton::Skeleton(const SkeletonConfig* config) } } +dv::value Skeleton::serialize(bool saveTextures, bool savePose) const { + auto root = dv::object(); + if (saveTextures) { + auto& map = root.object("textures"); + for (auto& [slot, texture] : textures) { + map[slot] = texture; + } + } + if (savePose) { + auto& list = root.list("pose"); + for (auto& mat : pose.matrices) { + list.add(dv::to_value(mat)); + } + } + return root; +} + static void get_all_nodes(std::vector& nodes, Bone* node) { nodes[node->getIndex()] = node; for (auto& subnode : node->getSubnodes()) { diff --git a/src/objects/rigging.hpp b/src/objects/rigging.hpp index 2c326a4a..0c377c43 100644 --- a/src/objects/rigging.hpp +++ b/src/objects/rigging.hpp @@ -9,6 +9,7 @@ #include #include "typedefs.hpp" +#include "data/dv_fwd.hpp" #include "util/Interpolation.hpp" class Assets; @@ -50,7 +51,7 @@ namespace rigging { std::string name, std::string model, std::vector> bones, - glm::vec3 offset + const glm::vec3& offset ); void setModel(const std::string& name); @@ -89,6 +90,8 @@ namespace rigging { util::VecInterpolation<3, float> interpolation {false}; Skeleton(const SkeletonConfig* config); + + dv::value serialize(bool saveTextures, bool savePose) const; }; class SkeletonConfig { diff --git a/src/voxels/GlobalChunks.cpp b/src/voxels/GlobalChunks.cpp index fbca2eec..7451a563 100644 --- a/src/voxels/GlobalChunks.cpp +++ b/src/voxels/GlobalChunks.cpp @@ -10,6 +10,7 @@ #include "lighting/Lightmap.hpp" #include "maths/voxmaths.hpp" #include "objects/Entities.hpp" +#include "objects/Entity.hpp" #include "voxels/blocks_agent.hpp" #include "typedefs.hpp" #include "world/LevelEvents.hpp" diff --git a/src/world/Level.cpp b/src/world/Level.cpp index c33c7e0f..2a1583bd 100644 --- a/src/world/Level.cpp +++ b/src/world/Level.cpp @@ -5,6 +5,7 @@ #include "items/Inventories.hpp" #include "items/Inventory.hpp" #include "objects/Entities.hpp" +#include "objects/Entity.hpp" #include "objects/Player.hpp" #include "objects/Players.hpp" #include "physics/Hitbox.hpp"