refactor Entities
This commit is contained in:
parent
36a522bee0
commit
3eae377024
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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<rigging::Skeleton>(entity);
|
||||
}
|
||||
|
||||
void Entity::setRig(const rigging::SkeletonConfig* rigConfig) {
|
||||
auto& skeleton = registry.get<rigging::Skeleton>(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 <void (*callback)(const Entity&, size_t, entityid_t)>
|
||||
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<scripting::on_sensor_enter>(entities),
|
||||
create_sensor_callback<scripting::on_sensor_exit>(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<scripting::on_sensor_enter>(entities),
|
||||
create_sensor_callback<scripting::on_sensor_exit>(entities)};
|
||||
std::optional<Entity> 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<Sensor> {}
|
||||
);
|
||||
initialize_body(def, body, id, this);
|
||||
body.initialize(def, id, *this);
|
||||
|
||||
auto& scripting = registry.emplace<ScriptComponents>(entity);
|
||||
registry.emplace<rigging::Skeleton>(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::RaycastResult> 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<Entity>& entities) {
|
||||
auto list = dv::list();
|
||||
for (auto& entity : entities) {
|
||||
@ -375,7 +221,7 @@ dv::value Entities::serialize(const std::vector<Entity>& entities) {
|
||||
}
|
||||
level.entities->onSave(entity);
|
||||
if (!eid.destroyFlag) {
|
||||
list.add(level.entities->serialize(entity));
|
||||
list.add(entity.serialize());
|
||||
}
|
||||
}
|
||||
return list;
|
||||
|
||||
@ -5,108 +5,21 @@
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#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 <entt/entity/registry.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
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 <entt/entity/registry.hpp>
|
||||
#include <unordered_map>
|
||||
|
||||
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<Sensor> 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<std::unique_ptr<UserComponent>> 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<EntityId>(entity);
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return registry.valid(entity);
|
||||
}
|
||||
|
||||
const EntityDef& getDef() const {
|
||||
return registry.get<EntityId>(entity).def;
|
||||
}
|
||||
|
||||
Transform& getTransform() const {
|
||||
return registry.get<Transform>(entity);
|
||||
}
|
||||
|
||||
Rigidbody& getRigidbody() const {
|
||||
return registry.get<Rigidbody>(entity);
|
||||
}
|
||||
|
||||
ScriptComponents& getScripting() const {
|
||||
return registry.get<ScriptComponents>(entity);
|
||||
}
|
||||
|
||||
rigging::Skeleton& getSkeleton() const;
|
||||
|
||||
void setRig(const rigging::SkeletonConfig* rigConfig);
|
||||
|
||||
entityid_t getUID() const {
|
||||
return registry.get<EntityId>(entity).uid;
|
||||
}
|
||||
|
||||
entt::entity getHandler() const {
|
||||
return entity;
|
||||
}
|
||||
|
||||
int64_t getPlayer() const {
|
||||
return registry.get<EntityId>(entity).player;
|
||||
}
|
||||
|
||||
void setPlayer(int64_t id) {
|
||||
registry.get<EntityId>(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<Entity> 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<Entity> get(entityid_t id);
|
||||
|
||||
/// @brief Entities raycast. No blocks check included, use combined with
|
||||
/// Chunks.rayCast
|
||||
@ -260,7 +101,6 @@ public:
|
||||
std::vector<Entity> getAllInRadius(glm::vec3 center, float radius);
|
||||
void despawn(entityid_t id);
|
||||
void despawn(std::vector<Entity> entities);
|
||||
dv::value serialize(const Entity& entity);
|
||||
dv::value serialize(const std::vector<Entity>& entities);
|
||||
|
||||
void setNextID(entityid_t id) {
|
||||
|
||||
119
src/objects/Entity.cpp
Normal file
119
src/objects/Entity.cpp
Normal file
@ -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 <entt/entt.hpp>
|
||||
|
||||
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<rigging::Skeleton>(entity);
|
||||
}
|
||||
|
||||
void Entity::setRig(const rigging::SkeletonConfig* rigConfig) {
|
||||
auto& skeleton = registry.get<rigging::Skeleton>(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<EntityId>(entity);
|
||||
}
|
||||
|
||||
bool Entity::isValid() const {
|
||||
return registry.valid(entity);
|
||||
}
|
||||
|
||||
Transform& Entity::getTransform() const {
|
||||
return registry.get<Transform>(entity);
|
||||
}
|
||||
|
||||
|
||||
ScriptComponents& Entity::getScripting() const {
|
||||
return registry.get<ScriptComponents>(entity);
|
||||
}
|
||||
|
||||
const EntityDef& Entity::getDef() const {
|
||||
return registry.get<EntityId>(entity).def;
|
||||
}
|
||||
|
||||
Rigidbody& Entity::getRigidbody() const {
|
||||
return registry.get<Rigidbody>(entity);
|
||||
}
|
||||
|
||||
entityid_t Entity::getUID() const {
|
||||
return registry.get<EntityId>(entity).uid;
|
||||
}
|
||||
|
||||
int64_t Entity::getPlayer() const {
|
||||
return registry.get<EntityId>(entity).player;
|
||||
}
|
||||
|
||||
void Entity::setPlayer(int64_t id) {
|
||||
registry.get<EntityId>(entity).player = id;
|
||||
}
|
||||
|
||||
79
src/objects/Entity.hpp
Normal file
79
src/objects/Entity.hpp
Normal file
@ -0,0 +1,79 @@
|
||||
#pragma once
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "data/dv_fwd.hpp"
|
||||
|
||||
#include <entt/fwd.hpp>
|
||||
#include <glm/vec3.hpp>
|
||||
|
||||
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();
|
||||
};
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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};
|
||||
|
||||
74
src/objects/Rigidbody.cpp
Normal file
74
src/objects/Rigidbody.cpp
Normal file
@ -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 <void (*callback)(const Entity&, size_t, entityid_t)>
|
||||
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<scripting::on_sensor_enter>(entities),
|
||||
create_sensor_callback<scripting::on_sensor_exit>(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<scripting::on_sensor_enter>(entities),
|
||||
create_sensor_callback<scripting::on_sensor_exit>(entities)};
|
||||
}
|
||||
}
|
||||
22
src/objects/Rigidbody.hpp
Normal file
22
src/objects/Rigidbody.hpp
Normal file
@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "data/dv_fwd.hpp"
|
||||
#include "physics/Hitbox.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <entt/fwd.hpp>
|
||||
|
||||
class Entities;
|
||||
struct EntityDef;
|
||||
|
||||
struct Rigidbody {
|
||||
bool enabled = true;
|
||||
Hitbox hitbox;
|
||||
std::vector<Sensor> sensors;
|
||||
|
||||
dv::value serialize(bool saveVelocity, bool saveBodySettings) const;
|
||||
|
||||
void initialize(
|
||||
const EntityDef& def, entityid_t id, Entities& entities
|
||||
);
|
||||
};
|
||||
49
src/objects/ScriptComponents.hpp
Normal file
49
src/objects/ScriptComponents.hpp
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "data/dv.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
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<std::unique_ptr<UserComponent>> components;
|
||||
|
||||
ScriptComponents() = default;
|
||||
|
||||
ScriptComponents(ScriptComponents&& other)
|
||||
: components(std::move(other.components)) {
|
||||
}
|
||||
};
|
||||
25
src/objects/Transform.cpp
Normal file
25
src/objects/Transform.cpp
Normal file
@ -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;
|
||||
}
|
||||
43
src/objects/Transform.hpp
Normal file
43
src/objects/Transform.hpp
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
|
||||
#define GLM_ENABLE_EXPERIMENTAL
|
||||
|
||||
#include <glm/vec3.hpp>
|
||||
#include <glm/mat4x4.hpp>
|
||||
#include <glm/gtx/norm.hpp>
|
||||
#include <data/dv_fwd.hpp>
|
||||
|
||||
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;
|
||||
}
|
||||
};
|
||||
@ -23,7 +23,7 @@ Bone::Bone(
|
||||
std::string name,
|
||||
std::string model,
|
||||
std::vector<std::unique_ptr<Bone>> 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<Bone*>& nodes, Bone* node) {
|
||||
nodes[node->getIndex()] = node;
|
||||
for (auto& subnode : node->getSubnodes()) {
|
||||
|
||||
@ -9,6 +9,7 @@
|
||||
#include <vector>
|
||||
|
||||
#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<std::unique_ptr<Bone>> 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 {
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user