From afe57c4bc1b22fcec1a4e45c96e149c1267242b4 Mon Sep 17 00:00:00 2001 From: HJfod <60038575+HJfod@users.noreply.github.com> Date: Mon, 12 Dec 2022 00:19:54 +0200 Subject: [PATCH] add featured items to Index - also fix index checksum not being saved if you close the game with the console X button like i do when developing --- loader/include/Geode/loader/Index.hpp | 9 ++-- loader/src/loader/Index.cpp | 52 +++++++++++--------- loader/src/ui/internal/list/ModListLayer.cpp | 15 +++++- 3 files changed, 48 insertions(+), 28 deletions(-) diff --git a/loader/include/Geode/loader/Index.hpp b/loader/include/Geode/loader/Index.hpp index 2c39b19f..af703780 100644 --- a/loader/include/Geode/loader/Index.hpp +++ b/loader/include/Geode/loader/Index.hpp @@ -115,16 +115,19 @@ namespace geode { void removeSource(std::string const& repository); std::vector getSources() const; + /** + * Get all tags + */ std::unordered_set getTags() const; /** - * Get all index items available on this platform + * Get all index items */ std::vector getItems() const; /** - * Get all index items regardless of platform + * Get all featured index items */ - std::vector getAllItems() const; + std::vector getFeaturedItems() const; /** * Check if an item with this ID is found on the index, and optionally * provide the version sought after diff --git a/loader/src/loader/Index.cpp b/loader/src/loader/Index.cpp index c3e1a99f..609d418c 100644 --- a/loader/src/loader/Index.cpp +++ b/loader/src/loader/Index.cpp @@ -9,18 +9,6 @@ USE_GEODE_NAMESPACE(); -// Save data - -struct IndexSourceSaveData { - std::string downloadedCommitSHA; -}; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IndexSourceSaveData, downloadedCommitSHA); - -struct IndexSaveData { - std::unordered_map sources; -}; -NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(IndexSaveData, sources); - // ModInstallEvent ModInstallEvent::ModInstallEvent( @@ -54,6 +42,12 @@ struct geode::IndexSourceImpl final { ghc::filesystem::path path() const { return dirs::getIndexDir() / this->dirname(); } + + ghc::filesystem::path checksum() const { + // not storing this in the source's directory as that gets replaced by + // the newly fetched index + return dirs::getIndexDir() / (this->dirname() + ".checksum"); + } }; void IndexSourceImplDeleter::operator()(IndexSourceImpl* src) { @@ -124,7 +118,7 @@ Result IndexItem::createFromDir( .hash = root.has("mod").obj().has("hash").template get(), .platforms = platforms, }, - .isFeatured = root.has("is-featured").template get(), + .isFeatured = root.has("featured").template get(), .tags = root.has("tags").template get>() }); if (checker.isError()) { @@ -219,6 +213,7 @@ void Index::onSourceUpdate(SourceUpdateEvent* event) { switch (whatToPost) { case Finished: { + log::debug("Index up-to-date"); // clear source statuses to allow updating index again m_sourceStatuses.clear(); // post finish event @@ -250,6 +245,7 @@ void Index::onSourceUpdate(SourceUpdateEvent* event) { info += src + ": " + std::get(status) + "\n"; } } + log::debug("Index update failed: {}", info); // clear source statuses to allow updating index again m_sourceStatuses.clear(); // post finish event @@ -262,9 +258,14 @@ void Index::checkSourceUpdates(IndexSourceImpl* src) { if (src->isUpToDate) { return this->updateSourceFromLocal(src); } + + log::debug("Checking updates for source {}", src->repository); SourceUpdateEvent(src, UpdateProgress(0, "Checking status")).post(); - auto data = Mod::get()->getSavedMutable("index"); - auto oldSHA = data.sources[src->repository].downloadedCommitSHA; + + // read old commit SHA + // not using saved values for this one as we don't want to refetch + // index even if the game crashes + auto oldSHA = file::readString(src->checksum()).unwrapOr(""); web::AsyncWebRequest() .join(fmt::format("index-update-{}", src->repository)) .header(fmt::format("If-None-Match: \"{}\"", oldSHA)) @@ -285,8 +286,7 @@ void Index::checkSourceUpdates(IndexSourceImpl* src) { } // otherwise save hash and download source else { - auto data = Mod::get()->getSavedMutable("index"); - data.sources[src->repository].downloadedCommitSHA = newSHA; + (void)file::writeString(src->checksum(), newSHA); this->downloadSource(src); } }) @@ -299,6 +299,8 @@ void Index::checkSourceUpdates(IndexSourceImpl* src) { } void Index::downloadSource(IndexSourceImpl* src) { + log::debug("Downloading source {}", src->repository); + SourceUpdateEvent(src, UpdateProgress(0, "Beginning download")).post(); auto targetFile = dirs::getIndexDir() / fmt::format("{}.zip", src->dirname()); @@ -353,6 +355,7 @@ void Index::downloadSource(IndexSourceImpl* src) { } void Index::updateSourceFromLocal(IndexSourceImpl* src) { + log::debug("Updating local cache for source {}", src->repository); SourceUpdateEvent(src, UpdateProgress(100, "Updating local cache")).post(); // delete old items from this url if such exist for (auto& [_, versions] : m_items) { @@ -457,20 +460,19 @@ std::vector Index::getItems() const { std::vector res; for (auto& items : map::values(m_items)) { if (items.size()) { - auto item = items.rbegin()->second; - if (item->download.platforms.count(GEODE_PLATFORM_TARGET)) { - res.push_back(item); - } + res.push_back(items.rbegin()->second); } } return res; } -std::vector Index::getAllItems() const { +std::vector Index::getFeaturedItems() const { std::vector res; for (auto& items : map::values(m_items)) { if (items.size()) { - res.push_back(items.rbegin()->second); + if (items.rbegin()->second->isFeatured) { + res.push_back(items.rbegin()->second); + } } } return res; @@ -549,6 +551,10 @@ bool Index::areUpdatesAvailable() const { // Item installation Result Index::getInstallList(IndexItemHandle item) const { + if (!item->download.platforms.count(GEODE_PLATFORM_TARGET)) { + return Err("Mod is not available on {}", GEODE_PLATFORM_NAME); + } + IndexInstallList list; list.target = item; for (auto& dep : item->info.dependencies) { diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index b987c9e7..76619043 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -185,7 +185,6 @@ CCArray* ModListLayer::createModCells(ModListType type, ModListQuery const& quer if (auto match = queryMatch(query, item)) { sorted.insert({ match.value(), item }); } - if (!queryMatch(query, item)) continue; } // add the mods sorted @@ -195,7 +194,19 @@ CCArray* ModListLayer::createModCells(ModListType type, ModListQuery const& quer } break; case ModListType::Featured: { - // todo: featured + // sort the mods by match score + std::multimap sorted; + + for (auto const& item : Index::get()->getFeaturedItems()) { + if (auto match = queryMatch(query, item)) { + sorted.insert({ match.value(), item }); + } + } + + // add the mods sorted + for (auto& [score, item] : ranges::reverse(sorted)) { + mods->addObject(IndexItemCell::create(item, this, this->getCellSize())); + } } break; } return mods;