diff --git a/src/content/Content.hpp b/src/content/Content.hpp index b95ef247..a7f56b56 100644 --- a/src/content/Content.hpp +++ b/src/content/Content.hpp @@ -121,6 +121,14 @@ public: return *found->second; } + T& require(const std::string& id) { + const auto& found = defs.find(id); + if (found == defs.end()) { + throw std::runtime_error("missing content unit " + id); + } + return *found->second; + } + const auto& getDefs() const { return defs; } diff --git a/src/content/ContentLoader.cpp b/src/content/ContentLoader.cpp index bc8598bd..47fca715 100644 --- a/src/content/ContentLoader.cpp +++ b/src/content/ContentLoader.cpp @@ -853,26 +853,40 @@ void ContentLoader::load() { } template -static void load_scripts(Content& content, ContentUnitDefs& units) { - for (const auto& [name, def] : units.getDefs()) { - size_t pos = name.find(':'); - if (pos == std::string::npos) { - throw std::runtime_error("invalid content unit name"); - } - const auto runtime = content.getPackRuntime(name.substr(0, pos)); - const auto& pack = runtime->getInfo(); - const auto& folder = pack.folder; - auto scriptfile = folder / ("scripts/" + def->scriptName + ".lua"); - if (io::is_regular_file(scriptfile)) { - scripting::load_content_script( - runtime->getEnvironment(), - name, - scriptfile, - def->scriptFile, - def->rt.funcsset - ); - } +static void load_script(const Content& content, T& def) { + const auto& name = def.name; + size_t pos = name.find(':'); + if (pos == std::string::npos) { + throw std::runtime_error("invalid content unit name"); } + const auto runtime = content.getPackRuntime(name.substr(0, pos)); + const auto& pack = runtime->getInfo(); + const auto& folder = pack.folder; + auto scriptfile = folder / ("scripts/" + def.scriptName + ".lua"); + if (io::is_regular_file(scriptfile)) { + scripting::load_content_script( + runtime->getEnvironment(), + name, + scriptfile, + def.scriptFile, + def.rt.funcsset + ); + } +} + +template +static void load_scripts(const Content& content, ContentUnitDefs& units) { + for (const auto& [_, def] : units.getDefs()) { + load_script(content, *def); + } +} + +void ContentLoader::reloadScript(const Content& content, Block& block) { + load_script(content, block); +} + +void ContentLoader::reloadScript(const Content& content, ItemDef& item) { + load_script(content, item); } void ContentLoader::loadScripts(Content& content) { diff --git a/src/content/ContentLoader.hpp b/src/content/ContentLoader.hpp index f1135ee3..8860cc77 100644 --- a/src/content/ContentLoader.hpp +++ b/src/content/ContentLoader.hpp @@ -77,4 +77,6 @@ public: void load(); static void loadScripts(Content& content); + static void reloadScript(const Content& content, Block& block); + static void reloadScript(const Content& content, ItemDef& item); }; diff --git a/src/engine/Engine.cpp b/src/engine/Engine.cpp index c9184383..5778ed98 100644 --- a/src/engine/Engine.cpp +++ b/src/engine/Engine.cpp @@ -484,6 +484,10 @@ const Content* Engine::getContent() const { return content.get(); } +Content* Engine::getWriteableContent() { + return content.get(); +} + std::vector Engine::getAllContentPacks() { auto packs = getContentPacks(); packs.insert(packs.begin(), ContentPack::createCore(paths)); diff --git a/src/engine/Engine.hpp b/src/engine/Engine.hpp index b05881f6..ccfabeed 100644 --- a/src/engine/Engine.hpp +++ b/src/engine/Engine.hpp @@ -151,6 +151,8 @@ public: /// @brief Get current Content instance const Content* getContent() const; + Content* getWriteableContent(); + /// @brief Get selected content packs std::vector& getContentPacks(); diff --git a/src/logic/scripting/lua/libs/libblock.cpp b/src/logic/scripting/lua/libs/libblock.cpp index f37b4ba3..8e1b82c4 100644 --- a/src/logic/scripting/lua/libs/libblock.cpp +++ b/src/logic/scripting/lua/libs/libblock.cpp @@ -1,4 +1,5 @@ #include "content/Content.hpp" +#include "content/ContentLoader.hpp" #include "lighting/Lighting.hpp" #include "logic/BlocksController.hpp" #include "logic/LevelController.hpp" @@ -12,6 +13,7 @@ #include "world/Level.hpp" #include "maths/voxmaths.hpp" #include "data/StructLayout.hpp" +#include "engine/Engine.hpp" #include "api_lua.hpp" using namespace scripting; @@ -617,6 +619,17 @@ static int l_set_field(lua::State* L) { return set_field(L, dst, *field, index, dataStruct, value); } +static int l_reload_script(lua::State* L) { + auto name = lua::require_string(L, 1); + if (content == nullptr) { + throw std::runtime_error("content is not initialized"); + } + auto& writeableContent = *engine->getWriteableContent(); + auto& def = writeableContent.blocks.require(name); + ContentLoader::reloadScript(writeableContent, def); + return 0; +} + const luaL_Reg blocklib[] = { {"index", lua::wrap}, {"name", lua::wrap}, @@ -652,5 +665,6 @@ const luaL_Reg blocklib[] = { {"decompose_state", lua::wrap}, {"get_field", lua::wrap}, {"set_field", lua::wrap}, + {"reload_script", lua::wrap}, {NULL, NULL} }; diff --git a/src/logic/scripting/lua/libs/libitem.cpp b/src/logic/scripting/lua/libs/libitem.cpp index b905f1d9..e7cc241b 100644 --- a/src/logic/scripting/lua/libs/libitem.cpp +++ b/src/logic/scripting/lua/libs/libitem.cpp @@ -1,6 +1,8 @@ #include "content/Content.hpp" +#include "content/ContentLoader.hpp" #include "items/ItemDef.hpp" #include "api_lua.hpp" +#include "engine/Engine.hpp" using namespace scripting; @@ -87,6 +89,17 @@ static int l_uses(lua::State* L) { return 0; } +static int l_reload_script(lua::State* L) { + auto name = lua::require_string(L, 1); + if (content == nullptr) { + throw std::runtime_error("content is not initialized"); + } + auto& writeableContent = *engine->getWriteableContent(); + auto& def = writeableContent.items.require(name); + ContentLoader::reloadScript(writeableContent, def); + return 0; +} + const luaL_Reg itemlib[] = { {"index", lua::wrap}, {"name", lua::wrap}, @@ -98,5 +111,6 @@ const luaL_Reg itemlib[] = { {"model_name", lua::wrap}, {"emission", lua::wrap}, {"uses", lua::wrap}, + {"reload_script", lua::wrap}, {NULL, NULL} };