From 5583734bc2773a1a08ad0a6a01f1be29f420e164 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Sat, 9 Aug 2025 22:43:06 +0300 Subject: [PATCH] refactor --- src/data/dv_util.hpp | 6 +- src/logic/scripting/scripting.cpp | 275 -------------------- src/logic/scripting/scripting_entities.cpp | 288 +++++++++++++++++++++ src/objects/Entities.cpp | 33 +-- src/objects/Rigidbody.cpp | 9 + src/objects/Rigidbody.hpp | 1 + src/objects/Transform.cpp | 6 + src/objects/Transform.hpp | 3 +- src/objects/rigging.cpp | 16 ++ src/objects/rigging.hpp | 1 + 10 files changed, 331 insertions(+), 307 deletions(-) create mode 100644 src/logic/scripting/scripting_entities.cpp diff --git a/src/data/dv_util.hpp b/src/data/dv_util.hpp index 3f09ffde..ffec61dd 100644 --- a/src/data/dv_util.hpp +++ b/src/data/dv_util.hpp @@ -46,12 +46,12 @@ namespace dv { if (!map.has(key)) { return; } - auto& list = map[key]; + const auto& srcList = map[key]; for (size_t i = 0; i < n; i++) { if constexpr (std::is_floating_point()) { - vec[i] = list[i].asNumber(); + vec[i] = srcList[i].asNumber(); } else { - vec[i] = list[i].asInteger(); + vec[i] = srcList[i].asInteger(); } } } diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 87044201..6a2ca0a5 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -19,9 +19,6 @@ #include "lua/lua_engine.hpp" #include "lua/lua_custom_types.hpp" #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" @@ -34,8 +31,6 @@ using namespace scripting; static debug::Logger logger("scripting"); -static inline const std::string STDCOMP = "stdcomp"; - std::ostream* scripting::output_stream = &std::cout; std::ostream* scripting::error_stream = &std::cerr; Engine* scripting::engine = nullptr; @@ -198,36 +193,6 @@ std::unique_ptr scripting::start_coroutine( }); } -[[nodiscard]] static scriptenv create_component_environment( - const scriptenv& parent, int entityIdx, const std::string& name -) { - auto L = lua::get_main_state(); - int id = lua::create_environment(L, *parent); - - lua::pushvalue(L, entityIdx); - - lua::pushenv(L, id); - - lua::pushvalue(L, -1); - lua::setfield(L, "this"); - - lua::pushvalue(L, -2); - lua::setfield(L, "entity"); - - lua::pop(L); - if (lua::getfield(L, "components")) { - lua::pushenv(L, id); - lua::setfield(L, name); - lua::pop(L); - } - lua::pop(L); - - return std::shared_ptr(new int(id), [=](int* id) { //-V508 - lua::remove_environment(L, *id); - delete id; - }); -} - void scripting::process_post_runnables() { auto L = lua::get_main_state(); if (lua::getglobal(L, "__process_post_runnables")) { @@ -559,246 +524,6 @@ bool scripting::on_item_break_block( ); } -dv::value scripting::get_component_value( - const scriptenv& env, const std::string& name -) { - auto L = lua::get_main_state(); - lua::pushenv(L, *env); - if (lua::getfield(L, name)) { - return lua::tovalue(L, -1); - } - return nullptr; -} - -void scripting::on_entity_spawn( - const EntityDef&, - entityid_t eid, - const std::vector>& components, - const dv::value& args, - const dv::value& saved -) { - auto L = lua::get_main_state(); - lua::stackguard guard(L); - lua::requireglobal(L, STDCOMP); - if (lua::getfield(L, "new_Entity")) { - lua::pushinteger(L, eid); - lua::call(L, 1); - } - if (components.size() > 1) { - for (size_t i = 0; i < components.size() - 1; i++) { - lua::pushvalue(L, -1); - } - } - for (auto& component : components) { - auto compenv = create_component_environment( - get_root_environment(), -1, component->name - ); - lua::get_from(L, lua::CHUNKS_TABLE, component->name, true); - lua::pushenv(L, *compenv); - - if (args != nullptr) { - std::string compfieldname = component->name; - util::replaceAll(compfieldname, ":", "__"); - if (args.has(compfieldname)) { - lua::pushvalue(L, args[compfieldname]); - } else { - lua::createtable(L, 0, 0); - } - } else if (component->params != nullptr) { - lua::pushvalue(L, component->params); - } else { - lua::createtable(L, 0, 0); - } - lua::setfield(L, "ARGS"); - - if (saved == nullptr) { - lua::createtable(L, 0, 0); - } else { - if (saved.has(component->name)) { - lua::pushvalue(L, saved[component->name]); - } else { - lua::createtable(L, 0, 0); - } - } - lua::setfield(L, "SAVED_DATA"); - - lua::setfenv(L); - lua::call_nothrow(L, 0, 0); - - lua::pushenv(L, *compenv); - auto& funcsset = component->funcsset; - funcsset.on_grounded = lua::hasfield(L, "on_grounded"); - funcsset.on_fall = lua::hasfield(L, "on_fall"); - funcsset.on_despawn = lua::hasfield(L, "on_despawn"); - funcsset.on_sensor_enter = lua::hasfield(L, "on_sensor_enter"); - funcsset.on_sensor_exit = lua::hasfield(L, "on_sensor_exit"); - funcsset.on_save = lua::hasfield(L, "on_save"); - funcsset.on_aim_on = lua::hasfield(L, "on_aim_on"); - funcsset.on_aim_off = lua::hasfield(L, "on_aim_off"); - funcsset.on_attacked = lua::hasfield(L, "on_attacked"); - funcsset.on_used = lua::hasfield(L, "on_used"); - lua::pop(L, 2); - - component->env = compenv; - } -} - -static void process_entity_callback( - const scriptenv& env, - const std::string& name, - std::function args -) { - auto L = lua::get_main_state(); - lua::pushenv(L, *env); - if (lua::hasfield(L, "__disabled")) { - lua::pop(L); - return; - } - if (lua::getfield(L, name)) { - if (args) { - lua::call_nothrow(L, args(L), 0); - } else { - lua::call_nothrow(L, 0, 0); - } - } - lua::pop(L); -} - -static void process_entity_callback( - const Entity& entity, - const std::string& name, - bool EntityFuncsSet::*flag, - std::function args -) { - const auto& script = entity.getScripting(); - for (auto& component : script.components) { - if (component->funcsset.*flag) { - process_entity_callback(component->env, name, args); - } - } -} - -void scripting::on_entity_despawn(const Entity& entity) { - process_entity_callback( - entity, "on_despawn", &EntityFuncsSet::on_despawn, nullptr - ); - auto L = lua::get_main_state(); - lua::get_from(L, "stdcomp", "remove_Entity", true); - lua::pushinteger(L, entity.getUID()); - lua::call(L, 1, 0); -} - -void scripting::on_entity_grounded(const Entity& entity, float force) { - process_entity_callback( - entity, - "on_grounded", - &EntityFuncsSet::on_grounded, - [force](auto L) { return lua::pushnumber(L, force); } - ); -} - -void scripting::on_entity_fall(const Entity& entity) { - process_entity_callback( - entity, "on_fall", &EntityFuncsSet::on_fall, nullptr - ); -} - -void scripting::on_entity_save(const Entity& entity) { - process_entity_callback( - entity, "on_save", &EntityFuncsSet::on_save, nullptr - ); -} - -void scripting::on_sensor_enter( - const Entity& entity, size_t index, entityid_t oid -) { - process_entity_callback( - entity, - "on_sensor_enter", - &EntityFuncsSet::on_sensor_enter, - [index, oid](auto L) { - lua::pushinteger(L, index); - lua::pushinteger(L, oid); - return 2; - } - ); -} - -void scripting::on_sensor_exit( - const Entity& entity, size_t index, entityid_t oid -) { - process_entity_callback( - entity, - "on_sensor_exit", - &EntityFuncsSet::on_sensor_exit, - [index, oid](auto L) { - lua::pushinteger(L, index); - lua::pushinteger(L, oid); - return 2; - } - ); -} - -void scripting::on_aim_on(const Entity& entity, Player* player) { - process_entity_callback( - entity, - "on_aim_on", - &EntityFuncsSet::on_aim_on, - [player](auto L) { return lua::pushinteger(L, player->getId()); } - ); -} - -void scripting::on_aim_off(const Entity& entity, Player* player) { - process_entity_callback( - entity, - "on_aim_off", - &EntityFuncsSet::on_aim_off, - [player](auto L) { return lua::pushinteger(L, player->getId()); } - ); -} - -void scripting::on_attacked( - const Entity& entity, Player* player, entityid_t attacker -) { - process_entity_callback( - entity, - "on_attacked", - &EntityFuncsSet::on_attacked, - [player, attacker](auto L) { - lua::pushinteger(L, attacker); - lua::pushinteger(L, player->getId()); - return 2; - } - ); -} - -void scripting::on_entity_used(const Entity& entity, Player* player) { - process_entity_callback( - entity, - "on_used", - &EntityFuncsSet::on_used, - [player](auto L) { return lua::pushinteger(L, player->getId()); } - ); -} - -void scripting::on_entities_update(int tps, int parts, int part) { - auto L = lua::get_main_state(); - lua::get_from(L, STDCOMP, "update", true); - lua::pushinteger(L, tps); - lua::pushinteger(L, parts); - lua::pushinteger(L, part); - lua::call_nothrow(L, 3, 0); - lua::pop(L); -} - -void scripting::on_entities_render(float delta) { - auto L = lua::get_main_state(); - lua::get_from(L, STDCOMP, "render", true); - lua::pushnumber(L, delta); - lua::call_nothrow(L, 1, 0); - lua::pop(L); -} - void scripting::on_ui_open( UiDocument* layout, std::vector args ) { diff --git a/src/logic/scripting/scripting_entities.cpp b/src/logic/scripting/scripting_entities.cpp new file mode 100644 index 00000000..4deabd4b --- /dev/null +++ b/src/logic/scripting/scripting_entities.cpp @@ -0,0 +1,288 @@ +#include "scripting.hpp" + +#include "lua/lua_engine.hpp" +#include "objects/Entities.hpp" +#include "objects/EntityDef.hpp" +#include "objects/Entity.hpp" +#include "objects/Player.hpp" +#include "util/stringutil.hpp" + +using namespace scripting; + +static inline const std::string STDCOMP = "stdcomp"; + +[[nodiscard]] static scriptenv create_component_environment( + const scriptenv& parent, int entityIdx, const std::string& name +) { + auto L = lua::get_main_state(); + int id = lua::create_environment(L, *parent); + + lua::pushvalue(L, entityIdx); + + lua::pushenv(L, id); + + lua::pushvalue(L, -1); + lua::setfield(L, "this"); + + lua::pushvalue(L, -2); + lua::setfield(L, "entity"); + + lua::pop(L); + if (lua::getfield(L, "components")) { + lua::pushenv(L, id); + lua::setfield(L, name); + lua::pop(L); + } + lua::pop(L); + + return std::shared_ptr(new int(id), [=](int* id) { //-V508 + lua::remove_environment(L, *id); + delete id; + }); +} + +dv::value scripting::get_component_value( + const scriptenv& env, const std::string& name +) { + auto L = lua::get_main_state(); + lua::pushenv(L, *env); + if (lua::getfield(L, name)) { + return lua::tovalue(L, -1); + } + return nullptr; +} + +static void create_component( + lua::State* L, + int entityIdx, + UserComponent& component, + const dv::value& args, + const dv::value& saved +) { + lua::pushvalue(L, entityIdx); + auto compenv = create_component_environment( + get_root_environment(), -1, component.name + ); + lua::get_from(L, lua::CHUNKS_TABLE, component.name, true); + lua::pushenv(L, *compenv); + + if (args != nullptr) { + std::string compfieldname = component.name; + util::replaceAll(compfieldname, ":", "__"); + if (args.has(compfieldname)) { + lua::pushvalue(L, args[compfieldname]); + } else { + lua::createtable(L, 0, 0); + } + } else if (component.params != nullptr) { + lua::pushvalue(L, component.params); + } else { + lua::createtable(L, 0, 0); + } + lua::setfield(L, "ARGS"); + + if (saved == nullptr) { + lua::createtable(L, 0, 0); + } else { + if (saved.has(component.name)) { + lua::pushvalue(L, saved[component.name]); + } else { + lua::createtable(L, 0, 0); + } + } + lua::setfield(L, "SAVED_DATA"); + + lua::setfenv(L); + lua::call_nothrow(L, 0, 0); + + lua::pushenv(L, *compenv); + auto& funcsset = component.funcsset; + funcsset.on_grounded = lua::hasfield(L, "on_grounded"); + funcsset.on_fall = lua::hasfield(L, "on_fall"); + funcsset.on_despawn = lua::hasfield(L, "on_despawn"); + funcsset.on_sensor_enter = lua::hasfield(L, "on_sensor_enter"); + funcsset.on_sensor_exit = lua::hasfield(L, "on_sensor_exit"); + funcsset.on_save = lua::hasfield(L, "on_save"); + funcsset.on_aim_on = lua::hasfield(L, "on_aim_on"); + funcsset.on_aim_off = lua::hasfield(L, "on_aim_off"); + funcsset.on_attacked = lua::hasfield(L, "on_attacked"); + funcsset.on_used = lua::hasfield(L, "on_used"); + lua::pop(L, 2); + + component.env = compenv; +} + +void scripting::on_entity_spawn( + const EntityDef&, + entityid_t eid, + const std::vector>& components, + const dv::value& args, + const dv::value& saved +) { + auto L = lua::get_main_state(); + lua::stackguard guard(L); + lua::requireglobal(L, STDCOMP); + if (lua::getfield(L, "new_Entity")) { + lua::pushinteger(L, eid); + lua::call(L, 1); + } + for (auto& component : components) { + create_component(L, -1, *component, args, saved); + } +} + +static void process_entity_callback( + const scriptenv& env, + const std::string& name, + std::function args +) { + auto L = lua::get_main_state(); + lua::pushenv(L, *env); + if (lua::hasfield(L, "__disabled")) { + lua::pop(L); + return; + } + if (lua::getfield(L, name)) { + if (args) { + lua::call_nothrow(L, args(L), 0); + } else { + lua::call_nothrow(L, 0, 0); + } + } + lua::pop(L); +} + +static void process_entity_callback( + const Entity& entity, + const std::string& name, + bool EntityFuncsSet::*flag, + std::function args +) { + const auto& script = entity.getScripting(); + for (auto& component : script.components) { + if (component->funcsset.*flag) { + process_entity_callback(component->env, name, args); + } + } +} + +void scripting::on_entity_despawn(const Entity& entity) { + process_entity_callback( + entity, "on_despawn", &EntityFuncsSet::on_despawn, nullptr + ); + auto L = lua::get_main_state(); + lua::get_from(L, "stdcomp", "remove_Entity", true); + lua::pushinteger(L, entity.getUID()); + lua::call(L, 1, 0); +} + +void scripting::on_entity_grounded(const Entity& entity, float force) { + process_entity_callback( + entity, + "on_grounded", + &EntityFuncsSet::on_grounded, + [force](auto L) { return lua::pushnumber(L, force); } + ); +} + +void scripting::on_entity_fall(const Entity& entity) { + process_entity_callback( + entity, "on_fall", &EntityFuncsSet::on_fall, nullptr + ); +} + +void scripting::on_entity_save(const Entity& entity) { + process_entity_callback( + entity, "on_save", &EntityFuncsSet::on_save, nullptr + ); +} + +void scripting::on_sensor_enter( + const Entity& entity, size_t index, entityid_t oid +) { + process_entity_callback( + entity, + "on_sensor_enter", + &EntityFuncsSet::on_sensor_enter, + [index, oid](auto L) { + lua::pushinteger(L, index); + lua::pushinteger(L, oid); + return 2; + } + ); +} + +void scripting::on_sensor_exit( + const Entity& entity, size_t index, entityid_t oid +) { + process_entity_callback( + entity, + "on_sensor_exit", + &EntityFuncsSet::on_sensor_exit, + [index, oid](auto L) { + lua::pushinteger(L, index); + lua::pushinteger(L, oid); + return 2; + } + ); +} + +void scripting::on_aim_on(const Entity& entity, Player* player) { + process_entity_callback( + entity, + "on_aim_on", + &EntityFuncsSet::on_aim_on, + [player](auto L) { return lua::pushinteger(L, player->getId()); } + ); +} + +void scripting::on_aim_off(const Entity& entity, Player* player) { + process_entity_callback( + entity, + "on_aim_off", + &EntityFuncsSet::on_aim_off, + [player](auto L) { return lua::pushinteger(L, player->getId()); } + ); +} + +void scripting::on_attacked( + const Entity& entity, Player* player, entityid_t attacker +) { + process_entity_callback( + entity, + "on_attacked", + &EntityFuncsSet::on_attacked, + [player, attacker](auto L) { + lua::pushinteger(L, attacker); + lua::pushinteger(L, player->getId()); + return 2; + } + ); +} + +void scripting::on_entity_used(const Entity& entity, Player* player) { + process_entity_callback( + entity, + "on_used", + &EntityFuncsSet::on_used, + [player](auto L) { return lua::pushinteger(L, player->getId()); } + ); +} + +void scripting::on_entities_update(int tps, int parts, int part) { + auto L = lua::get_main_state(); + lua::get_from(L, STDCOMP, "update", true); + lua::pushinteger(L, tps); + lua::pushinteger(L, parts); + lua::pushinteger(L, part); + lua::call_nothrow(L, 3, 0); + lua::pop(L); +} + +void scripting::on_entities_render(float delta) { + auto L = lua::get_main_state(); + lua::get_from(L, STDCOMP, "render", true); + lua::pushnumber(L, delta); + lua::call_nothrow(L, 1, 0); + lua::pop(L); +} diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index 5088a70d..8f3d3cb1 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -19,7 +19,6 @@ #include "EntityDef.hpp" #include "Entity.hpp" #include "rigging.hpp" -#include "physics/Hitbox.hpp" #include "physics/PhysicsSolver.hpp" #include "world/Level.hpp" @@ -100,7 +99,8 @@ entityid_t Entities::spawn( } body.hitbox.position = tsf.pos; scripting::on_entity_spawn( - def, id, scripting.components, args, componentsMap); + def, id, scripting.components, args, componentsMap + ); return id; } @@ -127,19 +127,10 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { auto& skeleton = entity.getSkeleton(); if (map.has(COMP_RIGIDBODY)) { - auto& bodymap = map[COMP_RIGIDBODY]; - dv::get_vec(bodymap, "vel", body.hitbox.velocity); - std::string bodyTypeName; - map.at("type").get(bodyTypeName); - BodyTypeMeta.getItem(bodyTypeName, body.hitbox.type); - bodymap["crouch"].asBoolean(body.hitbox.crouching); - bodymap["damping"].asNumber(body.hitbox.linearDamping); + body.deserialize(map[COMP_RIGIDBODY]); } if (map.has(COMP_TRANSFORM)) { - auto& tsfmap = map[COMP_TRANSFORM]; - dv::get_vec(tsfmap, "pos", transform.pos); - dv::get_vec(tsfmap, "size", transform.size); - dv::get_mat(tsfmap, "rot", transform.rot); + transform.deserialize(map[COMP_TRANSFORM]); } std::string skeletonName = skeleton.config->getName(); map.at("skeleton").get(skeletonName); @@ -147,21 +138,7 @@ void Entities::loadEntity(const dv::value& map, Entity entity) { skeleton.config = level.content.getSkeleton(skeletonName); } if (auto foundSkeleton = map.at(COMP_SKELETON)) { - auto& skeletonmap = *foundSkeleton; - if (auto found = skeletonmap.at("textures")) { - auto& texturesmap = *found; - for (auto& [slot, _] : texturesmap.asObject()) { - texturesmap.at(slot).get(skeleton.textures[slot]); - } - } - if (auto found = skeletonmap.at("pose")) { - auto& posearr = *found; - for (size_t i = 0; - i < std::min(skeleton.pose.matrices.size(), posearr.size()); - i++) { - dv::get_mat(posearr[i], skeleton.pose.matrices[i]); - } - } + skeleton.deserialize(*foundSkeleton); } } diff --git a/src/objects/Rigidbody.cpp b/src/objects/Rigidbody.cpp index 62f88128..9b1f78d2 100644 --- a/src/objects/Rigidbody.cpp +++ b/src/objects/Rigidbody.cpp @@ -26,6 +26,15 @@ dv::value Rigidbody::serialize(bool saveVelocity, bool saveBodySettings) const { return bodymap; } +void Rigidbody::deserialize(const dv::value& root) { + dv::get_vec(root, "vel", hitbox.velocity); + std::string bodyTypeName; + root.at("type").get(bodyTypeName); + BodyTypeMeta.getItem(bodyTypeName, hitbox.type); + root["crouch"].asBoolean(hitbox.crouching); + root["damping"].asNumber(hitbox.linearDamping); +} + template static sensorcallback create_sensor_callback(Entities& entities) { return [&entities](auto entityid, auto index, auto otherid) { diff --git a/src/objects/Rigidbody.hpp b/src/objects/Rigidbody.hpp index 818329d2..91790d8a 100644 --- a/src/objects/Rigidbody.hpp +++ b/src/objects/Rigidbody.hpp @@ -15,6 +15,7 @@ struct Rigidbody { std::vector sensors; dv::value serialize(bool saveVelocity, bool saveBodySettings) const; + void deserialize(const dv::value& root); void initialize( const EntityDef& def, entityid_t id, Entities& entities diff --git a/src/objects/Transform.cpp b/src/objects/Transform.cpp index 9c14353e..87ed4a73 100644 --- a/src/objects/Transform.cpp +++ b/src/objects/Transform.cpp @@ -23,3 +23,9 @@ dv::value Transform::serialize() const { } return tsfmap; } + +void Transform::deserialize(const dv::value& root) { + dv::get_vec(root, "pos", pos); + dv::get_vec(root, "size", size); + dv::get_mat(root, "rot", rot); +} diff --git a/src/objects/Transform.hpp b/src/objects/Transform.hpp index 0eb73236..183890dd 100644 --- a/src/objects/Transform.hpp +++ b/src/objects/Transform.hpp @@ -8,7 +8,7 @@ #include struct Transform { - static inline constexpr float EPSILON = 0.0000001f; + static inline constexpr float EPSILON = 1e-7f; glm::vec3 pos; glm::vec3 size; glm::mat3 rot; @@ -19,6 +19,7 @@ struct Transform { glm::vec3 displaySize; dv::value serialize() const; + void deserialize(const dv::value& root); void refresh(); diff --git a/src/objects/rigging.cpp b/src/objects/rigging.cpp index 58138a48..1da11f8c 100644 --- a/src/objects/rigging.cpp +++ b/src/objects/rigging.cpp @@ -70,6 +70,22 @@ dv::value Skeleton::serialize(bool saveTextures, bool savePose) const { return root; } +void Skeleton::deserialize(const dv::value& root) { + if (auto found = root.at("textures")) { + auto& texturesmap = *found; + for (auto& [slot, _] : texturesmap.asObject()) { + texturesmap.at(slot).get(textures[slot]); + } + } + if (auto found = root.at("pose")) { + auto& posearr = *found; + auto& matrices = pose.matrices; + for (size_t i = 0; i < std::min(matrices.size(), posearr.size()); i++) { + dv::get_mat(posearr[i], pose.matrices[i]); + } + } +} + 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 0c377c43..76ee764b 100644 --- a/src/objects/rigging.hpp +++ b/src/objects/rigging.hpp @@ -92,6 +92,7 @@ namespace rigging { Skeleton(const SkeletonConfig* config); dv::value serialize(bool saveTextures, bool savePose) const; + void deserialize(const dv::value& root); }; class SkeletonConfig {