#pragma once #include #include #include #include #include "constants.hpp" #include "physics/Hitbox.hpp" #include "Transform.hpp" #include "Rigidbody.hpp" #include "ScriptComponents.hpp" #include "typedefs.hpp" #include "util/Clock.hpp" #include #include struct EntityDef; class Level; class Assets; class Entity; class LineBatch; class ModelBatch; class Frustum; class Entities; class DrawContext; namespace rigging { struct Skeleton; class SkeletonConfig; } class Entities final { std::unique_ptr registry; Level& level; std::unordered_map entities; std::unordered_map uids; entityid_t nextID = 1; util::Clock sensorsTickClock; util::Clock updateTickClock; Assets* assets = nullptr; void updateSensors( Rigidbody& body, const Transform& tsf, std::vector& sensors ); void preparePhysics(float delta); public: Entities(Level& level); ~Entities(); void setAssets(Assets& assets); void clean(); void updatePhysics(float delta); void update(float delta); void renderDebug( LineBatch& batch, const Frustum* frustum, const DrawContext& ctx ); void render( const Assets& assets, ModelBatch& batch, const Frustum* frustum, entityid_t fpsEntity ); entityid_t spawn( const EntityDef& def, glm::vec3 position, dv::value args = nullptr, dv::value saved = nullptr, entityid_t uid = 0 ); std::optional get(entityid_t id); struct RaycastSettings { /// @param ignore Ignored entity uid entityid_t ignoredUid; /// @param solidEntitiesOnly If true, only entities with solid hitboxes /// will be checked bool solidEntitiesOnly = false; bool entityFilterExcludeMode = false; const std::set* entitiesFilter = nullptr; bool includeNonSelectable = false; }; struct RaycastResult { entityid_t entity; glm::ivec3 normal; float distance; }; /// @brief Entities raycast. No blocks check included, use combined with /// Chunks.rayCast /// @param start Ray start /// @param dir Ray direction normalized vector /// @param maxDistance Max ray length /// @return An optional structure containing entity, normal and distance std::optional rayCast( glm::vec3 start, glm::vec3 dir, float maxDistance, const RaycastSettings& settings ); void loadEntities(dv::value map); void loadEntity(const dv::value& map); void loadEntity(const dv::value& map, Entity entity); void onSave(const Entity& entity); bool hasBlockingInside(AABB aabb); std::vector getAllInside(AABB aabb); std::vector getAllInRadius(glm::vec3 center, float radius); void despawn(entityid_t id); void despawn(std::vector entities); dv::value serialize(const std::vector& entities); void setNextID(entityid_t id) { nextID = id; } inline size_t size() const { return entities.size(); } inline entityid_t peekNextID() const { return nextID; } };