Веб-сайт самохостера Lotigara

summaryrefslogtreecommitdiff
path: root/source/base
diff options
context:
space:
mode:
authorKae <80987908+Novaenia@users.noreply.github.com>2024-03-21 00:57:49 +1100
committerKae <80987908+Novaenia@users.noreply.github.com>2024-03-21 00:57:49 +1100
commit57ca6776e41eb4d72fd65bc6b88ca8074180ef15 (patch)
tree154c718fa32d4454c017d5f50ea0ea87b57b49ae /source/base
parenta096fa3ffc3627ace2d858b61456e578fb7bc25a (diff)
Lua patches
Diffstat (limited to 'source/base')
-rw-r--r--source/base/StarAssets.cpp107
-rw-r--r--source/base/StarAssets.hpp8
-rw-r--r--source/base/StarCellularLighting.hpp12
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;
}