Add .patchlist

#73
This commit is contained in:
Kae 2024-06-25 19:56:44 +10:00
parent 67c7257c3b
commit 9edbe8cf2d

View File

@ -104,6 +104,7 @@ Maybe<RectU> FramesSpecification::getRect(String const& frame) const {
Assets::Assets(Settings settings, StringList assetSources) { Assets::Assets(Settings settings, StringList assetSources) {
const char* AssetsPatchSuffix = ".patch"; const char* AssetsPatchSuffix = ".patch";
const char* AssetsPatchListSuffix = ".patchlist";
const char* AssetsLuaPatchSuffix = ".patch.lua"; const char* AssetsLuaPatchSuffix = ".patch.lua";
m_settings = std::move(settings); m_settings = std::move(settings);
@ -204,6 +205,24 @@ Assets::Assets(Settings settings, StringList assetSources) {
auto targetPatchFile = filename.substr(0, filename.size() - strlen(AssetsLuaPatchSuffix)); auto targetPatchFile = filename.substr(0, filename.size() - strlen(AssetsLuaPatchSuffix));
if (auto p = m_files.ptr(targetPatchFile)) if (auto p = m_files.ptr(targetPatchFile))
p->patchSources.append({filename, source}); p->patchSources.append({filename, source});
} else if (filename.endsWith(AssetsPatchListSuffix, String::CaseInsensitive)) {
auto stream = source->read(filename);
size_t patchIndex = 0;
for (auto const& patchPair : inputUtf8Json(stream.begin(), stream.end(), JsonParseType::Top).iterateArray()) {
auto& patches = patchPair.getArray("patches");
for (auto& path : patchPair.getArray("paths")) {
if (auto p = m_files.ptr(path.toString())) {
for (size_t i = 0; i != patches.size(); ++i) {
auto& patch = patches[i];
if (patch.isType(Json::Type::String))
p->patchSources.append({patch.toString(), source});
else
p->patchSources.append({strf("{}:[{}].patches[{}]", filename, patchIndex, i), source});
}
}
}
patchIndex++;
}
} else { } else {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
if (filename.endsWith(AssetsPatchSuffix + toString(i), String::CaseInsensitive)) { if (filename.endsWith(AssetsPatchSuffix + toString(i), String::CaseInsensitive)) {
@ -289,7 +308,7 @@ Assets::Assets(Settings settings, StringList assetSources) {
digest.push(assetPath); digest.push(assetPath);
digest.push(DataStreamBuffer::serialize(descriptor.source->open(descriptor.sourceName)->size())); digest.push(DataStreamBuffer::serialize(descriptor.source->open(descriptor.sourceName)->size()));
for (auto const& pair : descriptor.patchSources) for (auto const& pair : descriptor.patchSources)
digest.push(DataStreamBuffer::serialize(pair.second->open(pair.first)->size())); digest.push(DataStreamBuffer::serialize(pair.second->open(AssetPath::removeSubPath(pair.first))->size()));
} }
} }
@ -956,32 +975,35 @@ Json Assets::readJson(String const& path) const {
try { try {
Json result = inputUtf8Json(streamData.begin(), streamData.end(), JsonParseType::Top); Json result = inputUtf8Json(streamData.begin(), streamData.end(), JsonParseType::Top);
for (auto const& pair : m_files.get(path).patchSources) { for (auto const& pair : m_files.get(path).patchSources) {
auto& patchPath = pair.first; auto patchAssetPath = AssetPath::split(pair.first);
auto& patchBasePath = patchAssetPath.basePath;
auto& patchSource = pair.second; auto& patchSource = pair.second;
auto patchStream = patchSource->read(patchPath); auto patchStream = patchSource->read(patchBasePath);
if (patchPath.endsWith(".lua")) { if (patchBasePath.endsWith(".lua")) {
RecursiveMutexLocker luaLocker(m_luaMutex); RecursiveMutexLocker luaLocker(m_luaMutex);
// Kae: i don't like that lock. perhaps have a LuaEngine and patch context cache per worker thread later on? // 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]; LuaContextPtr& context = m_patchContexts[patchBasePath];
if (!context) { if (!context) {
context = make_shared<LuaContext>(as<LuaEngine>(m_luaEngine.get())->createContext()); context = make_shared<LuaContext>(as<LuaEngine>(m_luaEngine.get())->createContext());
context->load(patchStream, patchPath); context->load(patchStream, patchBasePath);
} }
auto newResult = context->invokePath<Json>("patch", result, path); auto newResult = context->invokePath<Json>("patch", result, path);
if (newResult) if (newResult)
result = std::move(newResult); result = std::move(newResult);
} else { } else {
auto patchJson = inputUtf8Json(patchStream.begin(), patchStream.end(), JsonParseType::Top); auto patchJson = inputUtf8Json(patchStream.begin(), patchStream.end(), JsonParseType::Top);
if (patchAssetPath.subPath)
patchJson = patchJson.query(*patchAssetPath.subPath);
if (patchJson.isType(Json::Type::Array)) { if (patchJson.isType(Json::Type::Array)) {
auto patchData = patchJson.toArray(); auto patchData = patchJson.toArray();
try { try {
result = checkPatchArray(patchPath, patchSource, result, patchData, {}); result = checkPatchArray(pair.first, patchSource, result, patchData, {});
} catch (JsonPatchTestFail const& e) { } 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()); Logger::debug("Patch test failure from file {} in source: '{}' at '{}'. Caused by: {}", pair.first, patchSource->metadata().value("name", ""), m_assetSourcePaths.getLeft(patchSource), e.what());
} catch (JsonPatchException const& e) { } 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()); Logger::error("Could not apply patch from file {} in source: '{}' at '{}'. Caused by: {}", pair.first, 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 } else if (patchJson.isType(Json::Type::Object)) {
result = jsonMergeNulling(result, patchJson.toObject()); result = jsonMergeNulling(result, patchJson.toObject());
} }
} }