diff --git a/changelog.md b/changelog.md index 2b04e0b..d7effa3 100644 --- a/changelog.md +++ b/changelog.md @@ -1,4 +1,9 @@ # Integrated Demonlist Changelog +## v1.4.7 (2024-05-15) +- Fixed a bug where two-player demons would appear twice in the demonlist +- Fixed a few bugs with the demonlist search +- Changed the logo to be more in line with Geode's logo style + ## v1.4.6 (2024-04-30) - Tweaked the appearance of the demonlist button - Fixed incompatibility with DarkMode V4 diff --git a/logo.png b/logo.png index da09c5f..c098eca 100644 Binary files a/logo.png and b/logo.png differ diff --git a/mod.json b/mod.json index 3726f48..79e0876 100644 --- a/mod.json +++ b/mod.json @@ -1,11 +1,11 @@ { - "geode": "2.0.0-beta.25", + "geode": "2.0.0-beta.26", "gd": { "android": "2.205", "win": "2.204", "mac": "2.200" }, - "version": "v1.4.6", + "version": "v1.4.7", "id": "hiimjustin000.integrated_demonlist", "name": "Integrated Demonlist", "developer": "hiimjustin000", @@ -33,7 +33,7 @@ "dependencies": [ { "id": "geode.node-ids", - "version": ">=v1.9.0", + "version": ">=v1.9.1", "importance": "required" } ] diff --git a/src/IDListLayer.cpp b/src/IDListLayer.cpp index ab5ac78..25d095a 100644 --- a/src/IDListLayer.cpp +++ b/src/IDListLayer.cpp @@ -1,23 +1,17 @@ -#include "IDListLayer.hpp" #include #include #include +#include "IDListLayer.hpp" template std::vector pluck(matjson::Value const& json, std::string const& key) { std::vector ret; for (auto const& val : json.as_array()) { - if (!val.contains("legacy") || !val["legacy"].as_bool()) ret.push_back(val[key].as()); + if ((!val.contains("legacy") || !val["legacy"].as_bool()) && !val["two_player"].as_bool()) ret.push_back(val[key].as()); } return ret; } -std::string toLowerCase(std::string str) { - auto strCopy = std::string(str); - std::transform(strCopy.begin(), strCopy.end(), strCopy.begin(), ::tolower); - return strCopy; -} - int paddedSize(int size, int pad) { return size % pad == 0 ? size : size + (pad - (size % pad)); } @@ -188,7 +182,10 @@ bool IDListLayer::init() { addChild(m_leftSearchMenu); m_loadingCircle = LoadingCircle::create(); - addChild(m_loadingCircle); + m_loadingCircle->setParentLayer(this); + m_loadingCircle->retain(); + m_loadingCircle->show(); + m_loadingCircle->setVisible(false); m_searchBarView->setVisible(false); m_searchBar->setVisible(false); @@ -228,7 +225,6 @@ void IDListLayer::addSearchBar() { void IDListLayer::populateList(std::string query) { m_pageLabel->setString(std::to_string(m_page + 1).c_str()); m_loadingCircle->setVisible(true); - m_loadingCircle->show(); m_list->m_listView->setVisible(false); m_searchBarView->setVisible(false); m_searchBar->setVisible(false); @@ -245,29 +241,37 @@ void IDListLayer::populateList(std::string query) { m_leftSearchMenu->setEnabled(false); m_rightSearchMenu->setVisible(false); m_rightSearchMenu->setEnabled(false); + m_fullSearchResults.clear(); if (query.compare(m_query) != 0 && !query.empty()) { - auto queryLowercase = toLowerCase(query); - m_fullSearchResults = {}; + auto queryLowercase = string::toLower(query); for (int i = 0; i < AREDL.size(); i++) { - if (toLowerCase(AREDL_NAMES[i]).rfind(queryLowercase, 0) != std::string::npos) m_fullSearchResults.push_back(AREDL[i]); + if (string::toLower(AREDL_NAMES[i]).rfind(queryLowercase, 0) != std::string::npos) m_fullSearchResults.push_back(std::to_string(AREDL[i])); } } m_query = query; - if (query.empty()) m_fullSearchResults = AREDL; - - auto glm = GameLevelManager::sharedState(); - glm->m_levelManagerDelegate = this; - auto searchResults = std::vector(m_fullSearchResults.begin() + m_page * 10, - m_fullSearchResults.begin() + std::min(static_cast(m_fullSearchResults.size()), (m_page + 1) * 10)); - auto searchResultsStr = std::vector(searchResults.size()); - std::transform(searchResults.begin(), searchResults.end(), searchResultsStr.begin(), [](int i) { return std::to_string(i); }); - auto searchObject = GJSearchObject::create(SearchType::MapPackOnClick, string::join(searchResultsStr, ",")); - auto storedLevels = glm->getStoredOnlineLevels(searchObject->getKey()); - if (storedLevels) { - loadLevelsFinished(storedLevels, ""); - setupPageInfo("", ""); + if (query.empty()) { + for (int i = 0; i < AREDL.size(); i++) { + m_fullSearchResults.push_back(std::to_string(AREDL[i])); + } + } + + if (m_fullSearchResults.empty()) { + loadLevelsFinished(CCArray::create(), ""); + m_countLabel->setString(""); + } + else { + auto glm = GameLevelManager::sharedState(); + glm->m_levelManagerDelegate = this; + auto searchResults = std::vector(m_fullSearchResults.begin() + m_page * 10, + m_fullSearchResults.begin() + std::min(static_cast(m_fullSearchResults.size()), (m_page + 1) * 10)); + auto searchObject = GJSearchObject::create(SearchType::MapPackOnClick, string::join(searchResults, ",")); + auto storedLevels = glm->getStoredOnlineLevels(searchObject->getKey()); + if (storedLevels) { + loadLevelsFinished(storedLevels, ""); + setupPageInfo("", ""); + } + else glm->getOnlineLevels(searchObject); } - else glm->getOnlineLevels(searchObject); } void IDListLayer::loadLevelsFinished(CCArray* levels, const char*) { @@ -275,12 +279,11 @@ void IDListLayer::loadLevelsFinished(CCArray* levels, const char*) { if (m_list->getParent() == this) removeChild(m_list); m_list = GJListLayer::create(CustomListView::create(levels, BoomListType::Level, 190.0f, 358.0f), "All Rated Extreme Demons List", { 0, 0, 0, 180 }, 358.0f, 220.0f, 0); m_list->setZOrder(2); - m_list->setPosition(winSize / 2 - m_list->getScaledContentSize() / 2); + m_list->setPosition(winSize / 2 - m_list->getContentSize() / 2); addChild(m_list); addSearchBar(); m_searchBar->setVisible(true); m_countLabel->setVisible(true); - m_loadingCircle->fadeAndRemove(); m_loadingCircle->setVisible(false); if (m_fullSearchResults.size() > 10) { auto maxPage = paddedSize(m_fullSearchResults.size(), 10) / 10 - 1; @@ -301,8 +304,8 @@ void IDListLayer::loadLevelsFinished(CCArray* levels, const char*) { void IDListLayer::loadLevelsFailed(const char*) { m_searchBar->setVisible(true); + m_searchBarView->setVisible(true); m_countLabel->setVisible(true); - m_loadingCircle->fadeAndRemove(); m_loadingCircle->setVisible(false); FLAlertLayer::create("Load Failed", "Failed to load levels. Please try again later.", "OK")->show(); } @@ -318,10 +321,11 @@ void IDListLayer::onClose(CCObject*) { } void IDListLayer::onSearch(CCObject*) { - if (m_query.compare(m_searchBar->getString()) != 0) { - loadAREDL(false, [this]() { + auto searchString = m_searchBar->getString(); + if (m_query.compare(searchString) != 0) { + loadAREDL(false, [this, searchString]() { m_page = 0; - populateList(m_searchBar->getString()); + populateList(searchString); }); } } @@ -401,4 +405,8 @@ void IDListLayer::keyBackClicked() { void IDListLayer::setIDPopupClosed(SetIDPopup*, int page) { m_page = std::min(std::max(page - 1, 0), paddedSize(m_fullSearchResults.size(), 10) / 10 - 1); populateList(m_query); -} \ No newline at end of file +} + +IDListLayer::~IDListLayer() { + m_loadingCircle->release(); +} diff --git a/src/IDListLayer.hpp b/src/IDListLayer.hpp index c4a5433..d76cf97 100644 --- a/src/IDListLayer.hpp +++ b/src/IDListLayer.hpp @@ -26,6 +26,8 @@ class IDListLayer : public CCLayer, SetIDPopupDelegate, LevelManagerDelegate { void onLast(CCObject*); void keyDown(enumKeyCodes) override; void keyBackClicked() override; + + ~IDListLayer(); protected: GJListLayer* m_list; CCMenu* m_backMenu; @@ -45,7 +47,7 @@ class IDListLayer : public CCLayer, SetIDPopupDelegate, LevelManagerDelegate { CCMenuItemSpriteExtra* m_lastButton; int m_page = 0; std::string m_query = ""; - std::vector m_fullSearchResults; + std::vector m_fullSearchResults; bool init() override; void addSearchBar(); @@ -60,4 +62,4 @@ class IDListLayer : public CCLayer, SetIDPopupDelegate, LevelManagerDelegate { } void setupPageInfo(gd::string, const char*) override; void setIDPopupClosed(SetIDPopup*, int) override; -}; \ No newline at end of file +}; diff --git a/src/main.cpp b/src/main.cpp index b403d15..1bc31c3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,10 +1,6 @@ #include "IDListLayer.hpp" -#include -#include #include -#include - class $modify(IDMenuLayer, MenuLayer) { bool init() { if (!MenuLayer::init()) return false; @@ -16,6 +12,7 @@ class $modify(IDMenuLayer, MenuLayer) { } }; +#include class $modify(IDLevelSearchLayer, LevelSearchLayer) { bool init(int searchType) { if (!LevelSearchLayer::init(searchType)) return false; @@ -24,7 +21,7 @@ class $modify(IDLevelSearchLayer, LevelSearchLayer) { demonlistButtonSprite->setScale(0.8f); auto demonlistButton = CCMenuItemSpriteExtra::create(demonlistButtonSprite, this, menu_selector(IDLevelSearchLayer::onDemonList)); demonlistButton->setID("demonlist-button"_spr); - auto menu = static_cast(getChildByID("other-filter-menu")); + auto menu = getChildByID("other-filter-menu"); menu->addChild(demonlistButton); menu->updateLayout(); @@ -40,6 +37,7 @@ class $modify(IDLevelSearchLayer, LevelSearchLayer) { // Thanks Cvolton for the code // https://github.com/Cvolton/betterinfo-geode/blob/v4.0.0/src/hooks/LevelCell.cpp#L113 +#include class $modify(IDLevelCell, LevelCell) { void loadCustomLevelCell() { LevelCell::loadCustomLevelCell(); @@ -68,6 +66,7 @@ class $modify(IDLevelCell, LevelCell) { } }; +#include class $modify(IDKeyboardDispatcher, CCKeyboardDispatcher) { bool dispatchKeyboardMSG(enumKeyCodes key, bool down, bool repeat) { auto layer = CCDirector::sharedDirector()->getRunningScene()->getChildByID("IDListLayer"_spr); @@ -77,4 +76,4 @@ class $modify(IDKeyboardDispatcher, CCKeyboardDispatcher) { } else return CCKeyboardDispatcher::dispatchKeyboardMSG(key, down, repeat); } -}; \ No newline at end of file +};