diff options
author | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-03-21 00:57:49 +1100 |
---|---|---|
committer | Kae <80987908+Novaenia@users.noreply.github.com> | 2024-03-21 00:57:49 +1100 |
commit | 57ca6776e41eb4d72fd65bc6b88ca8074180ef15 (patch) | |
tree | 154c718fa32d4454c017d5f50ea0ea87b57b49ae /source/base | |
parent | a096fa3ffc3627ace2d858b61456e578fb7bc25a (diff) |
Lua patches
Diffstat (limited to 'source/base')
-rw-r--r-- | source/base/StarAssets.cpp | 107 | ||||
-rw-r--r-- | source/base/StarAssets.hpp | 8 | ||||
-rw-r--r-- | source/base/StarCellularLighting.hpp | 12 |
3 files changed, 85 insertions, 42 deletions
diff --git a/source/base/StarAssets.cpp b/source/base/StarAssets.cpp index 6593d3d..2bbe509 100644 --- a/source/base/StarAssets.cpp +++ b/source/base/StarAssets.cpp @@ -110,8 +110,15 @@ Assets::Assets(Settings settings, StringList assetSources) { m_assetSources = std::move(assetSources); auto luaEngine = LuaEngine::create(); + m_luaEngine = luaEngine; + auto pushGlobalContext = [&luaEngine](String const& name, LuaCallbacks & callbacks) { + auto table = luaEngine->createTable(); + for (auto const& p : callbacks.callbacks()) + table.set(p.first, luaEngine->createWrappedFunction(p.second)); + luaEngine->setGlobal(name, table); + }; + pushGlobalContext("sb", LuaBindings::makeUtilityCallbacks()); auto decorateLuaContext = [this](LuaContext& context, MemoryAssetSourcePtr newFiles) { - context.setCallbacks("sb", LuaBindings::makeUtilityCallbacks()); LuaCallbacks callbacks; callbacks.registerCallbackWithSignature<StringSet, String>("byExtension", bind(&Assets::scanExtension, this, _1)); callbacks.registerCallbackWithSignature<Json, String>("json", bind(&Assets::json, this, _1)); @@ -133,38 +140,40 @@ Assets::Assets(Settings settings, StringList assetSources) { return b ? scan(a.value(), *b) : scan(a.value()); }); - callbacks.registerCallback("add", [this, &newFiles](LuaEngine& engine, String const& path, LuaValue const& data) { - ByteArray bytes; - if (auto str = engine.luaMaybeTo<String>(data)) - bytes = ByteArray(str->utf8Ptr(), str->utf8Size()); - else { - auto json = engine.luaTo<Json>(data).repr(); - bytes = ByteArray(json.utf8Ptr(), json.utf8Size()); - } - newFiles->set(path, bytes); - }); + if (newFiles) { + callbacks.registerCallback("add", [this, &newFiles](LuaEngine& engine, String const& path, LuaValue const& data) { + ByteArray bytes; + if (auto str = engine.luaMaybeTo<String>(data)) + bytes = ByteArray(str->utf8Ptr(), str->utf8Size()); + else { + auto json = engine.luaTo<Json>(data).repr(); + bytes = ByteArray(json.utf8Ptr(), json.utf8Size()); + } + newFiles->set(path, bytes); + }); - callbacks.registerCallback("patch", [this, &newFiles](String const& path, String const& patchPath) -> bool { - if (auto file = m_files.ptr(path)) { - if (newFiles->contains(patchPath)) { - file->patchSources.append(make_pair(patchPath, newFiles)); - return true; - } else { - if (auto asset = m_files.ptr(patchPath)) { - file->patchSources.append(make_pair(patchPath, asset->source)); + callbacks.registerCallback("patch", [this, &newFiles](String const& path, String const& patchPath) -> bool { + if (auto file = m_files.ptr(path)) { + if (newFiles->contains(patchPath)) { + file->patchSources.append(make_pair(patchPath, newFiles)); return true; + } else { + if (auto asset = m_files.ptr(patchPath)) { + file->patchSources.append(make_pair(patchPath, asset->source)); + return true; + } } } - } - return false; - }); + return false; + }); - callbacks.registerCallback("erase", [this](String const& path) -> bool { - bool erased = m_files.erase(path); - if (erased) - m_filesByExtension[AssetPath::extension(path).toLower()].erase(path); - return erased; - }); + callbacks.registerCallback("erase", [this](String const& path) -> bool { + bool erased = m_files.erase(path); + if (erased) + m_filesByExtension[AssetPath::extension(path).toLower()].erase(path); + return erased; + }); + } context.setCallbacks("assets", callbacks); }; @@ -883,21 +892,35 @@ Json Assets::readJson(String const& path) const { try { Json result = inputUtf8Json(streamData.begin(), streamData.end(), false); for (auto const& pair : m_files.get(path).patchSources) { - auto patchStream = pair.second->read(pair.first); - auto patchJson = inputUtf8Json(patchStream.begin(), patchStream.end(), false); - if (patchJson.isType(Json::Type::Array)) { - auto patchData = patchJson.toArray(); - try { - result = checkPatchArray(pair.first, pair.second, result, patchData, {}); - } catch (JsonPatchTestFail const& e) { - Logger::debug("Patch test failure from file {} in source: '{}' at '{}'. Caused by: {}", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); - } catch (JsonPatchException const& e) { - Logger::error("Could not apply patch from file {} in source: '{}' at '{}'. Caused by: {}", pair.first, pair.second->metadata().value("name", ""), m_assetSourcePaths.getLeft(pair.second), e.what()); + auto& patchPath = pair.first; + auto& patchSource = pair.second; + auto patchStream = patchSource->read(patchPath); + if (pair.first.endsWith(".lua")) { + MutexLocker luaLocker(m_luaMutex); + // Kae: i don't like that lock. perhaps have a LuaEngine and patch context cache per worker thread later on? + LuaContextPtr& context = m_patchContexts[patchPath]; + if (!context) { + context = make_shared<LuaContext>(as<LuaEngine>(m_luaEngine.get())->createContext()); + context->load(patchStream, patchPath); + } + auto newResult = context->invokePath<Json>("patch", result, path); + if (newResult) + result = std::move(newResult); + } else { + auto patchJson = inputUtf8Json(patchStream.begin(), patchStream.end(), false); + if (patchJson.isType(Json::Type::Array)) { + auto patchData = patchJson.toArray(); + try { + result = checkPatchArray(patchPath, patchSource, result, patchData, {}); + } catch (JsonPatchTestFail const& e) { + Logger::debug("Patch test failure from file {} in source: '{}' at '{}'. Caused by: {}", patchPath, patchSource->metadata().value("name", ""), m_assetSourcePaths.getLeft(patchSource), e.what()); + } catch (JsonPatchException const& e) { + Logger::error("Could not apply patch from file {} in source: '{}' at '{}'. Caused by: {}", patchPath, patchSource->metadata().value("name", ""), m_assetSourcePaths.getLeft(patchSource), e.what()); + } + } else if (patchJson.isType(Json::Type::Object)) {//Kae: Do a good ol' json merge instead if the .patch file is a Json object + result = jsonMergeNulling(result, patchJson.toObject()); + } } - } else if (patchJson.isType(Json::Type::Object)) { //Kae: Do a good ol' json merge instead if the .patch file is a Json object - auto patchData = patchJson.toObject(); - result = jsonMergeNulling(result, patchData); - } } return result; } catch (std::exception const& e) { diff --git a/source/base/StarAssets.hpp b/source/base/StarAssets.hpp index f945cf8..8cfbc52 100644 --- a/source/base/StarAssets.hpp +++ b/source/base/StarAssets.hpp @@ -7,6 +7,7 @@ #include "StarThread.hpp" #include "StarAssetSource.hpp" #include "StarAssetPath.hpp" +#include "StarRefPtr.hpp" namespace Star { @@ -16,6 +17,8 @@ STAR_CLASS(Image); STAR_STRUCT(FramesSpecification); STAR_CLASS(Assets); +STAR_CLASS(LuaContext); + STAR_EXCEPTION(AssetException, StarException); // The contents of an assets .frames file, which can be associated with one or @@ -313,6 +316,11 @@ private: mutable StringMap<String> m_bestFramesFiles; mutable StringMap<FramesSpecificationConstPtr> m_framesSpecifications; + // Lua + RefPtr<RefCounter> m_luaEngine; // dumb but to avoid including Lua.hpp in here... + mutable StringMap<LuaContextPtr> m_patchContexts; + mutable Mutex m_luaMutex; + // Paths of all used asset sources, in load order. StringList m_assetSources; diff --git a/source/base/StarCellularLighting.hpp b/source/base/StarCellularLighting.hpp index 170cbb5..7cb230f 100644 --- a/source/base/StarCellularLighting.hpp +++ b/source/base/StarCellularLighting.hpp @@ -27,6 +27,7 @@ public: void set(unsigned x, unsigned y, float v); void set(unsigned x, unsigned y, Vec3F const& v); + void add(unsigned x, unsigned y, Vec3F const& v); Vec3F get(unsigned x, unsigned y) const; bool empty() const; @@ -64,6 +65,16 @@ inline void Lightmap::set(unsigned x, unsigned y, Vec3F const& v) { ptr[2] = v.z(); } +inline void Lightmap::add(unsigned x, unsigned y, Vec3F const& v) { + if (x >= m_width || y >= m_height) { + throw LightmapException(strf("[{}, {}] out of range in Lightmap::add", x, y)); + return; + } + float* ptr = m_data.get() + (y * m_width * 3 + x * 3); + ptr[0] += v.x(); + ptr[1] += v.y(); + ptr[2] += v.z(); +} inline Vec3F Lightmap::get(unsigned x, unsigned y) const { if (x >= m_width || y >= m_height) { @@ -74,6 +85,7 @@ inline Vec3F Lightmap::get(unsigned x, unsigned y) const { return Vec3F(ptr[0], ptr[1], ptr[2]); } + inline bool Lightmap::empty() const { return m_width == 0 || m_height == 0; } |