From e19ed3d23950cc5c13c7ad38b3feed1b84ec1659 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 14 Aug 2024 00:24:22 +0300 Subject: [PATCH 01/16] add pseudopack 'core' --- src/content/ContentPack.cpp | 7 +++++++ src/content/ContentPack.hpp | 2 ++ src/engine.cpp | 15 +++++++++++++-- src/files/engine_paths.cpp | 19 ------------------- src/logic/scripting/scripting.cpp | 1 - 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/content/ContentPack.cpp b/src/content/ContentPack.cpp index 90e4b73a..9bcd8aef 100644 --- a/src/content/ContentPack.cpp +++ b/src/content/ContentPack.cpp @@ -4,6 +4,7 @@ #include #include +#include "constants.hpp" #include "coders/json.hpp" #include "data/dynamic.hpp" #include "files/engine_paths.hpp" @@ -11,6 +12,12 @@ namespace fs = std::filesystem; +ContentPack ContentPack::createCore(const EnginePaths* paths) { + return ContentPack { + "core", "Core", ENGINE_VERSION_STRING, "", "", paths->getResourcesFolder(), {} + }; +} + const std::vector ContentPack::RESERVED_NAMES = { "res", "abs", "local", "core", "user", "world", "none", "null"}; diff --git a/src/content/ContentPack.hpp b/src/content/ContentPack.hpp index 70b34472..7815d009 100644 --- a/src/content/ContentPack.hpp +++ b/src/content/ContentPack.hpp @@ -67,6 +67,8 @@ struct ContentPack { const fs::path& worldDir, const std::string& name ); + + static ContentPack createCore(const EnginePaths*); }; struct ContentPackStats { diff --git a/src/engine.cpp b/src/engine.cpp index 17bb2b8b..787a257b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -313,12 +313,17 @@ void Engine::loadContent() { contentPacks = manager.getAll(names); std::vector resRoots; + { + auto pack = ContentPack::createCore(paths); + resRoots.push_back({"core", pack.folder}); + ContentLoader(&pack, contentBuilder).load(); + load_configs(pack.folder); + } for (auto& pack : contentPacks) { resRoots.push_back({pack.id, pack.folder}); ContentLoader(&pack, contentBuilder).load(); load_configs(pack.folder); } - load_configs(paths->getResourcesFolder()); content = contentBuilder.build(); resPaths = std::make_unique(resdir, resRoots); @@ -330,7 +335,13 @@ void Engine::loadContent() { void Engine::resetContent() { auto resdir = paths->getResourcesFolder(); - resPaths = std::make_unique(resdir, std::vector()); + std::vector resRoots; + { + auto pack = ContentPack::createCore(paths); + resRoots.push_back({"core", pack.folder}); + load_configs(pack.folder); + } + resPaths = std::make_unique(resdir, resRoots); contentPacks.clear(); content.reset(); diff --git a/src/files/engine_paths.cpp b/src/files/engine_paths.cpp index 759d277e..1be3ca20 100644 --- a/src/files/engine_paths.cpp +++ b/src/files/engine_paths.cpp @@ -218,10 +218,6 @@ std::string ResPaths::findRaw(const std::string& filename) const { return root.name + ":" + filename; } } - auto resDir = mainRoot; - if (fs::exists(resDir / std::filesystem::path(filename))) { - return "core:" + filename; - } throw std::runtime_error("could not to find file " + util::quote(filename)); } @@ -236,14 +232,6 @@ std::vector ResPaths::listdirRaw(const std::string& folderName) con entries.emplace_back(root.name + ":" + folderName + "/" + name); } } - { - auto folder = mainRoot / fs::u8path(folderName); - if (!fs::is_directory(folder)) return entries; - for (const auto& entry : fs::directory_iterator(folder)) { - auto name = entry.path().filename().u8string(); - entries.emplace_back("core:" + folderName + "/" + name); - } - } return entries; } @@ -259,13 +247,6 @@ std::vector ResPaths::listdir( entries.push_back(entry.path()); } } - { - auto folder = mainRoot / fs::u8path(folderName); - if (!fs::is_directory(folder)) return entries; - for (const auto& entry : fs::directory_iterator(folder)) { - entries.push_back(entry.path()); - } - } return entries; } diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index 05beaa32..aeedc1d9 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -39,7 +39,6 @@ LevelController* scripting::controller = nullptr; static void load_script(const fs::path& name, bool throwable) { auto paths = scripting::engine->getPaths(); fs::path file = paths->getResourcesFolder() / fs::path("scripts") / name; - std::string src = files::read_string(file); auto L = lua::get_main_thread(); lua::loadbuffer(L, 0, src, file.u8string()); From ddee38681e1b4b82218c2932680a8503f5b1e549 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 14 Aug 2024 01:31:56 +0300 Subject: [PATCH 02/16] fix: slow world saving --- src/voxels/Chunks.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 86311359..1dbfd5a1 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -750,7 +750,9 @@ void Chunks::save(Chunk* chunk) { chunk->flags.entities = true; } worldFiles->getRegions().put( - chunk, json::to_binary(root, true) + chunk, + chunk->flags.entities ? json::to_binary(root, true) + : std::vector() ); } } From 8ef288c18997f19681f2a2c0222bb32f133fe335 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Mon, 19 Aug 2024 00:49:28 +0300 Subject: [PATCH 03/16] refactor lua scripting a bit --- src/logic/scripting/lua/libaudio.cpp | 4 +- src/logic/scripting/lua/libblock.cpp | 28 ++--- src/logic/scripting/lua/libmat4.cpp | 4 +- src/logic/scripting/lua/libplayer.cpp | 14 +-- src/logic/scripting/lua/lua_util.hpp | 159 ++++++++---------------- src/logic/scripting/lua/lua_wrapper.hpp | 85 +++++++++++++ src/logic/scripting/scripting.cpp | 18 +-- 7 files changed, 169 insertions(+), 143 deletions(-) create mode 100644 src/logic/scripting/lua/lua_wrapper.hpp diff --git a/src/logic/scripting/lua/libaudio.cpp b/src/logic/scripting/lua/libaudio.cpp index 03214e6e..ee311585 100644 --- a/src/logic/scripting/lua/libaudio.cpp +++ b/src/logic/scripting/lua/libaudio.cpp @@ -335,7 +335,7 @@ static int l_audio_get_duration(lua::State* L) { static int l_audio_get_position(lua::State* L) { auto speaker = audio::get_speaker(lua::tointeger(L, 1)); if (speaker != nullptr) { - return lua::pushvec3_stack(L, speaker->getPosition()); + return lua::pushvec_stack(L, speaker->getPosition()); } return 0; } @@ -344,7 +344,7 @@ static int l_audio_get_position(lua::State* L) { static int l_audio_get_velocity(lua::State* L) { auto speaker = audio::get_speaker(lua::tointeger(L, 1)); if (speaker != nullptr) { - return lua::pushvec3_stack(L, speaker->getVelocity()); + return lua::pushvec_stack(L, speaker->getVelocity()); } return 0; } diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index 145362b7..f346098a 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -57,7 +57,7 @@ static int l_is_extended(lua::State* L) { static int l_get_size(lua::State* L) { if (auto def = require_block(L)) { - return lua::pushivec3_stack(L, def->size.x, def->size.y, def->size.z); + return lua::pushivec_stack(L, glm::ivec3(def->size)); } return 0; } @@ -76,7 +76,7 @@ static int l_seek_origin(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); auto& def = indices->blocks.require(vox->id); - return lua::pushivec3_stack( + return lua::pushivec_stack( L, level->chunks->seekOrigin({x, y, z}, def, vox->state) ); } @@ -117,14 +117,14 @@ static int l_get_x(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); if (vox == nullptr) { - return lua::pushivec3_stack(L, 1, 0, 0); + return lua::pushivec_stack(L, glm::ivec3(1, 0, 0)); } - auto& def = level->content->getIndices()->blocks.require(vox->id); + const auto& def = level->content->getIndices()->blocks.require(vox->id); if (!def.rotatable) { - return lua::pushivec3_stack(L, 1, 0, 0); + return lua::pushivec_stack(L, glm::ivec3(1, 0, 0)); } else { const CoordSystem& rot = def.rotations.variants[vox->state.rotation]; - return lua::pushivec3_stack(L, rot.axisX.x, rot.axisX.y, rot.axisX.z); + return lua::pushivec_stack(L, rot.axisX); } } @@ -134,14 +134,14 @@ static int l_get_y(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); if (vox == nullptr) { - return lua::pushivec3_stack(L, 0, 1, 0); + return lua::pushivec_stack(L, glm::ivec3(0, 1, 0)); } - auto& def = level->content->getIndices()->blocks.require(vox->id); + const auto& def = level->content->getIndices()->blocks.require(vox->id); if (!def.rotatable) { - return lua::pushivec3_stack(L, 0, 1, 0); + return lua::pushivec_stack(L, glm::ivec3(0, 1, 0)); } else { const CoordSystem& rot = def.rotations.variants[vox->state.rotation]; - return lua::pushivec3_stack(L, rot.axisY.x, rot.axisY.y, rot.axisY.z); + return lua::pushivec_stack(L, rot.axisY); } } @@ -151,14 +151,14 @@ static int l_get_z(lua::State* L) { auto z = lua::tointeger(L, 3); auto vox = level->chunks->get(x, y, z); if (vox == nullptr) { - return lua::pushivec3_stack(L, 0, 0, 1); + return lua::pushivec_stack(L, glm::ivec3(0, 0, 1)); } - auto& def = level->content->getIndices()->blocks.require(vox->id); + const auto& def = level->content->getIndices()->blocks.require(vox->id); if (!def.rotatable) { - return lua::pushivec3_stack(L, 0, 0, 1); + return lua::pushivec_stack(L, glm::ivec3(0, 0, 1)); } else { const CoordSystem& rot = def.rotations.variants[vox->state.rotation]; - return lua::pushivec3_stack(L, rot.axisZ.x, rot.axisZ.y, rot.axisZ.z); + return lua::pushivec_stack(L, rot.axisZ); } } diff --git a/src/logic/scripting/lua/libmat4.cpp b/src/logic/scripting/lua/libmat4.cpp index 44721ca6..078c229a 100644 --- a/src/logic/scripting/lua/libmat4.cpp +++ b/src/logic/scripting/lua/libmat4.cpp @@ -49,9 +49,9 @@ static int l_mul(lua::State* L) { switch (argc) { case 2: { if (len2 == 4) { - return lua::pushvec4_stack(L, matrix1 * lua::tovec4(L, 2)); + return lua::pushvec(L, matrix1 * lua::tovec4(L, 2)); } else if (len2 == 3) { - return lua::pushvec3_stack( + return lua::pushvec( L, matrix1 * glm::vec4(lua::tovec3(L, 2), 1.0f) ); } diff --git a/src/logic/scripting/lua/libplayer.cpp b/src/logic/scripting/lua/libplayer.cpp index 943e12da..fb4c9f0f 100644 --- a/src/logic/scripting/lua/libplayer.cpp +++ b/src/logic/scripting/lua/libplayer.cpp @@ -17,7 +17,7 @@ inline std::shared_ptr get_player(lua::State* L, int idx) { static int l_get_pos(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3_stack(L, player->getPosition()); + return lua::pushvec_stack(L, player->getPosition()); } return 0; } @@ -37,7 +37,7 @@ static int l_set_pos(lua::State* L) { static int l_get_vel(lua::State* L) { if (auto player = get_player(L, 1)) { if (auto hitbox = player->getHitbox()) { - return lua::pushvec3_stack(L, hitbox->velocity); + return lua::pushvec_stack(L, hitbox->velocity); } } return 0; @@ -59,7 +59,7 @@ static int l_set_vel(lua::State* L) { static int l_get_rot(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3_stack(L, player->cam); + return lua::pushvec_stack(L, player->cam); } return 0; } @@ -133,7 +133,7 @@ static int l_get_selected_block(lua::State* L) { if (player->selection.vox.id == BLOCK_VOID) { return 0; } - return lua::pushivec3_stack(L, player->selection.position); + return lua::pushivec_stack(L, player->selection.position); } return 0; } @@ -149,15 +149,13 @@ static int l_get_selected_entity(lua::State* L) { static int l_get_spawnpoint(lua::State* L) { if (auto player = get_player(L, 1)) { - return lua::pushvec3_stack(L, player->getSpawnPoint()); + return lua::pushvec_stack(L, player->getSpawnPoint()); } return 0; } static int l_set_spawnpoint(lua::State* L) { - auto player = get_player(L, 1); - - if (player) { + if (auto player = get_player(L, 1)) { auto x = lua::tonumber(L, 2); auto y = lua::tonumber(L, 3); auto z = lua::tonumber(L, 4); diff --git a/src/logic/scripting/lua/lua_util.hpp b/src/logic/scripting/lua/lua_util.hpp index 0822e5bc..23ab4c80 100644 --- a/src/logic/scripting/lua/lua_util.hpp +++ b/src/logic/scripting/lua/lua_util.hpp @@ -4,7 +4,7 @@ #include #include -#include "lua_commons.hpp" +#include "lua_wrapper.hpp" #include "lua_custom_types.hpp" #define GLM_ENABLE_EXPERIMENTAL #include @@ -18,68 +18,6 @@ namespace lua { std::string env_name(int env); - template - int wrap(lua_State* L) { - int result = 0; - try { - result = func(L); - } - // transform exception with description into lua_error - catch (std::exception& e) { - luaL_error(L, e.what()); - } - // Rethrow any other exception (lua error for example) - catch (...) { - throw; - } - return result; - } - - inline void pop(lua::State* L, int n = 1) { - lua_pop(L, n); - } - inline void insert(lua::State* L, int idx) { - lua_insert(L, idx); - } - inline void remove(lua::State* L, int idx) { - lua_remove(L, idx); - } - inline int gettop(lua::State* L) { - return lua_gettop(L); - } - inline size_t objlen(lua::State* L, int idx) { - return lua_objlen(L, idx); - } - inline int next(lua::State* L, int idx) { - return lua_next(L, idx); - } - inline int type(lua::State* L, int idx) { - return lua_type(L, idx); - } - inline const char* type_name(lua::State* L, int idx) { - return lua_typename(L, idx); - } - inline int rawget(lua::State* L, int idx = -2) { - lua_rawget(L, idx); - return 1; - } - inline int rawgeti(lua::State* L, int n, int idx = -1) { - lua_rawgeti(L, idx, n); - return 1; - } - inline void rawseti(lua::State* L, int n, int idx = -2) { - lua_rawseti(L, idx, n); - } - - inline int createtable(lua::State* L, int narr, int nrec) { - lua_createtable(L, narr, nrec); - return 1; - } - - inline bool isnil(lua::State* L, int idx) { - return lua_isnil(L, idx); - } - inline bool getglobal(lua::State* L, const std::string& name) { lua_getglobal(L, name.c_str()); if (isnil(L, -1)) { @@ -107,25 +45,8 @@ namespace lua { return true; } - // function wrappers with number of pushed values as return value - - inline int pushnil(lua::State* L) { - lua_pushnil(L); - return 1; - } - - inline int pushinteger(lua::State* L, lua::Integer x) { - lua_pushinteger(L, x); - return 1; - } - - inline int pushnumber(lua::State* L, lua::Number x) { - lua_pushnumber(L, x); - return 1; - } - template - inline int pushvec(lua::State* L, glm::vec vec) { + inline int pushvec(lua::State* L, const glm::vec& vec) { createtable(L, n, 0); for (int i = 0; i < n; i++) { pushnumber(L, vec[i]); @@ -135,7 +56,7 @@ namespace lua { } template - inline int pushivec(lua::State* L, glm::vec vec) { + inline int pushivec(lua::State* L, const glm::vec& vec) { createtable(L, n, 0); for (int i = 0; i < n; i++) { pushinteger(L, vec[i]); @@ -144,34 +65,20 @@ namespace lua { return 1; } - inline int pushivec3_stack( - lua::State* L, lua::Integer x, lua::Integer y, lua::Integer z - ) { - pushinteger(L, x); - pushinteger(L, y); - pushinteger(L, z); - return 3; + template + inline int pushvec_stack(lua::State* L, const glm::vec& vec) { + for (int i = 0; i < n; i++) { + pushnumber(L, vec[i]); + } + return n; } - inline int pushivec3_stack(lua::State* L, glm::ivec3 vec) { - pushinteger(L, vec.x); - pushinteger(L, vec.y); - pushinteger(L, vec.z); - return 3; - } - - inline int pushvec3_stack(lua::State* L, glm::vec3 vec) { - pushnumber(L, vec.x); - pushnumber(L, vec.y); - pushnumber(L, vec.z); - return 3; - } - inline int pushvec4_stack(lua::State* L, glm::vec4 vec) { - pushnumber(L, vec.x); - pushnumber(L, vec.y); - pushnumber(L, vec.z); - pushnumber(L, vec.w); - return 4; + template + inline int pushivec_stack(lua::State* L, const glm::vec& vec) { + for (int i = 0; i < n; i++) { + pushinteger(L, vec[i]); + } + return n; } inline void setmetatable(lua::State* L, int idx = -2) { @@ -637,4 +544,40 @@ namespace lua { luaL_setfuncs(L, libfuncs, 0); setglobal(L, name); } + + inline int requirefield(lua::State* L, const std::string& name, int idx = -1) { + if (getfield(L, name, idx)) { + return 1; + } + throw std::runtime_error("object has no member '"+name+"'"); + } + + inline const char* require_string_field( + lua::State* L, const std::string& name, int idx=-1 + ) { + requirefield(L, name, idx); + auto value = require_string(L, -1); + lua::pop(L); + return value; + } + + inline Integer require_integer_field( + lua::State* L, const std::string& name, int idx=-1 + ) { + requirefield(L, name, idx); + auto value = tointeger(L, -1); + lua::pop(L); + return value; + } + + inline bool get_boolean_field( + lua::State* L, const std::string& name, bool def, int idx=-1 + ) { + if (getfield(L, name, idx)) { + bool value = toboolean(L, -1); + pop(L); + return value; + } + return def; + } } diff --git a/src/logic/scripting/lua/lua_wrapper.hpp b/src/logic/scripting/lua/lua_wrapper.hpp new file mode 100644 index 00000000..ee184cb1 --- /dev/null +++ b/src/logic/scripting/lua/lua_wrapper.hpp @@ -0,0 +1,85 @@ +#pragma once + +#include "lua_commons.hpp" + +namespace lua { + template + int wrap(lua_State* L) { + int result = 0; + try { + result = func(L); + } + // transform exception with description into lua_error + catch (std::exception& e) { + luaL_error(L, e.what()); + } + // Rethrow any other exception (lua error for example) + catch (...) { + throw; + } + return result; + } + + inline void pop(lua::State* L, int n = 1) { + lua_pop(L, n); + } + inline void insert(lua::State* L, int idx) { + lua_insert(L, idx); + } + inline void remove(lua::State* L, int idx) { + lua_remove(L, idx); + } + inline int gettop(lua::State* L) { + return lua_gettop(L); + } + inline size_t objlen(lua::State* L, int idx) { + return lua_objlen(L, idx); + } + inline int next(lua::State* L, int idx) { + return lua_next(L, idx); + } + inline int type(lua::State* L, int idx) { + return lua_type(L, idx); + } + inline const char* type_name(lua::State* L, int idx) { + return lua_typename(L, idx); + } + inline int rawget(lua::State* L, int idx = -2) { + lua_rawget(L, idx); + return 1; + } + inline int rawgeti(lua::State* L, int n, int idx = -1) { + lua_rawgeti(L, idx, n); + return 1; + } + inline void rawseti(lua::State* L, int n, int idx = -2) { + lua_rawseti(L, idx, n); + } + + inline int createtable(lua::State* L, int narr, int nrec) { + lua_createtable(L, narr, nrec); + return 1; + } + + inline bool isnil(lua::State* L, int idx) { + return lua_isnil(L, idx); + } + + // function wrappers with number of pushed values as return value + + inline int pushnil(lua::State* L) { + lua_pushnil(L); + return 1; + } + + inline int pushinteger(lua::State* L, lua::Integer x) { + lua_pushinteger(L, x); + return 1; + } + + inline int pushnumber(lua::State* L, lua::Number x) { + lua_pushnumber(L, x); + return 1; + } + +} diff --git a/src/logic/scripting/scripting.cpp b/src/logic/scripting/scripting.cpp index aeedc1d9..9fa17a91 100644 --- a/src/logic/scripting/scripting.cpp +++ b/src/logic/scripting/scripting.cpp @@ -205,14 +205,14 @@ void scripting::on_blocks_tick(const Block& block, int tps) { void scripting::update_block(const Block& block, int x, int y, int z) { std::string name = block.name + ".update"; lua::emit_event(lua::get_main_thread(), name, [x, y, z](auto L) { - return lua::pushivec3_stack(L, x, y, z); + return lua::pushivec_stack(L, glm::ivec3(x, y, z)); }); } void scripting::random_update_block(const Block& block, int x, int y, int z) { std::string name = block.name + ".randupdate"; lua::emit_event(lua::get_main_thread(), name, [x, y, z](auto L) { - return lua::pushivec3_stack(L, x, y, z); + return lua::pushivec_stack(L, glm::ivec3(x, y, z)); }); } @@ -221,13 +221,13 @@ void scripting::on_block_placed( ) { std::string name = block.name + ".placed"; lua::emit_event(lua::get_main_thread(), name, [x, y, z, player](auto L) { - lua::pushivec3_stack(L, x, y, z); + lua::pushivec_stack(L, glm::ivec3(x, y, z)); lua::pushinteger(L, player ? player->getId() : -1); return 4; }); auto world_event_args = [&](lua::State* L) { lua::pushinteger(L, block.rt.id); - lua::pushivec3_stack(L, x, y, z); + lua::pushivec_stack(L, glm::ivec3(x, y, z)); lua::pushinteger(L, player ? player->getId() : -1); return 5; }; @@ -251,7 +251,7 @@ void scripting::on_block_broken( lua::get_main_thread(), name, [x, y, z, player](auto L) { - lua::pushivec3_stack(L, x, y, z); + lua::pushivec_stack(L, glm::ivec3(x, y, z)); lua::pushinteger(L, player ? player->getId() : -1); return 4; } @@ -259,7 +259,7 @@ void scripting::on_block_broken( } auto world_event_args = [&](lua::State* L) { lua::pushinteger(L, block.rt.id); - lua::pushivec3_stack(L, x, y, z); + lua::pushivec_stack(L, glm::ivec3(x, y, z)); lua::pushinteger(L, player ? player->getId() : -1); return 5; }; @@ -279,7 +279,7 @@ bool scripting::on_block_interact( ) { std::string name = block.name + ".interact"; return lua::emit_event(lua::get_main_thread(), name, [pos, player](auto L) { - lua::pushivec3_stack(L, pos.x, pos.y, pos.z); + lua::pushivec_stack(L, pos); lua::pushinteger(L, player->getId()); return 4; }); @@ -302,7 +302,7 @@ bool scripting::on_item_use_on_block( lua::get_main_thread(), name, [ipos, normal, player](auto L) { - lua::pushivec3_stack(L, ipos.x, ipos.y, ipos.z); + lua::pushivec_stack(L, ipos); lua::pushinteger(L, player->getId()); lua::pushivec(L, normal); return 5; @@ -318,7 +318,7 @@ bool scripting::on_item_break_block( lua::get_main_thread(), name, [x, y, z, player](auto L) { - lua::pushivec3_stack(L, x, y, z); + lua::pushivec_stack(L, glm::ivec3(x, y, z)); lua::pushinteger(L, player->getId()); return 4; } From 1be50c2e06079e66798bb8eb05b58da3a9301797 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Mon, 19 Aug 2024 21:36:30 +0300 Subject: [PATCH 04/16] libblock.raycast: Add argument to specify blocks to ignore during ray casting libentity.raycast: Add argument to specify blocks to ignore during ray casting Chunk::rayCast: Add argument to specify blocks to ignore during ray casting. On lua side filter blocks are passed as list of strings in form of "MOD:BLOCK_NAME" On C++ size filter blocks are std::set of blockid_t --- src/logic/scripting/lua/libblock.cpp | 24 ++++++++++++++++--- src/logic/scripting/lua/libentity.cpp | 33 ++++++++++++++++++++++----- src/voxels/Chunks.cpp | 7 ++++-- src/voxels/Chunks.hpp | 4 +++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index f346098a..342f7899 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -353,13 +353,30 @@ static int l_raycast(lua::State* L) { auto start = lua::tovec<3>(L, 1); auto dir = lua::tovec<3>(L, 2); auto maxDistance = lua::tonumber(L, 3); + std::set filteredBlocks {}; + if (lua::gettop(L) >= 5) { + if (lua::istable(L, 5)) { + int addLen = lua::objlen(L, 5); + for (int i = 0; i < addLen; i++) { + lua::rawgeti(L, i + 1, 5); + auto blockName = std::string(lua::tostring(L, -1)); + Block* block = content->blocks.find(blockName); + if (block != nullptr) { + filteredBlocks.insert(block->rt.id); + } + lua::pop(L); + } + } else { + throw std::runtime_error("table expected for filter"); + } + } glm::vec3 end; glm::ivec3 normal; glm::ivec3 iend; if (auto voxel = level->chunks->rayCast( - start, dir, maxDistance, end, normal, iend + start, dir, maxDistance, end, normal, iend, filteredBlocks )) { - if (lua::gettop(L) >= 4) { + if (lua::gettop(L) >= 4 && !lua::isnil(L, 4)) { lua::pushvalue(L, 4); } else { lua::createtable(L, 0, 5); @@ -452,4 +469,5 @@ const luaL_Reg blocklib[] = { {"raycast", lua::wrap}, {"compose_state", lua::wrap}, {"decompose_state", lua::wrap}, - {NULL, NULL}}; + {NULL, NULL} +}; diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index f952a83d..1d21c6ef 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -8,6 +8,7 @@ #include "objects/rigging.hpp" #include "physics/Hitbox.hpp" #include "voxels/Chunks.hpp" +#include "voxels/Block.hpp" #include "window/Camera.hpp" using namespace scripting; @@ -118,7 +119,25 @@ static int l_raycast(lua::State* L) { auto start = lua::tovec<3>(L, 1); auto dir = lua::tovec<3>(L, 2); auto maxDistance = lua::tonumber(L, 3); - auto ignore = lua::tointeger(L, 4); + auto ignoreEntityId = lua::tointeger(L, 4); + std::set filteredBlocks {}; + if (lua::gettop(L) >= 6) { + if (lua::istable(L, 6)) { + int addLen = lua::objlen(L, 6); + for (int i = 0; i < addLen; i++) { + lua::rawgeti(L, i + 1, 6); + auto blockName = std::string(lua::tostring(L, -1)); + Block* block = content->blocks.find(blockName); + if (block != nullptr) { + filteredBlocks.insert(block->rt.id); + } + lua::pop(L); + } + } else { + throw std::runtime_error("table expected for filter"); + } + } + glm::vec3 end; glm::ivec3 normal; glm::ivec3 iend; @@ -126,13 +145,14 @@ static int l_raycast(lua::State* L) { blockid_t block = BLOCK_VOID; if (auto voxel = level->chunks->rayCast( - start, dir, maxDistance, end, normal, iend + start, dir, maxDistance, end, normal, iend, filteredBlocks )) { maxDistance = glm::distance(start, end); block = voxel->id; } - if (auto ray = level->entities->rayCast(start, dir, maxDistance, ignore)) { - if (lua::gettop(L) >= 5) { + if (auto ray = + level->entities->rayCast(start, dir, maxDistance, ignoreEntityId)) { + if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) { lua::pushvalue(L, 5); } else { lua::createtable(L, 0, 6); @@ -157,7 +177,7 @@ static int l_raycast(lua::State* L) { lua::setfield(L, "entity"); return 1; } else if (block != BLOCK_VOID) { - if (lua::gettop(L) >= 5) { + if (lua::gettop(L) >= 5 && !lua::isnil(L, 5)) { lua::pushvalue(L, 5); } else { lua::createtable(L, 0, 5); @@ -194,4 +214,5 @@ const luaL_Reg entitylib[] = { {"get_all_in_box", lua::wrap}, {"get_all_in_radius", lua::wrap}, {"raycast", lua::wrap}, - {NULL, NULL}}; + {NULL, NULL} +}; diff --git a/src/voxels/Chunks.cpp b/src/voxels/Chunks.cpp index 1dbfd5a1..d22ec3cc 100644 --- a/src/voxels/Chunks.cpp +++ b/src/voxels/Chunks.cpp @@ -414,7 +414,8 @@ voxel* Chunks::rayCast( float maxDist, glm::vec3& end, glm::ivec3& norm, - glm::ivec3& iend + glm::ivec3& iend, + std::set filter ) { float px = start.x; float py = start.y; @@ -454,8 +455,10 @@ voxel* Chunks::rayCast( if (voxel == nullptr) { return nullptr; } + const auto& def = indices->blocks.require(voxel->id); - if (def.selectable) { + if ((filter.empty() && def.selectable) || + (!filter.empty() && filter.find(def.rt.id) == filter.end())) { end.x = px + t * dx; end.y = py + t * dy; end.z = pz + t * dz; diff --git a/src/voxels/Chunks.hpp b/src/voxels/Chunks.hpp index d17cf9b9..0d3e07e4 100644 --- a/src/voxels/Chunks.hpp +++ b/src/voxels/Chunks.hpp @@ -4,6 +4,7 @@ #include #include +#include #include #include "typedefs.hpp" @@ -93,7 +94,8 @@ public: float maxLength, glm::vec3& end, glm::ivec3& norm, - glm::ivec3& iend + glm::ivec3& iend, + std::set filter = {} ); glm::vec3 rayCastToObstacle(glm::vec3 start, glm::vec3 dir, float maxDist); From 7fa061c9410548debe380d92a929082f9b7bade5 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 15:09:32 +0300 Subject: [PATCH 05/16] lua_extensions: Add debug.print function that can pretty-print tables recursively(with depth limit of 10) --- src/logic/scripting/lua/lua_extensions.cpp | 90 +++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/src/logic/scripting/lua/lua_extensions.cpp b/src/logic/scripting/lua/lua_extensions.cpp index cb095e9f..f3424e93 100644 --- a/src/logic/scripting/lua/lua_extensions.cpp +++ b/src/logic/scripting/lua/lua_extensions.cpp @@ -1,5 +1,7 @@ -#include "debug/Logger.hpp" +#include + #include "api_lua.hpp" +#include "debug/Logger.hpp" static debug::Logger logger("lua-debug"); @@ -21,6 +23,89 @@ static int l_debug_log(lua::State* L) { return 0; } +const int MAX_DEPTH = 10; + +int l_debug_print(lua::State* L) { + auto addIndentation = [](int depth) { + std::cout << std::string(depth * 2, ' '); + }; + + auto pointerToHexString = [](const void* ptr, size_t size) { + std::stringstream ss; + const auto* bytePtr = reinterpret_cast(ptr); + for (size_t i = 0; i < size; ++i) { + ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(bytePtr[i]) + << ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " "); + } + return ss.str(); + }; + + std::function debugPrint = [&](int index, int depth, bool is_key) { + if (depth > MAX_DEPTH) { + std::cout << "{...}"; + return; + } + switch (lua::type(L, index)) { + case LUA_TSTRING: + std::cout << (is_key ? lua::tostring(L, index) : "\"" + std::string(lua::tostring(L, index)) + "\""); + break; + case LUA_TBOOLEAN: + std::cout << (lua::toboolean(L, index) ? "true" : "false"); + break; + case LUA_TNUMBER: + std::cout << lua::tonumber(L, index); + break; + case LUA_TTABLE: { + bool is_list = lua::objlen(L, index) > 0, hadItems = false; + int absTableIndex = index > 0 ? index : lua::gettop(L) + index + 1; + std::cout << "{"; + lua::pushnil(L); + while (lua::next(L, absTableIndex) != 0) { + if (hadItems) std::cout << "," << std::endl; + else std::cout << std::endl; + addIndentation(depth + 1); + if (!is_list) debugPrint(-2, depth, true), std::cout << " = "; + debugPrint(-1, depth + 1, false); + lua::pop(L, 1); + hadItems = true; + } + if (hadItems) std::cout << std::endl; + addIndentation(depth); + std::cout << "}"; + break; + } + case LUA_TFUNCTION: + std::cout << "function(0x" << std::hex << lua::topointer(L, index) << std::dec << ")"; + break; + case LUA_TUSERDATA: + std::cout << "userdata:\n" << pointerToHexString(lua::topointer(L, index), lua::objlen(L, index)); + break; + case LUA_TLIGHTUSERDATA: + std::cout << "lightuserdata:\n" << pointerToHexString(lua::topointer(L, index), sizeof(void*)); + break; + case LUA_TNIL: + std::cout << "nil"; + break; + default: + std::cout << lua::type_name(L, lua::type(L, index)); + break; + } + }; + + int n = lua::gettop(L); + std::cout << "debug_print(" << std::endl; + for (int i = 1; i <= n; ++i) { + addIndentation(1); + debugPrint(i, 1, false); + if (i < n) std::cout << "," << std::endl; + } + std::cout << std::endl << ")" << std::endl; + lua::pop(L, n); + return 0; +} + + + void initialize_libs_extends(lua::State* L) { if (lua::getglobal(L, "debug")) { lua::pushcfunction(L, lua::wrap); @@ -32,6 +117,9 @@ void initialize_libs_extends(lua::State* L) { lua::pushcfunction(L, lua::wrap); lua::setfield(L, "log"); + lua::pushcfunction(L, lua::wrap); + lua::setfield(L, "print"); + lua::pop(L); } } From 6ff608c012e9add310630d8b4522621aefd1f6b1 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 15:14:27 +0300 Subject: [PATCH 06/16] lua_extensions: Fix wrong repr function name --- src/logic/scripting/lua/lua_extensions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/scripting/lua/lua_extensions.cpp b/src/logic/scripting/lua/lua_extensions.cpp index f3424e93..ab0dacaf 100644 --- a/src/logic/scripting/lua/lua_extensions.cpp +++ b/src/logic/scripting/lua/lua_extensions.cpp @@ -93,7 +93,7 @@ int l_debug_print(lua::State* L) { }; int n = lua::gettop(L); - std::cout << "debug_print(" << std::endl; + std::cout << "debug.print(" << std::endl; for (int i = 1; i <= n; ++i) { addIndentation(1); debugPrint(i, 1, false); From a48d54aa27b090d5e8627a04b7cdbba12be4089e Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 15:33:29 +0300 Subject: [PATCH 07/16] block.raycast/entity.raycast: Updated docs to reflect changes --- doc/en/scripting/builtins/libblock.md | 7 ++++++- doc/en/scripting/builtins/libentities.md | 2 +- doc/ru/scripting/builtins/libblock.md | 7 ++++++- doc/ru/scripting/builtins/libentities.md | 2 +- 4 files changed, 14 insertions(+), 4 deletions(-) diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 2c2c0182..1d11417c 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -120,12 +120,17 @@ block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: tab endpoint: vec3, -- point of the ray hit point iendpoint: vec3, -- position of the block hit by the ray length: number, -- ray length - normal: vec3 -- normal vector of the surface hit by the ray + normal: vec3, -- normal vector of the surface hit by the ray + [optional] dest: table, -- table where result will be written to instead of function return + [optional] filter: table -- list of block names that are "transparent" for ray } or nil ``` Casts a ray from the start point in the direction of *dir*. Max_distance specifies the maximum ray length. +Argument `filter` can be used to tell ray what blocks can be skipped(passed through) during ray-casting. +To use filter `dest` argument must be filled with some value(can be nil), it's done for backwards compatability + The function returns a table with the results or nil if the ray does not hit any block. The result will use the destination table instead of creating a new one if the optional argument specified. diff --git a/doc/en/scripting/builtins/libentities.md b/doc/en/scripting/builtins/libentities.md index bd50c0e1..c0a5d260 100644 --- a/doc/en/scripting/builtins/libentities.md +++ b/doc/en/scripting/builtins/libentities.md @@ -51,7 +51,7 @@ entities.get_all_in_radius(center: vec3, radius: number) -> array ```lua entities.raycast(start: vec3, dir: vec3, max_distance: number, - ignore: int, [optional] destination: table) -> table or nil + ignore: int, [optional] destination: table, [optional] filter: table) -> table or nil ``` The function is an extended version of [block.raycast](libblock.md#raycast). Returns a table with the results if the ray touches a block or entity. diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index d4d28a28..77633c17 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -65,12 +65,17 @@ block.raycast(start: vec3, dir: vec3, max_distance: number, [опциональ endpoint: vec3, -- точка касания луча iendpoint: vec3, -- позиция блока, которого касается луч length: number, -- длина луча - normal: vec3 -- вектор нормали поверхности, которой касается луч + normal: vec3, -- вектор нормали поверхности, которой касается луч + [optional] dest: table, -- таблица куда будет записан результат вместо возврата из функции + [optional] filter: table -- массив имён блоков которые "прозрачны" для луча } или nil ``` Бросает луч из точки start в направлении dir. Max_distance указывает максимальную длину луча. +Аргумент `filter` позволяет указать какие блоки являются "прозрачными" для луча, прим.: {"base:glass","base:water"}. +Для использования агрумент `dest` нужно чем-то заполнить(можно nil), это сделано для обратной совместимости + Функция возвращает таблицу с результатами или nil, если луч не касается блока. Для результата будет использоваться целевая (dest) таблица вместо создания новой, если указан опциональный аргумент. diff --git a/doc/ru/scripting/builtins/libentities.md b/doc/ru/scripting/builtins/libentities.md index ebb23497..93275e5b 100644 --- a/doc/ru/scripting/builtins/libentities.md +++ b/doc/ru/scripting/builtins/libentities.md @@ -51,7 +51,7 @@ entities.get_all_in_radius(center: vec3, radius: number) -> array ```lua entities.raycast(start: vec3, dir: vec3, max_distance: number, - ignore: int, [optional] destination: table) -> table или nil + ignore: int, [optional] destination: table, [optional] filter: table) -> table или nil ``` Функция является расширенным вариантом [block.raycast](libblock.md#raycast). Возвращает таблицу с результатами если луч касается блока, либо сущности. From 408e7fd7633fb1d38bc55392050975912d4f58bc Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 18:10:05 +0300 Subject: [PATCH 08/16] debug.print: remove as many allocations as possible, modified string print to escape any special characters --- src/logic/scripting/lua/lua_extensions.cpp | 81 ++++++++++++++++------ 1 file changed, 60 insertions(+), 21 deletions(-) diff --git a/src/logic/scripting/lua/lua_extensions.cpp b/src/logic/scripting/lua/lua_extensions.cpp index ab0dacaf..51185898 100644 --- a/src/logic/scripting/lua/lua_extensions.cpp +++ b/src/logic/scripting/lua/lua_extensions.cpp @@ -27,27 +27,58 @@ const int MAX_DEPTH = 10; int l_debug_print(lua::State* L) { auto addIndentation = [](int depth) { - std::cout << std::string(depth * 2, ' '); + for (int i = 0; i < depth; ++i) std::cout << " "; }; - auto pointerToHexString = [](const void* ptr, size_t size) { - std::stringstream ss; + auto printHexData = [](const void* ptr, size_t size) { const auto* bytePtr = reinterpret_cast(ptr); for (size_t i = 0; i < size; ++i) { - ss << std::hex << std::setw(2) << std::setfill('0') << static_cast(bytePtr[i]) - << ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " "); + std::cout << std::hex << std::setw(2) << std::setfill('0') + << static_cast(bytePtr[i]) + << ((i + 1) % 8 == 0 && i + 1 < size ? "\n" : " "); } - return ss.str(); }; - std::function debugPrint = [&](int index, int depth, bool is_key) { + auto printEscapedString = [](const char* str) { + while (*str) { + switch (*str) { + case '\\': std::cout << "\\\\"; break; + case '\"': std::cout << "\\\""; break; + case '\n': std::cout << "\\n"; break; + case '\t': std::cout << "\\t"; break; + case '\r': std::cout << "\\r"; break; + case '\b': std::cout << "\\b"; break; + case '\f': std::cout << "\\f"; break; + default: + if (iscntrl(static_cast(*str))) { + // Print other control characters in \xHH format + std::cout << "\\x" << std::hex << std::setw(2) << std::setfill('0') + << static_cast(static_cast(*str)) << std::dec; + } else { + std::cout << *str; + } + break; + } + ++str; + } + }; + + std::function debugPrint = [&](int index, + int depth, + bool is_key) { if (depth > MAX_DEPTH) { std::cout << "{...}"; return; } switch (lua::type(L, index)) { case LUA_TSTRING: - std::cout << (is_key ? lua::tostring(L, index) : "\"" + std::string(lua::tostring(L, index)) + "\""); + if (is_key){ + std::cout << lua::tostring(L, index); + }else{ + std::cout << "\""; + printEscapedString(lua::tostring(L, index)); + std::cout << "\""; + } break; case LUA_TBOOLEAN: std::cout << (lua::toboolean(L, index) ? "true" : "false"); @@ -57,31 +88,41 @@ int l_debug_print(lua::State* L) { break; case LUA_TTABLE: { bool is_list = lua::objlen(L, index) > 0, hadItems = false; - int absTableIndex = index > 0 ? index : lua::gettop(L) + index + 1; + int absTableIndex = + index > 0 ? index : lua::gettop(L) + index + 1; std::cout << "{"; lua::pushnil(L); while (lua::next(L, absTableIndex) != 0) { - if (hadItems) std::cout << "," << std::endl; - else std::cout << std::endl; + if (hadItems) + std::cout << "," << '\n'; + else + std::cout << '\n'; + addIndentation(depth + 1); - if (!is_list) debugPrint(-2, depth, true), std::cout << " = "; + if (!is_list) { + debugPrint(-2, depth, true); + std::cout << " = "; + } debugPrint(-1, depth + 1, false); lua::pop(L, 1); hadItems = true; } - if (hadItems) std::cout << std::endl; + if (hadItems) std::cout << '\n'; addIndentation(depth); std::cout << "}"; break; } case LUA_TFUNCTION: - std::cout << "function(0x" << std::hex << lua::topointer(L, index) << std::dec << ")"; + std::cout << "function(0x" << std::hex + << lua::topointer(L, index) << std::dec << ")"; break; case LUA_TUSERDATA: - std::cout << "userdata:\n" << pointerToHexString(lua::topointer(L, index), lua::objlen(L, index)); + std::cout << "userdata:\n"; + printHexData(lua::topointer(L, index), lua::objlen(L, index)); break; case LUA_TLIGHTUSERDATA: - std::cout << "lightuserdata:\n" << pointerToHexString(lua::topointer(L, index), sizeof(void*)); + std::cout << "lightuserdata:\n"; + printHexData(lua::topointer(L, index), sizeof(void*)); break; case LUA_TNIL: std::cout << "nil"; @@ -93,19 +134,17 @@ int l_debug_print(lua::State* L) { }; int n = lua::gettop(L); - std::cout << "debug.print(" << std::endl; + std::cout << "debug.print(" << '\n'; for (int i = 1; i <= n; ++i) { addIndentation(1); debugPrint(i, 1, false); - if (i < n) std::cout << "," << std::endl; + if (i < n) std::cout << "," << '\n'; } - std::cout << std::endl << ")" << std::endl; + std::cout << '\n' << ")" << std::endl; lua::pop(L, n); return 0; } - - void initialize_libs_extends(lua::State* L) { if (lua::getglobal(L, "debug")) { lua::pushcfunction(L, lua::wrap); From 615dd239136fbe5bbe4e60cda13d92c5648c63a5 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 18:17:11 +0300 Subject: [PATCH 09/16] block.raycast: fix documentation --- doc/en/scripting/builtins/libblock.md | 4 +--- doc/ru/scripting/builtins/libblock.md | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/doc/en/scripting/builtins/libblock.md b/doc/en/scripting/builtins/libblock.md index 1d11417c..87176e20 100644 --- a/doc/en/scripting/builtins/libblock.md +++ b/doc/en/scripting/builtins/libblock.md @@ -115,14 +115,12 @@ Set specified bits. ## Raycast ```lua -block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: table) -> { +block.raycast(start: vec3, dir: vec3, max_distance: number, [optional] dest: table, [optional] filter: table) -> { block: int, -- block id endpoint: vec3, -- point of the ray hit point iendpoint: vec3, -- position of the block hit by the ray length: number, -- ray length normal: vec3, -- normal vector of the surface hit by the ray - [optional] dest: table, -- table where result will be written to instead of function return - [optional] filter: table -- list of block names that are "transparent" for ray } or nil ``` diff --git a/doc/ru/scripting/builtins/libblock.md b/doc/ru/scripting/builtins/libblock.md index 77633c17..150e776e 100644 --- a/doc/ru/scripting/builtins/libblock.md +++ b/doc/ru/scripting/builtins/libblock.md @@ -60,14 +60,12 @@ block.get_picking_item(id: int) -> int ### Raycast ```lua -block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table) -> { +block.raycast(start: vec3, dir: vec3, max_distance: number, [опционально] dest: table, [опционально] filter: table) -> { block: int, -- id блока endpoint: vec3, -- точка касания луча iendpoint: vec3, -- позиция блока, которого касается луч length: number, -- длина луча normal: vec3, -- вектор нормали поверхности, которой касается луч - [optional] dest: table, -- таблица куда будет записан результат вместо возврата из функции - [optional] filter: table -- массив имён блоков которые "прозрачны" для луча } или nil ``` From 5f6ae5daba600ae738f534426665df399daa8afe Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Tue, 20 Aug 2024 21:58:01 +0300 Subject: [PATCH 10/16] ItemDef/EntityDef/Block: Add method `cloneTo` to definition to other definition ContentBuilder: Add method `get` to get definition or nullptr ContentLoader: Add functionality to clone from definition specified in `parent` field in json --- src/content/ContentBuilder.hpp | 8 ++++++ src/content/ContentLoader.cpp | 47 +++++++++++++++++++++++++++++++--- src/content/ContentLoader.hpp | 6 ++--- src/items/ItemDef.cpp | 10 ++++++++ src/items/ItemDef.hpp | 1 + src/objects/EntityDef.cpp | 12 +++++++++ src/objects/EntityDef.hpp | 6 +++-- src/voxels/Block.cpp | 44 ++++++++++++++++++++++++++++--- src/voxels/Block.hpp | 2 ++ 9 files changed, 123 insertions(+), 13 deletions(-) create mode 100644 src/objects/EntityDef.cpp diff --git a/src/content/ContentBuilder.hpp b/src/content/ContentBuilder.hpp index 9207316c..d3e8f536 100644 --- a/src/content/ContentBuilder.hpp +++ b/src/content/ContentBuilder.hpp @@ -44,6 +44,14 @@ public: defs[id] = std::make_unique(id); return *defs[id]; } + // Only fetch existing definition, return null otherwise. + T* get(const std::string& id) { + auto found = defs.find(id); + if (found != defs.end()) { + return &*found->second; + } + return nullptr; + } auto build() { return std::move(defs); diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 26e8f5f0..ba07791b 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -6,6 +6,9 @@ #include #include +#include "Content.hpp" +#include "ContentBuilder.hpp" +#include "ContentPack.hpp" #include "coders/json.hpp" #include "core_defs.hpp" #include "data/dynamic.hpp" @@ -18,9 +21,6 @@ #include "util/listutil.hpp" #include "util/stringutil.hpp" #include "voxels/Block.hpp" -#include "Content.hpp" -#include "ContentBuilder.hpp" -#include "ContentPack.hpp" namespace fs = std::filesystem; @@ -123,6 +123,18 @@ void ContentLoader::loadBlock( ) { auto root = files::read_json(file); + if (root->has("parent")) { + std::string parentName; + root->str("parent", parentName); + auto parentDef = this->builder.blocks.get(parentName); + if (parentDef == nullptr) { + throw std::runtime_error( + "Failed to find parent(" + parentName + ") for " + name + ); + } + parentDef->cloneTo(def); + } + root->str("caption", def.caption); // block texturing @@ -289,6 +301,19 @@ void ContentLoader::loadItem( ItemDef& def, const std::string& name, const fs::path& file ) { auto root = files::read_json(file); + + if (root->has("parent")) { + std::string parentName; + root->str("parent", parentName); + auto parentDef = this->builder.items.get(parentName); + if (parentDef == nullptr) { + throw std::runtime_error( + "Failed to find parent(" + parentName + ") for " + name + ); + } + parentDef->cloneTo(def); + } + root->str("caption", def.caption); std::string iconTypeStr = ""; @@ -319,6 +344,19 @@ void ContentLoader::loadEntity( EntityDef& def, const std::string& name, const fs::path& file ) { auto root = files::read_json(file); + + if (root->has("parent")) { + std::string parentName; + root->str("parent", parentName); + auto parentDef = this->builder.entities.get(parentName); + if (parentDef == nullptr) { + throw std::runtime_error( + "Failed to find parent(" + parentName + ") for " + name + ); + } + parentDef->cloneTo(def); + } + if (auto componentsarr = root->list("components")) { for (size_t i = 0; i < componentsarr->size(); i++) { def.components.emplace_back(componentsarr->str(i)); @@ -340,7 +378,8 @@ void ContentLoader::loadEntity( sensorarr->num(3)}, {sensorarr->num(4), sensorarr->num(5), - sensorarr->num(6)}} + sensorarr->num(6)} + } ); } else if (sensorType == "radius") { def.radialSensors.emplace_back(i, sensorarr->num(1)); diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp index 0673a96d..5087378b 100644 --- a/src/content/ContentLoader.hpp +++ b/src/content/ContentLoader.hpp @@ -42,13 +42,13 @@ class ContentLoader { static void loadCustomBlockModel(Block& def, dynamic::Map* primitives); static void loadBlockMaterial(BlockMaterial& def, const fs::path& file); - static void loadBlock( + void loadBlock( Block& def, const std::string& name, const fs::path& file ); - static void loadItem( + void loadItem( ItemDef& def, const std::string& name, const fs::path& file ); - static void loadEntity( + void loadEntity( EntityDef& def, const std::string& name, const fs::path& file ); void loadResources(ResourceType type, dynamic::List* list); diff --git a/src/items/ItemDef.cpp b/src/items/ItemDef.cpp index 539682c6..321f7be7 100644 --- a/src/items/ItemDef.cpp +++ b/src/items/ItemDef.cpp @@ -5,3 +5,13 @@ ItemDef::ItemDef(const std::string& name) : name(name) { caption = util::id_to_caption(name); } +void ItemDef::cloneTo(ItemDef& dst) { + dst.caption = caption; + dst.stackSize = stackSize; + dst.generated = generated; + std::copy(&emission[0], &emission[3], dst.emission); + dst.iconType = iconType; + dst.icon = icon; + dst.placingBlock = placingBlock; + dst.scriptName = scriptName; +} diff --git a/src/items/ItemDef.hpp b/src/items/ItemDef.hpp index 348ff844..a306dce2 100644 --- a/src/items/ItemDef.hpp +++ b/src/items/ItemDef.hpp @@ -44,4 +44,5 @@ struct ItemDef { ItemDef(const std::string& name); ItemDef(const ItemDef&) = delete; + void cloneTo(ItemDef& dst); }; diff --git a/src/objects/EntityDef.cpp b/src/objects/EntityDef.cpp new file mode 100644 index 00000000..8fa9c129 --- /dev/null +++ b/src/objects/EntityDef.cpp @@ -0,0 +1,12 @@ +#include "EntityDef.hpp" +void EntityDef::cloneTo(EntityDef& dst) { + dst.components = components; + dst.bodyType = bodyType; + dst.hitbox = hitbox; + dst.boxSensors = boxSensors; + dst.radialSensors = radialSensors; + dst.skeletonName = skeletonName; + dst.blocking = blocking; + dst.save = save; + +} \ No newline at end of file diff --git a/src/objects/EntityDef.hpp b/src/objects/EntityDef.hpp index 021c67f1..dec61730 100644 --- a/src/objects/EntityDef.hpp +++ b/src/objects/EntityDef.hpp @@ -24,12 +24,12 @@ struct EntityDef { /// @brief Hitbox size glm::vec3 hitbox {0.25f}; - + /// @brief 'aabb' sensors std::vector> boxSensors {}; /// @brief 'radius' sensors std::vector> radialSensors {}; - + /// @brief Skeleton ID std::string skeletonName = name; @@ -56,4 +56,6 @@ struct EntityDef { EntityDef(const std::string& name) : name(name) {} EntityDef(const EntityDef&) = delete; + void cloneTo(EntityDef& dst); }; + diff --git a/src/voxels/Block.cpp b/src/voxels/Block.cpp index aee744a1..ec125430 100644 --- a/src/voxels/Block.cpp +++ b/src/voxels/Block.cpp @@ -64,7 +64,8 @@ const BlockRotProfile BlockRotProfile::NONE { {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, // West {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, // Up {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, // Down - }}; + } +}; const BlockRotProfile BlockRotProfile::PIPE { "pipe", @@ -75,7 +76,8 @@ const BlockRotProfile BlockRotProfile::PIPE { {{0, 0, -1}, {1, 0, 0}, {0, -1, 0}}, // West {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}, // Up {{1, 0, 0}, {0, -1, 0}, {0, 0, -1}}, // Down - }}; + } +}; const BlockRotProfile BlockRotProfile::PANE { "pane", @@ -84,7 +86,8 @@ const BlockRotProfile BlockRotProfile::PANE { {{0, 0, -1}, {0, 1, 0}, {1, 0, 0}}, // East {{-1, 0, 0}, {0, 1, 0}, {0, 0, -1}}, // South {{0, 0, 1}, {0, 1, 0}, {-1, 0, 0}}, // West - }}; + } +}; Block::Block(const std::string& name) : name(name), @@ -95,10 +98,43 @@ Block::Block(const std::string& name) TEXTURE_NOTFOUND, TEXTURE_NOTFOUND, TEXTURE_NOTFOUND, - TEXTURE_NOTFOUND} { + TEXTURE_NOTFOUND + } { } Block::Block(std::string name, const std::string& texture) : name(std::move(name)), textureFaces {texture, texture, texture, texture, texture, texture} { } +void Block::cloneTo(Block& dst) { + dst.caption = caption; + for (int i = 0; i < 6; i++) { + dst.textureFaces[i] = textureFaces[i]; + } + dst.modelTextures = modelTextures; + dst.modelBoxes = modelBoxes; + dst.modelExtraPoints = modelExtraPoints; + dst.modelUVs = modelUVs; + dst.material = material; + std::copy(&emission[0], &emission[3], dst.emission); + dst.size = size; + dst.model = model; + dst.lightPassing = lightPassing; + dst.skyLightPassing = skyLightPassing; + dst.shadeless = shadeless; + dst.ambientOcclusion = ambientOcclusion; + dst.obstacle = obstacle; + dst.selectable = selectable; + dst.replaceable = replaceable; + dst.breakable = breakable; + dst.rotatable = rotatable; + dst.grounded = grounded; + dst.hidden = hidden; + dst.hitboxes = hitboxes; + dst.rotations = rotations; + dst.pickingItem = pickingItem; + dst.scriptName = scriptName; + dst.uiLayout = uiLayout; + dst.inventorySize = inventorySize; + dst.tickInterval = tickInterval; +} diff --git a/src/voxels/Block.hpp b/src/voxels/Block.hpp index a32ddd1c..210972bb 100644 --- a/src/voxels/Block.hpp +++ b/src/voxels/Block.hpp @@ -211,6 +211,8 @@ public: Block(const std::string& name); Block(std::string name, const std::string& texture); Block(const Block&) = delete; + + void cloneTo(Block& dst); }; inline glm::ivec3 get_ground_direction(const Block& def, int rotation) { From 333cbfe6f56e6bf625e9d95044879ea1d96aeafa Mon Sep 17 00:00:00 2001 From: MihailRis Date: Tue, 20 Aug 2024 22:00:30 +0300 Subject: [PATCH 11/16] refactor: add 'const' qualifier for content units --- src/content/Content.hpp | 12 ++---------- src/logic/scripting/lua/libblock.cpp | 2 +- src/logic/scripting/lua/libentity.cpp | 2 +- src/objects/Entities.cpp | 4 ++-- src/objects/Entities.hpp | 2 +- 5 files changed, 7 insertions(+), 15 deletions(-) diff --git a/src/content/Content.hpp b/src/content/Content.hpp index 4178b7d8..1931c262 100644 --- a/src/content/Content.hpp +++ b/src/content/Content.hpp @@ -65,14 +65,6 @@ public: return defs[id]; } - [[deprecated]] - inline T* getWriteable(blockid_t id) const { // TODO: remove - if (id >= defs.size()) { - return nullptr; - } - return defs[id]; - } - inline const T& require(blockid_t id) const { return *defs.at(id); } @@ -111,14 +103,14 @@ public: ContentUnitDefs(UptrsMap defs) : defs(std::move(defs)) { } - T* find(const std::string& id) const { + const T* find(const std::string& id) const { const auto& found = defs.find(id); if (found == defs.end()) { return nullptr; } return found->second.get(); } - T& require(const std::string& id) const { + const T& require(const std::string& id) const { const auto& found = defs.find(id); if (found == defs.end()) { throw std::runtime_error("missing content unit " + id); diff --git a/src/logic/scripting/lua/libblock.cpp b/src/logic/scripting/lua/libblock.cpp index 342f7899..bd906f5d 100644 --- a/src/logic/scripting/lua/libblock.cpp +++ b/src/logic/scripting/lua/libblock.cpp @@ -360,7 +360,7 @@ static int l_raycast(lua::State* L) { for (int i = 0; i < addLen; i++) { lua::rawgeti(L, i + 1, 5); auto blockName = std::string(lua::tostring(L, -1)); - Block* block = content->blocks.find(blockName); + const Block* block = content->blocks.find(blockName); if (block != nullptr) { filteredBlocks.insert(block->rt.id); } diff --git a/src/logic/scripting/lua/libentity.cpp b/src/logic/scripting/lua/libentity.cpp index 1d21c6ef..e4c49c8f 100644 --- a/src/logic/scripting/lua/libentity.cpp +++ b/src/logic/scripting/lua/libentity.cpp @@ -127,7 +127,7 @@ static int l_raycast(lua::State* L) { for (int i = 0; i < addLen; i++) { lua::rawgeti(L, i + 1, 6); auto blockName = std::string(lua::tostring(L, -1)); - Block* block = content->blocks.find(blockName); + const Block* block = content->blocks.find(blockName); if (block != nullptr) { filteredBlocks.insert(block->rt.id); } diff --git a/src/objects/Entities.cpp b/src/objects/Entities.cpp index cbb023cc..b50b4318 100644 --- a/src/objects/Entities.cpp +++ b/src/objects/Entities.cpp @@ -75,7 +75,7 @@ static sensorcallback create_sensor_callback(Entities* entities) { } static void initialize_body( - EntityDef& def, Rigidbody& body, entityid_t id, Entities* entities + 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) { @@ -111,7 +111,7 @@ static void initialize_body( } entityid_t Entities::spawn( - EntityDef& def, + const EntityDef& def, glm::vec3 position, dynamic::Map_sptr args, dynamic::Map_sptr saved, diff --git a/src/objects/Entities.hpp b/src/objects/Entities.hpp index adf36ce5..9ef2edd6 100644 --- a/src/objects/Entities.hpp +++ b/src/objects/Entities.hpp @@ -202,7 +202,7 @@ public: ); entityid_t spawn( - EntityDef& def, + const EntityDef& def, glm::vec3 position, dynamic::Map_sptr args = nullptr, dynamic::Map_sptr saved = nullptr, From 16ddd943c20cbae9c480ad2c7ba51661740b13c3 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Wed, 21 Aug 2024 19:15:09 +0300 Subject: [PATCH 12/16] ItemDef/EntityDef/Block: Add proper dependency resolution for blocks, items, entities --- src/content/ContentLoader.cpp | 165 ++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 28 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index ba07791b..42fbf7c7 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -480,46 +480,155 @@ void ContentLoader::load() { if (!fs::is_regular_file(pack->getContentFile())) return; auto root = files::read_json(pack->getContentFile()); + std::vector> pendingDefs; + auto getJsonParent = [&](std::string prerix, std::string name) { + auto configFile = + pack->folder / fs::path(prerix + "/" + name + ".json"); + std::string parent; + if (fs::exists(configFile)) { + auto root = files::read_json(configFile); + if (root->has("parent")) root->str("parent", parent); + } + return parent; + }; + auto processName = [&](std::string name) { + auto colon = name.find(':'); + std::string full = + colon == std::string::npos ? pack->id + ":" + name : name; + if (colon != std::string::npos) name[colon] = '/'; + + return std::make_pair(full, name); + }; if (auto blocksarr = root->list("blocks")) { for (size_t i = 0; i < blocksarr->size(); i++) { - std::string name = blocksarr->str(i); - auto colon = name.find(':'); - std::string full = - colon == std::string::npos ? pack->id + ":" + name : name; - if (colon != std::string::npos) name[colon] = '/'; - auto& def = builder.blocks.create(full); - if (colon != std::string::npos) - def.scriptName = name.substr(0, colon) + '/' + def.scriptName; - loadBlock(def, full, name); - stats->totalBlocks++; + auto [full, name] = processName(blocksarr->str(i)); + auto parent = getJsonParent("blocks", name); + if (parent.empty() || builder.blocks.get(parent)) { + // No dependency or dependency already loaded/exists in another + // content pack + auto& def = builder.blocks.create(full); + loadBlock(def, full, name); + stats->totalBlocks++; + } else { + // Dependency not loaded yet, add to pending items + pendingDefs.emplace_back(full, name); + } + } + + // Resolve dependencies for pending items + bool progressMade = true; + while (!pendingDefs.empty() && progressMade) { + progressMade = false; + + for (auto it = pendingDefs.begin(); it != pendingDefs.end();) { + auto parent = getJsonParent("blocks", it->second); + if (builder.blocks.get(parent)) { + // Dependency resolved or parent exists in another pack, + // load the item + auto& def = builder.blocks.create(it->first); + loadBlock(def, it->first, it->second); + stats->totalBlocks++; + it = pendingDefs.erase(it); // Remove resolved item + progressMade = true; + } else { + ++it; + } + } + } + + if (!pendingDefs.empty()) { + // Handle circular dependencies or missing dependencies + // You can log an error or throw an exception here if necessary + throw std::runtime_error("Unresolved block dependencies detected."); } } + if (auto itemsarr = root->list("items")) { for (size_t i = 0; i < itemsarr->size(); i++) { - std::string name = itemsarr->str(i); - auto colon = name.find(':'); - std::string full = - colon == std::string::npos ? pack->id + ":" + name : name; - if (colon != std::string::npos) name[colon] = '/'; - auto& def = builder.items.create(full); - if (colon != std::string::npos) - def.scriptName = name.substr(0, colon) + '/' + def.scriptName; - loadItem(def, full, name); - stats->totalItems++; + auto [full, name] = processName(itemsarr->str(i)); + auto parent = getJsonParent("items", name); + if (parent.empty() || builder.items.get(parent)) { + // No dependency or dependency already loaded/exists in another + // content pack + auto& def = builder.items.create(full); + loadItem(def, full, name); + stats->totalItems++; + } else { + // Dependency not loaded yet, add to pending items + pendingDefs.emplace_back(full, name); + } + } + + // Resolve dependencies for pending items + bool progressMade = true; + while (!pendingDefs.empty() && progressMade) { + progressMade = false; + + for (auto it = pendingDefs.begin(); it != pendingDefs.end();) { + auto parent = getJsonParent("items", it->second); + if (builder.items.get(parent)) { + // Dependency resolved or parent exists in another pack, + // load the item + auto& def = builder.items.create(it->first); + loadItem(def, it->first, it->second); + stats->totalItems++; + it = pendingDefs.erase(it); // Remove resolved item + progressMade = true; + } else { + ++it; + } + } + } + + if (!pendingDefs.empty()) { + // Handle circular dependencies or missing dependencies + // You can log an error or throw an exception here if necessary + throw std::runtime_error("Unresolved item dependencies detected."); } } if (auto entitiesarr = root->list("entities")) { for (size_t i = 0; i < entitiesarr->size(); i++) { - std::string name = entitiesarr->str(i); - auto colon = name.find(':'); - std::string full = - colon == std::string::npos ? pack->id + ":" + name : name; - if (colon != std::string::npos) name[colon] = '/'; - auto& def = builder.entities.create(full); - loadEntity(def, full, name); - stats->totalEntities++; + auto [full, name] = processName(entitiesarr->str(i)); + auto parent = getJsonParent("entities", name); + if (parent.empty() || builder.entities.get(parent)) { + // No dependency or dependency already loaded/exists in another + // content pack + auto& def = builder.entities.create(full); + loadEntity(def, full, name); + stats->totalEntities++; + } else { + // Dependency not loaded yet, add to pending items + pendingDefs.emplace_back(full, name); + } + } + + // Resolve dependencies for pending items + bool progressMade = true; + while (!pendingDefs.empty() && progressMade) { + progressMade = false; + + for (auto it = pendingDefs.begin(); it != pendingDefs.end();) { + auto parent = getJsonParent("entities", it->second); + if (builder.entities.get(parent)) { + // Dependency resolved or parent exists in another pack, + // load the item + auto& def = builder.entities.create(it->first); + loadEntity(def, it->first, it->second); + stats->totalEntities++; + it = pendingDefs.erase(it); // Remove resolved item + progressMade = true; + } else { + ++it; + } + } + } + + if (!pendingDefs.empty()) { + // Handle circular dependencies or missing dependencies + // You can log an error or throw an exception here if necessary + throw std::runtime_error("Unresolved entities dependencies detected."); } } From fcd26f4b10f8c0059385edf556375f63fe4fe168 Mon Sep 17 00:00:00 2001 From: REDxEYE Date: Wed, 21 Aug 2024 19:28:08 +0300 Subject: [PATCH 13/16] ContentLoader::load: Minor cleanup --- src/content/ContentLoader.cpp | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index 42fbf7c7..45abb7f9 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -481,23 +481,23 @@ void ContentLoader::load() { auto root = files::read_json(pack->getContentFile()); std::vector> pendingDefs; - auto getJsonParent = [&](std::string prerix, std::string name) { - auto configFile = - pack->folder / fs::path(prerix + "/" + name + ".json"); - std::string parent; - if (fs::exists(configFile)) { - auto root = files::read_json(configFile); - if (root->has("parent")) root->str("parent", parent); - } - return parent; - }; - auto processName = [&](std::string name) { + auto getJsonParent = [this](const std::string& prefix, const std::string& name) { + auto configFile = pack->folder / fs::path(prefix + "/" + name + ".json"); + std::string parent; + if (fs::exists(configFile)) { + auto root = files::read_json(configFile); + if (root->has("parent")) root->str("parent", parent); + } + return parent; + }; + auto processName = [this](const std::string& name) { auto colon = name.find(':'); + auto new_name = name; std::string full = colon == std::string::npos ? pack->id + ":" + name : name; - if (colon != std::string::npos) name[colon] = '/'; + if (colon != std::string::npos) new_name[colon] = '/'; - return std::make_pair(full, name); + return std::make_pair(full, new_name); }; if (auto blocksarr = root->list("blocks")) { @@ -628,7 +628,9 @@ void ContentLoader::load() { if (!pendingDefs.empty()) { // Handle circular dependencies or missing dependencies // You can log an error or throw an exception here if necessary - throw std::runtime_error("Unresolved entities dependencies detected."); + throw std::runtime_error( + "Unresolved entities dependencies detected." + ); } } From 719135fe19de0b9f96e457b2f3d9293381fa3466 Mon Sep 17 00:00:00 2001 From: MihailRis Date: Thu, 22 Aug 2024 23:50:46 +0300 Subject: [PATCH 14/16] fix animation loading --- src/assets/AssetsLoader.cpp | 3 +++ src/assets/assetload_funcs.cpp | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/assets/AssetsLoader.cpp b/src/assets/AssetsLoader.cpp index 9a570fc2..a4853606 100644 --- a/src/assets/AssetsLoader.cpp +++ b/src/assets/AssetsLoader.cpp @@ -194,6 +194,9 @@ void AssetsLoader::processPreloadConfigs(const Content* content) { return; } for (auto& entry : content->getPacks()) { + if (entry.first == "core") { + continue; + } const auto& pack = entry.second; auto preloadFile = pack->getInfo().folder / fs::path("preload.json"); if (fs::exists(preloadFile)) { diff --git a/src/assets/assetload_funcs.cpp b/src/assets/assetload_funcs.cpp index 97107862..35133264 100644 --- a/src/assets/assetload_funcs.cpp +++ b/src/assets/assetload_funcs.cpp @@ -12,6 +12,7 @@ #include "coders/obj.hpp" #include "constants.hpp" #include "data/dynamic.hpp" +#include "debug/Logger.hpp" #include "files/engine_paths.hpp" #include "files/files.hpp" #include "frontend/UiDocument.hpp" @@ -26,6 +27,8 @@ #include "Assets.hpp" #include "AssetsLoader.hpp" +static debug::Logger logger("assetload-funcs"); + namespace fs = std::filesystem; static bool animation( @@ -263,7 +266,7 @@ static TextureAnimation create_animation( for (const auto& elem : frameList) { if (!srcAtlas->has(elem.first)) { - std::cerr << "Unknown frame name: " << elem.first << std::endl; + logger.error() << "unknown frame name: " << elem.first; continue; } region = srcAtlas->get(elem.first); From 545cf49642dabb11bea5016184cac1f3915f70a4 Mon Sep 17 00:00:00 2001 From: "@clasher113" Date: Sat, 24 Aug 2024 22:40:18 +0300 Subject: [PATCH 15/16] block model "x" preview fix --- src/graphics/render/BlocksPreview.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/graphics/render/BlocksPreview.cpp b/src/graphics/render/BlocksPreview.cpp index bf6b2a10..619266bd 100644 --- a/src/graphics/render/BlocksPreview.cpp +++ b/src/graphics/render/BlocksPreview.cpp @@ -102,6 +102,7 @@ std::unique_ptr BlocksPreview::draw( } break; case BlockModel::xsprite: { + shader->uniformMatrix("u_apply", glm::translate(glm::mat4(1.0f), offset)); glm::vec3 right = glm::normalize(glm::vec3(1.f, 0.f, -1.f)); batch->sprite( right*float(size)*0.43f+glm::vec3(0, size*0.4f, 0), From f2b9d0620aad052574aafaf1a8f804b2fa07588c Mon Sep 17 00:00:00 2001 From: MihailRis Date: Wed, 28 Aug 2024 11:59:35 +0300 Subject: [PATCH 16/16] add cameras.get(int) overload --- res/scripts/classes.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/res/scripts/classes.lua b/res/scripts/classes.lua index 1c2b0cba..3c23fdc4 100644 --- a/res/scripts/classes.lua +++ b/res/scripts/classes.lua @@ -22,6 +22,9 @@ local Camera = {__index={ local wrappers = {} cameras.get = function(name) + if type(name) == 'number' then + return cameras.get(cameras.name(name)) + end local wrapper = wrappers[name] if wrapper ~= nil then return wrapper