From 6d599a5e19f8aadd1c66237a88464dc1ccc8e24f Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Fri, 8 Sep 2023 12:44:26 -0500 Subject: [PATCH 001/135] allow logging to be disabled per-mod --- loader/include/Geode/loader/Mod.hpp | 3 +++ loader/src/loader/Log.cpp | 10 ++++++---- loader/src/loader/Mod.cpp | 8 ++++++++ loader/src/loader/ModImpl.cpp | 8 ++++++++ loader/src/loader/ModImpl.hpp | 9 ++++++++- 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index 27f8eb448..4df6f9c2c 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -394,6 +394,9 @@ namespace geode { */ ModJson getRuntimeInfo() const; + bool isLoggingEnabled() const; + void setLoggingEnabled(bool enabled); + friend class ModImpl; }; } diff --git a/loader/src/loader/Log.cpp b/loader/src/loader/Log.cpp index ec69eed75..915f7e418 100644 --- a/loader/src/loader/Log.cpp +++ b/loader/src/loader/Log.cpp @@ -222,12 +222,14 @@ void Logger::setup() { } void Logger::push(Log&& log) { - std::string logStr = log.toString(true, nestLevel()); + if (log.getSender()->isLoggingEnabled()) { + std::string logStr = log.toString(true, nestLevel()); - LoaderImpl::get()->logConsoleMessageWithSeverity(logStr, log.getSeverity()); - logStream() << logStr << std::endl; + LoaderImpl::get()->logConsoleMessageWithSeverity(logStr, log.getSeverity()); + logStream() << logStr << std::endl; - logs().emplace_back(std::forward(log)); + logs().emplace_back(std::forward(log)); + } } void Logger::pop(Log* log) { diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 392d91c46..100e39eeb 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -231,6 +231,14 @@ ModJson Mod::getRuntimeInfo() const { return m_impl->getRuntimeInfo(); } +bool Mod::isLoggingEnabled() const { + return m_impl->isLoggingEnabled(); +} + +void Mod::setLoggingEnabled(bool enabled) { + m_impl->setLoggingEnabled(enabled); +} + bool Mod::hasSavedValue(std::string const& key) { return this->getSaveContainer().contains(key); } diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index dc1c838a2..f932af84f 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -622,6 +622,14 @@ ModJson Mod::Impl::getRuntimeInfo() const { return json; } +bool Mod::Impl::isLoggingEnabled() const { + return m_loggingEnabled; +} + +void Mod::Impl::setLoggingEnabled(bool enabled) { + m_loggingEnabled = enabled; +} + static Result getModImplInfo() { std::string err; json::Value json; diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index 9048036d9..e79dc8ae5 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -56,11 +56,15 @@ namespace geode { * Settings save data. Stored for efficient loading of custom settings */ json::Value m_savedSettingsData = json::Object(); - /** * Whether the mod resources are loaded or not */ bool m_resourcesLoaded = false; + /** + * Whether logging is enabled for this mod + */ + bool m_loggingEnabled = true; + ModRequestedAction m_requestedAction = ModRequestedAction::None; @@ -139,6 +143,9 @@ namespace geode { char const* expandSpriteName(char const* name); ModJson getRuntimeInfo() const; + + bool isLoggingEnabled() const; + void setLoggingEnabled(bool enabled); }; class ModImpl : public Mod::Impl { From 3f8cdd994a9cc746a7a50ab85336cd6cd990f22a Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Fri, 8 Sep 2023 19:48:27 -0500 Subject: [PATCH 002/135] proper platform console for mac --- .gitignore | 1 + loader/src/loader/LoaderImpl.hpp | 4 +- loader/src/platform/mac/LoaderImpl.mm | 56 +++++++++++++++++++++++++-- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 6149f0676..eed1617fc 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,7 @@ **/*.tmlanguage.cache **/*.tmPreferences.cache **/*.stTheme.cache +.cache # Workspace files are user-specific **/*.sublime-workspace diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index 92468f2a8..24920413c 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -72,10 +72,12 @@ namespace geode { std::vector> m_gdThreadQueue; mutable std::mutex m_gdThreadMutex; - bool m_platformConsoleOpen = false; std::vector> m_internalHooks; bool m_readyToHook = false; + bool m_platformConsoleOpen = false; + void* m_platformData = nullptr; + std::mutex m_nextModMutex; std::unique_lock m_nextModLock = std::unique_lock(m_nextModMutex, std::defer_lock); std::condition_variable m_nextModCV; diff --git a/loader/src/platform/mac/LoaderImpl.mm b/loader/src/platform/mac/LoaderImpl.mm index a1a8148e9..5446c16ec 100644 --- a/loader/src/platform/mac/LoaderImpl.mm +++ b/loader/src/platform/mac/LoaderImpl.mm @@ -4,9 +4,16 @@ #include #include #import +#include using namespace geode::prelude; +struct MacConsoleData { + std::string logFile; + std::string scriptFile; + int logFd; +}; + void Loader::Impl::platformMessageBox(char const* title, std::string const& info) { CFStringRef cfTitle = CFStringCreateWithCString(NULL, title, kCFStringEncodingUTF8); CFStringRef cfMessage = CFStringCreateWithCString(NULL, info.c_str(), kCFStringEncodingUTF8); @@ -33,9 +40,42 @@ } void Loader::Impl::openPlatformConsole() { - // it's not possible to redirect stdout to a terminal - // and the console.app is too clunky - + if (m_platformConsoleOpen) return; + + std::string outFile = "/tmp/command_output_XXXXXX"; + int outFd = mkstemp(&outFile[0]); + + auto script = outFile + ".command"; + auto scriptContent = fmt::format(R"( + #!/bin/sh + echo -n -e "\033]0;Geode Console\007" + tail -f {} & + trap "" SIGINT + while [ $(lsof -t {} 2>/dev/null | wc -l) -gt 1 ]; do :; done + osascript -e 'tell application "Terminal" + close (every window whose name contains "Geode Console") + if (count windows) is 0 then quit + end tell' & + exit + )", outFile, outFile); + + if (file::writeString(script, scriptContent)) { + chmod(script.c_str(), 0777); + dup2(outFd, 1); + dup2(outFd, 2); + + NSTask *task = [[NSTask alloc] init]; + task.launchPath = @"/usr/bin/open"; + task.arguments = @[[NSString stringWithUTF8String:script.c_str()]]; + [task launch]; + + m_platformData = new MacConsoleData { + outFile, + script, + outFd + }; + } + m_platformConsoleOpen = true; for (auto const& log : log::Logger::list()) { @@ -44,6 +84,16 @@ } void Loader::Impl::closePlatformConsole() { + if (m_platformData) { + auto consoleData = reinterpret_cast(m_platformData); + close(consoleData->logFd); + unlink(consoleData->logFile.c_str()); + unlink(consoleData->scriptFile.c_str()); + + delete consoleData; + m_platformData = nullptr; + } + m_platformConsoleOpen = false; } From 114fa465a85125723acae2d82827ec8ec9fecd04 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 9 Sep 2023 14:32:20 +0300 Subject: [PATCH 003/135] Mod cells now use layouts & disable macos console temporarily --- VERSION | 2 +- .../Geode/cocos/base_nodes/SpacerNode.hpp | 24 ++ loader/src/cocos2d-ext/Layout.cpp | 45 +++- loader/src/platform/mac/LoaderImpl.mm | 66 ++--- loader/src/ui/internal/GeodeUI.cpp | 16 +- loader/src/ui/internal/list/ModListCell.cpp | 246 +++++++++--------- loader/src/ui/internal/list/ModListCell.hpp | 5 + loader/src/ui/internal/list/ModListLayer.cpp | 30 +-- 8 files changed, 256 insertions(+), 178 deletions(-) diff --git a/VERSION b/VERSION index f0bb29e76..e21e727f9 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.0 +1.4.0 \ No newline at end of file diff --git a/loader/include/Geode/cocos/base_nodes/SpacerNode.hpp b/loader/include/Geode/cocos/base_nodes/SpacerNode.hpp index 2e1536113..e600402a9 100644 --- a/loader/include/Geode/cocos/base_nodes/SpacerNode.hpp +++ b/loader/include/Geode/cocos/base_nodes/SpacerNode.hpp @@ -54,6 +54,30 @@ class GEODE_DLL SpacerNode : public CCNode { size_t getGrow() const; }; +/** + * A spacer node that updates the content size of its child to match its own + * @note This is useful for making a spacer node that takes up the remaining + * space in a layout + */ +class GEODE_DLL SpacerNodeChild : public SpacerNode { +protected: + CCNode* m_child = nullptr; + + bool init(CCNode* child, size_t grow); + +public: + /** + * Create a new spacer node. When the layout is applied, + * if there is space left over the remaining space is distributed among + * all spacer nodes in proportion to the sum of all the spacers' grow + * factors (akin to CSS flew grow) + * @param grow The grow factor for this node. Default is 1 + */ + static SpacerNodeChild* create(CCNode* child, size_t grow = 1); + + void setContentSize(CCSize const& size) override; +}; + #pragma warning(pop) NS_CC_END diff --git a/loader/src/cocos2d-ext/Layout.cpp b/loader/src/cocos2d-ext/Layout.cpp index 53b2976cf..06bdd3b90 100644 --- a/loader/src/cocos2d-ext/Layout.cpp +++ b/loader/src/cocos2d-ext/Layout.cpp @@ -177,7 +177,7 @@ struct AxisLayout::Row : public CCObject { this->autorelease(); } - void accountSpacers(Axis axis, float availableLength) { + void accountSpacers(Axis axis, float availableLength, float crossLength) { std::vector spacers; for (auto& node : CCArrayExt(nodes)) { if (auto spacer = typeinfo_cast(node)) { @@ -193,10 +193,10 @@ struct AxisLayout::Row : public CCObject { for (auto& spacer : spacers) { auto size = unusedSpace * spacer->getGrow() / static_cast(sum); if (axis == Axis::Row) { - spacer->setContentSize({ size, this->crossLength }); + spacer->setContentSize({ size, crossLength }); } else { - spacer->setContentSize({ this->crossLength, size }); + spacer->setContentSize({ crossLength, size }); } } this->axisLength = availableLength; @@ -376,16 +376,16 @@ AxisLayout::Row* AxisLayout::fitInRow( } // todo: make this calculation more smart to avoid so much unnecessary recursion - auto scaleDownFactor = scale - .0125f; + auto scaleDownFactor = scale - .002f; auto squishFactor = available.axisLength / (axisUnsquishedLength + .01f) * squish; // calculate row scale, squish, and prio int tries = 1000; while (axisLength > available.axisLength) { if (this->canTryScalingDown( - res, prio, scale, scale - .0125f, minMaxPrios + res, prio, scale, scale - .002f, minMaxPrios )) { - scale -= .0125f; + scale -= .002f; } else { squish = available.axisLength / (axisUnsquishedLength + .01f) * squish; @@ -643,7 +643,7 @@ void AxisLayout::tryFitLayout( float rowEvenSpace = available.crossLength / rows->count(); for (auto row : CCArrayExt(rows)) { - row->accountSpacers(m_axis, available.axisLength); + row->accountSpacers(m_axis, available.axisLength, available.crossLength); if (m_crossAlignment == AxisAlignment::Even) { rowCrossPos -= rowEvenSpace / 2 + row->crossLength / 2; @@ -1053,3 +1053,34 @@ void SpacerNode::setGrow(size_t grow) { size_t SpacerNode::getGrow() const { return m_grow; } + +bool SpacerNodeChild::init(CCNode* child, size_t grow) { + if (!SpacerNode::init(grow)) + return false; + + if (child) { + this->addChild(child); + m_child = child; + } + + return true; +} + +SpacerNodeChild* SpacerNodeChild::create(CCNode* child, size_t grow) { + auto ret = new SpacerNodeChild; + if (ret && ret->init(child, grow)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; +} + +void SpacerNodeChild::setContentSize(CCSize const& size) { + CCNode::setContentSize(size); + if (m_child) { + m_child->setPosition(CCPointZero); + m_child->setContentSize(size); + m_child->setAnchorPoint(CCPointZero); + } +} \ No newline at end of file diff --git a/loader/src/platform/mac/LoaderImpl.mm b/loader/src/platform/mac/LoaderImpl.mm index 5446c16ec..53f06ba81 100644 --- a/loader/src/platform/mac/LoaderImpl.mm +++ b/loader/src/platform/mac/LoaderImpl.mm @@ -42,39 +42,39 @@ void Loader::Impl::openPlatformConsole() { if (m_platformConsoleOpen) return; - std::string outFile = "/tmp/command_output_XXXXXX"; - int outFd = mkstemp(&outFile[0]); - - auto script = outFile + ".command"; - auto scriptContent = fmt::format(R"( - #!/bin/sh - echo -n -e "\033]0;Geode Console\007" - tail -f {} & - trap "" SIGINT - while [ $(lsof -t {} 2>/dev/null | wc -l) -gt 1 ]; do :; done - osascript -e 'tell application "Terminal" - close (every window whose name contains "Geode Console") - if (count windows) is 0 then quit - end tell' & - exit - )", outFile, outFile); - - if (file::writeString(script, scriptContent)) { - chmod(script.c_str(), 0777); - dup2(outFd, 1); - dup2(outFd, 2); - - NSTask *task = [[NSTask alloc] init]; - task.launchPath = @"/usr/bin/open"; - task.arguments = @[[NSString stringWithUTF8String:script.c_str()]]; - [task launch]; - - m_platformData = new MacConsoleData { - outFile, - script, - outFd - }; - } + // std::string outFile = "/tmp/command_output_XXXXXX"; + // int outFd = mkstemp(&outFile[0]); + + // auto script = outFile + ".command"; + // auto scriptContent = fmt::format(R"( + // #!/bin/sh + // echo -n -e "\033]0;Geode Console\007" + // tail -f {} & + // trap "" SIGINT + // while [ $(lsof -t {} 2>/dev/null | wc -l) -gt 1 ]; do :; done + // osascript -e 'tell application "Terminal" + // close (every window whose name contains "Geode Console") + // if (count windows) is 0 then quit + // end tell' & + // exit + // )", outFile, outFile); + + // if (file::writeString(script, scriptContent)) { + // chmod(script.c_str(), 0777); + // dup2(outFd, 1); + // dup2(outFd, 2); + + // NSTask *task = [[NSTask alloc] init]; + // task.launchPath = @"/usr/bin/open"; + // task.arguments = @[[NSString stringWithUTF8String:script.c_str()]]; + // [task launch]; + + // m_platformData = new MacConsoleData { + // outFile, + // script, + // outFd + // }; + // } m_platformConsoleOpen = true; diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp index a575a737e..5bc6705a9 100644 --- a/loader/src/ui/internal/GeodeUI.cpp +++ b/loader/src/ui/internal/GeodeUI.cpp @@ -79,7 +79,13 @@ CCNode* geode::createModLogo(Mod* mod, CCSize const& size) { if (!spr) spr = CCSprite::createWithSpriteFrameName("no-logo.png"_spr); if (!spr) spr = CCLabelBMFont::create("N/A", "goldFont.fnt"); limitNodeSize(spr, size, 1.f, .1f); - return spr; + spr->setPosition(size/2); + spr->setAnchorPoint({.5f, .5f}); + + auto node = CCNode::create(); + node->addChild(spr); + node->setContentSize(size); + return node; } CCNode* geode::createIndexItemLogo(IndexItemHandle item, CCSize const& size) { @@ -112,5 +118,11 @@ CCNode* geode::createIndexItemLogo(IndexItemHandle item, CCSize const& size) { else { limitNodeSize(spr, size, 1.f, .1f); } - return spr; + spr->setPosition(size/2); + spr->setAnchorPoint({.5f, .5f}); + + auto node = CCNode::create(); + node->addChild(spr); + node->setContentSize(size); + return node; } diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index 3c9c199d0..fa970c5a6 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -35,94 +35,95 @@ void ModListCell::setupInfo( bool inactive ) { m_menu = CCMenu::create(); - m_menu->setPosition(m_width - 40.f, m_height / 2); + m_menu->setPosition({m_width / 2, m_height / 2}); + m_menu->setContentSize({m_width - 20, m_height}); + m_menu->setAnchorPoint({.5f, .5f}); + m_menu->setLayout( + RowLayout::create() + ->setAxisAlignment(AxisAlignment::Start) + ->setAutoScale(false) + ->setCrossAxisOverflow(false) + ); + this->addChild(m_menu); auto logoSize = this->getLogoSize(); auto logoSpr = this->createLogo({ logoSize, logoSize }); - logoSpr->setPosition({ logoSize / 2 + 12.f, m_height / 2 }); auto logoSprColor = typeinfo_cast(logoSpr); if (inactive && logoSprColor) { logoSprColor->setColor({ 163, 163, 163 }); } - this->addChild(logoSpr); + m_menu->addChild(logoSpr); + + m_columnMenu = CCMenu::create(); + m_columnMenu->setContentSize({m_width, m_height}); + m_columnMenu->setLayout( + ColumnLayout::create() + ->setAxisAlignment(AxisAlignment::Center) + ->setCrossAxisLineAlignment(AxisAlignment::Start) + ->setAxisReverse(true) + ->setAutoScale(false) + ->setGap(spaceForTags ? 3.f : 5.f) + ); + m_menu->addChild(SpacerNodeChild::create(m_columnMenu)); + + m_labelMenu = CCMenu::create(); + m_labelMenu->setContentSize({m_width, m_height / 2}); + m_labelMenu->setLayout( + RowLayout::create() + ->setAxisAlignment(AxisAlignment::Start) + ->setAutoScale(false) + ); + m_labelMenu->setLayoutOptions( + AxisLayoutOptions::create() + ->setNextGap(spaceForTags ? -2.f : 0.f) + ->setPrevGap(0.f) + ); + m_columnMenu->addChild(m_labelMenu); bool hasDesc = display == ModListDisplay::Expanded && metadata.getDescription().has_value(); auto titleLabel = CCLabelBMFont::create(metadata.getName().c_str(), "bigFont.fnt"); - titleLabel->setAnchorPoint({ .0f, .5f }); - titleLabel->setPositionX(m_height / 2 + logoSize / 2 + 13.f); - if (hasDesc && spaceForTags) { - titleLabel->setPositionY(m_height / 2 + 20.f); - } - else if (spaceForTags) { - titleLabel->setPositionY(m_height / 2 + 12.f); - } - else if (hasDesc) { - titleLabel->setPositionY(m_height / 2 + 15.f); - } - else { - titleLabel->setPositionY(m_height / 2 + 7.f); - } titleLabel->limitLabelWidth(m_width / 2 - 40.f, .5f, .1f); + titleLabel->setLayoutOptions( + AxisLayoutOptions::create() + ->setAutoScale(true) + ->setMaxScale(0.5f) + ->setMinScale(0.1f) + ); if (inactive) { titleLabel->setColor({ 163, 163, 163 }); } - this->addChild(titleLabel); + m_labelMenu->addChild(titleLabel); auto versionLabel = CCLabelBMFont::create( metadata.getVersion().toString(false).c_str(), "bigFont.fnt" ); - versionLabel->setAnchorPoint({ .0f, .5f }); versionLabel->setScale(.3f); - versionLabel->setPosition( - titleLabel->getPositionX() + titleLabel->getScaledContentSize().width + 5.f, - titleLabel->getPositionY() - 1.f - ); versionLabel->setColor({ 0, 255, 0 }); if (inactive) { versionLabel->setColor({ 0, 163, 0 }); } - this->addChild(versionLabel); + m_labelMenu->addChild(versionLabel); TagNode* apiLabel = nullptr; - if (metadata.isAPI()) { - apiLabel = TagNode::create("API"); - apiLabel->setAnchorPoint({ .0f, .5f }); - apiLabel->setScale(.3f); - apiLabel->setPosition( - versionLabel->getPositionX() + - versionLabel->getScaledContentSize().width + 5.f, - versionLabel->getPositionY() - ); - } + if (auto tag = metadata.getVersion().getTag()) { auto tagLabel = TagNode::create(tag.value().toString().c_str()); - tagLabel->setAnchorPoint({ .0f, .5f }); tagLabel->setScale(.3f); - tagLabel->setPosition( - versionLabel->getPositionX() + - versionLabel->getScaledContentSize().width + 5.f, - versionLabel->getPositionY() - ); - this->addChild(tagLabel); - - if (apiLabel) { - apiLabel->setPosition( - tagLabel->getPositionX() + - tagLabel->getScaledContentSize().width + 5.f, - tagLabel->getPositionY() - ); - } + m_labelMenu->addChild(tagLabel); } - if (apiLabel) - this->addChild(apiLabel); + if (metadata.isAPI()) { + apiLabel = TagNode::create("API"); + apiLabel->setScale(.3f); + m_labelMenu->addChild(apiLabel); + } auto creatorStr = "by " + metadata.getDeveloper(); auto creatorLabel = CCLabelBMFont::create(creatorStr.c_str(), "goldFont.fnt"); @@ -134,47 +135,42 @@ void ModListCell::setupInfo( m_developerBtn = CCMenuItemSpriteExtra::create( creatorLabel, this, menu_selector(ModListCell::onViewDev) ); - m_developerBtn->setPositionX( - m_height / 2 + logoSize / 2 + 13.f - + creatorLabel->getScaledContentSize().width / 2 - - m_menu->getPositionX() - ); - if (hasDesc && spaceForTags) { - m_developerBtn->setPositionY(+7.5f); - } - else if (hasDesc || spaceForTags) { - m_developerBtn->setPositionY(0.f); - } - else { - m_developerBtn->setPositionY(-7.f); - } - m_menu->addChild(m_developerBtn); + m_columnMenu->addChild(m_developerBtn); if (hasDesc) { auto descBG = CCScale9Sprite::create("square02b_001.png", {0.0f, 0.0f, 80.0f, 80.0f}); descBG->setColor({0, 0, 0}); descBG->setOpacity(90); descBG->setContentSize({m_width * 2, 60.f}); - descBG->setAnchorPoint({.0f, .5f}); - descBG->setPositionX(m_height / 2 + logoSize / 2 + 13.f); - if (spaceForTags) { - descBG->setPositionY(m_height / 2 - 7.5f); - } - else { - descBG->setPositionY(m_height / 2 - 17.f); - } descBG->setScale(.25f); - this->addChild(descBG); + m_columnMenu->addChild(descBG); + + // limitLabelWidth defaults to 1.0 even though we give a bigger scale + auto node = CCNode::create(); + node->setContentSize(descBG->getContentSize() / 4); + node->setAnchorPoint({ .5f, .5f }); + node->setScale(4.f); + node->setPosition(descBG->getContentSize() / 2); + descBG->addChild(node); m_description = CCLabelBMFont::create(metadata.getDescription().value().c_str(), "chatFont.fnt"); - m_description->setAnchorPoint({ .0f, .5f }); - m_description->setPosition(m_height / 2 + logoSize / 2 + 18.f, descBG->getPositionY()); - m_description->limitLabelWidth(m_width / 2 - 10.f, .5f, .1f); + m_description->setAnchorPoint({ .5f, .5f }); + m_description->setPosition(node->getContentSize() / 2); + m_description->limitLabelWidth(node->getContentSize().width - 5.f, 0.5f, .1f); if (inactive) { m_description->setColor({ 163, 163, 163 }); } - this->addChild(m_description); + node->addChild(m_description); } + + this->updateCellLayout(); +} + +void ModListCell::updateCellLayout() { + m_menu->updateLayout(); + m_labelMenu->setContentSize(m_columnMenu->getContentSize()); + m_labelMenu->updateLayout(); + m_columnMenu->updateLayout(); } void ModListCell::onViewDev(CCObject*) { @@ -262,6 +258,8 @@ void ModCell::updateState() { break; } m_unresolvedExMark->setVisible(hasProblems); + + this->updateCellLayout(); } bool ModCell::init( @@ -276,15 +274,28 @@ bool ModCell::init( this->setupInfo(mod->getMetadata(), false, display, mod->getRequestedAction() != ModRequestedAction::None); + auto exMark = CCSprite::createWithSpriteFrameName("exMark_001.png"); + exMark->setScale(.5f); + + m_unresolvedExMark = + CCMenuItemSpriteExtra::create(exMark, this, menu_selector(ModCell::onUnresolvedInfo)); + m_unresolvedExMark->setVisible(false); + m_menu->addChild(m_unresolvedExMark); + if (mod->getRequestedAction() != ModRequestedAction::None) { auto restartSpr = ButtonSprite::create("Restart", "bigFont.fnt", "GJ_button_03.png", .8f); restartSpr->setScale(.65f); auto restartBtn = CCMenuItemSpriteExtra::create(restartSpr, this, menu_selector(ModCell::onRestart)); - restartBtn->setPositionX(-16.f); m_menu->addChild(restartBtn); } else { + if (m_mod->wasSuccessfullyLoaded() && m_mod->getMetadata().getID() != "geode.loader") { + m_enableToggle = + CCMenuItemToggler::createWithStandardSprites(this, menu_selector(ModCell::onEnable), .7f); + m_menu->addChild(m_enableToggle); + } + auto viewSpr = ButtonSprite::create("View", "bigFont.fnt", "GJ_button_01.png", .8f); viewSpr->setScale(.65f); @@ -306,33 +317,14 @@ bool ModCell::init( if (latestIndexItem->getMetadata().getVersion().getMajor() > minorIndexItem->getMetadata().getVersion().getMajor()) { auto updateIcon = CCSprite::createWithSpriteFrameName("updates-available.png"_spr); - updateIcon->setPosition(viewSpr->getContentSize() - CCSize { 2.f, 2.f }); updateIcon->setZOrder(99); updateIcon->setScale(.5f); viewSpr->addChild(updateIcon); } } } - - if (m_mod->wasSuccessfullyLoaded() && m_mod->getMetadata().getID() != "geode.loader") { - m_enableToggle = - CCMenuItemToggler::createWithStandardSprites(this, menu_selector(ModCell::onEnable), .7f); - m_enableToggle->setPosition(-45.f, 0.f); - m_menu->addChild(m_enableToggle); - } } - - - auto exMark = CCSprite::createWithSpriteFrameName("exMark_001.png"); - exMark->setScale(.5f); - - m_unresolvedExMark = - CCMenuItemSpriteExtra::create(exMark, this, menu_selector(ModCell::onUnresolvedInfo)); - m_unresolvedExMark->setPosition(-80.f, 0.f); - m_unresolvedExMark->setVisible(false); - m_menu->addChild(m_unresolvedExMark); - this->updateState(); return true; @@ -390,7 +382,6 @@ bool IndexItemCell::init( restartSpr->setScale(.65f); auto restartBtn = CCMenuItemSpriteExtra::create(restartSpr, this, menu_selector(IndexItemCell::onRestart)); - restartBtn->setPositionX(-16.f); m_menu->addChild(restartBtn); } else { @@ -403,22 +394,21 @@ bool IndexItemCell::init( } if (item->getTags().size()) { - float x = m_height / 2 + this->getLogoSize() / 2 + 13.f; + auto tagRow = CCNode::create(); + tagRow->setContentSize({m_width, m_height}); + tagRow->setLayout( + RowLayout::create() + ->setAxisAlignment(AxisAlignment::Start) + ->setAutoScale(false) + ->setGap(3.f) + ); + m_columnMenu->insertAfter(tagRow, m_developerBtn); for (auto& category : item->getTags()) { auto node = TagNode::create(category); - node->setAnchorPoint({ .0f, .5f }); - node->setPositionX(x); node->setScale(.3f); - if (m_description) { - node->setPositionY(m_height / 2 - 23.f); - } - else { - node->setPositionY(m_height / 2 - 12.f); - } - this->addChild(node); - - x += node->getScaledContentSize().width + 5.f; + tagRow->addChild(node); } + tagRow->updateLayout(); } this->updateState(); @@ -426,7 +416,9 @@ bool IndexItemCell::init( return true; } -void IndexItemCell::updateState() {} +void IndexItemCell::updateState() { + this->updateCellLayout(); +} std::string IndexItemCell::getDeveloper() const { return m_item->getMetadata().getDeveloper(); @@ -595,7 +587,15 @@ bool ProblemsCell::init( } m_menu = CCMenu::create(); - m_menu->setPosition(m_width - 40.f, m_height / 2); + m_menu->setPosition({m_width / 2, m_height / 2}); + m_menu->setContentSize({m_width - 20, m_height}); + m_menu->setAnchorPoint({.5f, .5f}); + m_menu->setLayout( + RowLayout::create() + ->setAxisAlignment(AxisAlignment::Start) + // ->setAutoScale(false) + ->setCrossAxisOverflow(false) + ); this->addChild(m_menu); auto logoSize = this->getLogoSize(); @@ -603,15 +603,19 @@ bool ProblemsCell::init( if (!icon.empty()) { auto logoSpr = CCSprite::createWithSpriteFrameName(icon.c_str()); limitNodeSize(logoSpr, size, 1.f, .1f); - logoSpr->setPosition({logoSize / 2 + 12.f, m_height / 2}); - this->addChild(logoSpr); + m_menu->addChild(logoSpr); } auto titleLabel = CCLabelBMFont::create(title.c_str(), "bigFont.fnt"); - titleLabel->setAnchorPoint({ .0f, .5f }); - titleLabel->setPosition(m_height / 2 + logoSize / 2 + 13.f, m_height / 2); - titleLabel->limitLabelWidth(m_width - 120.f, 1.f, .1f); - this->addChild(titleLabel); + titleLabel->setLayoutOptions( + AxisLayoutOptions::create() + ->setScalePriority(1) + ->setMaxScale(1.f) + ->setMinScale(0.1f) + ); + m_menu->addChild(titleLabel); + + // m_menu->addChild(SpacerNode::create()); auto viewSpr = ButtonSprite::create("View", "bigFont.fnt", "GJ_button_01.png", .8f); viewSpr->setScale(.65f); @@ -620,6 +624,8 @@ bool ProblemsCell::init( CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsCell::onInfo)); m_menu->addChild(viewBtn); + m_menu->updateLayout(); + return true; } diff --git a/loader/src/ui/internal/list/ModListCell.hpp b/loader/src/ui/internal/list/ModListCell.hpp index 0944d54a2..28e253d9d 100644 --- a/loader/src/ui/internal/list/ModListCell.hpp +++ b/loader/src/ui/internal/list/ModListCell.hpp @@ -24,6 +24,9 @@ class ModListCell : public CCLayer { CCMenuItemToggler* m_enableToggle = nullptr; CCMenuItemSpriteExtra* m_unresolvedExMark; CCMenuItemSpriteExtra* m_developerBtn; + SpacerNode* m_spacer = nullptr; + CCMenu* m_columnMenu = nullptr; + CCMenu* m_labelMenu = nullptr; bool init(ModListLayer* list, CCSize const& size); void setupInfo(ModMetadata const& metadata, bool spaceForTags, ModListDisplay display, bool inactive); @@ -32,6 +35,8 @@ class ModListCell : public CCLayer { float getLogoSize() const; void onViewDev(CCObject*); + void updateCellLayout(); + public: virtual void updateState() = 0; virtual CCNode* createLogo(CCSize const& size) = 0; diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index df4fbecc2..95d835f16 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -343,28 +343,28 @@ bool ModListLayer::init() { m_menu->addChild(m_featuredTabBtn); // tabs gradient - m_tabsGradientNode = CCClippingNode::create(); - m_tabsGradientNode->setContentSize(this->getContentSize()); - m_tabsGradientNode->setAnchorPoint({0.5f, 0.5f}); - m_tabsGradientNode->ignoreAnchorPointForPosition(true); - m_tabsGradientNode->setZOrder(9); - m_tabsGradientNode->setInverted(false); - m_tabsGradientNode->setAlphaThreshold(0.f); + // m_tabsGradientNode = CCClippingNode::create(); + // m_tabsGradientNode->setContentSize(this->getContentSize()); + // m_tabsGradientNode->setAnchorPoint({0.5f, 0.5f}); + // m_tabsGradientNode->ignoreAnchorPointForPosition(true); + // m_tabsGradientNode->setZOrder(9); + // m_tabsGradientNode->setInverted(false); + // m_tabsGradientNode->setAlphaThreshold(0.f); - m_tabsGradientSprite = CCSprite::create("tab-gradient.png"_spr); - m_tabsGradientNode->addChild(m_tabsGradientSprite); + // m_tabsGradientSprite = CCSprite::create("tab-gradient.png"_spr); + // m_tabsGradientNode->addChild(m_tabsGradientSprite); - m_tabsGradientStencil = CCSprite::create("tab-gradient-mask.png"_spr); - m_tabsGradientStencil->setAnchorPoint({0.f, 0.f}); - m_tabsGradientNode->setStencil(m_tabsGradientStencil); + // m_tabsGradientStencil = CCSprite::create("tab-gradient-mask.png"_spr); + // m_tabsGradientStencil->setAnchorPoint({0.f, 0.f}); + // m_tabsGradientNode->setStencil(m_tabsGradientStencil); // add menus m_menu->setZOrder(0); m_topMenu->setZOrder(10); this->addChild(m_menu); - this->addChild(m_tabsGradientNode); - this->addChild(m_tabsGradientStencil); + // this->addChild(m_tabsGradientNode); + // this->addChild(m_tabsGradientStencil); this->addChild(m_topMenu); // select first tab @@ -646,7 +646,7 @@ void ModListLayer::onExpand(CCObject* sender) { m_display = static_cast(sender)->isToggled() ? ModListDisplay::Concise : ModListDisplay::Expanded; - this->reloadList(); + this->reloadList(false); } void ModListLayer::onFilters(CCObject*) { From 32b622639c41a124df92ab66b6fd89022665f9b0 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 9 Sep 2023 14:33:00 +0300 Subject: [PATCH 004/135] readd stencil --- loader/src/ui/internal/list/ModListLayer.cpp | 28 ++++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index 95d835f16..6dde2e665 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -343,28 +343,28 @@ bool ModListLayer::init() { m_menu->addChild(m_featuredTabBtn); // tabs gradient - // m_tabsGradientNode = CCClippingNode::create(); - // m_tabsGradientNode->setContentSize(this->getContentSize()); - // m_tabsGradientNode->setAnchorPoint({0.5f, 0.5f}); - // m_tabsGradientNode->ignoreAnchorPointForPosition(true); - // m_tabsGradientNode->setZOrder(9); - // m_tabsGradientNode->setInverted(false); - // m_tabsGradientNode->setAlphaThreshold(0.f); + m_tabsGradientNode = CCClippingNode::create(); + m_tabsGradientNode->setContentSize(this->getContentSize()); + m_tabsGradientNode->setAnchorPoint({0.5f, 0.5f}); + m_tabsGradientNode->ignoreAnchorPointForPosition(true); + m_tabsGradientNode->setZOrder(9); + m_tabsGradientNode->setInverted(false); + m_tabsGradientNode->setAlphaThreshold(0.f); - // m_tabsGradientSprite = CCSprite::create("tab-gradient.png"_spr); - // m_tabsGradientNode->addChild(m_tabsGradientSprite); + m_tabsGradientSprite = CCSprite::create("tab-gradient.png"_spr); + m_tabsGradientNode->addChild(m_tabsGradientSprite); - // m_tabsGradientStencil = CCSprite::create("tab-gradient-mask.png"_spr); - // m_tabsGradientStencil->setAnchorPoint({0.f, 0.f}); - // m_tabsGradientNode->setStencil(m_tabsGradientStencil); + m_tabsGradientStencil = CCSprite::create("tab-gradient-mask.png"_spr); + m_tabsGradientStencil->setAnchorPoint({0.f, 0.f}); + m_tabsGradientNode->setStencil(m_tabsGradientStencil); // add menus m_menu->setZOrder(0); m_topMenu->setZOrder(10); this->addChild(m_menu); - // this->addChild(m_tabsGradientNode); - // this->addChild(m_tabsGradientStencil); + this->addChild(m_tabsGradientNode); + this->addChild(m_tabsGradientStencil); this->addChild(m_topMenu); // select first tab From b087574ac7a438f8a9f962da92747bed36db3d0c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 9 Sep 2023 14:39:14 +0300 Subject: [PATCH 005/135] Fix scaling on labelmenu --- loader/src/ui/internal/list/ModListCell.cpp | 22 ++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index fa970c5a6..1c8786a51 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -73,7 +73,7 @@ void ModListCell::setupInfo( m_labelMenu->setLayout( RowLayout::create() ->setAxisAlignment(AxisAlignment::Start) - ->setAutoScale(false) + ->setAutoScale(true) ); m_labelMenu->setLayoutOptions( AxisLayoutOptions::create() @@ -90,7 +90,7 @@ void ModListCell::setupInfo( titleLabel->limitLabelWidth(m_width / 2 - 40.f, .5f, .1f); titleLabel->setLayoutOptions( AxisLayoutOptions::create() - ->setAutoScale(true) + ->setScalePriority(1) ->setMaxScale(0.5f) ->setMinScale(0.1f) ); @@ -103,11 +103,15 @@ void ModListCell::setupInfo( metadata.getVersion().toString(false).c_str(), "bigFont.fnt" ); - versionLabel->setScale(.3f); versionLabel->setColor({ 0, 255, 0 }); if (inactive) { versionLabel->setColor({ 0, 163, 0 }); } + versionLabel->setLayoutOptions( + AxisLayoutOptions::create() + ->setMaxScale(0.3) + ->setMinScale(0.1) + ); m_labelMenu->addChild(versionLabel); TagNode* apiLabel = nullptr; @@ -115,13 +119,21 @@ void ModListCell::setupInfo( if (auto tag = metadata.getVersion().getTag()) { auto tagLabel = TagNode::create(tag.value().toString().c_str()); - tagLabel->setScale(.3f); + tagLabel->setLayoutOptions( + AxisLayoutOptions::create() + ->setMaxScale(0.3) + ->setMinScale(0.1) + ); m_labelMenu->addChild(tagLabel); } if (metadata.isAPI()) { apiLabel = TagNode::create("API"); - apiLabel->setScale(.3f); + apiLabel->setLayoutOptions( + AxisLayoutOptions::create() + ->setMaxScale(0.3) + ->setMinScale(0.1) + ); m_labelMenu->addChild(apiLabel); } From 2ecb658b2a058f7059fe4256a3cbcf4a08f3d5c4 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 9 Sep 2023 15:29:22 +0300 Subject: [PATCH 006/135] Don't hardcode userobject hooks to ccdirector --- loader/src/hooks/GeodeNodeMetadata.cpp | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/loader/src/hooks/GeodeNodeMetadata.cpp b/loader/src/hooks/GeodeNodeMetadata.cpp index 3daa411bd..d856922dd 100644 --- a/loader/src/hooks/GeodeNodeMetadata.cpp +++ b/loader/src/hooks/GeodeNodeMetadata.cpp @@ -69,15 +69,18 @@ class GeodeNodeMetadata final : public cocos2d::CCObject { #include struct ProxyCCNode : Modify { virtual CCObject* getUserObject() { - if (static_cast(this) == static_cast(CCDirector::get())) { - // apparently this function is the same as - // CCDirector::getNextScene so yeah - return m_pUserObject; + if (typeinfo_cast(this)) { + return GeodeNodeMetadata::set(this)->m_userObject; } - return GeodeNodeMetadata::set(this)->m_userObject; + // apparently this function is the same as + // CCDirector::getNextScene so yeah + return m_pUserObject; } virtual void setUserObject(CCObject* obj) { - GeodeNodeMetadata::set(this)->m_userObject = obj; + if (typeinfo_cast(this)) { + GeodeNodeMetadata::set(this)->m_userObject = obj; + } + m_pUserObject = obj; } }; From d277b9435c5434375b5c9e1954354af9d5cbc200 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 10 Sep 2023 17:19:59 +0300 Subject: [PATCH 007/135] Reenable platform console --- loader/src/platform/mac/LoaderImpl.mm | 69 ++++++++++++++------------- 1 file changed, 36 insertions(+), 33 deletions(-) diff --git a/loader/src/platform/mac/LoaderImpl.mm b/loader/src/platform/mac/LoaderImpl.mm index 53f06ba81..5d6cde66e 100644 --- a/loader/src/platform/mac/LoaderImpl.mm +++ b/loader/src/platform/mac/LoaderImpl.mm @@ -42,39 +42,42 @@ void Loader::Impl::openPlatformConsole() { if (m_platformConsoleOpen) return; - // std::string outFile = "/tmp/command_output_XXXXXX"; - // int outFd = mkstemp(&outFile[0]); - - // auto script = outFile + ".command"; - // auto scriptContent = fmt::format(R"( - // #!/bin/sh - // echo -n -e "\033]0;Geode Console\007" - // tail -f {} & - // trap "" SIGINT - // while [ $(lsof -t {} 2>/dev/null | wc -l) -gt 1 ]; do :; done - // osascript -e 'tell application "Terminal" - // close (every window whose name contains "Geode Console") - // if (count windows) is 0 then quit - // end tell' & - // exit - // )", outFile, outFile); - - // if (file::writeString(script, scriptContent)) { - // chmod(script.c_str(), 0777); - // dup2(outFd, 1); - // dup2(outFd, 2); - - // NSTask *task = [[NSTask alloc] init]; - // task.launchPath = @"/usr/bin/open"; - // task.arguments = @[[NSString stringWithUTF8String:script.c_str()]]; - // [task launch]; - - // m_platformData = new MacConsoleData { - // outFile, - // script, - // outFd - // }; - // } + std::string outFile = "/tmp/command_output_XXXXXX"; + int outFd = mkstemp(&outFile[0]); + + auto script = outFile + ".command"; + auto scriptContent = fmt::format(R"( + #!/bin/sh + echo -n -e "\033]0;Geode Console {}\007" + tail -f {} & + trap "" SIGINT + while [ $(lsof -t {} 2>/dev/null | wc -l) -gt 1 ] + do : + sleep 2 + done + osascript -e 'tell application "Terminal" + close (every window whose name contains "Geode Console {}") + if (count windows) is 0 then quit + end tell' & + exit + )", getpid(), outFile, outFile, getpid()); + + if (file::writeString(script, scriptContent)) { + chmod(script.c_str(), 0777); + dup2(outFd, 1); + dup2(outFd, 2); + + NSTask *task = [[NSTask alloc] init]; + task.launchPath = @"/usr/bin/open"; + task.arguments = @[[NSString stringWithUTF8String:script.c_str()]]; + [task launch]; + + m_platformData = new MacConsoleData { + outFile, + script, + outFd + }; + } m_platformConsoleOpen = true; From 182984d2913d2ae1298d39e7dff2ef874b436281 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 10 Sep 2023 18:01:23 +0300 Subject: [PATCH 008/135] Fix problems with macos console --- loader/src/platform/mac/LoaderImpl.mm | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/loader/src/platform/mac/LoaderImpl.mm b/loader/src/platform/mac/LoaderImpl.mm index 5d6cde66e..931c99587 100644 --- a/loader/src/platform/mac/LoaderImpl.mm +++ b/loader/src/platform/mac/LoaderImpl.mm @@ -51,16 +51,14 @@ echo -n -e "\033]0;Geode Console {}\007" tail -f {} & trap "" SIGINT - while [ $(lsof -t {} 2>/dev/null | wc -l) -gt 1 ] - do : - sleep 2 - done + lsof -p {} +r 1 &>/dev/null + pkill -P $$ osascript -e 'tell application "Terminal" close (every window whose name contains "Geode Console {}") if (count windows) is 0 then quit end tell' & exit - )", getpid(), outFile, outFile, getpid()); + )", getpid(), outFile, getpid(), getpid()); if (file::writeString(script, scriptContent)) { chmod(script.c_str(), 0777); From a738320e2cff6be45e3ded87a4e087b7d12d77d0 Mon Sep 17 00:00:00 2001 From: ConfiG Date: Mon, 11 Sep 2023 16:36:35 +0300 Subject: [PATCH 009/135] add uninstall button to geode mod --- installer/windows/installer.nsi | 2 + loader/include/Geode/loader/Mod.hpp | 11 +++- loader/include/Geode/utils/general.hpp | 2 + loader/src/loader/Mod.cpp | 5 +- loader/src/loader/ModImpl.cpp | 24 +++++++- loader/src/loader/ModImpl.hpp | 2 +- loader/src/platform/mac/util.mm | 36 ++++++++---- loader/src/platform/windows/util.cpp | 42 +++++++++++--- loader/src/ui/internal/info/ModInfoPopup.cpp | 58 +++++++++----------- loader/src/ui/internal/info/ModInfoPopup.hpp | 1 - 10 files changed, 125 insertions(+), 58 deletions(-) diff --git a/installer/windows/installer.nsi b/installer/windows/installer.nsi index dd9989ef4..43d6c3091 100644 --- a/installer/windows/installer.nsi +++ b/installer/windows/installer.nsi @@ -490,8 +490,10 @@ Function un.onInit FunctionEnd Section "Uninstall" DeleteRegKey /ifempty HKCU "Software\Geode" + Delete $INSTDIR\GeodeUninstaller.exe Delete $INSTDIR\Geode.dll Delete $INSTDIR\Geode.pdb + Delete $INSTDIR\Geode.lib Delete $INSTDIR\GeodeUpdater.exe Delete $INSTDIR\XInput9_1_0.dll diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index 4df6f9c2c..f7d02b012 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -38,6 +38,7 @@ namespace geode { Enable, Disable, Uninstall, + UninstallWithSaveData }; GEODE_HIDDEN Mod* takeNextLoaderMod(); @@ -336,12 +337,20 @@ namespace geode { */ Result<> disable(); + // TODO: in 2.0.0 make this use an optional arg instead /** - * Disable this mod (if supported), then delete the mod's .geode package. + * Delete the mod's .geode package. * @returns Successful result on success, * errorful result with info on error */ Result<> uninstall(); + /** + * Delete the mod's .geode package. + * @param deleteSaveData Whether should also delete the mod's save data + * @returns Successful result on success, + * errorful result with info on error + */ + Result<> uninstall(bool deleteSaveData); bool isUninstalled() const; ModRequestedAction getRequestedAction() const; diff --git a/loader/include/Geode/utils/general.hpp b/loader/include/Geode/utils/general.hpp index c4f5015f4..b4209af2e 100644 --- a/loader/include/Geode/utils/general.hpp +++ b/loader/include/Geode/utils/general.hpp @@ -129,5 +129,7 @@ namespace geode::utils::clipboard { } namespace geode::utils::game { + GEODE_DLL void exit(); GEODE_DLL void restart(); + GEODE_DLL void launchLoaderUninstaller(bool deleteSaveData); } diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 100e39eeb..79d7eebb5 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -191,7 +191,10 @@ Result<> Mod::disable() { } Result<> Mod::uninstall() { - return m_impl->uninstall(); + return m_impl->uninstall(false); +} +Result<> Mod::uninstall(bool deleteSaveData) { + return m_impl->uninstall(deleteSaveData); } bool Mod::isUninstalled() const { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index f932af84f..a5e830070 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -393,12 +393,20 @@ Result<> Mod::Impl::disable() { return Ok(); } -Result<> Mod::Impl::uninstall() { +Result<> Mod::Impl::uninstall(bool deleteSaveData) { if (m_requestedAction != ModRequestedAction::None) { return Err("Mod already has a requested action"); } - m_requestedAction = ModRequestedAction::Uninstall; + if (this->getID() == "geode.loader") { + utils::game::launchLoaderUninstaller(deleteSaveData); + utils::game::exit(); + return Ok(); + } + + m_requestedAction = deleteSaveData ? + ModRequestedAction::UninstallWithSaveData : + ModRequestedAction::Uninstall; std::error_code ec; ghc::filesystem::remove(m_metadata.getPath(), ec); @@ -408,11 +416,21 @@ Result<> Mod::Impl::uninstall() { ); } + if (deleteSaveData) { + ghc::filesystem::remove_all(this->getSaveDir(), ec); + if (ec) { + return Err( + "Unable to delete mod's save directory: " + ec.message() + ); + } + } + return Ok(); } bool Mod::Impl::isUninstalled() const { - return m_requestedAction == ModRequestedAction::Uninstall; + return m_requestedAction == ModRequestedAction::Uninstall || + m_requestedAction == ModRequestedAction::UninstallWithSaveData; } ModRequestedAction Mod::Impl::getRequestedAction() const { diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index e79dc8ae5..542bc1786 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -127,7 +127,7 @@ namespace geode { Result<> unpatch(Patch* patch); Result<> enable(); Result<> disable(); - Result<> uninstall(); + Result<> uninstall(bool deleteSaveData); bool isUninstalled() const; // 1.3.0 additions diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm index 4807ebcaa..6a100715d 100644 --- a/loader/src/platform/mac/util.mm +++ b/loader/src/platform/mac/util.mm @@ -200,22 +200,13 @@ @implementation FileDialog return path; } -void geode::utils::game::restart() { +void geode::utils::game::exit() { if (CCApplication::sharedApplication() && (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { log::error("Cannot restart in PlayLayer or LevelEditorLayer!"); return; } - auto restart = +[] { - log::info("Restarting game..."); - auto gdExec = dirs::getGameDir() / "MacOS" / "Geometry Dash"; - - NSTask *task = [NSTask new]; - [task setLaunchPath: [NSString stringWithUTF8String: gdExec.string().c_str()]]; - [task launch]; - }; - class Exit : public CCObject { public: void shutdown() { @@ -226,7 +217,6 @@ void shutdown() { } }; - std::atexit(restart); CCDirector::get()->getActionManager()->addAction(CCSequence::create( CCDelayTime::create(0.5f), CCCallFunc::create(nullptr, callfunc_selector(Exit::shutdown)), @@ -234,6 +224,30 @@ void shutdown() { ), CCDirector::get()->getRunningScene(), false); } +void geode::utils::game::restart() { + if (CCApplication::sharedApplication() && + (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { + log::error("Cannot restart in PlayLayer or LevelEditorLayer!"); + return; + } + + auto restart = +[] { + log::info("Restarting game..."); + auto gdExec = dirs::getGameDir() / "MacOS" / "Geometry Dash"; + + NSTask *task = [NSTask new]; + [task setLaunchPath: [NSString stringWithUTF8String: gdExec.string().c_str()]]; + [task launch]; + }; + + std::atexit(restart); + exit(); +} + +void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) { + log::error("Launching Geode uninstaller is not supported on macOS"); +} + Result<> geode::hook::addObjcMethod(std::string const& className, std::string const& selectorName, void* imp) { auto cls = objc_getClass(className.c_str()); if (!cls) diff --git a/loader/src/platform/windows/util.cpp b/loader/src/platform/windows/util.cpp index 74291a388..ee26861f5 100644 --- a/loader/src/platform/windows/util.cpp +++ b/loader/src/platform/windows/util.cpp @@ -158,6 +158,22 @@ ghc::filesystem::path dirs::getSaveDir() { return path; } +void geode::utils::game::exit() { + if (CCApplication::sharedApplication() && + (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { + log::error("Cannot exit in PlayLayer or LevelEditorLayer!"); + return; + } + + if (CCApplication::sharedApplication()) + // please forgive me.. + // manually set the closed flag + // TODO: actually call glfwSetWindowShouldClose + *reinterpret_cast(reinterpret_cast(CCEGLView::sharedOpenGLView()->getWindow()) + 0xa) = true; + else + std::exit(0); +} + void geode::utils::game::restart() { if (CCApplication::sharedApplication() && (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { @@ -175,13 +191,25 @@ void geode::utils::game::restart() { const auto updaterPath = (workingDir / "GeodeUpdater.exe").string(); ShellExecuteA(nullptr, "open", updaterPath.c_str(), gdName.c_str(), workingDir.string().c_str(), false); - if (CCApplication::sharedApplication()) - // please forgive me.. - // manually set the closed flag - // TODO: actually call glfwSetWindowShouldClose - *reinterpret_cast(reinterpret_cast(CCEGLView::sharedOpenGLView()->getWindow()) + 0xa) = true; - else - exit(0); + exit(); +} + +void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) { + const auto workingDir = dirs::getGameDir(); + + if (!exists((workingDir / "GeodeUninstaller.exe"))) { + log::error("Uninstaller not found! Not launching."); + return; + } + + std::string params; + if (deleteSaveData) { + params = "\"/DATA=" + dirs::getSaveDir().string() + "\""; + } + + // launch uninstaller + const auto uninstallerPath = (workingDir / "GeodeUninstaller.exe").string(); + ShellExecuteA(nullptr, "open", uninstallerPath.c_str(), params.c_str(), workingDir.string().c_str(), false); } Result<> geode::hook::addObjcMethod(std::string const& className, std::string const& selectorName, void* imp) { diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index 1ec147d13..e5a093b45 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -24,7 +24,7 @@ static constexpr int const TAG_CONFIRM_UNINSTALL = 5; static constexpr int const TAG_CONFIRM_UPDATE = 6; -static constexpr int const TAG_DELETE_SAVEDATA = 7; +static constexpr int const TAG_CONFIRM_UNINSTALL_WITH_SAVEDATA = 7; static const CCSize LAYER_SIZE = {440.f, 290.f}; bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { @@ -431,7 +431,12 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { disableBtnSpr->setColor({150, 150, 150}); } - if (mod != Mod::get()) { + bool shouldShowUninstall = mod != Mod::get(); +#if defined(GEODE_IS_WINDOWS) + shouldShowUninstall = shouldShowUninstall || + exists((dirs::getGameDir() / "GeodeUninstaller.exe")); +#endif + if (shouldShowUninstall) { auto uninstallBtnSpr = ButtonSprite::create("Uninstall", "bigFont.fnt", "GJ_button_05.png", .6f); uninstallBtnSpr->setScale(.6f); @@ -589,7 +594,10 @@ void LocalModInfoPopup::onUninstall(CCObject*) { auto layer = FLAlertLayer::create( this, "Confirm Uninstall", - fmt::format("Are you sure you want to uninstall {}?", m_mod->getName()), + fmt::format("Are you sure you want to uninstall {}?{}", + m_mod->getName(), m_mod == Mod::get() ? + "\nThis will close the game and launch the Geode Uninstaller. " + "You will have to restart the game manually after that." : ""), "Cancel", "OK" ); @@ -648,18 +656,23 @@ void LocalModInfoPopup::FLAlert_Clicked(FLAlertLayer* layer, bool btn2) { switch (layer->getTag()) { case TAG_CONFIRM_UNINSTALL: { if (btn2) { - this->doUninstall(); + auto layer2 = FLAlertLayer::create( + this, + "Confirm Uninstall", + "Would you also like to delete the mod's save data?", + "Keep", + "Delete", + 350.f + ); + layer2->setTag(TAG_CONFIRM_UNINSTALL_WITH_SAVEDATA); + layer2->show(); } } break; - case TAG_DELETE_SAVEDATA: { - if (btn2) { - if (ghc::filesystem::remove_all(m_mod->getSaveDir())) { - FLAlertLayer::create("Deleted", "The mod's save data was deleted.", "OK")->show(); - } - else { - FLAlertLayer::create("Error", "Unable to delete mod's save directory!", "OK")->show(); - } + case TAG_CONFIRM_UNINSTALL_WITH_SAVEDATA: { + auto res = m_mod->uninstall(btn2); + if (!res) { + return FLAlertLayer::create("Uninstall failed :(", res.unwrapErr(), "OK")->show(); } if (m_layer) { m_layer->reloadList(); @@ -669,27 +682,6 @@ void LocalModInfoPopup::FLAlert_Clicked(FLAlertLayer* layer, bool btn2) { } } -void LocalModInfoPopup::doUninstall() { - auto res = m_mod->uninstall(); - if (!res) { - return FLAlertLayer::create("Uninstall failed :(", res.unwrapErr(), "OK")->show(); - } - auto layer = FLAlertLayer::create( - this, - "Uninstall complete", - "Mod was successfully uninstalled! :) " - "(You have to restart the game " - "for the mod to take effect). " - "Would you also like to delete the mod's " - "save data?", - "Keep", - "Delete", - 350.f - ); - layer->setTag(TAG_DELETE_SAVEDATA); - layer->show(); -} - LocalModInfoPopup* LocalModInfoPopup::create(Mod* mod, ModListLayer* list) { auto ret = new LocalModInfoPopup; if (ret && ret->init(mod, list)) { diff --git a/loader/src/ui/internal/info/ModInfoPopup.hpp b/loader/src/ui/internal/info/ModInfoPopup.hpp index 7870dc9ce..808cd9181 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.hpp +++ b/loader/src/ui/internal/info/ModInfoPopup.hpp @@ -74,7 +74,6 @@ class LocalModInfoPopup : public ModInfoPopup, public FLAlertLayerProtocol { void onEnableMod(CCObject*); void onUninstall(CCObject*); void onOpenConfigDir(CCObject*); - void doUninstall(); void onUpdateProgress(ModInstallEvent* event); void onUpdate(CCObject*); From 20adf34d4a132d6f0fc217a39ff9941fad595df4 Mon Sep 17 00:00:00 2001 From: ConfiG Date: Mon, 11 Sep 2023 17:02:43 +0300 Subject: [PATCH 010/135] change some popups a bit --- loader/src/ui/internal/info/ModInfoPopup.cpp | 36 +++++++++----------- loader/src/ui/internal/list/ModListCell.cpp | 14 ++++---- 2 files changed, 22 insertions(+), 28 deletions(-) diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index e5a093b45..366732571 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -552,12 +552,11 @@ void LocalModInfoPopup::onUpdateProgress(ModInstallEvent* event) { std::visit(makeVisitor { [&](UpdateFinished const&) { this->setInstallStatus(std::nullopt); - + FLAlertLayer::create( - "Update complete", - "Mod successfully updated! :) " - "(You have to restart the game " - "for the mod to take effect)", + "Update Complete", + "Mod updated successfully!\n" + "Restart the game to apply changes.", "OK" )->show(); @@ -573,7 +572,7 @@ void LocalModInfoPopup::onUpdateProgress(ModInstallEvent* event) { this->setInstallStatus(std::nullopt); FLAlertLayer::create( - "Update failed :(", info, "OK" + "Update Failed", info, "OK" )->show(); m_installBtn->setEnabled(true); @@ -594,8 +593,8 @@ void LocalModInfoPopup::onUninstall(CCObject*) { auto layer = FLAlertLayer::create( this, "Confirm Uninstall", - fmt::format("Are you sure you want to uninstall {}?{}", - m_mod->getName(), m_mod == Mod::get() ? + fmt::format("Are you sure you want to uninstall {}?{}", m_mod->getName(), + m_mod == Mod::get() ? "\nThis will close the game and launch the Geode Uninstaller. " "You will have to restart the game manually after that." : ""), "Cancel", @@ -606,13 +605,11 @@ void LocalModInfoPopup::onUninstall(CCObject*) { } void LocalModInfoPopup::onEnableMod(CCObject* sender) { - if (!Mod::get()->setSavedValue("shown-disable-vs-unload-info", true)) { + if (!Mod::get()->setSavedValue("shown-mod-toggle-info", true)) { FLAlertLayer::create( "Notice", - "Disabling a mod removes its hooks & patches and " - "calls its user-defined disable function if one exists. You may " - "still see some effects of the mod left however, and you may " - "need to restart the game to have it fully unloaded.", + "Toggling a mod requires you to restart the game.\n" + "When a mod is disabled, it will not get loaded at all.", "OK" )->show(); } @@ -672,7 +669,7 @@ void LocalModInfoPopup::FLAlert_Clicked(FLAlertLayer* layer, bool btn2) { case TAG_CONFIRM_UNINSTALL_WITH_SAVEDATA: { auto res = m_mod->uninstall(btn2); if (!res) { - return FLAlertLayer::create("Uninstall failed :(", res.unwrapErr(), "OK")->show(); + return FLAlertLayer::create("Uninstall Failed", res.unwrapErr(), "OK")->show(); } if (m_layer) { m_layer->reloadList(); @@ -737,12 +734,11 @@ void IndexItemInfoPopup::onInstallProgress(ModInstallEvent* event) { std::visit(makeVisitor { [&](UpdateFinished const&) { this->setInstallStatus(std::nullopt); - + FLAlertLayer::create( - "Install complete", - "Mod successfully installed! :) " - "(You have to restart the game " - "for the mod to take effect)", + "Install Complete", + "Mod installed successfully!\n" + "Restart the game to apply changes.", "OK" )->show(); @@ -758,7 +754,7 @@ void IndexItemInfoPopup::onInstallProgress(ModInstallEvent* event) { this->setInstallStatus(std::nullopt); FLAlertLayer::create( - "Installation failed :(", info, "OK" + "Installation Failed", info, "OK" )->show(); m_installBtn->setEnabled(true); diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index 66ca0a14e..5b8839595 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -219,13 +219,11 @@ ModCell* ModCell::create( } void ModCell::onEnable(CCObject* sender) { - if (!Mod::get()->setSavedValue("shown-disable-vs-unload-info", true)) { + if (!Mod::get()->getSavedValue("shown-mod-toggle-info", true)) { FLAlertLayer::create( "Notice", - "Disabling a mod removes its hooks & patches and " - "calls its user-defined disable function if one exists. You may " - "still see some effects of the mod left however, and you may " - "need to restart the game to have it fully unloaded.", + "Toggling a mod requires you to restart the game.\n" + "When a mod is disabled, it will not get loaded at all.", "OK" )->show(); } @@ -455,19 +453,19 @@ void InvalidGeodeFileCell::FLAlert_Clicked(FLAlertLayer*, bool btn2) { try { if (ghc::filesystem::remove(m_info.path)) { FLAlertLayer::create( - "File removed", "Removed " + m_info.path.string() + "", "OK" + "File Removed", "Removed " + m_info.path.string() + "", "OK" )->show(); } else { FLAlertLayer::create( - "Unable to remove file", + "Unable to Remove File", "Unable to remove " + m_info.path.string() + "", "OK" )->show(); } } catch (std::exception& e) { FLAlertLayer::create( - "Unable to remove file", + "Unable to Remove File", "Unable to remove " + m_info.path.string() + ": " + std::string(e.what()) + "", "OK" From 0f179dad456dbab18af230d9f9f9d55f3e219e80 Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:12:15 -0500 Subject: [PATCH 011/135] make minor version label invisible on update --- loader/src/platform/mac/LoaderImpl.mm | 2 +- loader/src/ui/internal/info/ModInfoPopup.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/loader/src/platform/mac/LoaderImpl.mm b/loader/src/platform/mac/LoaderImpl.mm index 5446c16ec..f48d949e3 100644 --- a/loader/src/platform/mac/LoaderImpl.mm +++ b/loader/src/platform/mac/LoaderImpl.mm @@ -64,7 +64,7 @@ dup2(outFd, 1); dup2(outFd, 2); - NSTask *task = [[NSTask alloc] init]; + NSTask* task = [[NSTask alloc] init]; task.launchPath = @"/usr/bin/open"; task.arguments = @[[NSString stringWithUTF8String:script.c_str()]]; [task launch]; diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index 1ec147d13..4e071c46e 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -353,6 +353,9 @@ void ModInfoPopup::preInstall() { if (m_latestVersionLabel) { m_latestVersionLabel->setVisible(false); } + if (m_minorVersionLabel) { + m_minorVersionLabel->setVisible(false); + } this->setInstallStatus(UpdateProgress(0, "Starting install")); m_installBtn->setTarget( From ef4764728b4fc858a57db9a9514863ecc2240126 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:12:46 +0300 Subject: [PATCH 012/135] change loadinglayer, fix macos spritesheet issue, separate user disabled & problem disabled, fix not enabling a disabled mod that has dependency disabled, --- loader/include/Geode/loader/Mod.hpp | 2 + loader/src/hooks/LoadingLayer.cpp | 143 ++++++++++++++------ loader/src/hooks/updateResources.cpp | 15 -- loader/src/loader/LoaderImpl.cpp | 8 +- loader/src/loader/Mod.cpp | 4 + loader/src/loader/ModImpl.cpp | 8 +- loader/src/loader/ModImpl.hpp | 2 + loader/src/ui/internal/list/ModListCell.cpp | 3 +- 8 files changed, 122 insertions(+), 63 deletions(-) delete mode 100644 loader/src/hooks/updateResources.cpp diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index bede828dd..a51af6b97 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -406,6 +406,8 @@ namespace geode { bool isLoggingEnabled() const; void setLoggingEnabled(bool enabled); + bool shouldLoad() const; + friend class ModImpl; }; } diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index b3a24bd01..93e82f077 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -8,68 +8,77 @@ using namespace geode::prelude; struct CustomLoadingLayer : Modify { - CCLabelBMFont* m_loadedModsLabel; - bool m_updatingResources; - - CustomLoadingLayer() : m_loadedModsLabel(nullptr), m_updatingResources(false) {} + CCLabelBMFont* m_smallLabel = nullptr; + int m_geodeLoadStep = 0; void updateLoadedModsLabel() { auto allMods = Loader::get()->getAllMods(); auto count = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) { return item->isEnabled(); }); - auto str = fmt::format("Geode: Loaded {}/{} mods", count, allMods.size()); - m_fields->m_loadedModsLabel->setCString(str.c_str()); + auto totalCount = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) { + return item->shouldLoad(); + }); + auto str = fmt::format("Geode: Loaded {}/{} mods", count, totalCount); + this->setSmallText(str); } + void setSmallText(std::string const& text) { + m_fields->m_smallLabel->setString(text.c_str()); + } + + // hook bool init(bool fromReload) { CCFileUtils::get()->updatePaths(); if (!LoadingLayer::init(fromReload)) return false; - if (fromReload) return true; - auto winSize = CCDirector::sharedDirector()->getWinSize(); - m_fields->m_loadedModsLabel = CCLabelBMFont::create("Geode: Loaded 0/0 mods", "goldFont.fnt"); - m_fields->m_loadedModsLabel->setPosition(winSize.width / 2, 30.f); - m_fields->m_loadedModsLabel->setScale(.45f); - m_fields->m_loadedModsLabel->setID("geode-loaded-info"); - this->addChild(m_fields->m_loadedModsLabel); - this->updateLoadedModsLabel(); + m_fields->m_smallLabel = CCLabelBMFont::create("", "goldFont.fnt"); + m_fields->m_smallLabel->setPosition(winSize.width / 2, 30.f); + m_fields->m_smallLabel->setScale(.45f); + m_fields->m_smallLabel->setID("geode-small-label"); + this->addChild(m_fields->m_smallLabel); - // fields have unpredictable destructors - this->addChild(EventListenerNode::create( - this, &CustomLoadingLayer::updateResourcesProgress - )); + return true; + } + void setupLoadingMods() { + if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) { + this->updateLoadedModsLabel(); + this->waitLoadAssets(); + } + else { + this->continueLoadAssets(); + } + } + + void setupLoaderResources() { // verify loader resources if (!LoaderImpl::get()->verifyLoaderResources()) { - m_fields->m_updatingResources = true; - this->setUpdateText("Downloading Resources"); + this->setSmallText("Downloading Loader Resources"); + this->addChild(EventListenerNode::create( + this, &CustomLoadingLayer::updateResourcesProgress + )); } else { + this->setSmallText("Loading Loader Resources"); LoaderImpl::get()->updateSpecialFiles(); + this->continueLoadAssets(); } - - return true; - } - - void setUpdateText(std::string const& text) { - m_textArea->setString(text.c_str()); } void updateResourcesProgress(ResourceDownloadEvent* event) { std::visit(makeVisitor { [&](UpdateProgress const& progress) { - this->setUpdateText(fmt::format( - "Downloading Resources: {}%", progress.first + this->setSmallText(fmt::format( + "Downloading Loader Resources: {}%", progress.first )); }, [&](UpdateFinished) { - this->setUpdateText("Resources Downloaded"); - m_fields->m_updatingResources = false; - this->loadAssets(); + this->setSmallText("Downloaded Loader Resources"); + this->continueLoadAssets(); }, [&](UpdateFailed const& error) { LoaderImpl::get()->platformMessageBox( @@ -81,24 +90,70 @@ struct CustomLoadingLayer : Modify { "The game will be loaded as normal, but please be aware " "that it is very likely to crash. " ); - this->setUpdateText("Resource Download Failed"); - m_fields->m_updatingResources = false; - this->loadAssets(); + this->setSmallText("Failed Loader Resources"); + this->continueLoadAssets(); } }, event->status); } - void loadAssets() { - if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) { - this->updateLoadedModsLabel(); - Loader::get()->queueInMainThread([this]() { - this->loadAssets(); - }); - return; + void setupModResources() { + log::debug("Loading mod resources"); + this->setSmallText("Loading mod resources"); + Loader::get()->updateResources(true); + this->continueLoadAssets(); + } + + int getCurrentStep() { + return m_fields->m_geodeLoadStep + m_loadStep + 1; + } + + int getTotalStep() { + return 18; + } + + void updateLoadingBar() { + auto length = m_sliderGrooveXPos * this->getCurrentStep() / this->getTotalStep(); + m_sliderBar->setTextureRect({0, 0, length, m_sliderGrooveHeight}); + } + + void waitLoadAssets() { + Loader::get()->queueInMainThread([this]() { + this->loadAssets(); + }); + } + + void continueLoadAssets() { + ++m_fields->m_geodeLoadStep; + Loader::get()->queueInMainThread([this]() { + this->loadAssets(); + }); + } + + bool skipOnRefresh() { + if (m_fromRefresh) { + this->continueLoadAssets(); } - if (m_fields->m_updatingResources) { - return; + return !m_fromRefresh; + } + + // hook + void loadAssets() { + switch (m_fields->m_geodeLoadStep) { + case 0: + if (this->skipOnRefresh()) this->setupLoadingMods(); + break; + case 1: + if (this->skipOnRefresh()) this->setupLoaderResources(); + break; + case 2: + this->setupModResources(); + break; + case 3: + default: + this->setSmallText("Loading game resources"); + LoadingLayer::loadAssets(); + break; } - LoadingLayer::loadAssets(); + this->updateLoadingBar(); } }; diff --git a/loader/src/hooks/updateResources.cpp b/loader/src/hooks/updateResources.cpp deleted file mode 100644 index 858176356..000000000 --- a/loader/src/hooks/updateResources.cpp +++ /dev/null @@ -1,15 +0,0 @@ -#include -#include -#include - -using namespace geode::prelude; - -struct ResourcesUpdate : Modify { - void loadAssets() { - LoadingLayer::loadAssets(); - // this is in case the user refreshes texture quality at runtime - if (m_loadStep == 10) { - Loader::get()->updateResources(true); - } - } -}; diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 197676f53..8b955b53f 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -408,7 +408,7 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) { return; } - if (Mod::get()->getSavedValue("should-load-" + node->getID(), true)) { + if (node->shouldLoad()) { log::debug("Load"); auto res = node->m_impl->loadBinary(); if (!res) { @@ -432,6 +432,10 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) { void Loader::Impl::findProblems() { for (auto const& [id, mod] : m_mods) { + if (!mod->shouldLoad()) { + log::debug("{} is not enabled", id); + continue; + } log::debug(id); log::pushNest(); @@ -492,7 +496,7 @@ void Loader::Impl::findProblems() { Mod* myEpicMod = mod; // clang fix // if the mod is not loaded but there are no problems related to it if (!mod->isEnabled() && - Mod::get()->getSavedValue("should-load-" + mod->getID(), true) && + mod->shouldLoad() && !std::any_of(m_problems.begin(), m_problems.end(), [myEpicMod](auto& item) { return std::holds_alternative(item.cause) && std::get(item.cause).getID() == myEpicMod->getID() || diff --git a/loader/src/loader/Mod.cpp b/loader/src/loader/Mod.cpp index 77b551a41..0408ef101 100644 --- a/loader/src/loader/Mod.cpp +++ b/loader/src/loader/Mod.cpp @@ -245,3 +245,7 @@ void Mod::setLoggingEnabled(bool enabled) { bool Mod::hasSavedValue(std::string const& key) { return this->getSaveContainer().contains(key); } + +bool Mod::shouldLoad() const { + return m_impl->shouldLoad(); +} \ No newline at end of file diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 510693d16..43a94026d 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -43,7 +43,9 @@ Result<> Mod::Impl::setup() { log::warn("Unable to load data for \"{}\": {}", m_metadata.getID(), loadRes.unwrapErr()); } if (!m_resourcesLoaded) { - LoaderImpl::get()->updateModResources(m_self); + auto searchPathRoot = dirs::getModRuntimeDir() / m_metadata.getID() / "resources"; + CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); + m_resourcesLoaded = true; } @@ -633,6 +635,10 @@ void Mod::Impl::setLoggingEnabled(bool enabled) { m_loggingEnabled = enabled; } +bool Mod::Impl::shouldLoad() const { + return Mod::get()->getSavedValue("should-load-" + m_metadata.getID(), true); +} + static Result getModImplInfo() { std::string err; json::Value json; diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index c7a82dfe4..ff5084d61 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -137,6 +137,8 @@ namespace geode { bool isLoggingEnabled() const; void setLoggingEnabled(bool enabled); + + bool shouldLoad() const; }; class ModImpl : public Mod::Impl { diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index 5b8839595..b4f1923b8 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -250,9 +250,10 @@ void ModCell::onRestart(CCObject*) { void ModCell::updateState() { bool unresolved = m_mod->hasUnresolvedDependencies(); + bool shouldLoad = m_mod->shouldLoad(); if (m_enableToggle) { m_enableToggle->toggle(m_mod->isEnabled()); - m_enableToggle->setEnabled(!unresolved); + m_enableToggle->setEnabled(!unresolved || shouldLoad); m_enableToggle->m_offButton->setOpacity(unresolved ? 100 : 255); m_enableToggle->m_offButton->setColor(unresolved ? cc3x(155) : cc3x(255)); m_enableToggle->m_onButton->setOpacity(unresolved ? 100 : 255); From cd89ef190901c77cc0db78b39887c4140696f967 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:15:17 +0300 Subject: [PATCH 013/135] fix the toggling thing with dependencies --- loader/src/ui/internal/list/ModListCell.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index b4f1923b8..766ba83ee 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -251,13 +251,14 @@ void ModCell::onRestart(CCObject*) { void ModCell::updateState() { bool unresolved = m_mod->hasUnresolvedDependencies(); bool shouldLoad = m_mod->shouldLoad(); + auto toggleable = !unresolved || !shouldLoad; if (m_enableToggle) { m_enableToggle->toggle(m_mod->isEnabled()); - m_enableToggle->setEnabled(!unresolved || shouldLoad); - m_enableToggle->m_offButton->setOpacity(unresolved ? 100 : 255); - m_enableToggle->m_offButton->setColor(unresolved ? cc3x(155) : cc3x(255)); - m_enableToggle->m_onButton->setOpacity(unresolved ? 100 : 255); - m_enableToggle->m_onButton->setColor(unresolved ? cc3x(155) : cc3x(255)); + m_enableToggle->setEnabled(toggleable); + m_enableToggle->m_offButton->setOpacity(toggleable ? 100 : 255); + m_enableToggle->m_offButton->setColor(toggleable ? cc3x(155) : cc3x(255)); + m_enableToggle->m_onButton->setOpacity(toggleable ? 100 : 255); + m_enableToggle->m_onButton->setColor(toggleable ? cc3x(155) : cc3x(255)); } bool hasProblems = false; for (auto const& item : Loader::get()->getProblems()) { From e8b6c57c219df84ed30c1fa673124178c6d6a1af Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:16:03 +0300 Subject: [PATCH 014/135] fix grayed out --- loader/src/ui/internal/list/ModListCell.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index 766ba83ee..d98d9218d 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -255,10 +255,10 @@ void ModCell::updateState() { if (m_enableToggle) { m_enableToggle->toggle(m_mod->isEnabled()); m_enableToggle->setEnabled(toggleable); - m_enableToggle->m_offButton->setOpacity(toggleable ? 100 : 255); - m_enableToggle->m_offButton->setColor(toggleable ? cc3x(155) : cc3x(255)); - m_enableToggle->m_onButton->setOpacity(toggleable ? 100 : 255); - m_enableToggle->m_onButton->setColor(toggleable ? cc3x(155) : cc3x(255)); + m_enableToggle->m_offButton->setOpacity(!toggleable ? 100 : 255); + m_enableToggle->m_offButton->setColor(!toggleable ? cc3x(155) : cc3x(255)); + m_enableToggle->m_onButton->setOpacity(!toggleable ? 100 : 255); + m_enableToggle->m_onButton->setColor(!toggleable ? cc3x(155) : cc3x(255)); } bool hasProblems = false; for (auto const& item : Loader::get()->getProblems()) { From 607adc8fd0fa68a4fc8d8eacbe4e1479c9fb4805 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:24:31 +0300 Subject: [PATCH 015/135] Fix disabling problem mods from view popup --- loader/src/ui/internal/info/ModInfoPopup.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index ebe9ac9bc..4c33f1c30 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -425,7 +425,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { disableBtnSpr, enableBtnSpr, this, menu_selector(LocalModInfoPopup::onEnableMod) ); enableBtn->setPosition(-155.f, 75.f); - enableBtn->toggle(!mod->isEnabled()); + enableBtn->toggle(!mod->shouldLoad()); m_buttonMenu->addChild(enableBtn); if (!mod->supportsDisabling()) { @@ -629,9 +629,9 @@ void LocalModInfoPopup::onEnableMod(CCObject* sender) { } } if (m_layer) { - m_layer->updateAllStates(); + m_layer->reloadList(); } - as(sender)->toggle(m_mod->isEnabled()); + as(sender)->toggle(m_mod->shouldLoad()); } void LocalModInfoPopup::onOpenConfigDir(CCObject*) { @@ -640,7 +640,7 @@ void LocalModInfoPopup::onOpenConfigDir(CCObject*) { void LocalModInfoPopup::onDisablingNotSupported(CCObject* pSender) { FLAlertLayer::create("Unsupported", "Disabling is not supported for this mod.", "OK")->show(); - as(pSender)->toggle(m_mod->isEnabled()); + as(pSender)->toggle(m_mod->shouldLoad()); } void LocalModInfoPopup::onSettings(CCObject*) { From dd806e0532085972facb5ed33450a4e28c791bba Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:42:17 +0300 Subject: [PATCH 016/135] Make mod info popup top a layout --- loader/src/ui/internal/info/ModInfoPopup.cpp | 60 +++++++++++--------- 1 file changed, 33 insertions(+), 27 deletions(-) diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index 4c33f1c30..7b8902ca7 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -49,45 +49,51 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { constexpr float logoSize = 40.f; constexpr float logoOffset = 10.f; - auto nameLabel = CCLabelBMFont::create(metadata.getName().c_str(), "bigFont.fnt"); - nameLabel->setAnchorPoint({ .0f, .5f }); - nameLabel->limitLabelWidth(200.f, .7f, .1f); - m_mainLayer->addChild(nameLabel, 2); + auto topNode = CCNode::create(); + topNode->setContentSize({350.f, 80.f}); + topNode->setLayout( + RowLayout::create() + ->setAxisAlignment(AxisAlignment::Center) + ->setAutoScale(false) + ->setCrossAxisOverflow(true) + ); + m_mainLayer->addChild(topNode); + topNode->setAnchorPoint({.5f, .5f}); + topNode->setPosition(winSize.width / 2, winSize.height / 2 + 115.f); auto logoSpr = this->createLogo({logoSize, logoSize}); - m_mainLayer->addChild(logoSpr); + topNode->addChild(logoSpr); + + auto labelNode = CCNode::create(); + labelNode->setLayout( + ColumnLayout::create() + ->setAxisAlignment(AxisAlignment::Center) + ->setCrossAxisLineAlignment(AxisAlignment::Start) + ->setGap(0.f) + ->setAutoScale(false) + ->setCrossAxisOverflow(true) + ); + labelNode->setContentSize({200.f, 80.f}); + topNode->addChild(labelNode); + + auto nameLabel = CCLabelBMFont::create(metadata.getName().c_str(), "bigFont.fnt"); + nameLabel->limitLabelWidth(200.f, .7f, .1f); + labelNode->addChild(nameLabel, 2); auto developerStr = "by " + metadata.getDeveloper(); auto developerLabel = CCLabelBMFont::create(developerStr.c_str(), "goldFont.fnt"); developerLabel->setScale(.5f); - developerLabel->setAnchorPoint({.0f, .5f}); - m_mainLayer->addChild(developerLabel); - - auto logoTitleWidth = - std::max(nameLabel->getScaledContentSize().width, developerLabel->getScaledContentSize().width) + - logoSize + logoOffset; - - nameLabel->setPosition( - winSize.width / 2 - logoTitleWidth / 2 + logoSize + logoOffset, winSize.height / 2 + 125.f - ); - logoSpr->setPosition( - {winSize.width / 2 - logoTitleWidth / 2 + logoSize / 2, winSize.height / 2 + 115.f} - ); - developerLabel->setPosition( - winSize.width / 2 - logoTitleWidth / 2 + logoSize + logoOffset, winSize.height / 2 + 105.f - ); + labelNode->addChild(developerLabel); auto versionLabel = CCLabelBMFont::create(metadata.getVersion().toString().c_str(), "bigFont.fnt" ); - versionLabel->setAnchorPoint({ .0f, .5f }); versionLabel->setScale(.4f); - versionLabel->setPosition( - nameLabel->getPositionX() + nameLabel->getScaledContentSize().width + 5.f, - winSize.height / 2 + 125.f - ); versionLabel->setColor({0, 255, 0}); - m_mainLayer->addChild(versionLabel); + topNode->addChild(versionLabel); + + labelNode->updateLayout(); + topNode->updateLayout(); this->setTouchEnabled(true); From ac74e056cfb1367989b2bc3c3ed98813dc9bb547 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 18:46:14 +0300 Subject: [PATCH 017/135] fix blue view spacing --- loader/src/ui/internal/list/ModListCell.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index d98d9218d..95e903866 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -311,9 +311,6 @@ bool ModCell::init( auto viewSpr = ButtonSprite::create("View", "bigFont.fnt", "GJ_button_01.png", .8f); viewSpr->setScale(.65f); - auto viewBtn = CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ModCell::onInfo)); - m_menu->addChild(viewBtn); - if (m_mod->isEnabled()) { auto latestIndexItem = Index::get()->getMajorItem( mod->getMetadata().getID() @@ -335,6 +332,9 @@ bool ModCell::init( } } } + + auto viewBtn = CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ModCell::onInfo)); + m_menu->addChild(viewBtn); } this->updateState(); From f64c74a128f49b062b8eedab5bf3b8160e066802 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 19:46:26 +0300 Subject: [PATCH 018/135] Fix nested lists in md --- loader/src/ui/nodes/MDTextArea.cpp | 20 ++++++++++++++++++-- loader/src/ui/nodes/TextRenderer.cpp | 6 +++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index 051d5bcda..c6afcda20 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -209,6 +209,7 @@ struct MDParser { static float s_codeStart; static size_t s_orderedListNum; static std::vector s_codeSpans; + static bool s_breakListLine; static int parseText(MD_TEXTTYPE type, MD_CHAR const* rawText, MD_SIZE size, void* mdtextarea) { auto textarea = static_cast(mdtextarea); @@ -364,6 +365,10 @@ struct MDParser { renderer->pushIndent(g_indent); s_isOrderedList = type == MD_BLOCKTYPE::MD_BLOCK_OL; s_orderedListNum = 0; + if (s_breakListLine) { + renderer->breakLine(); + s_breakListLine = false; + } } break; @@ -377,6 +382,10 @@ struct MDParser { case MD_BLOCKTYPE::MD_BLOCK_LI: { + if (s_breakListLine) { + renderer->breakLine(); + s_breakListLine = false; + } renderer->pushOpacity(renderer->getCurrentOpacity() / 2); auto lidetail = static_cast(detail); if (s_isOrderedList) { @@ -387,6 +396,7 @@ struct MDParser { renderer->renderString("• "); } renderer->popOpacity(); + s_breakListLine = true; } break; @@ -446,7 +456,13 @@ struct MDParser { case MD_BLOCKTYPE::MD_BLOCK_UL: { renderer->popIndent(); - renderer->breakLine(); + if (s_breakListLine) { + renderer->breakLine(); + s_breakListLine = false; + } + if (renderer->getCurrentIndent() == 0) { + renderer->breakLine(); + } } break; @@ -489,7 +505,6 @@ struct MDParser { case MD_BLOCKTYPE::MD_BLOCK_LI: { - renderer->breakLine(); } break; @@ -626,6 +641,7 @@ size_t MDParser::s_orderedListNum = 0; bool MDParser::s_isCodeBlock = false; float MDParser::s_codeStart = 0; decltype(MDParser::s_codeSpans) MDParser::s_codeSpans = {}; +bool MDParser::s_breakListLine = false; void MDTextArea::updateLabel() { m_renderer->begin(m_content, CCPointZero, m_size); diff --git a/loader/src/ui/nodes/TextRenderer.cpp b/loader/src/ui/nodes/TextRenderer.cpp index fe2c712df..ca7396b38 100644 --- a/loader/src/ui/nodes/TextRenderer.cpp +++ b/loader/src/ui/nodes/TextRenderer.cpp @@ -341,8 +341,8 @@ std::vector TextRenderer::renderStringEx( auto lastIndent = m_indentationStack.size() > 1 ? m_indentationStack.at(m_indentationStack.size() - 1) : .0f; - if (m_cursor.x == m_origin.x + lastIndent && this->getCurrentIndent() > .0f) { - m_cursor.x += this->getCurrentIndent(); + if (m_cursor.x < m_origin.x + this->getCurrentIndent()) { + m_cursor.x = this->getCurrentIndent(); } auto createLabel = [&]() -> bool { @@ -487,7 +487,7 @@ void TextRenderer::breakLine(float incY) { } if (h > y) y = h; m_cursor.y -= y; - m_cursor.x = m_origin.x + getCurrentIndent(); + m_cursor.x = m_origin.x; } float TextRenderer::adjustLineAlignment() { From 71a79ab4dd59b419ada7516036e98296d47a96e3 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 21:07:53 +0300 Subject: [PATCH 019/135] add GEODE_HIDDEN to _spr --- loader/include/Geode/loader/Mod.hpp | 2 +- loader/src/loader/ModImpl.cpp | 6 +++--- loader/src/loader/ModImpl.hpp | 2 ++ 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/loader/include/Geode/loader/Mod.hpp b/loader/include/Geode/loader/Mod.hpp index a51af6b97..01f9380ad 100644 --- a/loader/include/Geode/loader/Mod.hpp +++ b/loader/include/Geode/loader/Mod.hpp @@ -412,6 +412,6 @@ namespace geode { }; } -inline char const* operator"" _spr(char const* str, size_t) { +GEODE_HIDDEN inline char const* operator"" _spr(char const* str, size_t) { return geode::Mod::get()->expandSpriteName(str); } diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 43a94026d..1f2a85737 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -592,14 +592,14 @@ ghc::filesystem::path Mod::Impl::getConfigDir(bool create) const { } char const* Mod::Impl::expandSpriteName(char const* name) { - static std::unordered_map expanded = {}; - if (expanded.count(name)) return expanded[name]; + log::debug("Expanding sprite name {} for {}", name, m_metadata.getID()); + if (m_expandedSprites.count(name)) return m_expandedSprites[name]; auto exp = new char[strlen(name) + 2 + m_metadata.getID().size()]; auto exps = m_metadata.getID() + "/" + name; memcpy(exp, exps.c_str(), exps.size() + 1); - expanded[name] = exp; + m_expandedSprites[name] = exp; return exp; } diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index ff5084d61..55e5c88d0 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -61,6 +61,8 @@ namespace geode { */ bool m_loggingEnabled = true; + std::unordered_map m_expandedSprites; + ModRequestedAction m_requestedAction = ModRequestedAction::None; From 26a6c7e96d2df0c80656932b0a7c994239a9ca1d Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 12 Sep 2023 22:11:16 +0300 Subject: [PATCH 020/135] fix too big mod icons :fire: --- loader/src/ui/internal/GeodeUI.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp index 5bc6705a9..99d936b27 100644 --- a/loader/src/ui/internal/GeodeUI.cpp +++ b/loader/src/ui/internal/GeodeUI.cpp @@ -68,7 +68,7 @@ CCNode* geode::createDefaultLogo(CCSize const& size) { if (!spr) { spr = CCLabelBMFont::create("OwO", "goldFont.fnt"); } - limitNodeSize(spr, size, 1.f, .1f); + limitNodeSize(spr, size, 1.f, .01f); return spr; } @@ -78,7 +78,7 @@ CCNode* geode::createModLogo(Mod* mod, CCSize const& size) { CCSprite::create(fmt::format("{}/logo.png", mod->getID()).c_str()); if (!spr) spr = CCSprite::createWithSpriteFrameName("no-logo.png"_spr); if (!spr) spr = CCLabelBMFont::create("N/A", "goldFont.fnt"); - limitNodeSize(spr, size, 1.f, .1f); + limitNodeSize(spr, size, 1.f, .01f); spr->setPosition(size/2); spr->setAnchorPoint({.5f, .5f}); @@ -116,7 +116,7 @@ CCNode* geode::createIndexItemLogo(IndexItemHandle item, CCSize const& size) { spr = logoGlow; } else { - limitNodeSize(spr, size, 1.f, .1f); + limitNodeSize(spr, size, 1.f, .01f); } spr->setPosition(size/2); spr->setAnchorPoint({.5f, .5f}); From 46e4cdb3b1cd1377c237c168cb9764fd727ae631 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:43:55 +0300 Subject: [PATCH 021/135] Compiles until linking --- CMakeLists.txt | 2 +- bindings/Cocos2d.bro | 194 ++++++++--------- bindings/GeometryDash.bro | 264 +++++++++++++++++++++++- codegen/src/BindingGen.cpp | 4 +- loader/src/platform/android/ModImpl.cpp | 3 +- 5 files changed, 365 insertions(+), 102 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 99b5201fc..f8e9e9288 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#3423a29") +CPMAddPackage("gh:geode-sdk/TulipHook#9f1938f") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index 632ce503b..00844294a 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -1,11 +1,11 @@ // clang-format off -[[link(win)]] +[[link(win, android)]] class cocos2d::CCActionTween { static cocos2d::CCActionTween* create(float, char const*, float, float) = mac 0x447590; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCActionManager { CCActionManager() { m_pTargets = nullptr; @@ -21,17 +21,17 @@ class cocos2d::CCActionManager { auto resumeTarget(cocos2d::CCObject*) = mac 0x10bd20; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCAnimate { static cocos2d::CCAnimate* create(cocos2d::CCAnimation*) = mac 0x1f8fc0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCAnimation { static auto createWithSpriteFrames(cocos2d::CCArray*, float) = mac 0x140df0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCApplication { virtual auto run(); virtual auto getCurrentLanguage() = mac 0x1a3f40, ios 0x10e508; @@ -39,13 +39,15 @@ class cocos2d::CCApplication { virtual auto openURL(char const*) = mac 0x1a4550, ios 0x10e7a4; virtual auto setAnimationInterval(double) = mac 0x1a3ee0, ios 0x10e494; static auto sharedApplication() = mac 0x1a3f30; + + [[link(win)]] bool getControllerConnected() const = mac 0x27d1b0; // ~CCApplication() = mac 0x1a3d10, ios 0x10e384; CCApplication() {} ~CCApplication() {} } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCArray { // auto addObject(cocos2d::CCObject*) = mac 0x419f90, ios 0x16504c; auto addObjectNew(cocos2d::CCObject*) = mac 0x41a450; @@ -67,27 +69,27 @@ class cocos2d::CCArray { // auto stringAtIndex(unsigned int) = mac 0x41a320; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCBezierTo { static cocos2d::CCBezierTo* create(float, cocos2d::_ccBezierConfig const&) = mac 0x1f6c10; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCBMFontConfiguration { static cocos2d::CCBMFontConfiguration* create(char const*) = mac 0x3450f0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCCallFunc { static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFunc) = mac 0x454d90; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCCallFuncO { static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFuncO, cocos2d::CCObject*) = mac 0x455940; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCClippingNode { CCClippingNode() { m_pStencil = nullptr; @@ -121,12 +123,12 @@ class cocos2d::CCClippingNode { // void updateConnected() = win 0xc7fb0; //} -[[link(win)]] +[[link(win, android)]] class cocos2d::CCDelayTime { static cocos2d::CCDelayTime* create(float) = mac 0x1f4380; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCDictionary { auto allKeys() = mac 0x190450, ios 0x2de774; auto count() = mac 0x190430; @@ -142,7 +144,7 @@ class cocos2d::CCDictionary { auto valueForKey(gd::string const&) = mac 0x1907a0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCDirector { CCDirector() {} ~CCDirector() {} @@ -185,7 +187,7 @@ class cocos2d::CCDirector { auto popSceneWithTransition(float, cocos2d::PopTransition) = mac 0x24a8b0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCDrawNode { CCDrawNode() = mac 0x378b40, win 0x6b9f0; auto clear() = mac 0x379e80; @@ -201,7 +203,7 @@ class cocos2d::CCDrawNode { virtual ~CCDrawNode() = mac 0x378cc0, win 0x6ba60; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCAction { CCAction() = mac 0x35b610, win 0x7a6d0; virtual ~CCAction() = mac 0x35b6b0, win 0x7a7f0; @@ -213,13 +215,13 @@ class cocos2d::CCAction { auto update(float time) = mac 0x35b890; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCFiniteTimeAction { // same as CCActionInterval::reverse i think auto reverse() = mac 0x1f2720; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCActionInterval { auto copyWithZone(cocos2d::CCZone* zone) = mac 0x1f2550; auto isDone() = mac 0x1f2640; @@ -229,32 +231,32 @@ class cocos2d::CCActionInterval { bool initWithDuration(float d) = mac 0x1f2510; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEaseBackIn { static cocos2d::CCEaseBackIn* create(cocos2d::CCActionInterval*) = mac 0x2a41b0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEaseElasticIn { static cocos2d::CCEaseElasticIn* create(cocos2d::CCActionInterval*, float) = mac 0x2a2e00; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEaseElasticOut { static cocos2d::CCEaseElasticOut* create(cocos2d::CCActionInterval*, float) = mac 0x2a3080; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEaseIn { static cocos2d::CCEaseIn* create(cocos2d::CCActionInterval*, float) = mac 0x2a1960; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEaseInOut { static cocos2d::CCEaseInOut* create(cocos2d::CCActionInterval*, float) = mac 0x2a1d80; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEaseOut { static cocos2d::CCEaseOut* create(cocos2d::CCActionInterval*, float) = mac 0x2a1b70; } @@ -283,7 +285,7 @@ class cocos2d::CCEGLView { void onGLFWWindowSizeFunCallback(GLFWwindow* window, int width, int height); } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCEGLViewProtocol { CCEGLViewProtocol() = win 0xbac00; virtual ~CCEGLViewProtocol() = win 0xbacc0; @@ -294,17 +296,17 @@ class cocos2d::CCEGLViewProtocol { virtual void setFrameSize(float, float) = mac 0x29d960; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCFadeOut { static cocos2d::CCFadeOut* create(float) = mac 0x1f7d80; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCFadeTo { static cocos2d::CCFadeTo* create(float, unsigned char) = mac 0x1f7ff0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCFileUtils : cocos2d::TypeInfo { static cocos2d::CCFileUtils* sharedFileUtils() = mac 0x377030, ios 0x159450; static void purgeFileUtils(); @@ -314,19 +316,19 @@ class cocos2d::CCFileUtils : cocos2d::TypeInfo { void removeAllPaths() = mac 0x241600; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCGLProgram { auto setUniformsForBuiltins() = mac 0x232c70; auto use() = mac 0x231d70; bool compileShader(unsigned int* shader, unsigned int type, const char* source) = mac 0x231a30; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCHide { static cocos2d::CCHide* create() = mac 0x4543e0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCIMEDelegate { ~CCIMEDelegate() { CCIMEDispatcher::sharedDispatcher()->removeDelegate(this); @@ -338,7 +340,7 @@ class cocos2d::CCIMEDelegate { } } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCIMEDispatcher { static auto sharedDispatcher() = mac 0x2773f0, ios 0x12d170; auto addDelegate(cocos2d::CCIMEDelegate*) = mac 0x277480, ios 0x12d204; @@ -347,7 +349,7 @@ class cocos2d::CCIMEDispatcher { void dispatchDeleteBackward() = mac 0x277af0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCImage { CCImage() = mac 0x24fa00, win 0xc5fd0; virtual ~CCImage() = mac 0x24fa80, win 0xc6100; @@ -356,20 +358,20 @@ class cocos2d::CCImage { auto initWithImageData(void*, int, cocos2d::CCImage::EImageFormat, int, int, int) = mac 0x24fcb0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCKeyboardDispatcher { bool dispatchKeyboardMSG(cocos2d::enumKeyCodes, bool) = mac 0xe8190; const char* keyToString(cocos2d::enumKeyCodes) = mac 0xe8450; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCKeyboardHandler { static cocos2d::CCKeyboardHandler* handlerWithDelegate(cocos2d::CCKeyboardDelegate*) = mac 0x242030; virtual auto initWithDelegate(cocos2d::CCKeyboardDelegate*) = mac 0x241ff0, ios 0x13f8b8; ~CCKeyboardHandler() = mac 0x241e90, ios 0x13f87c, win 0x99a10; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCKeypadHandler { static cocos2d::CCKeypadHandler* handlerWithDelegate(cocos2d::CCKeypadDelegate*) = mac 0x1ff2d0; virtual auto initWithDelegate(cocos2d::CCKeypadDelegate*) = mac 0x1ff290, ios 0x69; // iOS stub @@ -378,7 +380,7 @@ class cocos2d::CCKeypadHandler { } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCLabelBMFont { static cocos2d::CCLabelBMFont* create(char const*, char const*) = mac 0x347660; auto limitLabelWidth(float, float, float) = mac 0x34a6e0, ios 0x21b740; @@ -418,7 +420,7 @@ class cocos2d::CCLabelBMFont { virtual ~CCLabelBMFont() = mac 0x347e80, win 0x9be70; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCLabelTTF { static cocos2d::CCLabelTTF* create() = mac 0x1fa7e0; static cocos2d::CCLabelTTF* create(char const*, char const*, float) = mac 0x1fa840; @@ -426,7 +428,7 @@ class cocos2d::CCLabelTTF { virtual auto setString(char const*) = mac 0x1fad70; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCLayer { CCLayer() = mac 0x2725b0, ios 0xc7708, win 0xa15e0; virtual auto ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x2734d0, ios 0xc810c; @@ -467,7 +469,7 @@ class cocos2d::CCLayer { virtual ~CCLayer() = mac 0x2727b0, ios 0xc7848, win 0xa1940; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCLayerColor { CCLayerColor() = mac 0x274320, ios 0xc8aec, win 0xa1710; static cocos2d::CCLayerColor* create(cocos2d::_ccColor4B const&, float, float) = mac 0x2745e0; @@ -485,7 +487,7 @@ class cocos2d::CCLayerColor { virtual ~CCLayerColor() = mac 0x2743d0, ios 0x2743e0, win 0xa1a20; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCLayerRGBA { CCLayerRGBA() = mac 0x2738d0, ios 0xc85cc, win 0xa1890; virtual auto init() = mac 0x273b40, ios 0xc8de8; @@ -506,7 +508,7 @@ class cocos2d::CCLayerRGBA { virtual ~CCLayerRGBA() = mac 0x273aa0, ios 0xc77b0, win 0xa1b20; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMenu { auto alignItemsHorizontallyWithPadding(float) = mac 0x4393e0, ios 0x132508; auto alignItemsVerticallyWithPadding(float) = mac 0x439190; @@ -530,7 +532,7 @@ class cocos2d::CCMenu { cocos2d::CCMenuItem* itemForTouch(cocos2d::CCTouch*) = mac 0x438dd0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMenuItem { bool initWithTarget(cocos2d::CCObject*, cocos2d::SEL_MenuHandler) = mac 0x1fb7f0; virtual ~CCMenuItem() = mac 0x1fb8e0, ios 0x2cdf4, win 0xab9c0; @@ -546,13 +548,13 @@ class cocos2d::CCMenuItem { auto rect() = mac 0x1fbb00, ios 0x2cf3c; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMenuItemImage { // virtual ~CCMenuItemImage() = mac 0x1febb0; virtual auto init() = mac 0x1fd750; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMenuItemLabel { virtual ~CCMenuItemLabel() = mac 0x1fc0d0; virtual auto activate() = mac 0x1fc240; @@ -565,7 +567,7 @@ class cocos2d::CCMenuItemLabel { virtual auto setLabel(cocos2d::CCNode*) = mac 0x1fbbc0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMenuItemSprite { // virtual ~CCMenuItemSprite() = mac 0x1feab0; virtual auto selected() = mac 0x1fd3f0, ios 0x2d2cc; @@ -585,7 +587,7 @@ class cocos2d::CCMenuItemSprite { static auto create(cocos2d::CCNode*, cocos2d::CCNode*, cocos2d::CCObject*, cocos2d::SEL_MenuHandler) = mac 0x1fd2d0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMotionStreak { CCMotionStreak() = win 0xae310; virtual ~CCMotionStreak() = win 0xae450; @@ -596,30 +598,30 @@ class cocos2d::CCMotionStreak { virtual auto draw(); } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMouseDispatcher { bool dispatchScrollMSG(float x, float y) = mac 0x2e8f40; void removeDelegate(cocos2d::CCMouseDelegate* delegate); } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMouseHandler { static cocos2d::CCMouseHandler* handlerWithDelegate(cocos2d::CCMouseDelegate*) = mac 0x12ef80; virtual auto initWithDelegate(cocos2d::CCMouseDelegate*) = mac 0x12ef40, ios 0x43798; ~CCMouseHandler() = mac 0x12ede0, ios 0x4375c, win 0xb1fd0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMoveBy { static cocos2d::CCMoveBy* create(float, cocos2d::CCPoint const&) = mac 0x1f50e0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCMoveTo { static cocos2d::CCMoveTo* create(float, cocos2d::CCPoint const&) = mac 0x1f54d0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCNode { CCNode() = mac 0x122550, win 0x5e7d0; auto boundingBox() = mac 0x123030; @@ -739,7 +741,7 @@ class cocos2d::CCNode { virtual ~CCNode() = mac 0x122750, ios 0x6c98, win 0x5ea40; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCNodeRGBA { CCNodeRGBA() = mac 0x124b30, win 0x5e9d0; virtual ~CCNodeRGBA() = mac 0x124bb0, ios 0x15f748, win 0x5ebb0; @@ -758,7 +760,7 @@ class cocos2d::CCNodeRGBA { virtual auto setCascadeColorEnabled(bool) = mac 0x125340, ios 0x15fb80; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCObject { CCObject() = mac 0x250ca0, ios 0x43864, win 0x69230; auto acceptVisitor(cocos2d::CCDataVisitor&) = mac 0x250f30, ios 0x439f0; @@ -774,7 +776,7 @@ class cocos2d::CCObject { ~CCObject() = mac 0x250d20, ios 0x6ac0, win 0x69270; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCParticleSystem { CCParticleSystem() = win 0xb6650; virtual ~CCParticleSystem() = win 0xb68e0; @@ -785,7 +787,7 @@ class cocos2d::CCParticleSystem { auto stopSystem() = mac 0x46bd10; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCParticleSystemQuad { CCParticleSystemQuad() = win 0xb9bd0; virtual ~CCParticleSystemQuad() = win 0xb9c10; @@ -794,18 +796,18 @@ class cocos2d::CCParticleSystemQuad { auto setupVBO(); } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCPoolManager { auto pop() = mac 0x214620; static cocos2d::CCPoolManager* sharedPoolManager() = mac 0x2142c0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCRemoveSelf { static cocos2d::CCRemoveSelf* create(bool) = mac 0x454700; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCRenderTexture { auto begin() = mac 0x35ce10; auto end() = mac 0x35d2c0; @@ -815,45 +817,45 @@ class cocos2d::CCRenderTexture { auto beginWithClear(float r, float g, float b, float a) = mac 0x35d010; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCRepeat { static cocos2d::CCRepeat* create(cocos2d::CCFiniteTimeAction*, unsigned int) = mac 0x1f3230; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCRepeatForever { static cocos2d::CCRepeatForever* create(cocos2d::CCActionInterval*) = mac 0x1f3920; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCRotateBy { static cocos2d::CCRotateBy* create(float, float) = mac 0x1f4c50; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCRotateTo { static cocos2d::CCRotateTo* create(float, float) = mac 0x1f47b0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCScaleTo { static cocos2d::CCScaleTo* create(float, float) = mac 0x1f6ff0; static cocos2d::CCScaleTo* create(float, float, float) = mac 0x1f70f0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCScaleBy { static cocos2d::CCScaleTo* create(float, float) = mac 0x1f73c0; static cocos2d::CCScaleTo* create(float, float, float) = mac 0x1f7480; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCScene { static cocos2d::CCScene* create() = mac 0x13c140, ios 0x163070; auto getHighestChildZ() = mac 0x13c200, ios 0x1630e4; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCScheduler { auto scheduleSelector(cocos2d::SEL_SCHEDULE, cocos2d::CCObject*, float, unsigned int, float, bool) = mac 0x242b20; void scheduleSelector(cocos2d::SEL_SCHEDULE selector, cocos2d::CCObject* target, float interval, bool paused) { @@ -868,12 +870,12 @@ class cocos2d::CCScheduler { virtual void update(float delta) = mac 0x2446d0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCSequence { static auto createWithVariableList(cocos2d::CCFiniteTimeAction*, va_list) = mac 0x1f2910; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCSet { CCSet() = mac 0x45ad80, ios 0x10e870, win 0x699e0; static auto create() = mac 0x45b0b0; @@ -888,14 +890,14 @@ class cocos2d::CCSet { } } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCShaderCache { static auto sharedShaderCache() = mac 0xe6d10; auto programForKey(const char*) = mac 0xe7d40; void reloadDefaultShaders(); } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCSprite { virtual ~CCSprite() = mac 0x133430, ios 0x15b92c, win 0xd2f90; virtual auto init() = mac 0x132ef0, ios 0x15b488; @@ -970,7 +972,7 @@ class cocos2d::CCSprite { void setFlipY(bool) = mac 0x134c30; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCSpriteBatchNode { static cocos2d::CCSpriteBatchNode* create(char const*, unsigned int) = mac 0xbb540; static auto createWithTexture(cocos2d::CCTexture2D*, unsigned int) = mac 0xbb310; @@ -995,28 +997,28 @@ class cocos2d::CCSpriteBatchNode { virtual auto getBlendFunc() = mac 0xbcd50, ios 0x131a60; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCSpriteFrame { static auto createWithTexture(cocos2d::CCTexture2D*, cocos2d::CCRect const&, bool, cocos2d::CCPoint const&, cocos2d::CCSize const&) = mac 0x1ac7f0; static auto createWithTexture(cocos2d::CCTexture2D*, cocos2d::CCRect const&) = mac 0x1ac5c0; auto getTexture() = mac 0x1ad250; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCSpriteFrameCache { auto addSpriteFramesWithFile(char const*) = mac 0x199a10, ios 0x29e818; static cocos2d::CCSpriteFrameCache* sharedSpriteFrameCache() = mac 0x198970, ios 0x29dc4c; auto spriteFrameByName(char const*) = mac 0x19a7e0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCStandardTouchHandler { static cocos2d::CCStandardTouchHandler* handlerWithDelegate(cocos2d::CCTouchDelegate*, int) = mac 0x247f30; virtual auto initWithDelegate(cocos2d::CCTouchDelegate*, int) = mac 0x247ed0, ios 0x69; // iOS stub ~CCStandardTouchHandler() = mac 0x2482a0, ios 0x6d28, win 0xf5a40; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCString { // virtual ~CCString() = mac 0x44c590; virtual auto isEqual(cocos2d::CCObject const*) = mac 0x44c8f0, ios 0x1a1e6c; @@ -1032,7 +1034,7 @@ class cocos2d::CCString { auto intValue() const = mac 0x44c780, ios 0x1a1ca8; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTargetedTouchHandler { static cocos2d::CCTargetedTouchHandler* handlerWithDelegate(cocos2d::CCTouchDelegate*, int, bool) = mac 0x248010; auto initWithDelegate(cocos2d::CCTouchDelegate*, int, bool) = mac 0x2480f0, ios 0x69; // iOS stub @@ -1040,7 +1042,7 @@ class cocos2d::CCTargetedTouchHandler { } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTexture2D { CCTexture2D() = mac 0x246280, win 0xe9300; ~CCTexture2D() = mac 0x246350, win 0xe93f0; @@ -1065,7 +1067,7 @@ class cocos2d::CCTexture2D { auto setTexParameters(cocos2d::_ccTexParams*) = mac 0x247980; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTextureAtlas { CCTextureAtlas() = win 0xea680; virtual ~CCTextureAtlas() = win 0xea6c0; @@ -1073,12 +1075,12 @@ class cocos2d::CCTextureAtlas { auto mapBuffers(); } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTextFieldTTF { static auto textFieldWithPlaceHolder(char const*, char const*, float) = mac 0x126220; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTextureCache { auto addImage(char const*, bool) = mac 0x358120, ios 0xa8388; auto textureForKey(char const*) = mac 0x359050; @@ -1086,17 +1088,17 @@ class cocos2d::CCTextureCache { static cocos2d::CCTextureCache* sharedTextureCache() = mac 0x356e00, ios 0xa81ec; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTime { static auto gettimeofdayCocos2d(cocos2d::cc_timeval*, void*) = mac 0x19eac0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTintTo { static cocos2d::CCTintTo* create(float, unsigned char, unsigned char, unsigned char) = mac 0x1f82a0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTouch { auto getDelta() const = mac 0x38340; auto getLocationInView() const = mac 0x38250; @@ -1106,7 +1108,7 @@ class cocos2d::CCTouch { auto getStartLocation() const = mac 0x38310; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTouchDispatcher { auto addTargetedDelegate(cocos2d::CCTouchDelegate*, int, bool) = mac 0x281180; auto addStandardDelegate(cocos2d::CCTouchDelegate*, int) = mac 0x281060; @@ -1116,7 +1118,7 @@ class cocos2d::CCTouchDispatcher { void touches(cocos2d::CCSet*, cocos2d::CCEvent*, unsigned int) = mac 0x281a60; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTouchHandler { virtual auto initWithDelegate(cocos2d::CCTouchDelegate*, int) = mac 0x247d10, ios 0x69f8; auto getPriority() = mac 0x247c20; @@ -1126,19 +1128,19 @@ class cocos2d::CCTouchHandler { ~CCTouchHandler() = mac 0x247de0, ios 0x6ac0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::CCTransitionFade { static cocos2d::CCTransitionFade* create(float, cocos2d::CCScene*) = mac 0x8ea30, ios 0x12c244; } -[[link(win)]] +[[link(win, android)]] class cocos2d::ZipUtils { static auto compressString(gd::string, bool, int) = mac 0xe9a50; static auto decompressString(gd::string, bool, int) = mac 0xea380; static int ccDeflateMemory(unsigned char*, unsigned int, unsigned char**) = mac 0xe9cf0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::extension::CCControl { CCControl() {} virtual bool init() = mac 0x1a71c0; @@ -1162,7 +1164,7 @@ class cocos2d::extension::CCControl { auto isSelected() = mac 0x1a7ec0; } -[[link(win)]] +[[link(win, android)]] class cocos2d::extension::CCControlColourPicker { CCControlColourPicker() {} ~CCControlColourPicker() = mac 0x1aae30; @@ -1176,13 +1178,13 @@ class cocos2d::extension::CCControlColourPicker { } -[[link(win)]] +[[link(win, android)]] class cocos2d::extension::CCControlUtils { static cocos2d::extension::HSV HSVfromRGB(cocos2d::extension::RGBA) = mac 0x1e6750; static cocos2d::extension::RGBA RGBfromHSV(cocos2d::extension::HSV) = mac 0x1e6850; } -[[link(win)]] +[[link(win, android)]] class cocos2d::extension::CCScale9Sprite { CCScale9Sprite() = mac 0x211330; static cocos2d::extension::CCScale9Sprite* create(char const*) = mac 0x2130d0; @@ -1228,7 +1230,7 @@ class cocos2d::extension::CCScale9Sprite { virtual auto setSpriteFrame(cocos2d::CCSpriteFrame*) = mac 0x213a90; } -[[link(win)]] +[[link(win, android)]] class cocos2d::extension::CCScrollView { CCScrollView() = mac 0x214800; virtual ~CCScrollView() = mac 0x214c30; @@ -1247,7 +1249,7 @@ class cocos2d::extension::CCScrollView { virtual auto setTouchEnabled(bool) = mac 0x215250; } -[[link(win)]] +[[link(win, android)]] class cocos2d { static auto FNTConfigLoadFile(char const*) = mac 0x344f10; static auto ccGLUseProgram(GLuint) = mac 0x1ae540; @@ -1261,7 +1263,7 @@ class cocos2d { static void CCMessageBox(const char* msg, const char* title) = mac 0xbabc0; } -[[link(win)]] +[[link(win, android)]] class DS_Dictionary { DS_Dictionary() = mac 0xbe9a0; ~DS_Dictionary() = mac 0x393c30; @@ -1274,7 +1276,7 @@ class DS_Dictionary { auto getObjectForKey(char const*) = mac 0xC4BB0; } -[[link(win)]] +[[link(win, android)]] class pugi::xml_document { xml_document() = mac 0x393a80; ~xml_document() = mac 0x393b50; diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index ab336f385..cda687a4d 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -18,18 +18,21 @@ class GDString { void testFunction(int a) = mac 0x100000; +[[link(android)]] class AchievementBar : cocos2d::CCNodeRGBA { static AchievementBar* create(const char* title, const char* desc, const char* icon, bool quest) = mac 0x379f80, win 0x3b120, ios 0x1a4784; PAD = win 0x24; } +[[link(android)]] class AchievementCell : cocos2d::CCLayer { void loadFromDict(cocos2d::CCDictionary*) = mac 0x10eaa0, win 0x59010; virtual bool init() = win 0x11070; } +[[link(android)]] class AchievementManager : cocos2d::CCNode { void getAllAchievements() = mac 0x434d60; static AchievementManager* sharedState() = mac 0x424420, win 0x7b10; @@ -40,6 +43,7 @@ class AchievementManager : cocos2d::CCNode { } +[[link(android)]] class AchievementNotifier : cocos2d::CCNode { void notifyAchievement(const char* title, const char* desc, const char* icon, bool quest) { m_queue->addObject(AchievementBar::create(title, desc, icon, quest)); @@ -57,16 +61,19 @@ class AchievementNotifier : cocos2d::CCNode { AchievementBar* m_currentAchievement; } +[[link(android)]] class AchievementsLayer : GJDropDownLayer { void customSetup() = mac 0x1bdea0, win 0x3c2f0; void loadPage(int) = mac 0x1be190, win 0x3c600; } +[[link(android)]] class AnimatedGameObject : GameObject, AnimatedSpriteDelegate, SpritePartDelegate { void playAnimation(int) = mac 0xc93d0, win 0x2539e0; void updateChildSpriteColor(cocos2d::_ccColor3B) = mac 0xc8450, win 0x2531f0; } +[[link(android)]] class AnimatedShopKeeper : CCAnimatedSprite { void animationFinished(const char*) {} @@ -78,10 +85,12 @@ class AnimatedShopKeeper : CCAnimatedSprite { bool m_unknown; } +[[link(android)]] class AnimatedSpriteDelegate { virtual void animationFinished(const char*) {} } +[[link(android)]] class AppDelegate : cocos2d::CCApplication, cocos2d::CCSceneDelegate { void bgScale() = mac 0x3aaab0; virtual bool applicationDidFinishLaunching() = mac 0x3aa900, win 0x3cbb0; @@ -109,6 +118,7 @@ class AppDelegate : cocos2d::CCApplication, cocos2d::CCSceneDelegate { bool m_unk4; } +[[link(android)]] class ArtistCell : TableViewCell { virtual void draw() = mac 0x11c980, win 0x59d40; // same as StatsCell virtual bool init() = mac 0x11c7c0, win 0x11250; @@ -119,6 +129,7 @@ class ArtistCell : TableViewCell { void* m_idk; } +[[link(android)]] class AudioEffectsLayer : cocos2d::CCLayerColor { void audioStep(float) = mac 0x271f40, win 0x3daa0; static AudioEffectsLayer* create(gd::string) = mac 0x271a00, win 0x3d850; @@ -136,6 +147,7 @@ class AudioEffectsLayer : cocos2d::CCLayerColor { bool m_unk1B4; } +[[link(android)]] class BoomListView : cocos2d::CCLayer, TableViewDelegate, TableViewDataSource { BoomListView() {} ~BoomListView() { @@ -170,6 +182,7 @@ class BoomListView : cocos2d::CCLayer, TableViewDelegate, TableViewDataSource { int m_currentPage; } +[[link(android)]] class BoomScrollLayer : cocos2d::CCLayer { BoomScrollLayer() = mac 0x1e42f0, win 0x11510; void instantMoveToPage(int page) = win 0x12330; @@ -182,6 +195,7 @@ class BoomScrollLayer : cocos2d::CCLayer { int m_page; } +[[link(android)]] class ButtonSprite : cocos2d::CCSprite { static ButtonSprite* create( const char* caption, @@ -265,6 +279,7 @@ class ButtonSprite : cocos2d::CCSprite { cocos2d::CCPoint m_spritePosition; } +[[link(android)]] class CCAnimatedSprite : cocos2d::CCSprite { void runAnimation(gd::string) = mac 0x1a6430, win 0x14f60; void tweenToAnimation(gd::string, float) = mac 0x1a65b0, win 0x15080; @@ -277,11 +292,13 @@ class CCAnimatedSprite : cocos2d::CCSprite { PAD = win 0x4; } +[[link(android)]] class CCAnimateFrameCache : cocos2d::CCObject { static CCAnimateFrameCache* sharedSpriteFrameCache() = mac 0x2e4df0, win 0x158f0; void addSpriteFramesWithFile(const char* file) = win 0x159b0; } +[[link(android)]] class CCBlockLayer : cocos2d::CCLayerColor { inline CCBlockLayer() {} virtual bool init() = mac 0x2a59c0, win 0x168d0; @@ -301,6 +318,7 @@ class CCBlockLayer : cocos2d::CCLayerColor { bool m_unknown2; } +[[link(android)]] class CCCircleWave : cocos2d::CCNode { static CCCircleWave* create(float, float, float, bool) = mac 0xbd270; static CCCircleWave* create(float, float, float, bool, bool) = mac 0xbd290, win 0x16c00; @@ -324,16 +342,19 @@ class CCCircleWave : cocos2d::CCNode { bool m_blendFuncDirty; } +[[link(android)]] class CCCircleWaveDelegate { virtual void circleWaveWillBeRemoved(CCCircleWave* wave) {} } +[[link(android)]] class CCContentLayer : cocos2d::CCLayerColor { inline CCContentLayer() {} static CCContentLayer* create(cocos2d::ccColor4B const& color, float width, float height) = win 0x172a0; virtual void setPosition(cocos2d::CCPoint const& pos) = mac 0x464c60, win 0x17400; } +[[link(android)]] class CCIndexPath : cocos2d::CCObject { static CCIndexPath* CCIndexPathWithSectionRow(int idk1, int idk2) = win 0x30e40; inline CCIndexPath() = default; @@ -341,11 +362,13 @@ class CCIndexPath : cocos2d::CCObject { int m_unknown2; } +[[link(android)]] class CCLightFlash { static CCLightFlash* create() = mac 0x295870, win 0x17920; void playEffect(cocos2d::CCPoint, cocos2d::_ccColor3B, float, float, float, float, float, float, float, float, float, float, float, float, float, float, int, bool, bool, float) = mac 0x295900, win 0x179f0; } +[[link(android)]] class CCMenuItemSpriteExtra : cocos2d::CCMenuItemSprite { void useAnimationType(MenuAnimationType type) { m_startPosition = this->getNormalImage()->getPosition(); @@ -407,6 +430,7 @@ class CCMenuItemSpriteExtra : cocos2d::CCMenuItemSprite { cocos2d::CCPoint m_startPosition; } +[[link(android)]] class CCMenuItemToggler : cocos2d::CCMenuItem { inline CCMenuItemToggler() : CCMenuItem(), m_onButton(nullptr), m_offButton(nullptr), m_toggled(false), m_notClickable(false) {} @@ -457,6 +481,7 @@ class CCMenuItemToggler : cocos2d::CCMenuItem { bool m_notClickable; } +[[link(android)]] class CCMoveCNode : cocos2d::CCNode { static CCMoveCNode* create() = mac 0x1842a0, win 0x121c70; ~CCMoveCNode() = mac 0x18b2c0; @@ -481,6 +506,7 @@ class CCMoveCNode : cocos2d::CCNode { GroupCommandObject* m_followCommand; } +[[link(android)]] class GroupCommandObject : cocos2d::CCNode { // too lazy to re rn // the ints are definitely real members but idk their types @@ -519,12 +545,14 @@ class GroupCommandObject : cocos2d::CCNode { bool m_184; } +[[link(android)]] class CCNodeContainer : cocos2d::CCNode { static CCNodeContainer* create() = mac 0xb1090, win 0x112370; virtual bool init() = mac 0xba950, win 0x33b40; void visit() = mac 0xba960, win 0x112420; } +[[link(android)]] class CCScrollLayerExt : cocos2d::CCLayer { inline CCScrollLayerExt() {} @@ -588,6 +616,7 @@ class CCScrollLayerExt : cocos2d::CCLayer { float m_peekLimitBottom; } +[[link(android)]] class CCScrollLayerExtDelegate { virtual void scrllViewWillBeginDecelerating(CCScrollLayerExt*) {} virtual void scrollViewDidEndDecelerating(CCScrollLayerExt*) {} @@ -597,10 +626,12 @@ class CCScrollLayerExtDelegate { virtual void scrollViewTouchEnd(CCScrollLayerExt*) {} } +[[link(android)]] class CCSpritePart : CCSpritePlus { } +[[link(android)]] class CCSpritePlus : cocos2d::CCSprite { virtual bool initWithSpriteFrameName(const char*) = mac 0x248670, win 0x1c1e0; virtual void setScaleX(float scale) = win 0x1c440; @@ -620,6 +651,7 @@ class CCSpritePlus : cocos2d::CCSprite { bool m_propagateFlipChanges; } +[[link(android)]] class CCTextInputNode : cocos2d::CCLayer, cocos2d::CCIMEDelegate, cocos2d::CCTextFieldDelegate { inline CCTextInputNode() : cocos2d::CCLayer(), cocos2d::CCIMEDelegate(), cocos2d::CCTextFieldDelegate(), m_caption(), m_allowedChars() { m_numberInput = false; @@ -735,10 +767,12 @@ class CCTextInputNode : cocos2d::CCLayer, cocos2d::CCIMEDelegate, cocos2d::CCTex bool m_forceOffset; } +[[link(android)]] class ChallengesPage { static ChallengesPage* create() = mac 0x1db350, win 0x3e050; } +[[link(android)]] class CheckpointObject : cocos2d::CCNode { static CheckpointObject* create() = mac 0x7e7d0, win 0x20DDD0; void getObject() = mac 0x7ef50; @@ -757,15 +791,18 @@ class CheckpointObject : cocos2d::CCNode { gd::string m_objectsStateString; } +[[link(android)]] class CollisionBlockPopup { static CollisionBlockPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x130010; void onNextItemID(cocos2d::CCObject*) = mac 0x130e60; } +[[link(android)]] class CollisionTriggerAction : cocos2d::CCNode { static CollisionTriggerAction* createFromString(gd::string) = mac 0x176ee0; } +[[link(android)]] class ColorAction : cocos2d::CCNode { static ColorAction* create() = mac 0x17c990, win 0x11ab10; static ColorAction* create(cocos2d::ccColor3B, cocos2d::ccColor3B, float, double, bool, int, float, float) = win 0x11ab60, mac 0x17cab0; @@ -793,12 +830,14 @@ class ColorAction : cocos2d::CCNode { PAD = mac 0x10; } +[[link(android)]] class ColorActionSprite : cocos2d::CCNode { float m_opacity; cocos2d::_ccColor3B m_f0124; cocos2d::_ccColor3B m_activeColor; } +[[link(android)]] class ColorChannelSprite : cocos2d::CCSprite { void updateBlending(bool) = mac 0x16e1d0, win 0x114710; void updateCopyLabel(int, bool) = mac 0x16ded0, win 0x114440; @@ -811,10 +850,12 @@ class ColorChannelSprite : cocos2d::CCSprite { cocos2d::CCLabelBMFont* m_blendingDot; } +[[link(android)]] class ColorSelectDelegate { virtual void colorSelectClosed(cocos2d::CCNode*) {} } +[[link(android)]] class ColorSelectLiveOverlay : FLAlertLayer { bool init(ColorAction*, ColorAction*, EffectGameObject*) = mac 0x2e2790, win 0x41db0; void sliderChanged(cocos2d::CCObject*) = mac 0x2e3830; @@ -828,6 +869,7 @@ class ColorSelectLiveOverlay : FLAlertLayer { bool m_detailMode; } +[[link(android)]] class ColorSelectPopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, TextInputDelegate, GJSpecialColorSelectDelegate { virtual void colorValueChanged(cocos2d::ccColor3B color) = mac 0x423320, win 0x46ee0; ColorSelectPopup() {} @@ -881,10 +923,12 @@ class ColorSelectPopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, bool m_copyColor; } +[[link(android)]] class ColorSetupDelegate { virtual void colorSetupClosed(int channel) {} } +[[link(android)]] class CommentCell : TableViewCell, LikeItemDelegate, FLAlertLayerProtocol { void loadFromComment(GJComment*) = mac 0x111c70, win 0x5f3d0; void onConfirmDelete(cocos2d::CCObject* sender) = mac 0x11d100, win 0x61140; @@ -898,12 +942,14 @@ class CommentCell : TableViewCell, LikeItemDelegate, FLAlertLayerProtocol { bool m_accountComment; } +[[link(android)]] class CommentUploadDelegate { virtual void commentUploadFinished(int) {} virtual void commentUploadFailed(int, CommentError) {} virtual void commentDeleteFailed(int, int) {} } +[[link(android)]] class ConfigureHSVWidget : cocos2d::CCNode { cocos2d::CCLabelBMFont* m_hueLabel; cocos2d::CCLabelBMFont* m_saturationLabel; @@ -914,6 +960,7 @@ class ConfigureHSVWidget : cocos2d::CCNode { cocos2d::ccHSVValue m_value; } +[[link(android)]] class CountTriggerAction : cocos2d::CCNode { static CountTriggerAction* createFromString(gd::string) = mac 0x1754f0; @@ -924,6 +971,7 @@ class CountTriggerAction : cocos2d::CCNode { bool m_multiActivate; } +[[link(android)]] class CreateGuidelinesLayer : FLAlertLayer, FLAlertLayerProtocol { void doClearGuidelines() = win 0x4cf60, mac 0x299690; void onStop(cocos2d::CCObject* sender) = win 0x4d2c0, mac 0x2990f0; @@ -933,6 +981,7 @@ class CreateGuidelinesLayer : FLAlertLayer, FLAlertLayerProtocol { gd::string m_guidelineString; } +[[link(android)]] class CreateMenuItem : CCMenuItemSpriteExtra { static CreateMenuItem* create(cocos2d::CCNode*, cocos2d::CCNode*, cocos2d::CCObject*, cocos2d::SEL_MenuHandler) = mac 0x1c580, win 0x93db0; @@ -942,6 +991,7 @@ class CreateMenuItem : CCMenuItemSpriteExtra { int m_buildTab; } +[[link(android)]] class CreatorLayer : cocos2d::CCLayer, cocos2d::CCSceneTransitionDelegate, DialogDelegate { void onBack(cocos2d::CCObject*) = win 0x4fae0; void onChallenge(cocos2d::CCObject*) = mac 0x142960, win 0x4f1b0; @@ -962,6 +1012,7 @@ class CreatorLayer : cocos2d::CCLayer, cocos2d::CCSceneTransitionDelegate, Dialo static CreatorLayer* create() = win 0x4dda0; } +[[link(android)]] class CurrencyRewardLayer : cocos2d::CCLayer { inline CurrencyRewardLayer() {} ~CurrencyRewardLayer() = mac 0x447950, win 0x4ffb0; @@ -975,10 +1026,12 @@ class CurrencyRewardLayer : cocos2d::CCLayer { ) = win 0x50050; } +[[link(android)]] class CurrencyRewardDelegate { virtual void currencyWillExit(CurrencyRewardLayer*) {} } +[[link(android)]] class CustomListView : BoomListView { static CustomListView* create(cocos2d::CCArray*, float, float, int, BoomListType) = mac 0x10d410, win 0x57f90, ios 0x99154; inline static CustomListView* create(cocos2d::CCArray* entries, BoomListType type, float width, float height) { @@ -990,10 +1043,12 @@ class CustomListView : BoomListView { inline CustomListView() {} } +[[link(android)]] class CustomSongCell : TableViewCell { void loadFromObject(SongInfoObject*) = mac 0x110220, win 0x5e9f0; } +[[link(android)]] class CustomSongLayer : FLAlertLayer, FLAlertLayerProtocol, TextInputDelegate, GJDropDownLayerDelegate { bool init(LevelSettingsObject*) = mac 0xf06f0, win 0x65c10; void onArtists(cocos2d::CCObject*) = mac 0xf1950; @@ -1005,6 +1060,7 @@ class CustomSongLayer : FLAlertLayer, FLAlertLayerProtocol, TextInputDelegate, G LevelSettingsLayer* m_levelSettingsLayer; } +[[link(android)]] class CustomSongWidget : cocos2d::CCNode, MusicDownloadDelegate, FLAlertLayerProtocol { bool init(SongInfoObject*, LevelSettingsObject*, bool, bool, bool, bool, bool hideBackground) = mac 0x37be20, win 0x685b0; void FLAlert_Clicked(FLAlertLayer*, bool) {} @@ -1018,6 +1074,7 @@ class CustomSongWidget : cocos2d::CCNode, MusicDownloadDelegate, FLAlertLayerPro PAD = win 0x30; } +[[link(android)]] class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDelegate, ColorSelectDelegate, ColorSetupDelegate { void onNextColorChannel(cocos2d::CCObject* sender) = mac 0xe0270, win 0x56c80; void onSelectColor(cocos2d::CCObject* sender) = mac 0xdfdc0, win 0x577b0; @@ -1045,7 +1102,7 @@ class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDele cocos2d::CCArray* m_colorButtons; cocos2d::CCArray* m_colorTabNodes; cocos2d::CCArray* m_textTabNodes; - PAD = win 0x4, mac 0x8; + PAD = win 0x4, mac 0x8, android 0x4; cocos2d::CCArray* m_detailTabNodes; int m_selectedMode; int m_customColorChannel; @@ -1072,6 +1129,7 @@ class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDele bool m_customColorSelected; } +[[link(android)]] class DailyLevelPage : FLAlertLayer, FLAlertLayerProtocol, GJDailyLevelDelegate, LevelDownloadDelegate { static DailyLevelPage* create(bool weekly) = win 0x6a860; bool init(bool weekly) = mac 0x108C90, win 0x6a900; @@ -1082,6 +1140,7 @@ class DailyLevelPage : FLAlertLayer, FLAlertLayerProtocol, GJDailyLevelDelegate, bool m_weekly; } +[[link(android)]] class DialogLayer : cocos2d::CCLayerColor { static DialogLayer* create(DialogObject* dialog, int color) { return DialogLayer::createDialogLayer(dialog, nullptr, color); @@ -1108,10 +1167,12 @@ class DialogLayer : cocos2d::CCLayerColor { virtual void fadeInTextFinished(TextArea*) = mac 0x205930, win 0x6e070; } +[[link(android)]] class DialogDelegate { virtual void dialogClosed(DialogLayer*) {} } +[[link(android)]] class DialogObject : cocos2d::CCObject { DialogObject() {} @@ -1126,8 +1187,10 @@ class DialogObject : cocos2d::CCObject { bool m_canSkip; } +[[link(android)]] class DownloadMessageDelegate {} +[[link(android)]] class DrawGridLayer : cocos2d::CCLayer { static DrawGridLayer* get() { auto editorLayer = LevelEditorLayer::get(); @@ -1175,6 +1238,7 @@ class DrawGridLayer : cocos2d::CCLayer { float m_gridSize; } +[[link(android)]] class EditButtonBar : cocos2d::CCNode { void removeAllItems() { m_buttonArray->removeAllObjects(); @@ -1214,6 +1278,7 @@ class EditButtonBar : cocos2d::CCNode { cocos2d::CCArray* m_pagesArray; } +[[link(android)]] class EditLevelLayer : cocos2d::CCLayer, FLAlertLayerProtocol, TextInputDelegate, UploadActionDelegate, UploadPopupDelegate, SetIDPopupDelegate { static cocos2d::CCScene* scene(GJGameLevel* level) { auto scene = cocos2d::CCScene::create(); @@ -1237,10 +1302,12 @@ class EditLevelLayer : cocos2d::CCLayer, FLAlertLayerProtocol, TextInputDelegate cocos2d::CCLabelBMFont* m_someFont; } +[[link(android)]] class EditorOptionsLayer { void onButtonsPerRow(cocos2d::CCObject*) = mac 0x147b30; } +[[link(android)]] class EditorPauseLayer : CCBlockLayer, FLAlertLayerProtocol { static EditorPauseLayer* get() { if (!EditorUI::get()) return nullptr; @@ -1289,6 +1356,7 @@ class EditorPauseLayer : CCBlockLayer, FLAlertLayerProtocol { LevelEditorLayer* m_editorLayer; } +[[link(android)]] class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJRotationControlDelegate, GJScaleControlDelegate, MusicDownloadDelegate { static EditorUI* get() { auto lel = LevelEditorLayer::get(); @@ -1526,6 +1594,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ bool m_spaceKeyPressed; } +[[link(android)]] class EffectGameObject : GameObject { void updateLabel() { auto label = static_cast(this->getChildByTag(999)); @@ -1628,6 +1697,7 @@ class EffectGameObject : GameObject { PAD = mac 0x28, win 0x24; } +[[link(android)]] class EndLevelLayer { static EndLevelLayer* create() = mac 0x2787d0, win 0x94b50; @@ -1635,13 +1705,16 @@ class EndLevelLayer { void onEdit(cocos2d::CCObject* sender) = mac 0x27a640, win 0x96d30; } +[[link(android)]] class EndPortalObject : GameObject { static EndPortalObject* create() = mac 0x1da8f0, win 0x98a50; void updateColors(cocos2d::_ccColor3B) = mac 0x1dacb0, win 0x98eb0; } +[[link(android)]] class ExtendedLayer {} +[[link(android)]] class FLAlertLayer : cocos2d::CCLayerColor { inline virtual ~FLAlertLayer() { cocos2d::CCDirector::sharedDirector()->getTouchDispatcher()->decrementForcePrio(2); @@ -1710,10 +1783,12 @@ class FLAlertLayer : cocos2d::CCLayerColor { bool m_noAction; } +[[link(android)]] class FLAlertLayerProtocol { virtual void FLAlert_Clicked(FLAlertLayer*, bool) {} } +[[link(android)]] class FMODAudioEngine : cocos2d::CCNode { static FMODAudioEngine* sharedEngine() = mac 0x20ef80, win 0x239f0; void preloadEffect(gd::string filename) = win 0x24240; @@ -1746,19 +1821,23 @@ class FMODAudioEngine : cocos2d::CCNode { int m_musicOffset; } +[[link(android)]] class FMODSound : cocos2d::CCNode { static FMODSound* create(FMOD::Sound* sound) = win 0x246b0; FMOD::Sound* m_sound; } +[[link(android)]] class FriendRequestDelegate {} +[[link(android)]] class FriendsProfilePage : FLAlertLayer, FLAlertLayerProtocol, UploadActionDelegate, UploadPopupDelegate, UserListDelegate { static FriendsProfilePage* create(UserListType) = win 0x9ce80; bool init(UserListType) = win 0x9cf30; } +[[link(android)]] class GJAccountBackupDelegate { virtual bool backupAccountFailed(BackupAccountError) { return false; @@ -1768,12 +1847,14 @@ class GJAccountBackupDelegate { } } +[[link(android)]] class GJAccountDelegate { virtual bool accountStatusChanged() { return false; } } +[[link(android)]] class GJAccountLoginDelegate { virtual bool loginAccountFailed(AccountError) { return false; @@ -1783,6 +1864,7 @@ class GJAccountLoginDelegate { } } +[[link(android)]] class GJAccountManager : cocos2d::CCNode { static GJAccountManager* sharedState() = mac 0x85070, win 0x107d50; @@ -1792,6 +1874,7 @@ class GJAccountManager : cocos2d::CCNode { int m_accountID; } +[[link(android)]] class GJAccountSyncDelegate { virtual bool syncAccountFailed(BackupAccountError) { return false; @@ -1801,6 +1884,7 @@ class GJAccountSyncDelegate { } } +[[link(android)]] class GJBaseGameLayer : cocos2d::CCLayer, TriggerEffectDelegate { cocos2d::CCLayer* getObjectLayer() { return m_objectLayer; @@ -1990,8 +2074,10 @@ class GJBaseGameLayer : cocos2d::CCLayer, TriggerEffectDelegate { PAD = mac 0x8, win 0x8; } +[[link(android)]] class GJChallengeDelegate {} +[[link(android)]] class GJChallengeItem : cocos2d::CCObject { GJChallengeType m_challengeType; @@ -2004,8 +2090,10 @@ class GJChallengeItem : cocos2d::CCObject { gd::string m_name; } +[[link(android)]] class GJColorSetupLayer {} +[[link(android)]] class GJComment : cocos2d::CCNode { ~GJComment() = mac 0x2dfd70, win 0xc3640; virtual bool init() = mac 0x2dfec0, win 0xc3ef0; @@ -2028,6 +2116,7 @@ class GJComment : cocos2d::CCNode { GJUserScore* m_userScore; } +[[link(android)]] class GJCommentListLayer : cocos2d::CCLayerColor { ~GJCommentListLayer() = mac 0x1482a0; static GJCommentListLayer* create(BoomListView*, char const*, cocos2d::_ccColor4B, float, float, bool) = mac 0x147d00, win 0x13a880; @@ -2035,11 +2124,13 @@ class GJCommentListLayer : cocos2d::CCLayerColor { BoomListView* m_list; } +[[link(android)]] class GJDailyLevelDelegate { virtual void dailyStatusFinished(bool) {} virtual void dailyStatusFailed(bool) {} } +[[link(android)]] class GJDropDownLayer : cocos2d::CCLayerColor { virtual void customSetup() {} virtual void enterLayer() = mac 0x3525c0, win 0x16970; @@ -2094,10 +2185,12 @@ class GJDropDownLayer : cocos2d::CCLayerColor { GJDropDownLayerDelegate* m_delegate; } +[[link(android)]] class GJDropDownLayerDelegate { virtual void dropDownLayerWillClose(GJDropDownLayer*) {} } +[[link(android)]] class GJEffectManager : cocos2d::CCNode { static GJEffectManager* get() { return GJEffectManager::fromGameLayer(); @@ -2263,6 +2356,7 @@ class GJEffectManager : cocos2d::CCNode { bool m_moveOptimizationEnabled; } +[[link(android)]] class GJGameLevel : cocos2d::CCNode { static GJGameLevel* createWithCoder(DS_Dictionary* dict) { auto ret = GJGameLevel::create(); @@ -2388,6 +2482,7 @@ class GJGameLevel : cocos2d::CCNode { gd::string m_personalBests; } +[[link(android)]] class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, GameRateDelegate, ListButtonBarDelegate, DialogDelegate { inline GJGarageLayer() { m_nameInput = nullptr; @@ -2448,10 +2543,12 @@ class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, bool m_updateSelector; } +[[link(android)]] class GJGroundLayer : cocos2d::CCLayer { void updateGroundWidth() = mac 0x356790, win 0x12dda0; } +[[link(android)]] class GJItemIcon : cocos2d::CCSprite { bool init( UnlockType, int, cocos2d::ccColor3B, cocos2d::ccColor3B, @@ -2469,10 +2566,12 @@ class GJItemIcon : cocos2d::CCSprite { static GJItemIcon* create(UnlockType _type, int _id, cocos2d::ccColor3B _col1, cocos2d::ccColor3B _col2, bool _un0, bool _un1, bool _un2, cocos2d::ccColor3B _col3) = mac 0x1bb330, win 0x12cbf0, ios 0x227188; } +[[link(android)]] class GJLevelScoreCell : TableViewCell { void updateBGColor(int index) = win 0x5c6b0; } +[[link(android)]] class GJListLayer : cocos2d::CCLayerColor { ~GJListLayer() = mac 0x344350; static GJListLayer* create(BoomListView* target, const char* title, cocos2d::ccColor4B color, float width, float height) = mac 0x343e10, win 0x12e000; @@ -2480,6 +2579,7 @@ class GJListLayer : cocos2d::CCLayerColor { BoomListView* m_listView; } +[[link(android)]] class GJMapPack : cocos2d::CCNode { cocos2d::CCArray* m_levels; int m_packID; @@ -2497,22 +2597,27 @@ class GJMapPack : cocos2d::CCNode { static GJMapPack *create() = win 0xbffe0; } +[[link(android)]] class GJMessageCell : TableViewCell { void updateBGColor(int index) = win 0x5c6b0; void loadFromMessage(GJUserMessage *) = win 0x64b60; } +[[link(android)]] class GJOptionsLayer : FLAlertLayer { static GJOptionsLayer* create() = mac 0x145ae0, win 0x0, ios 0x0; void addToggle(char const*, char const*, char const*) = mac 0x1464e0, win 0x0, ios 0x0; } +[[link(android)]] class GJRequestCell : TableViewCell { void updateBGColor(int index) = win 0x5c6b0; } +[[link(android)]] class GJRewardDelegate {} +[[link(android)]] class GJRewardItem : cocos2d::CCObject { int m_chestID; int m_timeRemaining; @@ -2521,6 +2626,7 @@ class GJRewardItem : cocos2d::CCObject { bool m_unk; } +[[link(android)]] class GJRewardObject : cocos2d::CCObject { SpecialRewardItem m_specialRewardItem; UnlockType m_unlockType; @@ -2528,6 +2634,7 @@ class GJRewardObject : cocos2d::CCObject { int m_total; } +[[link(android)]] class GJRobotSprite : CCAnimatedSprite { // virtual ~GJRobotSprite() = mac 0x34aaf0; inlined on windows, RE and recreate virtual bool init() = mac 0x34ad50, win 0x145840; @@ -2550,6 +2657,7 @@ class GJRobotSprite : CCAnimatedSprite { CCSpritePart* m_headSpritePart; } +[[link(android)]] class GJRotationControl : cocos2d::CCLayer { void setAngle(float angle) { m_sliderPosition = cocos2d::CCPointMake(sinf(angle) * 60.0f, cosf(angle) * 60.0f); @@ -2569,12 +2677,14 @@ class GJRotationControl : cocos2d::CCLayer { int m_touchID; } +[[link(android)]] class GJRotationControlDelegate { virtual void angleChangeBegin() {} virtual void angleChangeEnded() {} virtual void angleChanged(float) {} } +[[link(android)]] class GJScaleControl : cocos2d::CCLayer { virtual bool init() = mac 0x31b30, win 0x94490; virtual bool ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x31d30, win 0x947a0; @@ -2592,12 +2702,14 @@ class GJScaleControl : cocos2d::CCLayer { GJScaleControlDelegate* m_delegate; } +[[link(android)]] class GJScaleControlDelegate { virtual void scaleChangeBegin() {} virtual void scaleChangeEnded() {} virtual void scaleChanged(float) {} } +[[link(android)]] class GJScoreCell : TableViewCell, FLAlertLayerProtocol { virtual void FLAlert_Clicked(FLAlertLayer*, bool) = mac 0x11D8E0, win 0x624a0; void loadFromScore(GJUserScore* score) = mac 0x113AA0, win 0x61440; @@ -2608,6 +2720,7 @@ class GJScoreCell : TableViewCell, FLAlertLayerProtocol { GJUserScore* m_score; } +[[link(android)]] class GJSearchObject : cocos2d::CCNode { SearchType getType() { return m_searchType; @@ -2641,20 +2754,24 @@ class GJSearchObject : cocos2d::CCNode { bool m_songFilter; } +[[link(android)]] class GJSpecialColorSelect { static const char* textForColorIdx(int id) = mac 0x383a50, win 0x14e1d0, ios 0x113f6c; } +[[link(android)]] class GJSpecialColorSelectDelegate { virtual void colorSelectClosed(GJSpecialColorSelect*, int) {} } +[[link(android)]] class GJSpiderSprite : GJRobotSprite { // ~GJSpiderSprite() = mac 0x34c4a0; same as ~CCRobotSprite, fully merged on windows virtual bool init() = mac 0x34c700, win 0x146db0; static GJSpiderSprite* create() = mac 0x34c5b0, win 0x146cf0; } +[[link(android)]] class GJSpriteColor : cocos2d::CCNode { int m_colorID; int m_defaultColorID; @@ -2667,14 +2784,17 @@ class GJSpriteColor : cocos2d::CCNode { void resetCustomColorMode() = mac 0x342f10; } +[[link(android)]] class GJUserCell : TableViewCell { void updateBGColor(int index) = win 0x5c6b0; } +[[link(android)]] class GJUserMessage : cocos2d::CCNode { virtual bool init() = win 0x33b40; } +[[link(android)]] class GJUserScore : cocos2d::CCNode { IconType getIconType() const { return m_iconType; @@ -2774,6 +2894,7 @@ class GJUserScore : cocos2d::CCNode { gd::string m_lastScoreAge; } +[[link(android)]] class GManager : cocos2d::CCNode { virtual void setup() = mac 0x26EE20, win 0x28F60; virtual void encodeDataTo(DS_Dictionary* data) {} @@ -2794,16 +2915,19 @@ class GManager : cocos2d::CCNode { bool m_quickSave; } +[[link(android)]] class GooglePlayDelegate { virtual void googlePlaySignedIn() {} } +[[link(android)]] class GooglePlayManager : cocos2d::CCNode { virtual bool init() = win 0x11070; static GooglePlayManager* sharedState() = win 0x295a0; } +[[link(android)]] class GameLevelManager : cocos2d::CCNode { cocos2d::CCArray* createAndGetScores(gd::string, GJScoreType) = win 0xa2780; GJGameLevel* createNewLevel() = mac 0x2b8180, win 0xa0db0; @@ -2924,6 +3048,7 @@ class GameLevelManager : cocos2d::CCNode { cocos2d::CCString* m_unkStr4; } +[[link(android)]] class GameManager : GManager { int getPlayerFrame() { return m_playerFrame; @@ -3156,6 +3281,7 @@ class GameManager : GManager { cocos2d::TextureQuality m_quality; } +[[link(android)]] class GameObject : CCSpritePlus { cocos2d::CCPoint getStartPosition() { return m_startPosition; @@ -3508,6 +3634,7 @@ class GameObject : CCSpritePlus { bool m_orbMultiActivate; } +[[link(android)]] class GameObjectCopy : cocos2d::CCObject { virtual ~GameObjectCopy() = mac 0xa3290; static GameObjectCopy* create(GameObject*) = mac 0x975a0, win 0x16c020; @@ -3515,8 +3642,10 @@ class GameObjectCopy : cocos2d::CCObject { GameObject* m_object; } +[[link(android)]] class GameRateDelegate {} +[[link(android)]] class GameSoundManager : cocos2d::CCNode { void disableMetering() = mac 0x362d80, win 0x257D0; void enableMetering() = mac 0x362d00, win 0x256F0; @@ -3539,6 +3668,7 @@ class GameSoundManager : cocos2d::CCNode { gd::string m_filePath; } +[[link(android)]] class GameStatsManager : cocos2d::CCNode { void awardCurrencyForLevel(GJGameLevel*) = mac 0x43600; void awardDiamondsForLevel(GJGameLevel*) = mac 0x43c60; @@ -3589,6 +3719,7 @@ class GameStatsManager : cocos2d::CCNode { cocos2d::CCDictionary* m_miscChests; } +[[link(android)]] class GameToolbox { static gd::string stringFromHSV(cocos2d::ccHSVValue hsv, const char* separator) = mac 0x28cf90; static cocos2d::ccHSVValue hsvFromString(gd::string str, char const* separator) = mac 0x28cc30, win 0x26da0; @@ -3601,6 +3732,7 @@ class GameToolbox { static cocos2d::ccColor3B multipliedColorValue(cocos2d::ccColor3B color1, cocos2d::ccColor3B color2, float factor) = win 0x26CE0; } +[[link(android)]] class GaragePage : cocos2d::CCLayer, ListButtonBarDelegate { static GaragePage* create(IconType type, GJGarageLayer* pGarage, cocos2d::SEL_MenuHandler pSelectCallback) { auto pRet = new GaragePage(); @@ -3627,12 +3759,15 @@ class GaragePage : cocos2d::CCLayer, ListButtonBarDelegate { PAD = win 0x4; } +[[link(android)]] class GauntletSelectLayer { static GauntletSelectLayer* create(int) = win 0x105120; } +[[link(android)]] class GhostTrailEffect {} +[[link(android)]] class HSVWidgetPopup : FLAlertLayer { bool init(cocos2d::_ccHSVValue value, HSVWidgetPopupDelegate* delegate, gd::string title); void onClose(cocos2d::CCObject* sender) = win 0x4a280; @@ -3641,10 +3776,12 @@ class HSVWidgetPopup : FLAlertLayer { HSVWidgetPopupDelegate* m_delegate; } +[[link(android)]] class HSVWidgetPopupDelegate { virtual void hsvPopupClosed(HSVWidgetPopup* popup, cocos2d::ccHSVValue value) {} } +[[link(android)]] class HardStreak : cocos2d::CCDrawNode { // ~HardStreak() = mac 0x5bf00; inlined on windows virtual bool init() = mac 0x5c090, win 0x14e430; @@ -3666,6 +3803,7 @@ class HardStreak : cocos2d::CCDrawNode { bool m_isSolid; } +[[link(android)]] class InfoAlertButton : CCMenuItemSpriteExtra { bool init(gd::string title, gd::string text, float scale) = win 0x14ef50; void activate() = win 0x14f050; @@ -3673,6 +3811,7 @@ class InfoAlertButton : CCMenuItemSpriteExtra { static InfoAlertButton* create(gd::string title, gd::string text, float scale) = win 0x14ed20, mac 0x2ecad0; } +[[link(android)]] class InfoLayer : FLAlertLayer, LevelCommentDelegate, CommentUploadDelegate, FLAlertLayerProtocol { bool init(GJGameLevel* level, GJUserScore* score) = mac 0x456850, win 0x14f5a0; void setupCommentsBrowser(cocos2d::CCArray* comments) = mac 0x458590, win 0x152270; @@ -3703,8 +3842,10 @@ class InfoLayer : FLAlertLayer, LevelCommentDelegate, CommentUploadDelegate, FLA bool m_commentHistory; } +[[link(android)]] class InheritanceNode : cocos2d::CCObject {} +[[link(android)]] class KeybindingsLayer : FLAlertLayer { void onClose(cocos2d::CCObject* sender) = win 0x49c60; void onPrevPage(cocos2d::CCObject* sender) = win 0x153cd0; @@ -3720,11 +3861,13 @@ class KeybindingsLayer : FLAlertLayer { cocos2d::CCNode* m_rightArrow; } +[[link(android)]] class LabelGameObject : GameObject { virtual bool init() = mac 0x2f5520, win 0x25b7c0; void setObjectColor(cocos2d::_ccColor3B const&) = mac 0xdbca0; } +[[link(android)]] class LeaderboardManagerDelegate { virtual void updateUserScoreFinished() {} virtual void updateUserScoreFailed() {} @@ -3732,11 +3875,13 @@ class LeaderboardManagerDelegate { virtual void loadLeaderboardFailed(const char*) {} } +[[link(android)]] class LeaderboardsLayer : cocos2d::CCLayer { static LeaderboardsLayer* create(LeaderboardState state) = mac 0x29F590, win 0x158710; bool init(LeaderboardState state) = mac 0x29f6d0, win 0x1587b0; } +[[link(android)]] class LevelBrowserLayer : cocos2d::CCLayer, LevelManagerDelegate, FLAlertLayerProtocol, SetIDPopupDelegate, SetTextPopupDelegate { static cocos2d::CCScene* scene(GJSearchObject* search) { auto scene = cocos2d::CCScene::create(); @@ -3775,6 +3920,7 @@ class LevelBrowserLayer : cocos2d::CCLayer, LevelManagerDelegate, FLAlertLayerPr int m_pageEndIdx; } +[[link(android)]] class LevelCell : TableViewCell { CCMenuItemSpriteExtra* m_button; GJGameLevel* m_level; @@ -3787,6 +3933,7 @@ class LevelCell : TableViewCell { inline LevelCell(char const* identifier, float parentHeight, float height) : TableViewCell(identifier, parentHeight, height) {} } +[[link(android)]] class LevelCommentDelegate { virtual void loadCommentsFinished(cocos2d::CCArray*, char const*) {} virtual void loadCommentsFailed(char const*) {} @@ -3794,16 +3941,19 @@ class LevelCommentDelegate { virtual void setupPageInfo(gd::string, char const*) {} } +[[link(android)]] class LevelDeleteDelegate { virtual void levelDeleteFinished(int) {} virtual void levelDeleteFailed(int) {} } +[[link(android)]] class LevelDownloadDelegate { virtual void levelDownloadFinished(GJGameLevel*) {} virtual void levelDownloadFailed(int) {} } +[[link(android)]] class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate { static LevelEditorLayer* get() { return GameManager::sharedState()->m_levelEditorLayer; @@ -4009,6 +4159,7 @@ class LevelEditorLayer : GJBaseGameLayer, LevelSettingsDelegate { bool m_removingObjects; } +[[link(android)]] class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDelegate, RateLevelDelegate, LikeItemDelegate, FLAlertLayerProtocol, LevelDeleteDelegate, NumberInputDelegate, SetIDPopupDelegate { static LevelInfoLayer* create(GJGameLevel* level) = mac 0x15f290, win 0x175d50; bool init(GJGameLevel* level) = win 0x175df0, mac 0x15f520; @@ -4042,6 +4193,7 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg PAD = win 0x4, mac 0x8; } +[[link(android)]] class LevelLeaderboard : FLAlertLayer, LeaderboardManagerDelegate { void onChangeType(cocos2d::CCObject* sender) = mac 0x20e310, win 0x17d090; void onUpdate(cocos2d::CCObject* sender) = mac 0x20e240, win 0x17d1b0; @@ -4053,12 +4205,14 @@ class LevelLeaderboard : FLAlertLayer, LeaderboardManagerDelegate { LevelLeaderboardType m_type; } +[[link(android)]] class LevelManagerDelegate { virtual void loadLevelsFinished(cocos2d::CCArray *,char const*) {} virtual void loadLevelsFailed(char const*) {} virtual void setupPageInfo(gd::string,char const*) {} } +[[link(android)]] class LevelPage : cocos2d::CCLayer, DialogDelegate { PAD = mac 0x8, win 0x4; GJGameLevel* m_level; @@ -4066,6 +4220,7 @@ class LevelPage : cocos2d::CCLayer, DialogDelegate { void onInfo(cocos2d::CCObject* sender) = mac 0x23AAE0, win 0x189070; } +[[link(android)]] class LevelSearchLayer : cocos2d::CCLayer { static LevelSearchLayer* create() = win 0x17d9c0; virtual bool init() = mac 0x384770, win 0x17da60; @@ -4078,6 +4233,7 @@ class LevelSearchLayer : cocos2d::CCLayer { } +[[link(android)]] class LevelSelectLayer : cocos2d::CCLayer { static LevelSelectLayer* create(int lvl) = win 0x185500; @@ -4085,10 +4241,12 @@ class LevelSelectLayer : cocos2d::CCLayer { BoomScrollLayer* m_scrollLayer; } +[[link(android)]] class LevelSettingsDelegate { virtual void levelSettingsUpdated() {} } +[[link(android)]] class SecretLayer4 : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, DialogDelegate { static SecretLayer4* create() = mac 0x1ed500; static cocos2d::CCScene* scene() = mac 0x1ed4c0; @@ -4097,14 +4255,17 @@ class SecretLayer4 : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, void showDialog(int message) = mac 0x1effd0; } +[[link(android)]] class SelectArtDelegate { virtual void selectArtClosed(SelectArtLayer*) {} } +[[link(android)]] class CustomSongLayerDelegate { virtual void customSongLayerClosed() {} } +[[link(android)]] class LevelSettingsLayer : FLAlertLayer, ColorSelectDelegate, SelectArtDelegate, FLAlertLayerProtocol, CustomSongLayerDelegate { static LevelSettingsLayer* create(LevelSettingsObject* levelSettings, LevelEditorLayer* editor) = win 0x170d90; bool init(LevelSettingsObject* levelSettings, LevelEditorLayer* editor) = mac 0xa7e00, win 0x170e50; @@ -4135,6 +4296,7 @@ class LevelSettingsLayer : FLAlertLayer, ColorSelectDelegate, SelectArtDelegate, CustomSongWidget* m_customSongWidget; } +[[link(android)]] class LevelSettingsObject : cocos2d::CCNode { virtual ~LevelSettingsObject() = mac 0xa5650, win 0x16e800; virtual bool init() = mac 0xa5690, win 0x16e940; @@ -4173,17 +4335,21 @@ class LevelSettingsObject : cocos2d::CCNode { int m_groundLineIndex; } +[[link(android)]] class LevelUploadDelegate {} +[[link(android)]] class LevelUpdateDelegate { virtual void levelUpdateFinished(GJGameLevel*, UpdateResponse) {} virtual void levelUpdateFailed(int) {} } +[[link(android)]] class LikeItemDelegate { virtual void likedItem(LikeItemType, int, bool) {} } +[[link(android)]] class LikeItemLayer : FLAlertLayer { LikeItemType m_itemType; int m_itemID; @@ -4194,12 +4360,15 @@ class LikeItemLayer : FLAlertLayer { bool init(LikeItemType type, int itemID, int commentSourceID) = mac 0x35f900; } +[[link(android)]] class ListButtonBar : cocos2d::CCNode { BoomScrollLayer* m_scrollLayer; } +[[link(android)]] class ListButtonBarDelegate {} +[[link(android)]] class LoadingCircle : cocos2d::CCLayerColor { void setParentLayer(cocos2d::CCLayer* layer) { m_parentLayer = layer; @@ -4217,6 +4386,7 @@ class LoadingCircle : cocos2d::CCLayerColor { bool m_fade; } +[[link(android)]] class LoadingLayer : cocos2d::CCLayer { void setFromRefresh(bool value) { m_fromRefresh = value; @@ -4247,6 +4417,7 @@ class LoadingLayer : cocos2d::CCLayer { bool m_fromRefresh; } +[[link(android)]] class LocalLevelManager : GManager { static LocalLevelManager* sharedState() = mac 0x35dd60, win 0x18d260; inline static LocalLevelManager* get() { @@ -4264,11 +4435,13 @@ class LocalLevelManager : GManager { cocos2d::CCArray* m_localLevels; } +[[link(android)]] class MapPackCell : TableViewCell { void updateBGColor(int index) = win 0x5c6b0; void loadFromMapPack(GJMapPack *) = win 0x5cac0; } +[[link(android)]] class MenuGameLayer : cocos2d::CCLayer { void resetPlayer() = mac 0x28fdc0, win 0x18f4b0; void destroyPlayer() = win 0x190100; @@ -4277,6 +4450,7 @@ class MenuGameLayer : cocos2d::CCLayer { void updateColors() = win 0x18edd0; } +[[link(android)]] class MenuLayer : cocos2d::CCLayer, FLAlertLayerProtocol, GooglePlayDelegate { inline MenuLayer() {} virtual ~MenuLayer() = mac 0x1d1230, win 0x190620; @@ -4308,14 +4482,17 @@ class MenuLayer : cocos2d::CCLayer, FLAlertLayerProtocol, GooglePlayDelegate { CCMenuItemSpriteExtra* m_profileBtn; } +[[link(android)]] class MessageListDelegate {} +[[link(android)]] class MoreSearchLayer : FLAlertLayer { static MoreSearchLayer* create() = mac 0x38ab40, win 0x182520; virtual bool init() = mac 0x3896b0, win 0x1825c0; void onClose(cocos2d::CCObject*) = mac 0x38aa40, win 0x1848f0; } +[[link(android)]] class MoreOptionsLayer : FLAlertLayer, TextInputDelegate, GooglePlayDelegate { static MoreOptionsLayer* create() = win 0x1de850; virtual bool init() = mac 0x43f470, win 0x1DE8F0; @@ -4324,14 +4501,17 @@ class MoreOptionsLayer : FLAlertLayer, TextInputDelegate, GooglePlayDelegate { void onToggle(cocos2d::CCObject* sender) = mac 0x441370; } +[[link(android)]] class MoreVideoOptionsLayer : FLAlertLayer { static MoreVideoOptionsLayer* create() = mac 0x443c10, win 0x1e24f0; virtual bool init() = mac 0x444150, win 0x1e2590; void onClose(cocos2d::CCObject*) = mac 0x444aa0; } +[[link(android)]] class MultilineBitmapFont : cocos2d::CCSprite {} +[[link(android)]] class MusicDownloadDelegate { virtual void downloadSongFailed(int, GJSongError) {} virtual void downloadSongFinished(SongInfoObject*) {} @@ -4340,6 +4520,7 @@ class MusicDownloadDelegate { virtual void songStateChanged() {} } +[[link(android)]] class MusicDownloadManager : cocos2d::CCNode, PlatformDownloadDelegate { void incrementPriorityForSong(int) = mac 0x2ef750; static MusicDownloadManager* sharedState() = mac 0x2ee4c0, win 0x1945b0; @@ -4354,12 +4535,15 @@ class MusicDownloadManager : cocos2d::CCNode, PlatformDownloadDelegate { int m_priority; } +[[link(android)]] class NumberInputDelegate { virtual void numberInputClosed(NumberInputLayer*) {} } +[[link(android)]] class NumberInputLayer {} +[[link(android)]] class OBB2D : cocos2d::CCNode { void calculateWithCenter(cocos2d::CCPoint, float, float, float) = mac 0x35a9c0, win 0x2bc10; static OBB2D* create(cocos2d::CCPoint, float, float, float) = mac 0x35a890, win 0x2ba80; @@ -4384,15 +4568,18 @@ class OBB2D : cocos2d::CCNode { cocos2d::CCPoint m_center; } +[[link(android)]] class ObjectManager : cocos2d::CCNode { static ObjectManager* instance() = win 0x2c2c0; void setup() = win 0x2c3b0; } +[[link(android)]] class KeysLayer : cocos2d::CCLayer { virtual bool init() = win 0x154560; } +[[link(android)]] class ObjectToolbox : cocos2d::CCNode { cocos2d::CCArray* allKeys() { return m_frameToKeyDict->allKeys(); @@ -4420,6 +4607,7 @@ class ObjectToolbox : cocos2d::CCNode { cocos2d::CCDictionary* m_keyToFrameDict; } +[[link(android)]] class OpacityEffectAction : cocos2d::CCNode { static OpacityEffectAction* create(float, float, float, int) = mac 0x1789f0; static OpacityEffectAction* createFromString(gd::string) = mac 0x178c10; @@ -4437,12 +4625,14 @@ class OpacityEffectAction : cocos2d::CCNode { float m_delta; } +[[link(android)]] class OnlineListDelegate { virtual void loadListFinished(cocos2d::CCArray*, const char*) {} virtual void loadListFailed(const char*) {} virtual void setupPageInfo(gd::string, const char*) {} } +[[link(android)]] class OptionsLayer : GJDropDownLayer, FLAlertLayerProtocol { static OptionsLayer* addToCurrentScene(bool noTransition) { auto layer = OptionsLayer::create(); @@ -4459,6 +4649,7 @@ class OptionsLayer : GJDropDownLayer, FLAlertLayerProtocol { cocos2d::CCMenu* m_optionsMenu; } +[[link(android)]] class PauseLayer : CCBlockLayer { static PauseLayer* create(bool) = mac 0x20b1e0, win 0x1e4570; void onEdit(cocos2d::CCObject*) = mac 0x20c630, win 0x1e60e0; @@ -4478,11 +4669,13 @@ class PauseLayer : CCBlockLayer { bool m_unknown2; } +[[link(android)]] class PlatformDownloadDelegate { virtual void downloadFinished(char const*) {} virtual void downloadFailed(char const*) {} } +[[link(android)]] class PlatformToolbox { static void hideCursor() = mac 0x27c340; static void showCursor() = mac 0x27c360; @@ -4500,6 +4693,7 @@ class PlatformToolbox { static void resizeWindow() = mac 0x27cfe0; } +[[link(android)]] class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, DialogDelegate { static PlayLayer* get() { return GameManager::sharedState()->getPlayLayer(); @@ -4828,6 +5022,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, bool m_disableGravityEffect; } +[[link(android)]] class PlayerCheckpoint : cocos2d::CCNode { // virtual ~PlayerCheckpoint() = mac 0x80760; inlined on windows static PlayerCheckpoint* create() = mac 0x7e8c0, win 0x20dc40; @@ -4848,6 +5043,7 @@ class PlayerCheckpoint : cocos2d::CCNode { bool m_hidden; } +[[link(android)]] class PlayerObject : GameObject, AnimatedSpriteDelegate { virtual ~PlayerObject() = mac 0x217220, win 0x1e6be0; virtual void update(float) = mac 0x218bf0, win 0x1e8200; @@ -5132,12 +5328,14 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate { PAD = win 0x1c; } +[[link(android)]] class PointNode : cocos2d::CCObject { static PointNode* create(cocos2d::CCPoint point) = win 0x14ec80; cocos2d::CCPoint m_point; } +[[link(android)]] class ProfilePage : FLAlertLayer, FLAlertLayerProtocol, LevelCommentDelegate, CommentUploadDelegate, UserInfoDelegate, UploadActionDelegate, UploadPopupDelegate, LeaderboardManagerDelegate { static ProfilePage* create(int accountID, bool idk) = mac 0x45eed0, win 0x20ee50; virtual void getUserInfoFailed(int) = mac 0x463FB0, win 0x2133e0; @@ -5155,15 +5353,18 @@ class ProfilePage : FLAlertLayer, FLAlertLayerProtocol, LevelCommentDelegate, Co cocos2d::CCArray* m_buttons; } +[[link(android)]] class PulseEffectAction : cocos2d::CCNode { static PulseEffectAction* createFromString(gd::string) = mac 0x179e90, win 0x1198a0; gd::string getSaveString() = mac 0x17a850, win 0x119e70; } +[[link(android)]] class RateLevelDelegate { virtual void rateLevelClosed() {} } +[[link(android)]] class RateStarsLayer : FLAlertLayer, UploadPopupDelegate, UploadActionDelegate { bool m_uploadFinished; bool m_isModSuggest; @@ -5182,14 +5383,17 @@ class RateStarsLayer : FLAlertLayer, UploadPopupDelegate, UploadActionDelegate { bool init(int levelID, bool isModSuggest) = mac 0x136050; } +[[link(android)]] class RetryLevelLayer { static RetryLevelLayer* create() = mac 0x28dd60, win 0x216390; } +[[link(android)]] class RewardsPage : FLAlertLayer { bool init() = mac 0xf3800, win 0x2178F0; } +[[link(android)]] class RingObject : EffectGameObject { bool create(char const*) = win 0x252220; bool init(char const*) = win 0x2522E0; @@ -5205,14 +5409,17 @@ class RingObject : EffectGameObject { virtual void triggerActivated(float) = win 0x252350; } +[[link(android)]] class ScrollingLayer : cocos2d::CCLayerColor { static ScrollingLayer* create(cocos2d::CCSize, cocos2d::CCPoint, float) = mac 0x41a900, win 0x2d8e0; } +[[link(android)]] class SelectArtLayer { static SelectArtLayer* create(SelectArtType type) = win 0x174b00; } +[[link(android)]] class SelectFontLayer : FLAlertLayer { static SelectFontLayer* create(LevelEditorLayer* lel) = win 0x137270; bool init(LevelEditorLayer* lel) = win 0x137310; @@ -5229,6 +5436,7 @@ class SelectFontLayer : FLAlertLayer { cocos2d::CCLabelBMFont* m_fontLabel; } +[[link(android)]] class SetGroupIDLayer : FLAlertLayer, TextInputDelegate { bool init(GameObject* object, cocos2d::CCArray* objects) = mac 0x1947c0, win 0x22b670; void onNextGroupID1(cocos2d::CCObject*) = mac 0x1967a0, win 0x22d790; @@ -5265,10 +5473,12 @@ class SetGroupIDLayer : FLAlertLayer, TextInputDelegate { int m_unknown; } +[[link(android)]] class SetIDLayer { static SetIDLayer* create(GameObject*) = mac 0x168f20, win 0x22eb90; } +[[link(android)]] class SetIDPopup : FLAlertLayer, TextInputDelegate { void valueChanged() = win 0x10a60; @@ -5277,14 +5487,17 @@ class SetIDPopup : FLAlertLayer, TextInputDelegate { static SetIDPopup *create(int, int, int, gd::string, gd::string, bool, int) = win 0x143130; } +[[link(android)]] class SetIDPopupDelegate { virtual void setIDPopupClosed(SetIDPopup*, int) {} } +[[link(android)]] class SetItemIDLayer { static SetItemIDLayer* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x5a830; } +[[link(android)]] class SetTargetIDLayer { static SetTargetIDLayer* create(EffectGameObject*, cocos2d::CCArray*, gd::string) = mac 0x159d20; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x15aed0; @@ -5292,10 +5505,12 @@ class SetTargetIDLayer { void updateTargetID() = mac 0x15b4a0; } +[[link(android)]] class SetTextPopupDelegate { virtual void setIDPopupClosed(void*, gd::string) {} } +[[link(android)]] class SetupAnimationPopup : FLAlertLayer { static SetupAnimationPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x208b70; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x209fc0; @@ -5303,6 +5518,7 @@ class SetupAnimationPopup : FLAlertLayer { void updateTargetID() = mac 0x20a910; } +[[link(android)]] class SetupCollisionTriggerPopup : FLAlertLayer { static SetupCollisionTriggerPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x1d6120; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x1d77b0; @@ -5312,6 +5528,7 @@ class SetupCollisionTriggerPopup : FLAlertLayer { void onClose(cocos2d::CCObject*) = win 0x235970; } +[[link(android)]] class SetupCountTriggerPopup : FLAlertLayer { static SetupCountTriggerPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x15c6c0; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x15dd40; @@ -5319,6 +5536,7 @@ class SetupCountTriggerPopup : FLAlertLayer { void updateTargetID() = mac 0x15e8a0; } +[[link(android)]] class SetupInstantCountPopup : FLAlertLayer { static SetupInstantCountPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x352c10; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x354520; @@ -5326,6 +5544,7 @@ class SetupInstantCountPopup : FLAlertLayer { void updateTargetID() = mac 0x355170; } +[[link(android)]] class SetupInteractObjectPopup : FLAlertLayer { static SetupInteractObjectPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x29a400; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x29bbc0; @@ -5333,6 +5552,7 @@ class SetupInteractObjectPopup : FLAlertLayer { void updateTargetID() = mac 0x29c120; } +[[link(android)]] class SetupObjectTogglePopup : FLAlertLayer { static SetupObjectTogglePopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x1c0860; bool init(EffectGameObject*, cocos2d::CCArray*) = mac 0x1c0a40; @@ -5341,6 +5561,7 @@ class SetupObjectTogglePopup : FLAlertLayer { void updateTargetID() = mac 0x1c2440; } +[[link(android)]] class SetupOpacityPopup : FLAlertLayer { static SetupOpacityPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x32b70, win 0x23ba30; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x340a0; @@ -5348,6 +5569,7 @@ class SetupOpacityPopup : FLAlertLayer { void updateTargetID() = mac 0x34760; } +[[link(android)]] class SetupPickupTriggerPopup : FLAlertLayer { static SetupPickupTriggerPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x35e70, win 0x23d4a0; void onItemIDArrow(cocos2d::CCObject*) = mac 0x37100; @@ -5359,6 +5581,7 @@ class SetupPickupTriggerPopup : FLAlertLayer { CCTextInputNode* m_countInput; } +[[link(android)]] class SetupPulsePopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, TextInputDelegate, GJSpecialColorSelectDelegate { virtual void colorValueChanged(cocos2d::ccColor3B color) = win 0x242660, mac 0x1ec680; SetupPulsePopup() {} @@ -5377,10 +5600,12 @@ class SetupPulsePopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, T int m_pulseMode; // 0x38c on mac } +[[link(android)]] class SetupShakePopup : FLAlertLayer { static SetupShakePopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x3adc00; } +[[link(android)]] class SetupSpawnPopup : FLAlertLayer { static SetupSpawnPopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x139790; void createToggleButton(gd::string, cocos2d::SEL_MenuHandler, bool, cocos2d::CCMenu*, cocos2d::CCPoint, cocos2d::CCArray*) = mac 0x13b0e0; @@ -5406,6 +5631,7 @@ class SetupSpawnPopup : FLAlertLayer { bool m_editorDisable; } +[[link(android)]] class SetupTouchTogglePopup : FLAlertLayer { static SetupTouchTogglePopup* create(EffectGameObject*, cocos2d::CCArray*) = mac 0x1576a0; void onTargetIDArrow(cocos2d::CCObject*) = mac 0x158b60; @@ -5413,6 +5639,7 @@ class SetupTouchTogglePopup : FLAlertLayer { void updateTargetID() = mac 0x159480; } +[[link(android)]] class SimplePlayer : cocos2d::CCSprite { SimplePlayer() {} void setSecondColor(const cocos2d::ccColor3B& color) { @@ -5447,6 +5674,7 @@ class SimplePlayer : cocos2d::CCSprite { bool m_hasGlowOutline; } +[[link(android)]] class Slider : cocos2d::CCLayer { void setValue(float val) { m_touchLogic->getThumb()->setValue(val); @@ -5469,6 +5697,7 @@ class Slider : cocos2d::CCLayer { float m_height; } +[[link(android)]] class SliderThumb : cocos2d::CCMenuItemImage { void setValue(float val) = mac 0x18ce80, win 0x2e1b0, ios 0x210db4; float getValue() { @@ -5483,6 +5712,7 @@ class SliderThumb : cocos2d::CCMenuItemImage { bool m_vertical; } +[[link(android)]] class SliderTouchLogic : cocos2d::CCMenu { SliderThumb* getThumb() const { return m_thumb; } @@ -5495,10 +5725,12 @@ class SliderTouchLogic : cocos2d::CCMenu { bool m_rotated; } +[[link(android)]] class SongCell : TableViewCell { void updateBGColor(int index) = win 0x5c6b0; } +[[link(android)]] class SongInfoLayer : FLAlertLayer { static SongInfoLayer* create(int songID) = win 0x250520; static SongInfoLayer* create(gd::string songName, gd::string artistName, gd::string downloadLink, gd::string artistNG, gd::string artistYT, gd::string artistFB) = win 0x250830; @@ -5509,6 +5741,7 @@ class SongInfoLayer : FLAlertLayer { gd::string m_artistFacebook; } +[[link(android)]] class SongInfoObject : cocos2d::CCNode { virtual ~SongInfoObject() = mac 0x2f2040, win 0x196600; virtual void encodeWithCoder(DS_Dictionary*) = mac 0x2f2c70, win 0x1975c0; @@ -5527,6 +5760,7 @@ class SongInfoObject : cocos2d::CCNode { LevelSettingsObject* m_levelSettings; } +[[link(android)]] class SpawnTriggerAction : cocos2d::CCNode { static SpawnTriggerAction* createFromString(gd::string) = mac 0x17bf50; @@ -5537,6 +5771,7 @@ class SpawnTriggerAction : cocos2d::CCNode { int m_uuid; } +[[link(android)]] class SpeedObject : cocos2d::CCNode { float m_unknown; float m_somethingToCompare; @@ -5544,8 +5779,10 @@ class SpeedObject : cocos2d::CCNode { float m_idk4; } +[[link(android)]] class SpritePartDelegate {} +[[link(android)]] class StartPosObject : EffectGameObject { static StartPosObject* create() = mac 0xda7c0, win 0x25aa40; void setSettings(LevelSettingsObject*) = mac 0xda910; @@ -5553,6 +5790,7 @@ class StartPosObject : EffectGameObject { LevelSettingsObject* m_levelSettings; } +[[link(android)]] class StatsCell : TableViewCell { inline StatsCell() {} inline StatsCell(char const* identifier, float parentHeight, float height) : TableViewCell(identifier, parentHeight, height) {} @@ -5560,10 +5798,12 @@ class StatsCell : TableViewCell { virtual void draw() = mac 0x11bf80, win 0x59d40; } +[[link(android)]] class StatsLayer : GJDropDownLayer { static StatsLayer* create() = win 0x25BCF0; } +[[link(android)]] class TableView : CCScrollLayerExt, CCScrollLayerExtDelegate { inline TableView() {} inline TableView(cocos2d::CCRect rect) : CCScrollLayerExt(rect) {} @@ -5608,7 +5848,7 @@ class TableView : CCScrollLayerExt, CCScrollLayerExtDelegate { bool m_cancellingTouches; } -[[depends(CCIndexPath)]] +[[depends(CCIndexPath), link(android)]] class TableViewCell : cocos2d::CCLayer { inline TableViewCell() {} inline ~TableViewCell() { @@ -5646,6 +5886,7 @@ class TableViewCell : cocos2d::CCLayer { cocos2d::CCLayer* m_mainLayer; } +[[link(android)]] class TableViewDataSource { virtual int numberOfRowsInSection(unsigned int, TableView*) { return 0; } virtual unsigned int numberOfSectionsInTableView(TableView*) { return 0; } @@ -5653,6 +5894,7 @@ class TableViewDataSource { virtual TableViewCell* cellForRowAtIndexPath(CCIndexPath&, TableView*) { return nullptr; } } +[[link(android)]] class TableViewDelegate { virtual void willTweenToIndexPath(CCIndexPath&, TableViewCell*, TableView*) {} virtual void didEndTweenToIndexPath(CCIndexPath&, TableView*) {} @@ -5663,6 +5905,7 @@ class TableViewDelegate { virtual void didSelectRowAtIndexPath(CCIndexPath&, TableView*) {} } +[[link(android)]] class TeleportPortalObject : GameObject { PAD = mac 0x8, win 0x4; TeleportPortalObject* m_orangePortal; @@ -5671,10 +5914,12 @@ class TeleportPortalObject : GameObject { bool m_teleportEase; } +[[link(android)]] class TextAlertPopup : cocos2d::CCNode { static TextAlertPopup* create(gd::string text, float time, float scale) = mac 0x157080, win 0x1450b0; } +[[link(android)]] class TextArea : cocos2d::CCSprite { // https://www.youtube.com/watch?v=1LVW7IUyKMg TextArea() = mac 0x19fba0, win 0x33110, ios 0x92c28; @@ -5695,6 +5940,7 @@ class TextArea : cocos2d::CCSprite { float m_height; // 0x20c } +[[link(android)]] class TextInputDelegate { virtual void textChanged(CCTextInputNode*) {} virtual void textInputOpened(CCTextInputNode*) {} @@ -5704,10 +5950,12 @@ class TextInputDelegate { virtual bool allowTextInput(CCTextInputNode*) {return true;} } +[[link(android)]] class ToggleTriggerAction : cocos2d::CCNode { static ToggleTriggerAction* createFromString(gd::string) = mac 0x1765e0; } +[[link(android)]] class TopArtistsLayer : FLAlertLayer { static TopArtistsLayer* create() = mac 0x192a90, win 0x25d8e0; virtual ~TopArtistsLayer() = win 0x25d7c0; @@ -5717,15 +5965,18 @@ class TopArtistsLayer : FLAlertLayer { void setupPageInfo(gd::string, char const*) = mac 0x193730; } +[[link(android)]] class TouchToggleAction : cocos2d::CCNode { static TouchToggleAction* createFromString(gd::string) = mac 0x177e10; } +[[link(android)]] class TriggerEffectDelegate { virtual void toggleGroupTriggered(int, bool) {} virtual void spawnGroup(int) {} } +[[link(android)]] class UILayer : cocos2d::CCLayerColor { static UILayer* create() = mac 0x27fd10, win 0x25f310; virtual bool init() = mac 0x27fe40, win 0x25f3b0; @@ -5747,6 +5998,7 @@ class UILayer : cocos2d::CCLayerColor { cocos2d::CCMenu* m_checkPointMenu; } +[[link(android)]] class UndoObject : cocos2d::CCObject { ~UndoObject() = mac 0xa2fd0; static UndoObject* create(GameObject*, UndoCommand) = mac 0x94ea0, win 0x16bc20; @@ -5759,11 +6011,13 @@ class UndoObject : cocos2d::CCObject { bool m_redo; } +[[link(android)]] class UploadActionDelegate { virtual void uploadActionFinished(int, int) {} virtual void uploadActionFailed(int, int) {} } +[[link(android)]] class UploadActionPopup : FLAlertLayer { UploadPopupDelegate* m_popupDelegate; TextArea* m_messageArea; @@ -5771,18 +6025,22 @@ class UploadActionPopup : FLAlertLayer { CCMenuItemSpriteExtra* m_closeBtn; } +[[link(android)]] class UploadMessageDelegate {} +[[link(android)]] class UploadPopupDelegate { virtual void onClosePopup() {} } +[[link(android)]] class UserInfoDelegate { virtual void getUserInfoFinished(GJUserScore *) {} virtual void getUserInfoFailed(int) {} virtual void userInfoChanged(GJUserScore *) {} } +[[link(android)]] class UserListDelegate { virtual void forceReloadList(UserListType) {} virtual void getUserListFailed(UserListType, GJErrorCode) {} @@ -5790,6 +6048,7 @@ class UserListDelegate { virtual void userListChanged(cocos2d::CCArray*, UserListType) {} } +[[link(android)]] class VideoOptionsLayer : FLAlertLayer { VideoOptionsLayer* create() = win 0x1e0d70; bool init() = win 0x1e0e10; @@ -5815,6 +6074,7 @@ class VideoOptionsLayer : FLAlertLayer { int m_currentResolution; } +[[link(android)]] class LevelTools { static gd::string base64EncodeString(gd::string) = mac 0x294470, win 0x18b310; static gd::string base64DecodeString(gd::string) = mac 0x294510, win 0x18b3b0; diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index eb4359c32..1b5e3735d 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -62,7 +62,7 @@ class {class_name}{base_classes} {{ )GEN"; // requires: type, member_name, array - char const* member_definition = R"GEN({private} {type} {member_name};{public} + char const* member_definition = R"GEN(/*make this private when android headers are done*/{public} {type} {member_name};{public} )GEN"; char const* pad_definition = R"GEN( GEODE_PAD({hardcode}); @@ -233,7 +233,7 @@ std::string generateBindingHeader(Root const& root, ghc::filesystem::path const& } else if (auto fn = field.get_as()) { fb = &fn->prototype; - if (!codegen::platformNumber(fn->binds)) { + if (!codegen::platformNumber(fn->binds) && codegen::getStatus(field) != BindStatus::Binded) { used_format = format_strings::error_definition; if (fb->type != FunctionType::Normal) diff --git a/loader/src/platform/android/ModImpl.cpp b/loader/src/platform/android/ModImpl.cpp index e4d99fbda..998ed8d85 100644 --- a/loader/src/platform/android/ModImpl.cpp +++ b/loader/src/platform/android/ModImpl.cpp @@ -8,7 +8,8 @@ using namespace geode::prelude; Result<> Mod::Impl::loadPlatformBinary() { - auto so = dlopen((m_tempDirName / m_info.binaryName()).string().c_str(), RTLD_LAZY); + auto so = + dlopen((m_tempDirName / m_metadata.getBinaryName()).string().c_str(), RTLD_LAZY); if (so) { if (m_platformInfo) { delete m_platformInfo; From 175f488c23202079f190e57ae88f7ceff71622ca Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:50:13 +0300 Subject: [PATCH 022/135] Add android.cpp to test members --- loader/test/members/Android.cpp | 9 +++++++++ loader/test/members/CMakeLists.txt | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 loader/test/members/Android.cpp diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp new file mode 100644 index 000000000..87e816305 --- /dev/null +++ b/loader/test/members/Android.cpp @@ -0,0 +1,9 @@ +#include "Common.hpp" + +#ifdef GEODE_IS_ANDROID + +// Add known android struct members here + +// needed classes are ones in the ids folder and some generic ones (i think they are already done though so only ids) + +#endif \ No newline at end of file diff --git a/loader/test/members/CMakeLists.txt b/loader/test/members/CMakeLists.txt index c7a518f41..961d99863 100644 --- a/loader/test/members/CMakeLists.txt +++ b/loader/test/members/CMakeLists.txt @@ -4,7 +4,7 @@ set(PROJECT_NAME TestMembers) project(${PROJECT_NAME} VERSION 1.0.0) -add_library(${PROJECT_NAME} SHARED MacOS.cpp Windows.cpp) +add_library(${PROJECT_NAME} SHARED MacOS.cpp Windows.cpp Android.cpp) target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_20) target_include_directories(${PROJECT_NAME} PRIVATE From 1d53ce76957a476e09a40084b979084d69930b6c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 14:59:12 +0300 Subject: [PATCH 023/135] Make missimg members private, ifdef missing ids --- codegen/src/BindingGen.cpp | 2 +- loader/src/ids/EditorPauseLayer.cpp | 4 ++++ loader/src/ids/LevelBrowserLayer.cpp | 4 ++++ loader/src/ids/LevelInfoLayer.cpp | 4 ++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index 1b5e3735d..6aa89a231 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -62,7 +62,7 @@ class {class_name}{base_classes} {{ )GEN"; // requires: type, member_name, array - char const* member_definition = R"GEN(/*make this private when android headers are done*/{public} {type} {member_name};{public} + char const* member_definition = R"GEN( {private} {type} {member_name};{public} )GEN"; char const* pad_definition = R"GEN( GEODE_PAD({hardcode}); diff --git a/loader/src/ids/EditorPauseLayer.cpp b/loader/src/ids/EditorPauseLayer.cpp index 7c44a3f7e..c1284360d 100644 --- a/loader/src/ids/EditorPauseLayer.cpp +++ b/loader/src/ids/EditorPauseLayer.cpp @@ -2,6 +2,8 @@ #include +#if !defined(GEODE_IS_ANDROID) + using namespace geode::prelude; // special class for this because making it a CCMenuItemToggler would be very UB @@ -272,3 +274,5 @@ struct EditorPauseLayerIDs : Modify { return true; } }; + +#endif \ No newline at end of file diff --git a/loader/src/ids/LevelBrowserLayer.cpp b/loader/src/ids/LevelBrowserLayer.cpp index d3ef28e2d..7723454b8 100644 --- a/loader/src/ids/LevelBrowserLayer.cpp +++ b/loader/src/ids/LevelBrowserLayer.cpp @@ -4,6 +4,8 @@ #include #include +#if !defined(GEODE_IS_ANDROID) + using namespace geode::prelude; $register_ids(LevelBrowserLayer) { @@ -171,3 +173,5 @@ struct LevelBrowserLayerIDs : Modify { return true; } }; + +#endif \ No newline at end of file diff --git a/loader/src/ids/LevelInfoLayer.cpp b/loader/src/ids/LevelInfoLayer.cpp index d2f96629f..5edfe2526 100644 --- a/loader/src/ids/LevelInfoLayer.cpp +++ b/loader/src/ids/LevelInfoLayer.cpp @@ -3,6 +3,8 @@ #include #include +#if !defined(GEODE_IS_ANDROID) + $register_ids(LevelInfoLayer) { auto winSize = CCDirector::get()->getWinSize(); @@ -135,3 +137,5 @@ struct LevelInfoLayerIDs : Modify { return true; } }; + +#endif \ No newline at end of file From bb032cc160ed91eccc37b11cca5fba400d3a3dd2 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:25:28 +0300 Subject: [PATCH 024/135] Fix not linking to functions --- bindings/GeometryDash.bro | 17 ++++++++--------- codegen/src/BindingGen.cpp | 2 +- codegen/src/SourceGen.cpp | 6 +++--- loader/test/members/Android.cpp | 5 +++++ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index cda687a4d..29b12d1da 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -2071,7 +2071,7 @@ class GJBaseGameLayer : cocos2d::CCLayer, TriggerEffectDelegate { int m_lastVisibleSection; bool m_objectsAreDisabled; bool m_blending; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; } [[link(android)]] @@ -3192,19 +3192,18 @@ class GameManager : GManager { bool m_switchModes; bool m_toFullscreen; bool m_reloading; - bool m_unknown0; - PAD = mac 0x4, win 0x4; + PAD = mac 0x5, win 0x5, android 0x1; cocos2d::CCDictionary* m_valueKeeper; cocos2d::CCDictionary* m_unlockValueKeeper; cocos2d::CCDictionary* m_customObjectDict; double m_adTimer; double m_adCache; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; double m_unknownDouble; // TODO: according to wylie's decomp this pad was 0x4, gd.h has it as 0x8 (and its correct) // i have a feeling android gm and windows gm are different structs // so the extra member could be here (for windows) - PAD = mac 0x4, win 0x8; + PAD = mac 0x4, win 0x8, android 0x8; bool m_loaded; gd::string m_unknownString; PlayLayer* m_playLayer; @@ -4871,7 +4870,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, bool m_debugPauseOff; bool m_shouldSmoothCamera; float unused_4e0; - PAD = mac 0x4, win 0x4; + PAD = mac 0x4, win 0x4, android 0x4; cocos2d::CCDrawNode* unknown4e8; float m_camera4f0; int unused4f4; @@ -4885,7 +4884,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, float unknown510; float unknown514; float unknown518; - PAD = mac 0x4, win 0x4; + PAD = mac 0x4, win 0x4, android 0x4; StartPosObject* m_startPos; CheckpointObject* m_startPosCheckpoint; EndPortalObject* m_endPortal; @@ -4918,7 +4917,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, float unknown5c4; GJGroundLayer* m_bottomGround; GJGroundLayer* m_topGround; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; bool m_isDead; bool m_startCameraAtCorner; bool m_cameraYLocked; @@ -4952,7 +4951,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, int unknown680; int m_activeGravityEffects; int m_gravityEffectStatus; // ?? - PAD = mac 0x4, win 0x4; + PAD = mac 0x4, win 0x4, android 0x4; cocos2d::CCArray* m_gravitySprites; bool unk428; bool m_shouldRecordActions; diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index 6aa89a231..c1d5b0152 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -62,7 +62,7 @@ class {class_name}{base_classes} {{ )GEN"; // requires: type, member_name, array - char const* member_definition = R"GEN( {private} {type} {member_name};{public} + char const* member_definition = R"GEN({private} {type} {member_name};{public} )GEN"; char const* pad_definition = R"GEN( GEODE_PAD({hardcode}); diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 35f589623..eee73f196 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -157,9 +157,9 @@ std::string generateBindingSource(Root const& root) { // yeah there are no inlines on cocos } else if (auto fn = f.get_as()) { - if ((c.links & codegen::platform) != Platform::None) { - continue; - } + // if ((c.links & codegen::platform) != Platform::None) { + // continue; + // } if (codegen::getStatus(f) != BindStatus::Unbindable) { continue; } diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index 87e816305..fb5a10fd6 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -6,4 +6,9 @@ // needed classes are ones in the ids folder and some generic ones (i think they are already done though so only ids) +GEODE_MEMBER_CHECK(GameManager, m_playLayer, 0x138); +GEODE_MEMBER_CHECK(GameManager, m_levelEditorLayer, 0x13c); + +GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); + #endif \ No newline at end of file From 4e8f7866bf7e70b2890c20a8b398769fc4000ccc Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:38:03 +0300 Subject: [PATCH 025/135] Playlayer is different on android? --- bindings/GeometryDash.bro | 1 + loader/test/members/Android.cpp | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 29b12d1da..023c7cc46 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -4862,6 +4862,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, void xPosForTime(float) = mac 0x7d140, win 0x208840; ~PlayLayer() = mac 0x6b090, win 0x1fafc0; + // there is 0x10 more for android between this and ccdrawnode float unused4c8; bool unused4cc; bool m_hasCheated; diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index fb5a10fd6..ed8129cbc 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -9,6 +9,12 @@ GEODE_MEMBER_CHECK(GameManager, m_playLayer, 0x138); GEODE_MEMBER_CHECK(GameManager, m_levelEditorLayer, 0x13c); -GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); +static_assert(sizeof(GJBaseGameLayer) == 0x2cc); + +// GEODE_MEMBER_CHECK(PlayLayer, unknown4e8, 0x2e8); +// GEODE_MEMBER_CHECK(PlayLayer, m_endPortal, 0x324); +// GEODE_MEMBER_CHECK(PlayLayer, m_bottomGround, 0x37c); +// GEODE_MEMBER_CHECK(PlayLayer, m_topGround, 0x380); +// GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); #endif \ No newline at end of file From 0e324c444c98f0c67708bdb28caf215e7b187775 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:49:24 +0300 Subject: [PATCH 026/135] Add android gd string and comment out addresses for now --- codegen/src/AddressGen.cpp | 2 +- loader/src/platform/android/gdstdlib.cpp | 61 ++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 loader/src/platform/android/gdstdlib.cpp diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index bc154b1c5..295ccbde5 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -122,7 +122,7 @@ std::string generateAddressHeader(Root const& root) { } else if (codegen::getStatus(field) == BindStatus::Binded && fn->prototype.type == FunctionType::Normal) { address_str = fmt::format( - "addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))", + "0/*addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))*/", str_if("Non", !fn->prototype.is_virtual), codegen::getParameterTypes(fn->prototype), field.parent, diff --git a/loader/src/platform/android/gdstdlib.cpp b/loader/src/platform/android/gdstdlib.cpp new file mode 100644 index 000000000..d4ec86538 --- /dev/null +++ b/loader/src/platform/android/gdstdlib.cpp @@ -0,0 +1,61 @@ +#include + +#ifdef GEODE_IS_ANDROID + +namespace gd { + namespace { + static inline auto emptyInternalString() { + return reinterpret_cast<_internal_string*>( + *reinterpret_cast(geode::base::get() + 0x75fb24) + sizeof(_internal_string) + ); + } + } + + string::string() : m_data(nullptr) { + m_data = emptyInternalString(); + } + + string::string(char const* ok) : m_data(nullptr) { + reinterpret_cast(geode::base::get() + 0x506c08)(this, ok); + } + + string::string(string const& ok) : m_data(nullptr) { + if (*(string**)(&ok) == nullptr) return; + reinterpret_cast(geode::base::get() + 0x506634)(this, ok); + } + + string& string::operator=(char const* ok) { + this->~string(); + new (this) string(ok); + return *this; + } + + string& string::operator=(string const& ok) { + this->~string(); + new (this) string(ok); + return *this; + } + + string::~string() { + if (m_data == nullptr) return; + reinterpret_cast(geode::base::get() + 0x5054bc)( + &m_data[-1] + ); + } + + bool string::operator<(string const& other) const { + return std::string(*this) < std::string(other); + } + + bool string::operator==(string const& other) const { + return std::string(*this) == std::string(other); + } + + // TODO: these need to stay for old mods linking against geode <1.2.0, remove in 2.0.0 + template class map; + template class map; + template class map; + template class map; +} + +#endif \ No newline at end of file From 7bfc4e438e2ba2f190adf7dd461ced99e3b229d3 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:53:24 +0300 Subject: [PATCH 027/135] readd the thingy but uhh --- codegen/src/SourceGen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index eee73f196..000dd6dd9 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -157,9 +157,9 @@ std::string generateBindingSource(Root const& root) { // yeah there are no inlines on cocos } else if (auto fn = f.get_as()) { - // if ((c.links & codegen::platform) != Platform::None) { - // continue; - // } + if (is_cocos_class(c.name) && (c.links & codegen::platform) != Platform::None) { + continue; + } if (codegen::getStatus(f) != BindStatus::Unbindable) { continue; } From 4715072c8612909c2db89a8cfee43d6ee472f739 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 14 Sep 2023 15:56:51 +0300 Subject: [PATCH 028/135] Add platform specific funcs --- loader/src/platform/android/util.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 35e6f5975..f8d52e3e4 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -30,4 +30,18 @@ geode::Result utils::file:: return geode::Err("This function is currently unimplemented"); } +void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) { + log::error("Launching Geode uninstaller is not supported on android"); +} + +void geode::utils::game::exit() { + // Not implemented + log::error("Exiting the game is not implemented on android"); +} + +void geode::utils::game::restart() { + // Not implemented + log::error("Restarting the game is not implemented on android"); +} + #endif From 3559064b45a113020a288c1b1a71dc23d591ba0b Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Thu, 14 Sep 2023 16:31:39 -0300 Subject: [PATCH 029/135] add mangler for gd::string symbols --- codegen/src/AddressGen.cpp | 10 ++- codegen/src/AndroidSymbol.hpp | 143 ++++++++++++++++++++++++++++++++++ codegen/src/Shared.hpp | 9 +++ codegen/src/SourceGen.cpp | 4 +- 4 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 codegen/src/AndroidSymbol.hpp diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 295ccbde5..0e969dbe2 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -1,4 +1,5 @@ #include "Shared.hpp" +#include "AndroidSymbol.hpp" namespace { namespace format_strings { @@ -120,9 +121,16 @@ std::string generateAddressHeader(Root const& root) { address_str = fmt::format("base::get() + 0x{:x}", codegen::platformNumber(fn->binds)); } } + else if (codegen::shouldAndroidBind(fn)) { + auto const mangled = generateAndroidSymbol(c, fn); + address_str = fmt::format( + "reinterpret_cast(dlsym(reinterpret_cast(geode::base::get()), \"{}\"))", + mangled + ); + } else if (codegen::getStatus(field) == BindStatus::Binded && fn->prototype.type == FunctionType::Normal) { address_str = fmt::format( - "0/*addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))*/", + "addresser::get{}Virtual(Resolve<{}>::func(&{}::{}))", str_if("Non", !fn->prototype.is_virtual), codegen::getParameterTypes(fn->prototype), field.parent, diff --git a/codegen/src/AndroidSymbol.hpp b/codegen/src/AndroidSymbol.hpp new file mode 100644 index 000000000..dbb936e54 --- /dev/null +++ b/codegen/src/AndroidSymbol.hpp @@ -0,0 +1,143 @@ +#pragma once + +#include "Shared.hpp" + +#include +#include +#include +#include + +std::string mangleIdent(std::string_view str) { + if (str.find("::") != -1) { + std::string result = "N"; + auto s = str; + do { + const auto i = s.find("::"); + const auto t = s.substr(0, i); + result += std::to_string(t.size()) + std::string(t); + if (i == -1) s = ""; + else + s = s.substr(i + 2); + } while(s.size()); + return result + "E"; + } else { + return std::to_string(str.size()) + std::string(str); + } +}; + +std::string intToString(unsigned int value, unsigned int radix) { + static constexpr char base36[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + std::string result; + do { + unsigned int remainder = value % radix; + value /= radix; + result.insert(result.begin(), base36[remainder]); + } while (value); + return result; +} + +std::string lookForSeen(std::vector& seen, std::string mangled) { + for (int i = 0; i < seen.size(); ++i) { + if (seen[i] == mangled) { + if (i == 0) return "S_"; + // yes, its base 36 + return "S" + intToString(i - 1, 36) + "_"; + } + } + return ""; +} + +std::string subsSeen(std::vector& seen, std::string mangled, bool subs) { + if (!subs) return mangled; + if (mangled.empty()) return mangled; + if (auto x = lookForSeen(seen, mangled); !x.empty()) return x; + seen.push_back(mangled); + return mangled; +} + +std::string mangleType(std::vector& seen, std::string name, bool subs = true) { + if (name == "int") return "i"; + if (name == "float") return "f"; + if (name == "bool") return "b"; + if (name == "char") return "c"; + if (name == "gd::string") return "Ss"; + if (name == "cocos2d::ccColor3B") return mangleType(seen, "cocos2d::_ccColor3B", subs); + // too lazy + if (name == "gd::map") return "St3mapISsSsSt4lessISsESaISt4pairIKSsSsEEE"; + if (name == "cocos2d::SEL_MenuHandler") { + const auto a = mangleType(seen, "cocos2d::CCObject", subs); + const auto b = mangleType(seen, "cocos2d::CCObject*", subs); + const auto fnptr = subsSeen(seen, "Fv" + b + "E", subs); + return subsSeen(seen, "M" + a + fnptr, subs); + } + if (name.find('*') == name.size() - 1) { + auto inner = mangleType(seen, name.substr(0, name.size() - 1), false); + if (auto x = lookForSeen(seen, "P" + inner); !x.empty()) return x; + inner = mangleType(seen, name.substr(0, name.size() - 1), subs); + return subsSeen(seen, "P" + inner, subs); + } + if (name.find('&') == name.size() - 1) { + auto inner = mangleType(seen, name.substr(0, name.size() - 1), false); + if (auto x = lookForSeen(seen, "R" + inner); !x.empty()) return x; + inner = mangleType(seen, name.substr(0, name.size() - 1), subs); + return subsSeen(seen, "R" + inner, subs); + } + if (auto i = name.find("const"); i != -1) { + std::string inner; + // at the end of the name + if (i == name.size() - 5) { + inner = mangleType(seen, name.substr(0, i - 1)); + } else if (i == 0) { + inner = mangleType(seen, name.substr(6)); + } else { + inner = "v"; + std::cout << "um " << name << std::endl; + } + return subsSeen(seen, "K" + inner, subs); + } + + if (name.find("::") != -1) { + std::string result = ""; + std::string substituted = ""; + auto s = name; + do { + const auto i = s.find("::"); + const auto t = s.substr(0, i); + auto part = std::to_string(t.size()) + std::string(t); + if (auto x = lookForSeen(seen, result + part); !x.empty()) { + substituted = x; + } else { + substituted = subsSeen(seen, substituted + part, subs); + } + result += part; + + if (i == -1) s = ""; + else s = s.substr(i + 2); + } while(s.size()); + if (substituted.size() == 3 && substituted[0] == 'S') + return substituted; + return "N" + substituted + "E"; + } else { + return subsSeen(seen, mangleIdent(name), subs); + } +}; + +std::string generateAndroidSymbol(const Class& clazz, const FunctionBindField* fn) { + auto& decl = fn->prototype; + + std::string mangledSymbol = "_Z" + mangleIdent(clazz.name + "::" + decl.name); + if (decl.args.empty()) { + mangledSymbol += "v"; + } else { + std::vector seen; + static constexpr auto firstPart = [](std::string_view str, std::string_view sep) { + return str.substr(0, str.find(sep)); + }; + // this is S_ + seen.push_back(mangleIdent(firstPart(clazz.name, "::"))); + for (auto& [ty, _] : decl.args) { + mangledSymbol += mangleType(seen, ty.name); + } + } + return mangledSymbol; +} \ No newline at end of file diff --git a/codegen/src/Shared.hpp b/codegen/src/Shared.hpp index c8e07b6fb..a2a694434 100644 --- a/codegen/src/Shared.hpp +++ b/codegen/src/Shared.hpp @@ -129,6 +129,15 @@ namespace codegen { return BindStatus::Unbindable; } + inline bool shouldAndroidBind(const FunctionBindField* fn) { + if (codegen::platform == Platform::Android) { + for (auto& [type, name] : fn->prototype.args) { + if (can_find(type.name, "gd::")) return true; + } + } + return false; + } + inline BindStatus getStatus(Field const& field) { return getStatusWithPlatform(codegen::platform, field); } diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 000dd6dd9..230a31fcd 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -198,10 +198,10 @@ std::string generateBindingSource(Root const& root) { ) { used_declare_format = format_strings::declare_virtual_error; } - else if (codegen::getStatus(f) != BindStatus::NeedsBinding) { + else if (codegen::getStatus(f) != BindStatus::NeedsBinding && !codegen::shouldAndroidBind(fn)) { continue; } - + if (!used_declare_format) { switch (fn->prototype.type) { From 372ea0e78c49527396f642b04449dea424820905 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 08:17:40 +0300 Subject: [PATCH 030/135] remove the expand sprite log --- codegen/src/SourceGen.cpp | 2 +- loader/src/loader/ModImpl.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 35f589623..26a911a16 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -198,7 +198,7 @@ std::string generateBindingSource(Root const& root) { ) { used_declare_format = format_strings::declare_virtual_error; } - else if (codegen::getStatus(f) != BindStatus::NeedsBinding) { + else if (codegen::getStatus(f) != BindStatus::NeedsBinding && !android_has_boobs(f)) { continue; } diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 1f2a85737..bc21fc9f4 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -592,7 +592,6 @@ ghc::filesystem::path Mod::Impl::getConfigDir(bool create) const { } char const* Mod::Impl::expandSpriteName(char const* name) { - log::debug("Expanding sprite name {} for {}", name, m_metadata.getID()); if (m_expandedSprites.count(name)) return m_expandedSprites[name]; auto exp = new char[strlen(name) + 2 + m_metadata.getID().size()]; From 3b359726f86e943e74cfc8e269ebe815e67b7686 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 08:20:18 +0300 Subject: [PATCH 031/135] Remove the thing that was left when i was explaining to mat what to edit on the codegen to support android --- codegen/src/SourceGen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 26a911a16..35f589623 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -198,7 +198,7 @@ std::string generateBindingSource(Root const& root) { ) { used_declare_format = format_strings::declare_virtual_error; } - else if (codegen::getStatus(f) != BindStatus::NeedsBinding && !android_has_boobs(f)) { + else if (codegen::getStatus(f) != BindStatus::NeedsBinding) { continue; } From 887f82fc1d9f0ab25c54a88e983ce9c79552bd4c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 14:04:12 +0300 Subject: [PATCH 032/135] remove link from platform toolbox --- bindings/GeometryDash.bro | 1 - codegen/src/AddressGen.cpp | 1 - 2 files changed, 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 023c7cc46..bdc1bcf3c 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -4674,7 +4674,6 @@ class PlatformDownloadDelegate { virtual void downloadFailed(char const*) {} } -[[link(android)]] class PlatformToolbox { static void hideCursor() = mac 0x27c340; static void showCursor() = mac 0x27c360; diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 0e969dbe2..0db80e7c3 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -112,7 +112,6 @@ std::string generateAddressHeader(Root const& root) { continue; } - if (codegen::getStatus(field) == BindStatus::NeedsBinding || codegen::platformNumber(field)) { if (is_cocos_class(field.parent) && codegen::platform == Platform::Windows) { address_str = fmt::format("base::getCocos() + 0x{:x}", codegen::platformNumber(fn->binds)); From dc8e34d8b88ef8d473cee64ea1ed5eb9aa67518e Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 18:37:04 +0300 Subject: [PATCH 033/135] Update tuliphook --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f8e9e9288..ad961b7fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#9f1938f") +CPMAddPackage("gh:geode-sdk/TulipHook#086ea58") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies From 9906a8ff7893f4a63e176a574d466bab9d96bfa1 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 19:38:15 +0300 Subject: [PATCH 034/135] fix android empty string --- loader/src/platform/android/gdstdlib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/platform/android/gdstdlib.cpp b/loader/src/platform/android/gdstdlib.cpp index d4ec86538..b37ae929e 100644 --- a/loader/src/platform/android/gdstdlib.cpp +++ b/loader/src/platform/android/gdstdlib.cpp @@ -6,7 +6,7 @@ namespace gd { namespace { static inline auto emptyInternalString() { return reinterpret_cast<_internal_string*>( - *reinterpret_cast(geode::base::get() + 0x75fb24) + sizeof(_internal_string) + geode::base::get() + 0x75fb24 + sizeof(_internal_string) ); } } From 7c55b215d15cfb2a6f1a3c473400fdcf1c1e0575 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 19:59:55 +0300 Subject: [PATCH 035/135] comment string dtor & add +1 to dlsym --- codegen/src/AddressGen.cpp | 4 ++-- loader/src/platform/android/gdstdlib.cpp | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 0db80e7c3..aa7b3a338 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -122,8 +122,8 @@ std::string generateAddressHeader(Root const& root) { } else if (codegen::shouldAndroidBind(fn)) { auto const mangled = generateAndroidSymbol(c, fn); - address_str = fmt::format( - "reinterpret_cast(dlsym(reinterpret_cast(geode::base::get()), \"{}\"))", + address_str = fmt::format( // thumb + "reinterpret_cast(dlsym(reinterpret_cast(geode::base::get()), \"{}\")) + 1", mangled ); } diff --git a/loader/src/platform/android/gdstdlib.cpp b/loader/src/platform/android/gdstdlib.cpp index b37ae929e..da52cff9d 100644 --- a/loader/src/platform/android/gdstdlib.cpp +++ b/loader/src/platform/android/gdstdlib.cpp @@ -38,9 +38,7 @@ namespace gd { string::~string() { if (m_data == nullptr) return; - reinterpret_cast(geode::base::get() + 0x5054bc)( - &m_data[-1] - ); + // reinterpret_cast(geode::base::get() + 0x5054bc)(this); } bool string::operator<(string const& other) const { From 4294177be6fb8a5fa26753a5a29a7eabdc79042a Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Fri, 15 Sep 2023 23:37:18 +0300 Subject: [PATCH 036/135] gd opens rn lol! but i commented like everything --- CMakeLists.txt | 2 +- loader/include/Geode/platform/android.hpp | 5 +-- loader/src/cocos2d-ext/CCFileUtils.cpp | 1 + loader/src/hooks/LoadingLayer.cpp | 4 +++ loader/src/hooks/persist.cpp | 12 +++---- loader/src/hooks/save.cpp | 22 ++++++------- loader/src/hooks/update.cpp | 2 ++ loader/src/ids/CCTextInputNode.cpp | 38 +++++++++++----------- loader/src/loader/LoaderImpl.cpp | 34 +++++++++---------- loader/src/loader/ModImpl.cpp | 2 +- loader/src/platform/android/LoaderImpl.cpp | 2 +- loader/src/platform/android/gdstdlib.cpp | 11 ++++++- loader/src/platform/android/util.cpp | 4 +-- loader/src/utils/web.cpp | 8 +++++ 14 files changed, 84 insertions(+), 63 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index ad961b7fb..9bca4f8c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#086ea58") +CPMAddPackage("gh:geode-sdk/TulipHook#5959b87") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies diff --git a/loader/include/Geode/platform/android.hpp b/loader/include/Geode/platform/android.hpp index ce2b8e4de..e19402bcf 100644 --- a/loader/include/Geode/platform/android.hpp +++ b/loader/include/Geode/platform/android.hpp @@ -9,10 +9,7 @@ namespace geode { } namespace geode::base { - GEODE_NOINLINE inline uintptr_t get() { - static uintptr_t base = reinterpret_cast(dlopen("libcocos2dcpp.so", RTLD_LAZY)); - return base; - } + /*GEODE_NOINLINE inline*/ uintptr_t get(); } namespace geode::cast { diff --git a/loader/src/cocos2d-ext/CCFileUtils.cpp b/loader/src/cocos2d-ext/CCFileUtils.cpp index a88d1ec57..22dd82246 100644 --- a/loader/src/cocos2d-ext/CCFileUtils.cpp +++ b/loader/src/cocos2d-ext/CCFileUtils.cpp @@ -84,6 +84,7 @@ void CCFileUtils::updatePaths() { struct FileUtilsUpdatePaths : Modify { static CCFileUtils* sharedFileUtils() { + log::debug("im here"); static bool doAddPaths = true; auto ret = CCFileUtils::sharedFileUtils(); diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 93e82f077..24ed70adc 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -29,6 +29,10 @@ struct CustomLoadingLayer : Modify { // hook bool init(bool fromReload) { + if (!fromReload) { + LoaderImpl::get()->addSearchPaths(); + } + CCFileUtils::get()->updatePaths(); if (!LoadingLayer::init(fromReload)) return false; diff --git a/loader/src/hooks/persist.cpp b/loader/src/hooks/persist.cpp index 3f216069d..7be7ca061 100644 --- a/loader/src/hooks/persist.cpp +++ b/loader/src/hooks/persist.cpp @@ -4,9 +4,9 @@ using namespace geode::prelude; #include -struct SceneSwitch : Modify { - void willSwitchToScene(CCScene* scene) { - AchievementNotifier::willSwitchToScene(scene); - SceneManager::get()->willSwitchToScene(scene); - } -}; +// struct SceneSwitch : Modify { +// void willSwitchToScene(CCScene* scene) { +// AchievementNotifier::willSwitchToScene(scene); +// SceneManager::get()->willSwitchToScene(scene); +// } +// }; diff --git a/loader/src/hooks/save.cpp b/loader/src/hooks/save.cpp index c3dfde148..bdbf1bd33 100644 --- a/loader/src/hooks/save.cpp +++ b/loader/src/hooks/save.cpp @@ -4,17 +4,17 @@ using namespace geode::prelude; #include -struct SaveLoader : Modify { - void trySaveGame() { - log::info("Saving..."); +// struct SaveLoader : Modify { +// void trySaveGame() { +// log::info("Saving..."); - auto r = Loader::get()->saveData(); - if (!r) { - log::info("{}", r.unwrapErr()); - } +// auto r = Loader::get()->saveData(); +// if (!r) { +// log::info("{}", r.unwrapErr()); +// } - log::info("Saved"); +// log::info("Saved"); - return AppDelegate::trySaveGame(); - } -}; +// return AppDelegate::trySaveGame(); +// } +// }; diff --git a/loader/src/hooks/update.cpp b/loader/src/hooks/update.cpp index 287fb783a..128484f42 100644 --- a/loader/src/hooks/update.cpp +++ b/loader/src/hooks/update.cpp @@ -6,6 +6,8 @@ using namespace geode::prelude; struct FunctionQueue : Modify { void update(float dt) { + log::debug("Scheduler update"); + LoaderImpl::get()->executeGDThreadQueue(); return CCScheduler::update(dt); } diff --git a/loader/src/ids/CCTextInputNode.cpp b/loader/src/ids/CCTextInputNode.cpp index 037cac29e..6f4759e8e 100644 --- a/loader/src/ids/CCTextInputNode.cpp +++ b/loader/src/ids/CCTextInputNode.cpp @@ -6,26 +6,26 @@ // ignoreAnchorPointForPosition which causes the content size of // text input nodes to be way off -struct $modify(CCTextInputNode) { - bool init(float width, float height, const char* caption, const char* thonburi, int maxCharCount, const char* font) { - if (!CCTextInputNode::init(width, height, caption, thonburi, maxCharCount, font)) - return false; +// struct $modify(CCTextInputNode) { +// bool init(float width, float height, const char* caption, const char* thonburi, int maxCharCount, const char* font) { +// if (!CCTextInputNode::init(width, height, caption, thonburi, maxCharCount, font)) +// return false; - this->ignoreAnchorPointForPosition(false); - this->fixPosition(); +// this->ignoreAnchorPointForPosition(false); +// this->fixPosition(); - return true; - } +// return true; +// } - void fixPosition() { - if (!m_bIgnoreAnchorPointForPosition && m_placeholderLabel) { - this->setAnchorPoint(m_placeholderLabel->getAnchorPoint()); - m_placeholderLabel->setPosition(m_obContentSize * m_obAnchorPoint); - } - } +// void fixPosition() { +// if (!m_bIgnoreAnchorPointForPosition && m_placeholderLabel) { +// this->setAnchorPoint(m_placeholderLabel->getAnchorPoint()); +// m_placeholderLabel->setPosition(m_obContentSize * m_obAnchorPoint); +// } +// } - void updateLabel(gd::string text) { - CCTextInputNode::updateLabel(text); - this->fixPosition(); - } -}; +// void updateLabel(gd::string text) { +// CCTextInputNode::updateLabel(text); +// this->fixPosition(); +// } +// }; diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 8b955b53f..05dc7d679 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -87,7 +87,7 @@ Result<> Loader::Impl::setup() { this->createDirectories(); - this->addSearchPaths(); + // this->addSearchPaths(); this->refreshModGraph(); @@ -97,8 +97,8 @@ Result<> Loader::Impl::setup() { } void Loader::Impl::addSearchPaths() { - CCFileUtils::get()->addPriorityPath(dirs::getGeodeResourcesDir().string().c_str()); - CCFileUtils::get()->addPriorityPath(dirs::getModRuntimeDir().string().c_str()); + // CCFileUtils::get()->addPriorityPath(dirs::getGeodeResourcesDir().string().c_str()); + // CCFileUtils::get()->addPriorityPath(dirs::getModRuntimeDir().string().c_str()); } void Loader::Impl::updateResources() { @@ -218,7 +218,7 @@ void Loader::Impl::updateModResources(Mod* mod) { if (mod != Mod::get()) { // geode.loader resource is stored somewhere else, which is already added anyway auto searchPathRoot = dirs::getModRuntimeDir() / mod->getID() / "resources"; - CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); + // CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); } // only thing needs previous setup is spritesheets @@ -232,19 +232,19 @@ void Loader::Impl::updateModResources(Mod* mod) { log::debug("Adding sheet {}", sheet); auto png = sheet + ".png"; auto plist = sheet + ".plist"; - auto ccfu = CCFileUtils::get(); - - if (png == std::string(ccfu->fullPathForFilename(png.c_str(), false)) || - plist == std::string(ccfu->fullPathForFilename(plist.c_str(), false))) { - log::warn( - R"(The resource dir of "{}" is missing "{}" png and/or plist files)", - mod->getID(), sheet - ); - } - else { - CCTextureCache::get()->addImage(png.c_str(), false); - CCSpriteFrameCache::get()->addSpriteFramesWithFile(plist.c_str()); - } + // auto ccfu = CCFileUtils::get(); + + // if (png == std::string(ccfu->fullPathForFilename(png.c_str(), false)) || + // plist == std::string(ccfu->fullPathForFilename(plist.c_str(), false))) { + // log::warn( + // R"(The resource dir of "{}" is missing "{}" png and/or plist files)", + // mod->getID(), sheet + // ); + // } + // else { + // CCTextureCache::get()->addImage(png.c_str(), false); + // CCSpriteFrameCache::get()->addSpriteFramesWithFile(plist.c_str()); + // } } } diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 1f2a85737..501a30d95 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -44,7 +44,7 @@ Result<> Mod::Impl::setup() { } if (!m_resourcesLoaded) { auto searchPathRoot = dirs::getModRuntimeDir() / m_metadata.getID() / "resources"; - CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); + // CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); m_resourcesLoaded = true; } diff --git a/loader/src/platform/android/LoaderImpl.cpp b/loader/src/platform/android/LoaderImpl.cpp index 62b2def3f..89ac0144a 100644 --- a/loader/src/platform/android/LoaderImpl.cpp +++ b/loader/src/platform/android/LoaderImpl.cpp @@ -24,7 +24,7 @@ namespace { } void Loader::Impl::platformMessageBox(char const* title, std::string const& info) { - cocos2d::CCMessageBox(info.c_str(), title); + // cocos2d::CCMessageBox(info.c_str(), title); } void Loader::Impl::logConsoleMessageWithSeverity(std::string const& msg, Severity severity) { diff --git a/loader/src/platform/android/gdstdlib.cpp b/loader/src/platform/android/gdstdlib.cpp index da52cff9d..c96fd5888 100644 --- a/loader/src/platform/android/gdstdlib.cpp +++ b/loader/src/platform/android/gdstdlib.cpp @@ -2,6 +2,14 @@ #ifdef GEODE_IS_ANDROID +namespace geode::base { + uintptr_t get() { + static uintptr_t base = (reinterpret_cast(&UILayer::create) - 0x20f168) & (~0x1); + // static uintptr_t base = reinterpret_cast(dlopen("libcocos2dcpp.so", RTLD_NOW)); + return base; + } +} + namespace gd { namespace { static inline auto emptyInternalString() { @@ -38,7 +46,8 @@ namespace gd { string::~string() { if (m_data == nullptr) return; - // reinterpret_cast(geode::base::get() + 0x5054bc)(this); + + reinterpret_cast(geode::base::get() + 0x5054bc)(this); } bool string::operator<(string const& other) const { diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index f8d52e3e4..10eae65a1 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -10,11 +10,11 @@ using namespace geode::prelude; #include ghc::filesystem::path dirs::getGameDir() { - return ghc::filesystem::path(CCFileUtils::sharedFileUtils()->getWritablePath().c_str()); + return ghc::filesystem::path("/data/user/0/com.geode.launcher/files/"/*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/); } ghc::filesystem::path dirs::getSaveDir() { - return ghc::filesystem::path(CCFileUtils::sharedFileUtils()->getWritablePath().c_str()); + return ghc::filesystem::path("/data/user/0/com.geode.launcher/files/"/*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/); } void utils::web::openLinkInBrowser(std::string const& url) { diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 9bc7cd993..dd6f6ba93 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -32,6 +32,8 @@ namespace geode::utils::fetch { Result<> web::fetchFile( std::string const& url, ghc::filesystem::path const& into, FileProgressCallback prog ) { + return Err("Not implemented"); + auto curl = curl_easy_init(); if (!curl) return Err("Curl not initialized!"); @@ -70,6 +72,8 @@ Result<> web::fetchFile( } Result web::fetchBytes(std::string const& url) { + return Err("Not implemented"); + auto curl = curl_easy_init(); if (!curl) return Err("Curl not initialized!"); @@ -108,6 +112,8 @@ Result web::fetchJSON(std::string const& url) { } Result web::fetch(std::string const& url) { + return Err("Not implemented"); + auto curl = curl_easy_init(); if (!curl) return Err("Curl not initialized!"); @@ -207,6 +213,8 @@ SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const std::thread([this]() { AWAIT_RESUME(); + return this->error("Not implemented", -1); + auto curl = curl_easy_init(); if (!curl) { return this->error("Curl not initialized", -1); From 86de5ff7ddfde485bcbe4bdba03db961c2fb3f47 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Sep 2023 00:17:45 +0300 Subject: [PATCH 037/135] uncomment some stuff --- CMakeLists.txt | 2 +- codegen/src/AddressGen.cpp | 2 +- loader/src/cocos2d-ext/CCFileUtils.cpp | 1 - loader/src/hooks/LoadingLayer.cpp | 52 ++++++++++++---------- loader/src/hooks/update.cpp | 2 - loader/src/ids/CCTextInputNode.cpp | 38 ++++++++-------- loader/src/loader/LoaderImpl.cpp | 34 +++++++------- loader/src/platform/android/LoaderImpl.cpp | 2 +- 8 files changed, 66 insertions(+), 67 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9bca4f8c7..4a4263430 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#5959b87") +CPMAddPackage("gh:geode-sdk/TulipHook#5ba74ed") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index aa7b3a338..9acb8c78d 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -123,7 +123,7 @@ std::string generateAddressHeader(Root const& root) { else if (codegen::shouldAndroidBind(fn)) { auto const mangled = generateAndroidSymbol(c, fn); address_str = fmt::format( // thumb - "reinterpret_cast(dlsym(reinterpret_cast(geode::base::get()), \"{}\")) + 1", + "reinterpret_cast(dlsym(dlopen(\"libcocos2dcpp.so\", RTLD_NOW), \"{}\"))", mangled ); } diff --git a/loader/src/cocos2d-ext/CCFileUtils.cpp b/loader/src/cocos2d-ext/CCFileUtils.cpp index 22dd82246..a88d1ec57 100644 --- a/loader/src/cocos2d-ext/CCFileUtils.cpp +++ b/loader/src/cocos2d-ext/CCFileUtils.cpp @@ -84,7 +84,6 @@ void CCFileUtils::updatePaths() { struct FileUtilsUpdatePaths : Modify { static CCFileUtils* sharedFileUtils() { - log::debug("im here"); static bool doAddPaths = true; auto ret = CCFileUtils::sharedFileUtils(); diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 24ed70adc..12cef689e 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -29,12 +29,6 @@ struct CustomLoadingLayer : Modify { // hook bool init(bool fromReload) { - if (!fromReload) { - LoaderImpl::get()->addSearchPaths(); - } - - CCFileUtils::get()->updatePaths(); - if (!LoadingLayer::init(fromReload)) return false; auto winSize = CCDirector::sharedDirector()->getWinSize(); @@ -49,6 +43,8 @@ struct CustomLoadingLayer : Modify { } void setupLoadingMods() { + CCFileUtils::get()->updatePaths(); + if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) { this->updateLoadedModsLabel(); this->waitLoadAssets(); @@ -59,6 +55,8 @@ struct CustomLoadingLayer : Modify { } void setupLoaderResources() { + LoaderImpl::get()->addSearchPaths(); + // verify loader resources if (!LoaderImpl::get()->verifyLoaderResources()) { this->setSmallText("Downloading Loader Resources"); @@ -112,7 +110,7 @@ struct CustomLoadingLayer : Modify { } int getTotalStep() { - return 18; + return 17; } void updateLoadingBar() { @@ -141,23 +139,29 @@ struct CustomLoadingLayer : Modify { } // hook - void loadAssets() { - switch (m_fields->m_geodeLoadStep) { - case 0: - if (this->skipOnRefresh()) this->setupLoadingMods(); - break; - case 1: - if (this->skipOnRefresh()) this->setupLoaderResources(); - break; - case 2: - this->setupModResources(); - break; - case 3: - default: - this->setSmallText("Loading game resources"); - LoadingLayer::loadAssets(); - break; - } + void loadAssets() { + log::debug("Load step {}", this->getCurrentStep()); + if (m_loadStep == 14) { + switch (m_fields->m_geodeLoadStep) { + case 0: + if (this->skipOnRefresh()) this->setupLoadingMods(); + break; + case 1: + if (this->skipOnRefresh()) this->setupLoaderResources(); + break; + case 2: + this->setupModResources(); + break; + case 3: + default: + LoadingLayer::loadAssets(); + this->updateLoadingBar(); + break; + } + return; + } + this->setSmallText("Loading game resources"); + LoadingLayer::loadAssets(); this->updateLoadingBar(); } }; diff --git a/loader/src/hooks/update.cpp b/loader/src/hooks/update.cpp index 128484f42..287fb783a 100644 --- a/loader/src/hooks/update.cpp +++ b/loader/src/hooks/update.cpp @@ -6,8 +6,6 @@ using namespace geode::prelude; struct FunctionQueue : Modify { void update(float dt) { - log::debug("Scheduler update"); - LoaderImpl::get()->executeGDThreadQueue(); return CCScheduler::update(dt); } diff --git a/loader/src/ids/CCTextInputNode.cpp b/loader/src/ids/CCTextInputNode.cpp index 6f4759e8e..037cac29e 100644 --- a/loader/src/ids/CCTextInputNode.cpp +++ b/loader/src/ids/CCTextInputNode.cpp @@ -6,26 +6,26 @@ // ignoreAnchorPointForPosition which causes the content size of // text input nodes to be way off -// struct $modify(CCTextInputNode) { -// bool init(float width, float height, const char* caption, const char* thonburi, int maxCharCount, const char* font) { -// if (!CCTextInputNode::init(width, height, caption, thonburi, maxCharCount, font)) -// return false; +struct $modify(CCTextInputNode) { + bool init(float width, float height, const char* caption, const char* thonburi, int maxCharCount, const char* font) { + if (!CCTextInputNode::init(width, height, caption, thonburi, maxCharCount, font)) + return false; -// this->ignoreAnchorPointForPosition(false); -// this->fixPosition(); + this->ignoreAnchorPointForPosition(false); + this->fixPosition(); -// return true; -// } + return true; + } -// void fixPosition() { -// if (!m_bIgnoreAnchorPointForPosition && m_placeholderLabel) { -// this->setAnchorPoint(m_placeholderLabel->getAnchorPoint()); -// m_placeholderLabel->setPosition(m_obContentSize * m_obAnchorPoint); -// } -// } + void fixPosition() { + if (!m_bIgnoreAnchorPointForPosition && m_placeholderLabel) { + this->setAnchorPoint(m_placeholderLabel->getAnchorPoint()); + m_placeholderLabel->setPosition(m_obContentSize * m_obAnchorPoint); + } + } -// void updateLabel(gd::string text) { -// CCTextInputNode::updateLabel(text); -// this->fixPosition(); -// } -// }; + void updateLabel(gd::string text) { + CCTextInputNode::updateLabel(text); + this->fixPosition(); + } +}; diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 05dc7d679..86a03f54f 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -87,8 +87,6 @@ Result<> Loader::Impl::setup() { this->createDirectories(); - // this->addSearchPaths(); - this->refreshModGraph(); m_isSetup = true; @@ -97,8 +95,8 @@ Result<> Loader::Impl::setup() { } void Loader::Impl::addSearchPaths() { - // CCFileUtils::get()->addPriorityPath(dirs::getGeodeResourcesDir().string().c_str()); - // CCFileUtils::get()->addPriorityPath(dirs::getModRuntimeDir().string().c_str()); + CCFileUtils::get()->addPriorityPath(dirs::getGeodeResourcesDir().string().c_str()); + CCFileUtils::get()->addPriorityPath(dirs::getModRuntimeDir().string().c_str()); } void Loader::Impl::updateResources() { @@ -218,7 +216,7 @@ void Loader::Impl::updateModResources(Mod* mod) { if (mod != Mod::get()) { // geode.loader resource is stored somewhere else, which is already added anyway auto searchPathRoot = dirs::getModRuntimeDir() / mod->getID() / "resources"; - // CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); + CCFileUtils::get()->addSearchPath(searchPathRoot.string().c_str()); } // only thing needs previous setup is spritesheets @@ -232,19 +230,19 @@ void Loader::Impl::updateModResources(Mod* mod) { log::debug("Adding sheet {}", sheet); auto png = sheet + ".png"; auto plist = sheet + ".plist"; - // auto ccfu = CCFileUtils::get(); - - // if (png == std::string(ccfu->fullPathForFilename(png.c_str(), false)) || - // plist == std::string(ccfu->fullPathForFilename(plist.c_str(), false))) { - // log::warn( - // R"(The resource dir of "{}" is missing "{}" png and/or plist files)", - // mod->getID(), sheet - // ); - // } - // else { - // CCTextureCache::get()->addImage(png.c_str(), false); - // CCSpriteFrameCache::get()->addSpriteFramesWithFile(plist.c_str()); - // } + auto ccfu = CCFileUtils::get(); + + if (png == std::string(ccfu->fullPathForFilename(png.c_str(), false)) || + plist == std::string(ccfu->fullPathForFilename(plist.c_str(), false))) { + log::warn( + R"(The resource dir of "{}" is missing "{}" png and/or plist files)", + mod->getID(), sheet + ); + } + else { + CCTextureCache::get()->addImage(png.c_str(), false); + CCSpriteFrameCache::get()->addSpriteFramesWithFile(plist.c_str()); + } } } diff --git a/loader/src/platform/android/LoaderImpl.cpp b/loader/src/platform/android/LoaderImpl.cpp index 89ac0144a..62b2def3f 100644 --- a/loader/src/platform/android/LoaderImpl.cpp +++ b/loader/src/platform/android/LoaderImpl.cpp @@ -24,7 +24,7 @@ namespace { } void Loader::Impl::platformMessageBox(char const* title, std::string const& info) { - // cocos2d::CCMessageBox(info.c_str(), title); + cocos2d::CCMessageBox(info.c_str(), title); } void Loader::Impl::logConsoleMessageWithSeverity(std::string const& msg, Severity severity) { From 20d5e079bc72ed4bb508d7b500bd35544c191ca7 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Sep 2023 01:10:56 +0300 Subject: [PATCH 038/135] Fix tuliphook alignment intervener issue --- CMakeLists.txt | 2 +- loader/src/hooks/LoadingLayer.cpp | 3 +-- loader/src/hooks/save.cpp | 22 +++++++++++----------- loader/src/utils/web.cpp | 13 +++++++++++++ 4 files changed, 26 insertions(+), 14 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 4a4263430..e53924f80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#5ba74ed") +CPMAddPackage("gh:geode-sdk/TulipHook#41a18a1") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 12cef689e..ca048b648 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -44,7 +44,7 @@ struct CustomLoadingLayer : Modify { void setupLoadingMods() { CCFileUtils::get()->updatePaths(); - + if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) { this->updateLoadedModsLabel(); this->waitLoadAssets(); @@ -140,7 +140,6 @@ struct CustomLoadingLayer : Modify { // hook void loadAssets() { - log::debug("Load step {}", this->getCurrentStep()); if (m_loadStep == 14) { switch (m_fields->m_geodeLoadStep) { case 0: diff --git a/loader/src/hooks/save.cpp b/loader/src/hooks/save.cpp index bdbf1bd33..c3dfde148 100644 --- a/loader/src/hooks/save.cpp +++ b/loader/src/hooks/save.cpp @@ -4,17 +4,17 @@ using namespace geode::prelude; #include -// struct SaveLoader : Modify { -// void trySaveGame() { -// log::info("Saving..."); +struct SaveLoader : Modify { + void trySaveGame() { + log::info("Saving..."); -// auto r = Loader::get()->saveData(); -// if (!r) { -// log::info("{}", r.unwrapErr()); -// } + auto r = Loader::get()->saveData(); + if (!r) { + log::info("{}", r.unwrapErr()); + } -// log::info("Saved"); + log::info("Saved"); -// return AppDelegate::trySaveGame(); -// } -// }; + return AppDelegate::trySaveGame(); + } +}; diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index dd6f6ba93..08d77846c 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -220,6 +220,8 @@ SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const return this->error("Curl not initialized", -1); } + log::debug("curl init {}", curl); + // resulting byte array ByteVector ret; // output file if downloading to file. unique_ptr because not always @@ -312,17 +314,28 @@ SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const } ); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data); + log::debug("curl opts"); auto res = curl_easy_perform(curl); + log::debug("curl perform"); + if (res != CURLE_OK) { long code = 0; + log::debug("curl fail"); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); + log::debug("curl cleanup"); curl_easy_cleanup(curl); + log::debug("end"); return this->error("Fetch failed: " + std::string(curl_easy_strerror(res)), code); } + log::debug("curl cleanup 2"); curl_easy_cleanup(curl); + log::debug("end 2"); + AWAIT_RESUME(); + log::debug("end 3"); + // if something is still holding a handle to this // request, then they may still cancel it m_finished = true; From fda43ec617e59829f466fbded9607921ca02316c Mon Sep 17 00:00:00 2001 From: qimiko <25387744+qimiko@users.noreply.github.com> Date: Sat, 16 Sep 2023 03:53:24 -0700 Subject: [PATCH 039/135] fix web request crash --- cmake/Platform.cmake | 2 +- loader/src/utils/web.cpp | 1200 +++++++++++++++++++------------------- 2 files changed, 597 insertions(+), 605 deletions(-) diff --git a/cmake/Platform.cmake b/cmake/Platform.cmake index 22602b4b4..cf5d4241b 100644 --- a/cmake/Platform.cmake +++ b/cmake/Platform.cmake @@ -78,10 +78,10 @@ elseif (GEODE_TARGET_PLATFORM STREQUAL "Android") ) target_link_libraries(${PROJECT_NAME} INTERFACE - ${GEODE_LOADER_PATH}/include/link/android/libcocos2dcpp.so ${GEODE_LOADER_PATH}/include/link/android/libcurl.a ${GEODE_LOADER_PATH}/include/link/android/libssl.a ${GEODE_LOADER_PATH}/include/link/android/libcrypto.a + ${GEODE_LOADER_PATH}/include/link/android/libcocos2dcpp.so log ) diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 08d77846c..f7da4fc3e 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -1,604 +1,596 @@ -#include -#include -#include -#include -#include -#include - -using namespace geode::prelude; -using namespace web; - -namespace geode::utils::fetch { - static size_t writeBytes(char* data, size_t size, size_t nmemb, void* str) { - as(str)->insert(as(str)->end(), data, data + size * nmemb); - return size * nmemb; - } - - static size_t writeString(char* data, size_t size, size_t nmemb, void* str) { - as(str)->append(data, size * nmemb); - return size * nmemb; - } - - static size_t writeBinaryData(char* data, size_t size, size_t nmemb, void* file) { - as(file)->write(data, size * nmemb); - return size * nmemb; - } - - static int progress(void* ptr, double total, double now, double, double) { - return (*as(ptr))(now, total) != true; - } -} - -Result<> web::fetchFile( - std::string const& url, ghc::filesystem::path const& into, FileProgressCallback prog -) { - return Err("Not implemented"); - - auto curl = curl_easy_init(); - - if (!curl) return Err("Curl not initialized!"); - - std::ofstream file(into, std::ios::out | std::ios::binary); - - if (!file.is_open()) { - return Err("Unable to open output file"); - } - - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBinaryData); - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - if (prog) { - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, utils::fetch::progress); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); - } - auto res = curl_easy_perform(curl); - if (res != CURLE_OK) { - curl_easy_cleanup(curl); - return Err("Fetch failed: " + std::string(curl_easy_strerror(res))); - } - - char* ct; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); - if ((res == CURLE_OK) && ct) { - curl_easy_cleanup(curl); - return Ok(); - } - curl_easy_cleanup(curl); - return Err("Error getting info: " + std::string(curl_easy_strerror(res))); -} - -Result web::fetchBytes(std::string const& url) { - return Err("Not implemented"); - - auto curl = curl_easy_init(); - - if (!curl) return Err("Curl not initialized!"); - - ByteVector ret; - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ret); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBytes); - auto res = curl_easy_perform(curl); - if (res != CURLE_OK) { - curl_easy_cleanup(curl); - return Err("Fetch failed"); - } - - char* ct; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); - if ((res == CURLE_OK) && ct) { - curl_easy_cleanup(curl); - return Ok(ret); - } - curl_easy_cleanup(curl); - return Err("Error getting info: " + std::string(curl_easy_strerror(res))); -} - -Result web::fetchJSON(std::string const& url) { - std::string res; - GEODE_UNWRAP_INTO(res, fetch(url)); - try { - return Ok(json::parse(res)); - } - catch (std::exception& e) { - return Err(e.what()); - } -} - -Result web::fetch(std::string const& url) { - return Err("Not implemented"); - - auto curl = curl_easy_init(); - - if (!curl) return Err("Curl not initialized!"); - - std::string ret; - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ret); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeString); - auto res = curl_easy_perform(curl); - if (res != CURLE_OK) { - curl_easy_cleanup(curl); - return Err("Fetch failed"); - } - - char* ct; - res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); - if ((res == CURLE_OK) && ct) { - curl_easy_cleanup(curl); - return Ok(ret); - } - curl_easy_cleanup(curl); - return Err("Error getting info: " + std::string(curl_easy_strerror(res))); -} - -class SentAsyncWebRequest::Impl { -private: - enum class Status { - Paused, - Running, - Finished, - Cancelled, - CleanedUp, - }; - std::string m_id; - std::string m_url; - std::vector m_thens; - std::vector m_expects; - std::vector m_progresses; - std::vector m_cancelleds; - Status m_status = Status::Paused; - std::atomic m_paused = true; - std::atomic m_cancelled = false; - std::atomic m_finished = false; - std::atomic m_cleanedUp = false; - std::condition_variable m_statusCV; - std::mutex m_statusMutex; - SentAsyncWebRequest* m_self; - - mutable std::mutex m_mutex; - AsyncWebRequestData m_extra; - std::variant m_target; - std::vector m_httpHeaders; - - - template - friend class AsyncWebResult; - friend class AsyncWebRequest; - - void pause(); - void resume(); - void error(std::string const& error, int code); - void doCancel(); - -public: - Impl(SentAsyncWebRequest* self, AsyncWebRequest const&, std::string const& id); - void cancel(); - bool finished() const; - - friend class SentAsyncWebRequest; -}; - -static std::unordered_map RUNNING_REQUESTS{}; -static std::mutex RUNNING_REQUESTS_MUTEX; - -SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const& req, std::string const& id) : - m_id(id), m_url(req.m_url), m_target(req.m_target), m_extra(req.extra()), m_httpHeaders(req.m_httpHeaders) { - -#define AWAIT_RESUME() \ - {\ - auto lock = std::unique_lock(m_statusMutex);\ - m_statusCV.wait(lock, [this]() { \ - return !m_paused; \ - });\ - if (m_cancelled) {\ - this->doCancel();\ - return;\ - }\ - }\ - - if (req.m_then) m_thens.push_back(req.m_then); - if (req.m_progress) m_progresses.push_back(req.m_progress); - if (req.m_cancelled) m_cancelleds.push_back(req.m_cancelled); - if (req.m_expect) m_expects.push_back(req.m_expect); - - std::thread([this]() { - AWAIT_RESUME(); - - return this->error("Not implemented", -1); - - auto curl = curl_easy_init(); - if (!curl) { - return this->error("Curl not initialized", -1); - } - - log::debug("curl init {}", curl); - - // resulting byte array - ByteVector ret; - // output file if downloading to file. unique_ptr because not always - // initialized but don't wanna manually managed memory - std::unique_ptr file = nullptr; - - // into file - if (std::holds_alternative(m_target)) { - file = std::make_unique( - std::get(m_target), std::ios::out | std::ios::binary - ); - curl_easy_setopt(curl, CURLOPT_WRITEDATA, file.get()); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBinaryData); - } - // into stream - else if (std::holds_alternative(m_target)) { - curl_easy_setopt(curl, CURLOPT_WRITEDATA, std::get(m_target)); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBinaryData); - } - // into memory - else { - curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ret); - curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBytes); - } - curl_easy_setopt(curl, CURLOPT_URL, m_url.c_str()); - // No need to verify SSL, we trust our domains :-) - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); - curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); - // User Agent - curl_easy_setopt(curl, CURLOPT_USERAGENT, m_extra.m_userAgent.c_str()); - - // Headers - curl_slist* headers = nullptr; - for (auto& header : m_httpHeaders) { - headers = curl_slist_append(headers, header.c_str()); - } - - // Post request - if (m_extra.m_isPostRequest || m_extra.m_customRequest.size()) { - if (m_extra.m_isPostRequest) { - curl_easy_setopt(curl, CURLOPT_POST, 1L); - } - else { - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, m_extra.m_customRequest.c_str()); - } - if (m_extra.m_isJsonRequest) { - headers = curl_slist_append(headers, "Content-Type: application/json"); - } - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, m_extra.m_postFields.c_str()); - curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, m_extra.m_postFields.size()); - } - - // Track progress - curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); - // Follow redirects - curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); - // Fail if response code is 4XX or 5XX - curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); - - // Headers end - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); - - struct ProgressData { - SentAsyncWebRequest::Impl* self; - std::ofstream* file; - } data{this, file.get()}; - - curl_easy_setopt( - curl, - CURLOPT_PROGRESSFUNCTION, - +[](void* ptr, double total, double now, double, double) -> int { - auto data = static_cast(ptr); - auto lock = std::unique_lock(data->self->m_statusMutex); - data->self->m_statusCV.wait(lock, [data]() { - return !data->self->m_paused; - }); - if (data->self->m_cancelled) { - if (data->file) { - data->file->close(); - } - return 1; - } - Loader::get()->queueInMainThread([self = data->self, now, total]() { - std::lock_guard _(self->m_mutex); - for (auto& prog : self->m_progresses) { - prog(*self->m_self, now, total); - } - }); - return 0; - } - ); - curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data); - log::debug("curl opts"); - auto res = curl_easy_perform(curl); - log::debug("curl perform"); - - if (res != CURLE_OK) { - long code = 0; - log::debug("curl fail"); - curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); - log::debug("curl cleanup"); - curl_easy_cleanup(curl); - log::debug("end"); - return this->error("Fetch failed: " + std::string(curl_easy_strerror(res)), code); - } - log::debug("curl cleanup 2"); - curl_easy_cleanup(curl); - - log::debug("end 2"); - - AWAIT_RESUME(); - - log::debug("end 3"); - - // if something is still holding a handle to this - // request, then they may still cancel it - m_finished = true; - - Loader::get()->queueInMainThread([this, ret]() { - std::lock_guard _(m_mutex); - for (auto& then : m_thens) { - then(*m_self, ret); - } - std::lock_guard __(RUNNING_REQUESTS_MUTEX); - RUNNING_REQUESTS.erase(m_id); - }); - }).detach(); -} - -void SentAsyncWebRequest::Impl::doCancel() { - if (m_cleanedUp) return; - m_cleanedUp = true; - - // remove file if downloaded to one - if (std::holds_alternative(m_target)) { - auto path = std::get(m_target); - if (ghc::filesystem::exists(path)) { - try { - ghc::filesystem::remove(path); - } - catch (...) { - } - } - } - - Loader::get()->queueInMainThread([this]() { - std::lock_guard _(m_mutex); - for (auto& canc : m_cancelleds) { - canc(*m_self); - } - }); - - this->error("Request cancelled", -1); -} - -void SentAsyncWebRequest::Impl::cancel() { - m_cancelled = true; - // if already finished, cancel anyway to clean up - if (m_finished) { - this->doCancel(); - } -} - -void SentAsyncWebRequest::Impl::pause() { - m_paused = true; - m_statusCV.notify_all(); -} - -void SentAsyncWebRequest::Impl::resume() { - m_paused = false; - m_statusCV.notify_all(); -} - -bool SentAsyncWebRequest::Impl::finished() const { - return m_finished; -} - -void SentAsyncWebRequest::Impl::error(std::string const& error, int code) { - auto lock = std::unique_lock(m_statusMutex); - m_statusCV.wait(lock, [this]() { - return !m_paused; - }); - Loader::get()->queueInMainThread([this, error, code]() { - { - std::lock_guard _(m_mutex); - for (auto& expect : m_expects) { - expect(error, code); - } - } - std::lock_guard _(RUNNING_REQUESTS_MUTEX); - RUNNING_REQUESTS.erase(m_id); - }); -} - -SentAsyncWebRequest::SentAsyncWebRequest() : m_impl() {} -SentAsyncWebRequest::~SentAsyncWebRequest() {} - -std::shared_ptr SentAsyncWebRequest::create(AsyncWebRequest const& request, std::string const& id) { - auto ret = std::make_shared(); - ret->m_impl = std::move(std::make_shared(ret.get(), request, id)); - return ret; -} -void SentAsyncWebRequest::doCancel() { - return m_impl->doCancel(); -} - -void SentAsyncWebRequest::cancel() { - return m_impl->cancel(); -} - -void SentAsyncWebRequest::pause() { - return m_impl->pause(); -} - -void SentAsyncWebRequest::resume() { - return m_impl->resume(); -} - -bool SentAsyncWebRequest::finished() const { - return m_impl->finished(); -} - -void SentAsyncWebRequest::error(std::string const& error, int code) { - return m_impl->error(error, code); -} - -AsyncWebRequestData& AsyncWebRequest::extra() { - if (!m_extra) { - m_extra = new AsyncWebRequestData(); - } - return *m_extra; -} - -AsyncWebRequestData const& AsyncWebRequest::extra() const { - if (!m_extra) { - m_extra = new AsyncWebRequestData(); - } - return *m_extra; -} - -AsyncWebRequest& AsyncWebRequest::join(std::string const& requestID) { - m_joinID = requestID; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::userAgent(std::string const& userAgent) { - this->extra().m_userAgent = userAgent; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::postRequest() { - this->extra().m_isPostRequest = true; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::customRequest(std::string const& request) { - this->extra().m_customRequest = request; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::postFields(std::string const& fields) { - this->extra().m_postFields = fields; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::postFields(json::Value const& fields) { - this->extra().m_isJsonRequest = true; - return this->postFields(fields.dump()); -} - -AsyncWebRequest& AsyncWebRequest::header(std::string const& header) { - m_httpHeaders.push_back(header); - return *this; -} - -AsyncWebResponse AsyncWebRequest::fetch(std::string const& url) { - m_url = url; - return AsyncWebResponse(*this); -} - -AsyncWebRequest& AsyncWebRequest::expect(AsyncExpect handler) { - m_expect = [handler](std::string const& info, auto) { - return handler(info); - }; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::expect(AsyncExpectCode handler) { - m_expect = handler; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::progress(AsyncProgress progress) { - m_progress = progress; - return *this; -} - -AsyncWebRequest& AsyncWebRequest::cancelled(AsyncCancelled cancelledFunc) { - m_cancelled = cancelledFunc; - return *this; -} - -SentAsyncWebRequestHandle AsyncWebRequest::send() { - if (this->extra().m_sent) return nullptr; - this->extra().m_sent = true; - - std::lock_guard __(RUNNING_REQUESTS_MUTEX); - - // pause all running requests - for (auto& [_, req] : RUNNING_REQUESTS) { - req->pause(); - } - - SentAsyncWebRequestHandle ret; - - static size_t COUNTER = 0; - if (m_joinID && RUNNING_REQUESTS.count(m_joinID.value())) { - auto& req = RUNNING_REQUESTS.at(m_joinID.value()); - std::lock_guard _(req->m_impl->m_mutex); - if (m_then) req->m_impl->m_thens.push_back(m_then); - if (m_progress) req->m_impl->m_progresses.push_back(m_progress); - if (m_expect) req->m_impl->m_expects.push_back(m_expect); - if (m_cancelled) req->m_impl->m_cancelleds.push_back(m_cancelled); - ret = req; - } - else { - auto id = m_joinID.value_or("__anon_request_" + std::to_string(COUNTER++)); - ret = SentAsyncWebRequest::create(*this, id); - RUNNING_REQUESTS.insert({id, ret}); - } - - // resume all running requests - for (auto& [_, req] : RUNNING_REQUESTS) { - req->resume(); - } - - return ret; -} - -AsyncWebRequest::~AsyncWebRequest() { - this->send(); - delete m_extra; -} - -AsyncWebResult AsyncWebResponse::into(std::ostream& stream) { - m_request.m_target = &stream; - return this->as(+[](ByteVector const&) -> Result { - return Ok(std::monostate()); - }); -} - -AsyncWebResult AsyncWebResponse::into(ghc::filesystem::path const& path) { - m_request.m_target = path; - return this->as(+[](ByteVector const&) -> Result { - return Ok(std::monostate()); - }); -} - -AsyncWebResult AsyncWebResponse::text() { - return this->as(+[](ByteVector const& bytes) -> Result { - return Ok(std::string(bytes.begin(), bytes.end())); - }); -} - -AsyncWebResult AsyncWebResponse::bytes() { - return this->as(+[](ByteVector const& bytes) -> Result { - return Ok(bytes); - }); -} - -AsyncWebResult AsyncWebResponse::json() { - return this->as(+[](ByteVector const& bytes) -> Result { - try { - return Ok(json::parse(std::string(bytes.begin(), bytes.end()))); - } - catch (std::exception& e) { - return Err(std::string(e.what())); - } - }); -} +#include +#include +#include +#include +#include +#include + +using namespace geode::prelude; +using namespace web; + +namespace geode::utils::fetch { + static size_t writeBytes(char* data, size_t size, size_t nmemb, void* str) { + as(str)->insert(as(str)->end(), data, data + size * nmemb); + return size * nmemb; + } + + static size_t writeString(char* data, size_t size, size_t nmemb, void* str) { + as(str)->append(data, size * nmemb); + return size * nmemb; + } + + static size_t writeBinaryData(char* data, size_t size, size_t nmemb, void* file) { + as(file)->write(data, size * nmemb); + return size * nmemb; + } + + static int progress(void* ptr, double total, double now, double, double) { + return (*as(ptr))(now, total) != true; + } +} + +Result<> web::fetchFile( + std::string const& url, ghc::filesystem::path const& into, FileProgressCallback prog +) { + auto curl = curl_easy_init(); + + if (!curl) return Err("Curl not initialized!"); + + std::ofstream file(into, std::ios::out | std::ios::binary); + + if (!file.is_open()) { + return Err("Unable to open output file"); + } + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &file); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBinaryData); + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + if (prog) { + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, utils::fetch::progress); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &prog); + } + auto res = curl_easy_perform(curl); + if (res != CURLE_OK) { + curl_easy_cleanup(curl); + return Err("Fetch failed: " + std::string(curl_easy_strerror(res))); + } + + char* ct; + res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + if ((res == CURLE_OK) && ct) { + curl_easy_cleanup(curl); + return Ok(); + } + curl_easy_cleanup(curl); + return Err("Error getting info: " + std::string(curl_easy_strerror(res))); +} + +Result web::fetchBytes(std::string const& url) { + auto curl = curl_easy_init(); + + if (!curl) return Err("Curl not initialized!"); + + ByteVector ret; + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ret); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBytes); + auto res = curl_easy_perform(curl); + if (res != CURLE_OK) { + curl_easy_cleanup(curl); + return Err("Fetch failed"); + } + + char* ct; + res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + if ((res == CURLE_OK) && ct) { + curl_easy_cleanup(curl); + return Ok(ret); + } + curl_easy_cleanup(curl); + return Err("Error getting info: " + std::string(curl_easy_strerror(res))); +} + +Result web::fetchJSON(std::string const& url) { + std::string res; + GEODE_UNWRAP_INTO(res, fetch(url)); + try { + return Ok(json::parse(res)); + } + catch (std::exception& e) { + return Err(e.what()); + } +} + +Result web::fetch(std::string const& url) { + auto curl = curl_easy_init(); + + if (!curl) return Err("Curl not initialized!"); + + std::string ret; + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ret); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeString); + auto res = curl_easy_perform(curl); + if (res != CURLE_OK) { + curl_easy_cleanup(curl); + return Err("Fetch failed"); + } + + char* ct; + res = curl_easy_getinfo(curl, CURLINFO_CONTENT_TYPE, &ct); + if ((res == CURLE_OK) && ct) { + curl_easy_cleanup(curl); + return Ok(ret); + } + curl_easy_cleanup(curl); + return Err("Error getting info: " + std::string(curl_easy_strerror(res))); +} + +class SentAsyncWebRequest::Impl { +private: + enum class Status { + Paused, + Running, + Finished, + Cancelled, + CleanedUp, + }; + std::string m_id; + std::string m_url; + std::vector m_thens; + std::vector m_expects; + std::vector m_progresses; + std::vector m_cancelleds; + Status m_status = Status::Paused; + std::atomic m_paused = true; + std::atomic m_cancelled = false; + std::atomic m_finished = false; + std::atomic m_cleanedUp = false; + std::condition_variable m_statusCV; + std::mutex m_statusMutex; + SentAsyncWebRequest* m_self; + + mutable std::mutex m_mutex; + AsyncWebRequestData m_extra; + std::variant m_target; + std::vector m_httpHeaders; + + + template + friend class AsyncWebResult; + friend class AsyncWebRequest; + + void pause(); + void resume(); + void error(std::string const& error, int code); + void doCancel(); + +public: + Impl(SentAsyncWebRequest* self, AsyncWebRequest const&, std::string const& id); + void cancel(); + bool finished() const; + + friend class SentAsyncWebRequest; +}; + +static std::unordered_map RUNNING_REQUESTS{}; +static std::mutex RUNNING_REQUESTS_MUTEX; + +SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const& req, std::string const& id) : + m_id(id), m_url(req.m_url), m_target(req.m_target), m_extra(req.extra()), m_httpHeaders(req.m_httpHeaders) { + +#define AWAIT_RESUME() \ + {\ + auto lock = std::unique_lock(m_statusMutex);\ + m_statusCV.wait(lock, [this]() { \ + return !m_paused; \ + });\ + if (m_cancelled) {\ + this->doCancel();\ + return;\ + }\ + }\ + + if (req.m_then) m_thens.push_back(req.m_then); + if (req.m_progress) m_progresses.push_back(req.m_progress); + if (req.m_cancelled) m_cancelleds.push_back(req.m_cancelled); + if (req.m_expect) m_expects.push_back(req.m_expect); + + std::thread([this]() { + AWAIT_RESUME(); + + auto curl = curl_easy_init(); + if (!curl) { + return this->error("Curl not initialized", -1); + } + + log::debug("curl init {}", curl); + + // resulting byte array + ByteVector ret; + // output file if downloading to file. unique_ptr because not always + // initialized but don't wanna manually managed memory + std::unique_ptr file = nullptr; + + // into file + if (std::holds_alternative(m_target)) { + file = std::make_unique( + std::get(m_target), std::ios::out | std::ios::binary + ); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, file.get()); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBinaryData); + } + // into stream + else if (std::holds_alternative(m_target)) { + curl_easy_setopt(curl, CURLOPT_WRITEDATA, std::get(m_target)); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBinaryData); + } + // into memory + else { + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &ret); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, utils::fetch::writeBytes); + } + curl_easy_setopt(curl, CURLOPT_URL, m_url.c_str()); + // No need to verify SSL, we trust our domains :-) + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0); + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0); + // User Agent + curl_easy_setopt(curl, CURLOPT_USERAGENT, m_extra.m_userAgent.c_str()); + + // Headers + curl_slist* headers = nullptr; + for (auto& header : m_httpHeaders) { + headers = curl_slist_append(headers, header.c_str()); + } + + // Post request + if (m_extra.m_isPostRequest || m_extra.m_customRequest.size()) { + if (m_extra.m_isPostRequest) { + curl_easy_setopt(curl, CURLOPT_POST, 1L); + } + else { + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, m_extra.m_customRequest.c_str()); + } + if (m_extra.m_isJsonRequest) { + headers = curl_slist_append(headers, "Content-Type: application/json"); + } + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, m_extra.m_postFields.c_str()); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, m_extra.m_postFields.size()); + } + + // Track progress + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0); + // Follow redirects + curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); + // Fail if response code is 4XX or 5XX + curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1L); + + // Headers end + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers); + + struct ProgressData { + SentAsyncWebRequest::Impl* self; + std::ofstream* file; + } data{this, file.get()}; + + curl_easy_setopt( + curl, + CURLOPT_PROGRESSFUNCTION, + +[](void* ptr, double total, double now, double, double) -> int { + auto data = static_cast(ptr); + auto lock = std::unique_lock(data->self->m_statusMutex); + data->self->m_statusCV.wait(lock, [data]() { + return !data->self->m_paused; + }); + if (data->self->m_cancelled) { + if (data->file) { + data->file->close(); + } + return 1; + } + Loader::get()->queueInMainThread([self = data->self, now, total]() { + std::lock_guard _(self->m_mutex); + for (auto& prog : self->m_progresses) { + prog(*self->m_self, now, total); + } + }); + return 0; + } + ); + curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data); + log::debug("curl opts"); + auto res = curl_easy_perform(curl); + log::debug("curl perform"); + + if (res != CURLE_OK) { + long code = 0; + log::debug("curl fail"); + curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); + log::debug("curl cleanup"); + curl_easy_cleanup(curl); + log::debug("end"); + return this->error("Fetch failed: " + std::string(curl_easy_strerror(res)), code); + } + log::debug("curl cleanup 2"); + curl_easy_cleanup(curl); + + log::debug("end 2"); + + AWAIT_RESUME(); + + log::debug("end 3"); + + // if something is still holding a handle to this + // request, then they may still cancel it + m_finished = true; + + Loader::get()->queueInMainThread([this, ret]() { + std::lock_guard _(m_mutex); + for (auto& then : m_thens) { + then(*m_self, ret); + } + std::lock_guard __(RUNNING_REQUESTS_MUTEX); + RUNNING_REQUESTS.erase(m_id); + }); + }).detach(); +} + +void SentAsyncWebRequest::Impl::doCancel() { + if (m_cleanedUp) return; + m_cleanedUp = true; + + // remove file if downloaded to one + if (std::holds_alternative(m_target)) { + auto path = std::get(m_target); + if (ghc::filesystem::exists(path)) { + try { + ghc::filesystem::remove(path); + } + catch (...) { + } + } + } + + Loader::get()->queueInMainThread([this]() { + std::lock_guard _(m_mutex); + for (auto& canc : m_cancelleds) { + canc(*m_self); + } + }); + + this->error("Request cancelled", -1); +} + +void SentAsyncWebRequest::Impl::cancel() { + m_cancelled = true; + // if already finished, cancel anyway to clean up + if (m_finished) { + this->doCancel(); + } +} + +void SentAsyncWebRequest::Impl::pause() { + m_paused = true; + m_statusCV.notify_all(); +} + +void SentAsyncWebRequest::Impl::resume() { + m_paused = false; + m_statusCV.notify_all(); +} + +bool SentAsyncWebRequest::Impl::finished() const { + return m_finished; +} + +void SentAsyncWebRequest::Impl::error(std::string const& error, int code) { + auto lock = std::unique_lock(m_statusMutex); + m_statusCV.wait(lock, [this]() { + return !m_paused; + }); + Loader::get()->queueInMainThread([this, error, code]() { + { + std::lock_guard _(m_mutex); + for (auto& expect : m_expects) { + expect(error, code); + } + } + std::lock_guard _(RUNNING_REQUESTS_MUTEX); + RUNNING_REQUESTS.erase(m_id); + }); +} + +SentAsyncWebRequest::SentAsyncWebRequest() : m_impl() {} +SentAsyncWebRequest::~SentAsyncWebRequest() {} + +std::shared_ptr SentAsyncWebRequest::create(AsyncWebRequest const& request, std::string const& id) { + auto ret = std::make_shared(); + ret->m_impl = std::move(std::make_shared(ret.get(), request, id)); + return ret; +} +void SentAsyncWebRequest::doCancel() { + return m_impl->doCancel(); +} + +void SentAsyncWebRequest::cancel() { + return m_impl->cancel(); +} + +void SentAsyncWebRequest::pause() { + return m_impl->pause(); +} + +void SentAsyncWebRequest::resume() { + return m_impl->resume(); +} + +bool SentAsyncWebRequest::finished() const { + return m_impl->finished(); +} + +void SentAsyncWebRequest::error(std::string const& error, int code) { + return m_impl->error(error, code); +} + +AsyncWebRequestData& AsyncWebRequest::extra() { + if (!m_extra) { + m_extra = new AsyncWebRequestData(); + } + return *m_extra; +} + +AsyncWebRequestData const& AsyncWebRequest::extra() const { + if (!m_extra) { + m_extra = new AsyncWebRequestData(); + } + return *m_extra; +} + +AsyncWebRequest& AsyncWebRequest::join(std::string const& requestID) { + m_joinID = requestID; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::userAgent(std::string const& userAgent) { + this->extra().m_userAgent = userAgent; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::postRequest() { + this->extra().m_isPostRequest = true; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::customRequest(std::string const& request) { + this->extra().m_customRequest = request; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::postFields(std::string const& fields) { + this->extra().m_postFields = fields; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::postFields(json::Value const& fields) { + this->extra().m_isJsonRequest = true; + return this->postFields(fields.dump()); +} + +AsyncWebRequest& AsyncWebRequest::header(std::string const& header) { + m_httpHeaders.push_back(header); + return *this; +} + +AsyncWebResponse AsyncWebRequest::fetch(std::string const& url) { + m_url = url; + return AsyncWebResponse(*this); +} + +AsyncWebRequest& AsyncWebRequest::expect(AsyncExpect handler) { + m_expect = [handler](std::string const& info, auto) { + return handler(info); + }; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::expect(AsyncExpectCode handler) { + m_expect = handler; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::progress(AsyncProgress progress) { + m_progress = progress; + return *this; +} + +AsyncWebRequest& AsyncWebRequest::cancelled(AsyncCancelled cancelledFunc) { + m_cancelled = cancelledFunc; + return *this; +} + +SentAsyncWebRequestHandle AsyncWebRequest::send() { + if (this->extra().m_sent) return nullptr; + this->extra().m_sent = true; + + std::lock_guard __(RUNNING_REQUESTS_MUTEX); + + // pause all running requests + for (auto& [_, req] : RUNNING_REQUESTS) { + req->pause(); + } + + SentAsyncWebRequestHandle ret; + + static size_t COUNTER = 0; + if (m_joinID && RUNNING_REQUESTS.count(m_joinID.value())) { + auto& req = RUNNING_REQUESTS.at(m_joinID.value()); + std::lock_guard _(req->m_impl->m_mutex); + if (m_then) req->m_impl->m_thens.push_back(m_then); + if (m_progress) req->m_impl->m_progresses.push_back(m_progress); + if (m_expect) req->m_impl->m_expects.push_back(m_expect); + if (m_cancelled) req->m_impl->m_cancelleds.push_back(m_cancelled); + ret = req; + } + else { + auto id = m_joinID.value_or("__anon_request_" + std::to_string(COUNTER++)); + ret = SentAsyncWebRequest::create(*this, id); + RUNNING_REQUESTS.insert({id, ret}); + } + + // resume all running requests + for (auto& [_, req] : RUNNING_REQUESTS) { + req->resume(); + } + + return ret; +} + +AsyncWebRequest::~AsyncWebRequest() { + this->send(); + delete m_extra; +} + +AsyncWebResult AsyncWebResponse::into(std::ostream& stream) { + m_request.m_target = &stream; + return this->as(+[](ByteVector const&) -> Result { + return Ok(std::monostate()); + }); +} + +AsyncWebResult AsyncWebResponse::into(ghc::filesystem::path const& path) { + m_request.m_target = path; + return this->as(+[](ByteVector const&) -> Result { + return Ok(std::monostate()); + }); +} + +AsyncWebResult AsyncWebResponse::text() { + return this->as(+[](ByteVector const& bytes) -> Result { + return Ok(std::string(bytes.begin(), bytes.end())); + }); +} + +AsyncWebResult AsyncWebResponse::bytes() { + return this->as(+[](ByteVector const& bytes) -> Result { + return Ok(bytes); + }); +} + +AsyncWebResult AsyncWebResponse::json() { + return this->as(+[](ByteVector const& bytes) -> Result { + try { + return Ok(json::parse(std::string(bytes.begin(), bytes.end()))); + } + catch (std::exception& e) { + return Err(std::string(e.what())); + } + }); +} From e070fba8cbed2947a0ce3b31a2ef1cfd37e862bf Mon Sep 17 00:00:00 2001 From: qimiko <25387744+qimiko@users.noreply.github.com> Date: Sat, 16 Sep 2023 04:52:34 -0700 Subject: [PATCH 040/135] remove hardcodes for directory --- loader/src/platform/android/util.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 10eae65a1..78d33be48 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -10,11 +10,11 @@ using namespace geode::prelude; #include ghc::filesystem::path dirs::getGameDir() { - return ghc::filesystem::path("/data/user/0/com.geode.launcher/files/"/*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/); + return CCFileUtils::sharedFileUtils()->getWritablePath().c_str(); } ghc::filesystem::path dirs::getSaveDir() { - return ghc::filesystem::path("/data/user/0/com.geode.launcher/files/"/*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/); + return CCFileUtils::sharedFileUtils()->getWritablePath().c_str(); } void utils::web::openLinkInBrowser(std::string const& url) { From 28480a6dc4e88f92f3a413dcc22c0402b061d162 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Sep 2023 15:38:14 +0300 Subject: [PATCH 041/135] download latest loader resource if folder doesnt exist and the version doesnt exist --- loader/src/loader/LoaderImpl.cpp | 115 +++++++++++++++---------------- 1 file changed, 57 insertions(+), 58 deletions(-) diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index a339b2222..c281e2027 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -740,14 +740,12 @@ void Loader::Impl::tryDownloadLoaderResources( .expect([this, tryLatestOnError](std::string const& info, int code) { // if the url was not found, try downloading latest release instead // (for development versions) - if (code == 404 && tryLatestOnError) { - this->downloadLoaderResources(true); - } - else { - ResourceDownloadEvent( - UpdateFailed("Unable to download resources: " + info) - ).post(); + if (code == 404) { + log::warn("Unable to download resources: {}", info); } + ResourceDownloadEvent( + UpdateFailed("Unable to download resources: " + info) + ).post(); }) .progress([](auto&, double now, double total) { ResourceDownloadEvent( @@ -768,65 +766,66 @@ void Loader::Impl::updateSpecialFiles() { } void Loader::Impl::downloadLoaderResources(bool useLatestRelease) { - if (!useLatestRelease) { - web::AsyncWebRequest() - .join("loader-tag-exists-check") - .userAgent("github_api/1.0") - .fetch(fmt::format( - "https://api.github.com/repos/geode-sdk/geode/git/ref/tags/{}", + web::AsyncWebRequest() + .join("loader-tag-exists-check") + .userAgent("github_api/1.0") + .fetch(fmt::format( + "https://api.github.com/repos/geode-sdk/geode/git/ref/tags/{}", + this->getVersion().toString() + )) + .json() + .then([this](json::Value const& json) { + this->tryDownloadLoaderResources(fmt::format( + "https://github.com/geode-sdk/geode/releases/download/{}/resources.zip", this->getVersion().toString() - )) - .json() - .then([this](json::Value const& json) { - this->tryDownloadLoaderResources(fmt::format( - "https://github.com/geode-sdk/geode/releases/download/{}/resources.zip", - this->getVersion().toString() - ), true); - }) - .expect([this](std::string const& info, int code) { - if (code == 404) { - log::debug("Loader version {} does not exist on Github, not downloading the resources", this->getVersion().toString()); - ResourceDownloadEvent( - UpdateFinished() - ).post(); + ), true); + }) + .expect([=](std::string const& info, int code) { + if (code == 404) { + if (useLatestRelease) { + log::debug("Loader version {} does not exist on Github, downloading latest resources", this->getVersion().toString()); + fetchLatestGithubRelease( + [this](json::Value const& raw) { + auto json = raw; + JsonChecker checker(json); + auto root = checker.root("[]").obj(); + + // find release asset + for (auto asset : root.needs("assets").iterate()) { + auto obj = asset.obj(); + if (obj.needs("name").template get() == "resources.zip") { + this->tryDownloadLoaderResources( + obj.needs("browser_download_url").template get(), + false + ); + return; + } + } + + ResourceDownloadEvent( + UpdateFailed("Unable to find resources in latest GitHub release") + ).post(); + }, + [this](std::string const& info) { + ResourceDownloadEvent( + UpdateFailed("Unable to download resources: " + info) + ).post(); + } + ); } else { - ResourceDownloadEvent( - UpdateFailed("Unable to check if tag exists: " + info) - ).post(); - } - }); - } - else { - fetchLatestGithubRelease( - [this](json::Value const& raw) { - auto json = raw; - JsonChecker checker(json); - auto root = checker.root("[]").obj(); - - // find release asset - for (auto asset : root.needs("assets").iterate()) { - auto obj = asset.obj(); - if (obj.needs("name").template get() == "resources.zip") { - this->tryDownloadLoaderResources( - obj.needs("browser_download_url").template get(), - false - ); - return; - } + log::debug("Loader version {} does not exist on Github, not downloading the resources", this->getVersion().toString()); } - ResourceDownloadEvent( - UpdateFailed("Unable to find resources in latest GitHub release") + UpdateFinished() ).post(); - }, - [this](std::string const& info) { + } + else { ResourceDownloadEvent( - UpdateFailed("Unable to download resources: " + info) + UpdateFailed("Unable to check if tag exists: " + info) ).post(); } - ); - } + }); } bool Loader::Impl::verifyLoaderResources() { @@ -844,7 +843,7 @@ bool Loader::Impl::verifyLoaderResources() { ghc::filesystem::is_directory(resourcesDir) )) { log::debug("Resources directory does not exist"); - this->downloadLoaderResources(); + this->downloadLoaderResources(true); return false; } From bf1d47244f4d6bc6cec681b16fbc02f029a926d0 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Sep 2023 17:11:36 +0300 Subject: [PATCH 042/135] hardcode path utils to external for now --- loader/src/platform/android/util.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 78d33be48..37fdf550f 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -10,11 +10,19 @@ using namespace geode::prelude; #include ghc::filesystem::path dirs::getGameDir() { - return CCFileUtils::sharedFileUtils()->getWritablePath().c_str(); + return ghc::filesystem::path( + "/storage/emulated/0/Android/data/com.geode.launcher/files/game" + // "/data/user/0/com.geode.launcher/files/" + /*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/ + ); } ghc::filesystem::path dirs::getSaveDir() { - return CCFileUtils::sharedFileUtils()->getWritablePath().c_str(); + return ghc::filesystem::path( + "/storage/emulated/0/Android/data/com.geode.launcher/files/save" + // "/data/user/0/com.geode.launcher/files/" + /*CCFileUtils::sharedFileUtils()->getWritablePath().c_str()*/ + ); } void utils::web::openLinkInBrowser(std::string const& url) { From d33c508d482eee7effb3611c46e359b474c26e57 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Sep 2023 17:22:30 +0300 Subject: [PATCH 043/135] move unzipped to inside data --- loader/src/loader/Dirs.cpp | 4 ---- loader/src/platform/android/util.cpp | 7 +++++++ loader/src/platform/mac/util.mm | 4 ++++ loader/src/platform/windows/util.cpp | 4 ++++ 4 files changed, 15 insertions(+), 4 deletions(-) diff --git a/loader/src/loader/Dirs.cpp b/loader/src/loader/Dirs.cpp index 7cb3ab7cb..59aacc52b 100644 --- a/loader/src/loader/Dirs.cpp +++ b/loader/src/loader/Dirs.cpp @@ -35,10 +35,6 @@ ghc::filesystem::path dirs::getModsSaveDir() { return getGeodeSaveDir() / "mods"; } -ghc::filesystem::path dirs::getModRuntimeDir() { - return dirs::getGeodeDir() / "unzipped"; -} - ghc::filesystem::path dirs::getModConfigDir() { return dirs::getGeodeDir() / "config"; } diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 37fdf550f..8145a529e 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -25,6 +25,13 @@ ghc::filesystem::path dirs::getSaveDir() { ); } +ghc::filesystem::path dirs::getModRuntimeDir() { + return ghc::filesystem::path( + "/data/user/0/com.geode.launcher/files/geode/unzipped" + ); + // return dirs::getGeodeDir() / "unzipped"; +} + void utils::web::openLinkInBrowser(std::string const& url) { CCApplication::sharedApplication()->openURL(url.c_str()); } diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm index 6a100715d..31111cfa5 100644 --- a/loader/src/platform/mac/util.mm +++ b/loader/src/platform/mac/util.mm @@ -200,6 +200,10 @@ @implementation FileDialog return path; } +ghc::filesystem::path dirs::getModRuntimeDir() { + return dirs::getGeodeDir() / "unzipped"; +} + void geode::utils::game::exit() { if (CCApplication::sharedApplication() && (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { diff --git a/loader/src/platform/windows/util.cpp b/loader/src/platform/windows/util.cpp index ee26861f5..68e7ad526 100644 --- a/loader/src/platform/windows/util.cpp +++ b/loader/src/platform/windows/util.cpp @@ -158,6 +158,10 @@ ghc::filesystem::path dirs::getSaveDir() { return path; } +ghc::filesystem::path dirs::getModRuntimeDir() { + return dirs::getGeodeDir() / "unzipped"; +} + void geode::utils::game::exit() { if (CCApplication::sharedApplication() && (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { From b3ac20d2a7bda35f89ec33d4bbbf560b551c47f7 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sat, 16 Sep 2023 19:03:31 +0300 Subject: [PATCH 044/135] fix resources again --- loader/src/hooks/LoadingLayer.cpp | 6 ++---- loader/src/loader/LoaderImpl.cpp | 2 ++ 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index ca048b648..27c158243 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -29,6 +29,8 @@ struct CustomLoadingLayer : Modify { // hook bool init(bool fromReload) { + CCFileUtils::get()->updatePaths(); + if (!LoadingLayer::init(fromReload)) return false; auto winSize = CCDirector::sharedDirector()->getWinSize(); @@ -43,8 +45,6 @@ struct CustomLoadingLayer : Modify { } void setupLoadingMods() { - CCFileUtils::get()->updatePaths(); - if (Loader::get()->getLoadingState() != Loader::LoadingState::Done) { this->updateLoadedModsLabel(); this->waitLoadAssets(); @@ -55,8 +55,6 @@ struct CustomLoadingLayer : Modify { } void setupLoaderResources() { - LoaderImpl::get()->addSearchPaths(); - // verify loader resources if (!LoaderImpl::get()->verifyLoaderResources()) { this->setSmallText("Downloading Loader Resources"); diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index c281e2027..6baa2bd8c 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -87,6 +87,8 @@ Result<> Loader::Impl::setup() { this->createDirectories(); + this->addSearchPaths(); + this->refreshModGraph(); m_isSetup = true; From 81078e2effbbacd1aaeb7124cee8613d6a184a3b Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 16 Sep 2023 14:20:49 -0300 Subject: [PATCH 045/135] update tuliphook --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e53924f80..f1ebe0feb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#41a18a1") +CPMAddPackage("gh:geode-sdk/TulipHook#f2bed6c") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies From 77a6f8685dbdba38915ea3a0948aeec03a1bb2e9 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 16 Sep 2023 17:15:42 -0300 Subject: [PATCH 046/135] revert because im silly --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f1ebe0feb..e53924f80 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#f2bed6c") +CPMAddPackage("gh:geode-sdk/TulipHook#41a18a1") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies From 45d3be890321be11f2e2d17b73bc32e02ba195e4 Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sat, 16 Sep 2023 17:25:15 -0300 Subject: [PATCH 047/135] change these to createDirectoryAll --- loader/src/loader/LoaderImpl.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 6baa2bd8c..44ae6c774 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -45,11 +45,11 @@ void Loader::Impl::createDirectories() { try { ghc::filesystem::remove_all(dirs::getModRuntimeDir()); } catch(...) {} (void) utils::file::createDirectoryAll(dirs::getGeodeResourcesDir()); - (void) utils::file::createDirectory(dirs::getModConfigDir()); - (void) utils::file::createDirectory(dirs::getModsDir()); - (void) utils::file::createDirectory(dirs::getGeodeLogDir()); - (void) utils::file::createDirectory(dirs::getTempDir()); - (void) utils::file::createDirectory(dirs::getModRuntimeDir()); + (void) utils::file::createDirectoryAll(dirs::getModConfigDir()); + (void) utils::file::createDirectoryAll(dirs::getModsDir()); + (void) utils::file::createDirectoryAll(dirs::getGeodeLogDir()); + (void) utils::file::createDirectoryAll(dirs::getTempDir()); + (void) utils::file::createDirectoryAll(dirs::getModRuntimeDir()); if (!ranges::contains(m_modSearchDirectories, dirs::getModsDir())) { m_modSearchDirectories.push_back(dirs::getModsDir()); From 1ab86bd5c12a5275752a883b66dfd7293cc0d85e Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Sat, 16 Sep 2023 22:29:11 -0300 Subject: [PATCH 048/135] create temp ci script --- .github/workflows/build-android.yml | 57 +++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 .github/workflows/build-android.yml diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml new file mode 100644 index 000000000..d15024039 --- /dev/null +++ b/.github/workflows/build-android.yml @@ -0,0 +1,57 @@ +name: Build Android + +on: + workflow_dispatch: + push: + branches: + - '**' # every branch + - '!no-build-**' # unless marked as no-build + +jobs: + build: + name: Build Android + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r25c + add-to-path: false + + - name: Download CLI + uses: robinraju/release-downloader@v1.8 + with: + repository: geode-sdk/cli + latest: true + fileName: '*-linux.zip' + tarBall: false + zipBall: false + out-file-path: "cli" + + - name: Setup CLI + run: | + 7z x "${{ github.workspace }}/cli/*-linux.zip" -o"${{ github.workspace }}/cli" + chmod +x $GITHUB_WORKSPACE/cli/geode + echo "${{ github.workspace }}/cli" >> $GITHUB_PATH + + - name: Configure + env: + NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} + ANDROID_ABI: armeabi-v7a + MIN_SDK_VERSION: 24 + run: | + sudo apt install ninja-build + cmake -DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ANDROID_ABI -DANDROID_PLATFORM=android-$MIN_SDK_VERSION -DCMAKE_BUILD_TYPE=Debug -DGEODE_DONT_BUILD_TEST_MODS=1 -G Ninja -B build + + - name: Build + run: | + cmake --build build --config Debug + + - name: Upload Artifacts + uses: actions/upload-artifact@v3 + with: + name: geode-android + path: ./bin/nightly/*.so From 23cd456860589eb6c3dd13891231dcf0a7b7ab24 Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Sun, 17 Sep 2023 14:23:13 -0300 Subject: [PATCH 049/135] fix CCNode::removeChildByID not being exported properly --- loader/include/Geode/cocos/base_nodes/CCNode.h | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/loader/include/Geode/cocos/base_nodes/CCNode.h b/loader/include/Geode/cocos/base_nodes/CCNode.h index 51817e3c4..944001e0a 100644 --- a/loader/include/Geode/cocos/base_nodes/CCNode.h +++ b/loader/include/Geode/cocos/base_nodes/CCNode.h @@ -700,12 +700,6 @@ class CC_DLL CCNode : public CCObject * @param cleanup true if all running actions and callbacks on the child node will be cleanup, false otherwise. */ virtual void removeChildByTag(int tag, bool cleanup); - /** - * Removes a child from the container by its ID. - * @param id The ID of the node - * @note Geode addition - */ - void removeChildByID(std::string const& id); /** * Removes all children from the container with a cleanup. * @@ -890,6 +884,13 @@ class CC_DLL CCNode : public CCObject */ GEODE_DLL CCNode* getChildByIDRecursive(std::string const& id); + /** + * Removes a child from the container by its ID. + * @param id The ID of the node + * @note Geode addition + */ + GEODE_DLL void removeChildByID(std::string const& id); + /** * Add a child before a specified existing child * @param child The node to add. The node may not be a child of another From 19b0f726340b206331a7f2e7dda1590ceeeeec3b Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sun, 17 Sep 2023 14:41:27 -0300 Subject: [PATCH 050/135] some stuff for rgb color input --- bindings/Cocos2d.bro | 15 +++++++++++---- bindings/GeometryDash.bro | 10 +++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index b4fe40694..61b8a0935 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -1165,16 +1165,23 @@ class cocos2d::extension::CCControl { auto isSelected() = mac 0x1a7ec0; } -[[link(win, android)]] + class cocos2d::extension::CCControlColourPicker { - CCControlColourPicker() {} + [[link(win)]] + CCControlColourPicker() {} + [[link(win)]] ~CCControlColourPicker() = mac 0x1aae30; - auto setColorValue(cocos2d::_ccColor3B const&) = mac 0x1aac10; + [[link(win, android)]] + auto setColorValue(cocos2d::_ccColor3B const&) = mac 0x1aac10; + [[link(win)]] auto ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) = mac 0x1aae10; + [[link(win)]] auto init() = mac 0x1aa400; + [[link(win)]] static auto colourPicker() = mac 0x1aaa30; + [[link(win)]] cocos2d::ccColor3B const& getColorValue() const { - return m_rgb; + return m_rgb; } } diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 1b35b0ed2..3e3ef0667 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -909,14 +909,14 @@ class ColorSelectPopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, int m_copyChannelID; bool m_copyOpacity; ConfigureHSVWidget* m_hsvWidget; - PAD = win 0x10, mac 0x10; + PAD = win 0x10, mac 0x10, android 0x10; cocos2d::CCArray* m_unk254; cocos2d::CCArray* m_unk258; CCTextInputNode* m_textInput2; - PAD = win 0x4, mac 0x8; + PAD = win 0x4, mac 0x8, android 0x4; CCMenuItemToggler* m_toggler3; CCMenuItemToggler* m_toggler4; - PAD = win 0x8, mac 0x10; + PAD = win 0x8, mac 0x10, android 0x8; cocos2d::CCArray* m_unk274; bool m_spawnTrigger; bool m_multiTrigger; @@ -5592,10 +5592,10 @@ class SetupPulsePopup : FLAlertLayer, cocos2d::extension::ColorPickerDelegate, T cocos2d::extension::CCControlColourPicker* m_colorPicker; - PAD = win 0x30, mac 0x60; + PAD = win 0x30, mac 0x60, android 0x30; cocos2d::CCSprite* m_currentColorSpr; cocos2d::CCSprite* m_prevColorSpr; - PAD = win 0x64, mac 0xac; + PAD = win 0x64, mac 0xac, android 0x64; int m_pulseMode; // 0x38c on mac } From e7e5ee7f26d109373861eadcb34a04459c3d922e Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sun, 17 Sep 2023 15:01:34 -0300 Subject: [PATCH 051/135] add some opengl functions here, for now --- loader/CMakeLists.txt | 5 +++++ loader/src/platform/android/main.cpp | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt index 422bf8d57..50f844e1e 100644 --- a/loader/CMakeLists.txt +++ b/loader/CMakeLists.txt @@ -149,6 +149,11 @@ if (APPLE) file(COPY ${GEODE_LOADER_PATH}/include/link/libfmod.dylib DESTINATION ${GEODE_BIN_PATH}/nightly) endif() +if (ANDROID) + # needed to define some opengl functions + target_link_libraries(${PROJECT_NAME} EGL) +endif() + target_include_directories(${PROJECT_NAME} PRIVATE src/ src/loader/ diff --git a/loader/src/platform/android/main.cpp b/loader/src/platform/android/main.cpp index 5f6694112..3fd948b8d 100644 --- a/loader/src/platform/android/main.cpp +++ b/loader/src/platform/android/main.cpp @@ -5,7 +5,17 @@ #include "../load.hpp" #include +// idk where to put this +#include +PFNGLGENVERTEXARRAYSOESPROC glGenVertexArraysOESEXT = 0; +PFNGLBINDVERTEXARRAYOESPROC glBindVertexArrayOESEXT = 0; +PFNGLDELETEVERTEXARRAYSOESPROC glDeleteVertexArraysOESEXT = 0; + extern "C" [[gnu::visibility("default")]] jint JNI_OnLoad(JavaVM* vm, void* reserved) { + glGenVertexArraysOESEXT = (PFNGLGENVERTEXARRAYSOESPROC)eglGetProcAddress("glGenVertexArraysOES"); + glBindVertexArrayOESEXT = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); + glDeleteVertexArraysOESEXT = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); + geodeEntry(nullptr); return JNI_VERSION_1_1; } From 140f38bee0d0d7a0e5ae77280e0e07ebe992195c Mon Sep 17 00:00:00 2001 From: FigmentBoy <17240592+FigmentBoy@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:14:59 -0400 Subject: [PATCH 052/135] Make MDTextArea fit within provided size (and look better) --- loader/src/ui/nodes/MDTextArea.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/loader/src/ui/nodes/MDTextArea.cpp b/loader/src/ui/nodes/MDTextArea.cpp index c6afcda20..fb5e20464 100644 --- a/loader/src/ui/nodes/MDTextArea.cpp +++ b/loader/src/ui/nodes/MDTextArea.cpp @@ -109,8 +109,8 @@ bool MDTextArea::init(std::string const& str, CCSize const& size) { if (!CCLayer::init()) return false; m_text = str; - m_size = size; - this->setContentSize(size); + m_size = size - CCSize { 15.f, 0.f }; + this->setContentSize(m_size); m_renderer = TextRenderer::create(); CC_SAFE_RETAIN(m_renderer); @@ -118,8 +118,8 @@ bool MDTextArea::init(std::string const& str, CCSize const& size) { m_bgSprite->setScale(.5f); m_bgSprite->setColor({ 0, 0, 0 }); m_bgSprite->setOpacity(75); - m_bgSprite->setContentSize(size * 2 + CCSize { 25.f, 25.f }); - m_bgSprite->setPosition(size / 2); + m_bgSprite->setContentSize(size * 2); + m_bgSprite->setPosition(m_size / 2); this->addChild(m_bgSprite); m_scrollLayer = ScrollLayer::create({ 0, 0, m_size.width, m_size.height }, true); @@ -695,7 +695,16 @@ void MDTextArea::updateLabel() { m_renderer->end(); - m_scrollLayer->m_contentLayer->setContentSize(m_content->getContentSize()); + if (m_content->getContentSize().height > m_size.height) { + // Generate bottom padding + m_scrollLayer->m_contentLayer->setContentSize(m_content->getContentSize() + CCSize { 0.f, 12.5 }); + m_content->setPositionY(10.f); + } else { + m_scrollLayer->m_contentLayer->setContentSize(m_content->getContentSize()); + m_content->setPositionY(-2.5f); + } + + m_scrollLayer->moveToTop(); } From 152dc7edcf31691cd5d9a923b70387b4a562d40c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:07:25 +0300 Subject: [PATCH 053/135] Add MenuItemSprite --- bindings/Cocos2d.bro | 5 + loader/include/Geode/ui/MenuItemSprite.hpp | 47 ++++++++++ loader/include/Geode/ui/MenuItemToggle.hpp | 43 +++++++++ loader/include/Geode/utils/MiniFunction.hpp | 24 +++++ loader/src/ui/internal/list/ModListLayer.cpp | 4 +- loader/src/ui/nodes/MenuItemSprite.cpp | 98 ++++++++++++++++++++ 6 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 loader/include/Geode/ui/MenuItemSprite.hpp create mode 100644 loader/include/Geode/ui/MenuItemToggle.hpp create mode 100644 loader/src/ui/nodes/MenuItemSprite.cpp diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index bde65aff0..6f617e769 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -264,6 +264,11 @@ class cocos2d::CCEaseOut { static cocos2d::CCEaseOut* create(cocos2d::CCActionInterval*, float) = mac 0x2a1b70; } +[[link(win)]] +class cocos2d::CCEaseBounceOut { + static cocos2d::CCEaseBounceOut* create(cocos2d::CCActionInterval*) = mac 0x2a3b40; +} + [[link(win)]] class cocos2d::CCEGLView { CCEGLView(); diff --git a/loader/include/Geode/ui/MenuItemSprite.hpp b/loader/include/Geode/ui/MenuItemSprite.hpp new file mode 100644 index 000000000..113eb80d5 --- /dev/null +++ b/loader/include/Geode/ui/MenuItemSprite.hpp @@ -0,0 +1,47 @@ +#pragma once + +#include +#include "../utils/MiniFunction.hpp" + +#pragma warning(disable : 4275) + +namespace geode { + class GEODE_DLL MenuItemSprite : public cocos2d::CCMenuItemSprite { + protected: + + MenuItemSprite(); + ~MenuItemSprite() override; + + public: + static MenuItemSprite* create( + cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback + ); + + static MenuItemSprite* create( + cocos2d::CCNode* normalSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback + ); + + bool init( + cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback + ); + + void runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator); + void runActionOnSprites(utils::MiniFunction generator); + + utils::MiniFunction m_selectedAction; + utils::MiniFunction m_unselectedAction; + utils::MiniFunction m_activateAction; + + void activate() override; + void selected() override; + void unselected() override; + + void setImage(cocos2d::CCNode* image); + void setNormalImage(cocos2d::CCNode* image) override; + void setDisabledImage(cocos2d::CCNode* image) override; + void setSelectedImage(cocos2d::CCNode* image) override; + }; +} diff --git a/loader/include/Geode/ui/MenuItemToggle.hpp b/loader/include/Geode/ui/MenuItemToggle.hpp new file mode 100644 index 000000000..6399773aa --- /dev/null +++ b/loader/include/Geode/ui/MenuItemToggle.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include +#include "MenuItemSprite.hpp" + +#pragma warning(disable : 4275) + +namespace geode { + class GEODE_DLL MenuItemToggle : public cocos2d::CCMenuItem { + protected: + MenuItemSprite* m_offButton; + MenuItemSprite* m_onButton; + bool m_toggled; + + MenuItemToggle(); + ~MenuItemToggle() override; + + public: + static MenuItemToggle* create( + cocos2d::CCNode* onSprite, cocos2d::CCNode* offSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback + ); + + bool init( + cocos2d::CCNode* onSprite, cocos2d::CCNode* offSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback + ); + + void setOffButton(MenuItemSprite* button); + void setOnButton(MenuItemSprite* button); + MenuItemSprite* getOffButton() const; + MenuItemSprite* getOnButton() const; + + bool isToggled() const; + void toggle(bool enabled); + + void setScale(float scale) override; + void activate() override; + void selected() override; + void unselected() override; + void setEnabled(bool enabled) override; + }; +} diff --git a/loader/include/Geode/utils/MiniFunction.hpp b/loader/include/Geode/utils/MiniFunction.hpp index edb660526..72cf1e19c 100644 --- a/loader/include/Geode/utils/MiniFunction.hpp +++ b/loader/include/Geode/utils/MiniFunction.hpp @@ -123,6 +123,30 @@ namespace geode::utils { return *this; } + template + requires(MiniFunctionCallable && !std::is_same_v, MiniFunction>) + MiniFunction& operator=(Callable&& func) { + delete m_state; + m_state = new MiniFunctionState, Ret, Args...>(std::forward(func)); + return *this; + } + + template + requires(!MiniFunctionCallable && std::is_pointer_v && std::is_function_v>) + MiniFunction& operator=(FunctionPointer func) { + delete m_state; + m_state = new MiniFunctionStatePointer(func); + return *this; + } + + template + requires(std::is_member_function_pointer_v) + MiniFunction& operator=(MemberFunctionPointer func) { + delete m_state; + m_state = new MiniFunctionStateMemberPointer(func); + return *this; + } + Ret operator()(Args... args) const { if (!m_state) return Ret(); return m_state->call(args...); diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index a06e745c7..e950a5211 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -16,6 +16,8 @@ #include #include +#include + #define FTS_FUZZY_MATCH_IMPLEMENTATION #include @@ -259,7 +261,7 @@ bool ModListLayer::init() { m_topMenu = CCMenu::create(); // add back button - auto backBtn = CCMenuItemSpriteExtra::create( + auto backBtn = MenuItemSprite::create( CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"), this, menu_selector(ModListLayer::onExit) ); diff --git a/loader/src/ui/nodes/MenuItemSprite.cpp b/loader/src/ui/nodes/MenuItemSprite.cpp new file mode 100644 index 000000000..cb6ec2a2b --- /dev/null +++ b/loader/src/ui/nodes/MenuItemSprite.cpp @@ -0,0 +1,98 @@ +#include + +using namespace geode::prelude; + +MenuItemSprite* MenuItemSprite::create( + cocos2d::CCNode* normalSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback +) { + return MenuItemSprite::create(normalSprite, nullptr, target, callback); +} + +MenuItemSprite* MenuItemSprite::create( + cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback +) { + auto ret = new MenuItemSprite(); + if (ret && ret->init(normalSprite, disabledSprite, target, callback)) { + ret->autorelease(); + return ret; + } + CC_SAFE_DELETE(ret); + return nullptr; +} + +MenuItemSprite::MenuItemSprite() {} + +MenuItemSprite::~MenuItemSprite() { +} + +void MenuItemSprite::setImage(cocos2d::CCNode* image) { + if (image) { + image->setAnchorPoint({ 0.5f, 0.5f }); + image->setPosition(image->getContentSize() / 2); + } +} + +// why are the members private like what +void MenuItemSprite::setNormalImage(cocos2d::CCNode* image) { + CCMenuItemSprite::setNormalImage(image); + this->setImage(image); +} +void MenuItemSprite::setDisabledImage(cocos2d::CCNode* image) { + CCMenuItemSprite::setDisabledImage(image); + this->setImage(image); +} +void MenuItemSprite::setSelectedImage(cocos2d::CCNode* image) { + CCMenuItemSprite::setSelectedImage(image); + this->setImage(image); +} + +bool MenuItemSprite::init( + cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, + cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback +) { + if (!CCMenuItemSprite::initWithNormalSprite(normalSprite, disabledSprite, nullptr, target, callback)) return false; + + m_selectedAction = []() -> cocos2d::CCAction* { + return cocos2d::CCEaseBounceOut::create(cocos2d::CCScaleTo::create(0.3f, 1.26f)); + }; + m_unselectedAction = []() -> cocos2d::CCAction* { + return cocos2d::CCEaseBounceOut::create(cocos2d::CCScaleTo::create(0.4f, 1.0f)); + }; + m_activateAction = []() -> cocos2d::CCAction* { + return cocos2d::CCScaleTo::create(0.f, 1.0f); + }; + + return true; +} + +void MenuItemSprite::runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator) { + if (sprite) { + sprite->stopAllActions(); + if (generator) sprite->runAction(generator); + } +} + +void MenuItemSprite::runActionOnSprites(MiniFunction generator) { + this->runActionOnSprite(this->getNormalImage(), generator()); + this->runActionOnSprite(this->getDisabledImage(), generator()); + this->runActionOnSprite(this->getSelectedImage(), generator()); +} + +void MenuItemSprite::activate() { + this->runActionOnSprites(m_activateAction); + CCMenuItem::activate(); +} +void MenuItemSprite::selected() { + if (!m_bEnabled) return; + CCMenuItem::selected(); + + this->runActionOnSprites(m_selectedAction); +} +void MenuItemSprite::unselected() { + if (!m_bEnabled) return; + CCMenuItem::unselected(); + + this->runActionOnSprites(m_unselectedAction); +} \ No newline at end of file From e8b98e48f558af95ea14fc902a0a26967be24fc5 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:37:20 +0300 Subject: [PATCH 054/135] Fix some stuff related to menuitemspriteextra but gonna revert --- loader/include/Geode/UI.hpp | 1 + ...ItemSprite.hpp => MenuItemSpriteExtra.hpp} | 13 +++-- loader/include/Geode/ui/MenuItemToggle.hpp | 14 +++--- loader/src/hooks/MenuLayer.cpp | 2 +- loader/src/ui/internal/info/ModInfoPopup.cpp | 20 ++++---- loader/src/ui/internal/info/ModInfoPopup.hpp | 5 +- .../src/ui/internal/list/InstallListCell.cpp | 5 +- .../src/ui/internal/list/InstallListPopup.cpp | 2 +- loader/src/ui/internal/list/ModListCell.cpp | 17 +++---- loader/src/ui/internal/list/ModListCell.hpp | 5 +- loader/src/ui/internal/list/ModListLayer.cpp | 16 +++--- loader/src/ui/internal/list/ModListLayer.hpp | 9 ++-- .../src/ui/internal/list/ProblemsListCell.cpp | 4 +- .../ui/internal/settings/GeodeSettingNode.cpp | 12 ++--- .../ui/internal/settings/GeodeSettingNode.hpp | 24 ++++----- .../ui/internal/settings/ModSettingsPopup.cpp | 6 +-- .../ui/internal/settings/ModSettingsPopup.hpp | 2 +- loader/src/ui/nodes/ColorPickPopup.cpp | 2 +- loader/src/ui/nodes/MDPopup.cpp | 4 +- ...ItemSprite.cpp => MenuItemSpriteExtra.cpp} | 49 +++++++++++-------- loader/test/dependency/main.cpp | 6 +-- 21 files changed, 115 insertions(+), 103 deletions(-) rename loader/include/Geode/ui/{MenuItemSprite.hpp => MenuItemSpriteExtra.hpp} (81%) rename loader/src/ui/nodes/{MenuItemSprite.cpp => MenuItemSpriteExtra.cpp} (58%) diff --git a/loader/include/Geode/UI.hpp b/loader/include/Geode/UI.hpp index 2330064ca..fc326ce63 100644 --- a/loader/include/Geode/UI.hpp +++ b/loader/include/Geode/UI.hpp @@ -10,6 +10,7 @@ #include "ui/ListView.hpp" #include "ui/MDPopup.hpp" #include "ui/MDTextArea.hpp" +#include "ui/MenuItemSpriteExtra.hpp" #include "ui/Notification.hpp" #include "ui/Popup.hpp" #include "ui/SceneManager.hpp" diff --git a/loader/include/Geode/ui/MenuItemSprite.hpp b/loader/include/Geode/ui/MenuItemSpriteExtra.hpp similarity index 81% rename from loader/include/Geode/ui/MenuItemSprite.hpp rename to loader/include/Geode/ui/MenuItemSpriteExtra.hpp index 113eb80d5..776519eda 100644 --- a/loader/include/Geode/ui/MenuItemSprite.hpp +++ b/loader/include/Geode/ui/MenuItemSpriteExtra.hpp @@ -6,19 +6,20 @@ #pragma warning(disable : 4275) namespace geode { - class GEODE_DLL MenuItemSprite : public cocos2d::CCMenuItemSprite { + class GEODE_DLL MenuItemSpriteExtra : public cocos2d::CCMenuItemSprite { protected: + bool m_scaleSprites; - MenuItemSprite(); - ~MenuItemSprite() override; + MenuItemSpriteExtra(); + ~MenuItemSpriteExtra() override; public: - static MenuItemSprite* create( + static MenuItemSpriteExtra* create( cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ); - static MenuItemSprite* create( + static MenuItemSpriteExtra* create( cocos2d::CCNode* normalSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ); @@ -39,6 +40,8 @@ namespace geode { void selected() override; void unselected() override; + void setScaleSprites(bool scale); + void setImage(cocos2d::CCNode* image); void setNormalImage(cocos2d::CCNode* image) override; void setDisabledImage(cocos2d::CCNode* image) override; diff --git a/loader/include/Geode/ui/MenuItemToggle.hpp b/loader/include/Geode/ui/MenuItemToggle.hpp index 6399773aa..2e704c8ac 100644 --- a/loader/include/Geode/ui/MenuItemToggle.hpp +++ b/loader/include/Geode/ui/MenuItemToggle.hpp @@ -1,15 +1,15 @@ #pragma once #include -#include "MenuItemSprite.hpp" +#include "MenuItemSpriteExtra.hpp" #pragma warning(disable : 4275) namespace geode { class GEODE_DLL MenuItemToggle : public cocos2d::CCMenuItem { protected: - MenuItemSprite* m_offButton; - MenuItemSprite* m_onButton; + MenuItemSpriteExtra* m_offButton; + MenuItemSpriteExtra* m_onButton; bool m_toggled; MenuItemToggle(); @@ -26,10 +26,10 @@ namespace geode { cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ); - void setOffButton(MenuItemSprite* button); - void setOnButton(MenuItemSprite* button); - MenuItemSprite* getOffButton() const; - MenuItemSprite* getOnButton() const; + void setOffButton(MenuItemSpriteExtra* button); + void setOnButton(MenuItemSpriteExtra* button); + MenuItemSpriteExtra* getOffButton() const; + MenuItemSpriteExtra* getOnButton() const; bool isToggled() const; void toggle(bool enabled); diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp index 869d1bce2..4bddc8f12 100644 --- a/loader/src/hooks/MenuLayer.cpp +++ b/loader/src/hooks/MenuLayer.cpp @@ -77,7 +77,7 @@ struct CustomMenuLayer : Modify { auto bottomMenu = static_cast(this->getChildByID("bottom-menu")); - auto btn = CCMenuItemSpriteExtra::create( + auto btn = MenuItemSpriteExtra::create( m_fields->m_geodeButton, this, static_cast(geodeBtnSelector) ); diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index 945e5ec4b..d1c5c230a 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -151,13 +151,13 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { auto infoSpr = CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"); infoSpr->setScale(.85f); - m_infoBtn = CCMenuItemSpriteExtra::create(infoSpr, this, menu_selector(ModInfoPopup::onInfo)); + m_infoBtn = MenuItemSpriteExtra::create(infoSpr, this, menu_selector(ModInfoPopup::onInfo)); m_infoBtn->setPosition(LAYER_SIZE.width / 2 - 25.f, LAYER_SIZE.height / 2 - 25.f); m_buttonMenu->addChild(m_infoBtn); // repo button if (metadata.getRepository()) { - auto repoBtn = CCMenuItemSpriteExtra::create( + auto repoBtn = MenuItemSpriteExtra::create( CCSprite::createWithSpriteFrameName("github.png"_spr), this, menu_selector(ModInfoPopup::onRepository) @@ -168,7 +168,7 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { // support button if (metadata.getSupportInfo()) { - auto supportBtn = CCMenuItemSpriteExtra::create( + auto supportBtn = MenuItemSpriteExtra::create( CCSprite::createWithSpriteFrameName("gift.png"_spr), this, menu_selector(ModInfoPopup::onSupport) @@ -181,7 +181,7 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { closeSpr->setScale(.8f); auto closeBtn = - CCMenuItemSpriteExtra::create(closeSpr, this, menu_selector(ModInfoPopup::onClose)); + MenuItemSpriteExtra::create(closeSpr, this, menu_selector(ModInfoPopup::onClose)); closeBtn->setPosition(-LAYER_SIZE.width / 2 + 3.f, LAYER_SIZE.height / 2 - 3.f); m_buttonMenu->addChild(closeBtn); @@ -399,7 +399,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { settingsSpr->setScale(.65f); auto settingsBtn = - CCMenuItemSpriteExtra::create(settingsSpr, this, menu_selector(LocalModInfoPopup::onSettings)); + MenuItemSpriteExtra::create(settingsSpr, this, menu_selector(LocalModInfoPopup::onSettings)); settingsBtn->setPosition(-LAYER_SIZE.width / 2 + 25.f, -LAYER_SIZE.height / 2 + 25.f); m_buttonMenu->addChild(settingsBtn); @@ -410,7 +410,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ); configSpr->setScale(.65f); - auto configBtn = CCMenuItemSpriteExtra::create( + auto configBtn = MenuItemSpriteExtra::create( configSpr, this, menu_selector(LocalModInfoPopup::onOpenConfigDir) ); configBtn->setPosition(-LAYER_SIZE.width / 2 + 65.f, -LAYER_SIZE.height / 2 + 25.f); @@ -451,7 +451,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ButtonSprite::create("Uninstall", "bigFont.fnt", "GJ_button_05.png", .6f); uninstallBtnSpr->setScale(.6f); - auto uninstallBtn = CCMenuItemSpriteExtra::create( + auto uninstallBtn = MenuItemSpriteExtra::create( uninstallBtnSpr, this, menu_selector(LocalModInfoPopup::onUninstall) ); uninstallBtn->setPosition(-85.f, 75.f); @@ -467,7 +467,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ); m_installBtnSpr->setScale(.6f); - m_installBtn = CCMenuItemSpriteExtra::create(m_installBtnSpr, this, menu_selector(LocalModInfoPopup::onUpdate)); + m_installBtn = MenuItemSpriteExtra::create(m_installBtnSpr, this, menu_selector(LocalModInfoPopup::onUpdate)); m_installBtn->setPosition(-8.0f, 75.f); m_buttonMenu->addChild(m_installBtn); @@ -536,7 +536,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ); issuesBtnSpr->setScale(.75f); - auto issuesBtn = CCMenuItemSpriteExtra::create( + auto issuesBtn = MenuItemSpriteExtra::create( issuesBtnSpr, this, menu_selector(LocalModInfoPopup::onIssues) ); issuesBtn->setPosition(0.f, -LAYER_SIZE.height / 2 + 25.f); @@ -726,7 +726,7 @@ bool IndexItemInfoPopup::init(IndexItemHandle item, ModListLayer* list) { ); m_installBtnSpr->setScale(.6f); - m_installBtn = CCMenuItemSpriteExtra::create( + m_installBtn = MenuItemSpriteExtra::create( m_installBtnSpr, this, menu_selector(IndexItemInfoPopup::onInstall) ); m_installBtn->setPosition(-143.0f, 75.f); diff --git a/loader/src/ui/internal/info/ModInfoPopup.hpp b/loader/src/ui/internal/info/ModInfoPopup.hpp index 808cd9181..e9ab045af 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.hpp +++ b/loader/src/ui/internal/info/ModInfoPopup.hpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace geode::prelude; @@ -31,8 +32,8 @@ class ModInfoPopup : public FLAlertLayer { ModListLayer* m_layer = nullptr; DownloadStatusNode* m_installStatus = nullptr; IconButtonSprite* m_installBtnSpr; - CCMenuItemSpriteExtra* m_installBtn; - CCMenuItemSpriteExtra* m_infoBtn; + MenuItemSpriteExtra* m_installBtn; + MenuItemSpriteExtra* m_infoBtn; CCLabelBMFont* m_latestVersionLabel = nullptr; CCLabelBMFont* m_minorVersionLabel = nullptr; MDTextArea* m_detailsArea; diff --git a/loader/src/ui/internal/list/InstallListCell.cpp b/loader/src/ui/internal/list/InstallListCell.cpp index 352d8aaf0..ce309181d 100644 --- a/loader/src/ui/internal/list/InstallListCell.cpp +++ b/loader/src/ui/internal/list/InstallListCell.cpp @@ -1,7 +1,6 @@ #include "InstallListCell.hpp" #include "InstallListPopup.hpp" #include -#include #include #include #include @@ -213,7 +212,7 @@ bool IndexItemInstallListCell::init( versionSelectSpr->setScale(.7f); auto versionSelectBtn = - CCMenuItemSpriteExtra::create(versionSelectSpr, this, menu_selector(IndexItemInstallListCell::onSelectVersion)); + MenuItemSpriteExtra::create(versionSelectSpr, this, menu_selector(IndexItemInstallListCell::onSelectVersion)); versionSelectBtn->setAnchorPoint({1.f, .5f}); versionSelectBtn->setPosition({m_toggle->getPositionX() - m_toggle->getContentSize().width - 5, m_height / 2}); m_menu->addChild(versionSelectBtn); @@ -372,7 +371,7 @@ bool SelectVersionCell::init(IndexItemHandle item, SelectVersionPopup* versionPo ); selectSpr->setScale(.6f); - auto selectBtn = CCMenuItemSpriteExtra::create( + auto selectBtn = MenuItemSpriteExtra::create( selectSpr, this, menu_selector(SelectVersionCell::onSelected) ); selectBtn->setAnchorPoint({1.f, .5f}); diff --git a/loader/src/ui/internal/list/InstallListPopup.cpp b/loader/src/ui/internal/list/InstallListPopup.cpp index e561ca9b9..2acbb6707 100644 --- a/loader/src/ui/internal/list/InstallListPopup.cpp +++ b/loader/src/ui/internal/list/InstallListPopup.cpp @@ -22,7 +22,7 @@ bool InstallListPopup::setup(IndexItemHandle item, MiniFunctionsetScale(.6f); - auto installBtn = CCMenuItemSpriteExtra::create( + auto installBtn = MenuItemSpriteExtra::create( installBtnSpr, this, menu_selector(InstallListPopup::onInstall) diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index 061e6dcb3..b1614011b 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -2,7 +2,6 @@ #include "ModListLayer.hpp" #include "../info/ModInfoPopup.hpp" #include -#include #include #include #include @@ -144,7 +143,7 @@ void ModListCell::setupInfo( creatorLabel->setColor({ 163, 163, 163 }); } - m_developerBtn = CCMenuItemSpriteExtra::create( + m_developerBtn = MenuItemSpriteExtra::create( creatorLabel, this, menu_selector(ModListCell::onViewDev) ); m_columnMenu->addChild(m_developerBtn); @@ -292,7 +291,7 @@ bool ModCell::init( exMark->setScale(.5f); m_unresolvedExMark = - CCMenuItemSpriteExtra::create(exMark, this, menu_selector(ModCell::onUnresolvedInfo)); + MenuItemSpriteExtra::create(exMark, this, menu_selector(ModCell::onUnresolvedInfo)); m_unresolvedExMark->setVisible(false); m_menu->addChild(m_unresolvedExMark); @@ -300,7 +299,7 @@ bool ModCell::init( auto restartSpr = ButtonSprite::create("Restart", "bigFont.fnt", "GJ_button_03.png", .8f); restartSpr->setScale(.65f); - auto restartBtn = CCMenuItemSpriteExtra::create(restartSpr, this, menu_selector(ModCell::onRestart)); + auto restartBtn = MenuItemSpriteExtra::create(restartSpr, this, menu_selector(ModCell::onRestart)); m_menu->addChild(restartBtn); } else { @@ -335,7 +334,7 @@ bool ModCell::init( } } - auto viewBtn = CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ModCell::onInfo)); + auto viewBtn = MenuItemSpriteExtra::create(viewSpr, this, menu_selector(ModCell::onInfo)); m_menu->addChild(viewBtn); } @@ -395,7 +394,7 @@ bool IndexItemCell::init( auto restartSpr = ButtonSprite::create("Restart", "bigFont.fnt", "GJ_button_03.png", .8f); restartSpr->setScale(.65f); - auto restartBtn = CCMenuItemSpriteExtra::create(restartSpr, this, menu_selector(IndexItemCell::onRestart)); + auto restartBtn = MenuItemSpriteExtra::create(restartSpr, this, menu_selector(IndexItemCell::onRestart)); m_menu->addChild(restartBtn); } else { @@ -403,7 +402,7 @@ bool IndexItemCell::init( viewSpr->setScale(.65f); auto viewBtn = - CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(IndexItemCell::onInfo)); + MenuItemSpriteExtra::create(viewSpr, this, menu_selector(IndexItemCell::onInfo)); m_menu->addChild(viewBtn); } @@ -517,7 +516,7 @@ bool InvalidGeodeFileCell::init( whySpr->setScale(.65f); auto viewBtn = - CCMenuItemSpriteExtra::create(whySpr, this, menu_selector(InvalidGeodeFileCell::onInfo)); + MenuItemSpriteExtra::create(whySpr, this, menu_selector(InvalidGeodeFileCell::onInfo)); menu->addChild(viewBtn); return true; @@ -635,7 +634,7 @@ bool ProblemsCell::init( viewSpr->setScale(.65f); auto viewBtn = - CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsCell::onInfo)); + MenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsCell::onInfo)); m_menu->addChild(viewBtn); m_menu->updateLayout(); diff --git a/loader/src/ui/internal/list/ModListCell.hpp b/loader/src/ui/internal/list/ModListCell.hpp index 28e253d9d..446f5b067 100644 --- a/loader/src/ui/internal/list/ModListCell.hpp +++ b/loader/src/ui/internal/list/ModListCell.hpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace geode::prelude; @@ -22,8 +23,8 @@ class ModListCell : public CCLayer { CCMenu* m_menu; CCLabelBMFont* m_description; CCMenuItemToggler* m_enableToggle = nullptr; - CCMenuItemSpriteExtra* m_unresolvedExMark; - CCMenuItemSpriteExtra* m_developerBtn; + MenuItemSpriteExtra* m_unresolvedExMark; + MenuItemSpriteExtra* m_developerBtn; SpacerNode* m_spacer = nullptr; CCMenu* m_columnMenu = nullptr; CCMenu* m_labelMenu = nullptr; diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index e950a5211..7f44d9ae3 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -16,8 +16,6 @@ #include #include -#include - #define FTS_FUZZY_MATCH_IMPLEMENTATION #include @@ -261,7 +259,7 @@ bool ModListLayer::init() { m_topMenu = CCMenu::create(); // add back button - auto backBtn = MenuItemSprite::create( + auto backBtn = MenuItemSpriteExtra::create( CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"), this, menu_selector(ModListLayer::onExit) ); @@ -272,7 +270,7 @@ bool ModListLayer::init() { auto reloadSpr = CCSprite::createWithSpriteFrameName("GJ_updateBtn_001.png"); reloadSpr->setScale(.8f); auto reloadBtn = - CCMenuItemSpriteExtra::create(reloadSpr, this, menu_selector(ModListLayer::onReload)); + MenuItemSpriteExtra::create(reloadSpr, this, menu_selector(ModListLayer::onReload)); reloadBtn->setPosition(-winSize.width / 2 + 30.0f, -winSize.height / 2 + 30.0f); m_menu->addChild(reloadBtn); @@ -281,7 +279,7 @@ bool ModListLayer::init() { "gj_folderBtn_001.png", .7f, CircleBaseColor::Green, CircleBaseSize::Small ); auto openBtn = - CCMenuItemSpriteExtra::create(openSpr, this, menu_selector(ModListLayer::onOpenFolder)); + MenuItemSpriteExtra::create(openSpr, this, menu_selector(ModListLayer::onOpenFolder)); openBtn->setPosition(-winSize.width / 2 + 30.0f, -winSize.height / 2 + 80.0f); m_menu->addChild(openBtn); @@ -396,7 +394,7 @@ void ModListLayer::createSearchControl() { filterSpr->setScale(.7f); m_filterBtn = - CCMenuItemSpriteExtra::create(filterSpr, this, menu_selector(ModListLayer::onFilters)); + MenuItemSpriteExtra::create(filterSpr, this, menu_selector(ModListLayer::onFilters)); m_filterBtn->setPosition(-10.f, 0.f); menu->addChild(m_filterBtn); @@ -404,14 +402,14 @@ void ModListLayer::createSearchControl() { auto searchSpr = CCSprite::createWithSpriteFrameName("gj_findBtn_001.png"); searchSpr->setScale(.7f); - m_searchBtn = CCMenuItemSpriteExtra::create(searchSpr, this, nullptr); + m_searchBtn = MenuItemSpriteExtra::create(searchSpr, this, nullptr); m_searchBtn->setPosition(-35.f, 0.f); menu->addChild(m_searchBtn); auto searchClearSpr = CCSprite::createWithSpriteFrameName("gj_findBtnOff_001.png"); searchClearSpr->setScale(.7f); - m_searchClearBtn = CCMenuItemSpriteExtra::create( + m_searchClearBtn = MenuItemSpriteExtra::create( searchClearSpr, this, menu_selector(ModListLayer::onResetSearch) ); m_searchClearBtn->setPosition(-35.f, 0.f); @@ -563,7 +561,7 @@ void ModListLayer::reloadList(bool keepScroll, std::optional const if (!m_checkForUpdatesBtn) { auto checkSpr = ButtonSprite::create("Check for Updates"); checkSpr->setScale(.7f); - m_checkForUpdatesBtn = CCMenuItemSpriteExtra::create( + m_checkForUpdatesBtn = MenuItemSpriteExtra::create( checkSpr, this, menu_selector(ModListLayer::onCheckForUpdates) ); m_checkForUpdatesBtn->setPosition(0, -winSize.height / 2 + 40.f); diff --git a/loader/src/ui/internal/list/ModListLayer.hpp b/loader/src/ui/internal/list/ModListLayer.hpp index 0afa2839f..f9a3780af 100644 --- a/loader/src/ui/internal/list/ModListLayer.hpp +++ b/loader/src/ui/internal/list/ModListLayer.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include using namespace geode::prelude; @@ -54,13 +55,13 @@ class ModListLayer : public CCLayer, public TextInputDelegate { CCMenuItemToggler* m_installedTabBtn; CCMenuItemToggler* m_downloadTabBtn; CCMenuItemToggler* m_featuredTabBtn; - CCMenuItemSpriteExtra* m_searchBtn; - CCMenuItemSpriteExtra* m_searchClearBtn; - CCMenuItemSpriteExtra* m_checkForUpdatesBtn = nullptr; + MenuItemSpriteExtra* m_searchBtn; + MenuItemSpriteExtra* m_searchClearBtn; + MenuItemSpriteExtra* m_checkForUpdatesBtn = nullptr; CCNode* m_searchBG = nullptr; CCTextInputNode* m_searchInput = nullptr; LoadingCircle* m_loadingCircle = nullptr; - CCMenuItemSpriteExtra* m_filterBtn; + MenuItemSpriteExtra* m_filterBtn; ModListQuery m_query; ModListDisplay m_display = ModListDisplay::Concise; EventListener m_indexListener; diff --git a/loader/src/ui/internal/list/ProblemsListCell.cpp b/loader/src/ui/internal/list/ProblemsListCell.cpp index faa2086b6..4b545b701 100644 --- a/loader/src/ui/internal/list/ProblemsListCell.cpp +++ b/loader/src/ui/internal/list/ProblemsListCell.cpp @@ -1,7 +1,7 @@ #include "ProblemsListCell.hpp" #include "ProblemsListPopup.hpp" #include -#include +#include #include #include #include @@ -115,7 +115,7 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize viewSpr->setScale(.65f); auto viewBtn = - CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsListCell::onMore)); + MenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsListCell::onMore)); m_menu->addChild(viewBtn); } diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.cpp b/loader/src/ui/internal/settings/GeodeSettingNode.cpp index 28a37e1e2..4f603e5d1 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.cpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.cpp @@ -74,7 +74,7 @@ Slider* createSlider(C* node, GeodeSettingValue* setting, float width) { template std::pair< - CCMenuItemSpriteExtra*, CCMenuItemSpriteExtra* + MenuItemSpriteExtra*, MenuItemSpriteExtra* > createArrows(C* node, GeodeSettingValue* setting, float width, bool big) { auto yPos = setting->castDefinition().controls.slider ? 5.f : 0.f; auto decArrowSpr = CCSprite::createWithSpriteFrameName( @@ -83,7 +83,7 @@ std::pair< decArrowSpr->setFlipX(true); decArrowSpr->setScale(.3f); - auto decArrow = CCMenuItemSpriteExtra::create( + auto decArrow = MenuItemSpriteExtra::create( decArrowSpr, node, menu_selector(C::onArrow) ); decArrow->setPosition(-width / 2 + (big ? 65.f : 80.f), yPos); @@ -97,7 +97,7 @@ std::pair< ); incArrowSpr->setScale(.3f); - auto incArrow = CCMenuItemSpriteExtra::create( + auto incArrow = MenuItemSpriteExtra::create( incArrowSpr, node, menu_selector(C::onArrow) ); incArrow->setTag(big ? @@ -377,7 +377,7 @@ bool FileSettingNode::setup(FileSettingValue* setting, float width) { auto fileBtnSpr = CCSprite::createWithSpriteFrameName("gj_folderBtn_001.png"); fileBtnSpr->setScale(.5f); - auto fileBtn = CCMenuItemSpriteExtra::create( + auto fileBtn = MenuItemSpriteExtra::create( fileBtnSpr, this, menu_selector(FileSettingNode::onPickFile) ); fileBtn->setPosition(.0f, .0f); @@ -410,7 +410,7 @@ bool ColorSettingNode::setup(ColorSettingValue* setting, float width) { m_colorSpr->setColor(m_uncommittedValue); m_colorSpr->setScale(.65f); - auto button = CCMenuItemSpriteExtra::create( + auto button = MenuItemSpriteExtra::create( m_colorSpr, this, menu_selector(ColorSettingNode::onSelectColor) ); button->setPositionX(-10.f); @@ -445,7 +445,7 @@ bool ColorAlphaSettingNode::setup(ColorAlphaSettingValue* setting, float width) m_colorSpr->updateOpacity(m_uncommittedValue.a / 255.f); m_colorSpr->setScale(.65f); - auto button = CCMenuItemSpriteExtra::create( + auto button = MenuItemSpriteExtra::create( m_colorSpr, this, menu_selector(ColorAlphaSettingNode::onSelectColor) ); button->setPositionX(-10.f); diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.hpp b/loader/src/ui/internal/settings/GeodeSettingNode.hpp index c32a6066d..2a320b532 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.hpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -40,7 +40,7 @@ class GeodeSettingNode : public SettingNode { CCMenu* m_menu; CCLabelBMFont* m_nameLabel; CCLabelBMFont* m_errorLabel; - CCMenuItemSpriteExtra* m_resetBtn; + MenuItemSpriteExtra* m_resetBtn; bool init(GeodeSettingValue* setting, float width) { if (!SettingNode::init(setting)) @@ -81,7 +81,7 @@ class GeodeSettingNode : public SettingNode { auto infoSpr = CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"); infoSpr->setScale(.6f); - auto infoBtn = CCMenuItemSpriteExtra::create( + auto infoBtn = MenuItemSpriteExtra::create( infoSpr, this, menu_selector(GeodeSettingNode::onDescription) ); infoBtn->setPosition( @@ -97,7 +97,7 @@ class GeodeSettingNode : public SettingNode { auto resetBtnSpr = CCSprite::createWithSpriteFrameName("reset-gold.png"_spr); resetBtnSpr->setScale(.5f); - m_resetBtn = CCMenuItemSpriteExtra::create( + m_resetBtn = MenuItemSpriteExtra::create( resetBtnSpr, this, menu_selector(GeodeSettingNode::onReset) ); m_resetBtn->setPosition( @@ -210,10 +210,10 @@ class IntSettingNode : InputNode* m_input = nullptr; CCLabelBMFont* m_label = nullptr; Slider* m_slider = nullptr; - CCMenuItemSpriteExtra* m_decArrow = nullptr; - CCMenuItemSpriteExtra* m_incArrow = nullptr; - CCMenuItemSpriteExtra* m_bigDecArrow = nullptr; - CCMenuItemSpriteExtra* m_bigIncArrow = nullptr; + MenuItemSpriteExtra* m_decArrow = nullptr; + MenuItemSpriteExtra* m_incArrow = nullptr; + MenuItemSpriteExtra* m_bigDecArrow = nullptr; + MenuItemSpriteExtra* m_bigIncArrow = nullptr; void valueChanged(bool updateText) override; void textChanged(CCTextInputNode* input) override; @@ -239,10 +239,10 @@ class FloatSettingNode : InputNode* m_input = nullptr; CCLabelBMFont* m_label = nullptr; Slider* m_slider = nullptr; - CCMenuItemSpriteExtra* m_decArrow = nullptr; - CCMenuItemSpriteExtra* m_incArrow = nullptr; - CCMenuItemSpriteExtra* m_bigDecArrow = nullptr; - CCMenuItemSpriteExtra* m_bigIncArrow = nullptr; + MenuItemSpriteExtra* m_decArrow = nullptr; + MenuItemSpriteExtra* m_incArrow = nullptr; + MenuItemSpriteExtra* m_bigDecArrow = nullptr; + MenuItemSpriteExtra* m_bigIncArrow = nullptr; void valueChanged(bool updateText) override; void textChanged(CCTextInputNode* input) override; diff --git a/loader/src/ui/internal/settings/ModSettingsPopup.cpp b/loader/src/ui/internal/settings/ModSettingsPopup.cpp index 60f4b6f67..369041a13 100644 --- a/loader/src/ui/internal/settings/ModSettingsPopup.cpp +++ b/loader/src/ui/internal/settings/ModSettingsPopup.cpp @@ -90,7 +90,7 @@ bool ModSettingsPopup::setup(Mod* mod) { m_applyBtnSpr = ButtonSprite::create("Apply", "goldFont.fnt", "GJ_button_01.png", .7f); m_applyBtnSpr->setScale(.7f); - m_applyBtn = CCMenuItemSpriteExtra::create( + m_applyBtn = MenuItemSpriteExtra::create( m_applyBtnSpr, this, menu_selector(ModSettingsPopup::onApply) ); m_applyBtn->setPosition(.0f, -m_size.height / 2 + 20.f); @@ -99,7 +99,7 @@ bool ModSettingsPopup::setup(Mod* mod) { auto resetBtnSpr = ButtonSprite::create("Reset All", "goldFont.fnt", "GJ_button_05.png", .7f); resetBtnSpr->setScale(.7f); - auto resetBtn = CCMenuItemSpriteExtra::create( + auto resetBtn = MenuItemSpriteExtra::create( resetBtnSpr, this, menu_selector(ModSettingsPopup::onResetAll) ); resetBtn->setPosition(-m_size.width / 2 + 45.f, -m_size.height / 2 + 20.f); @@ -109,7 +109,7 @@ bool ModSettingsPopup::setup(Mod* mod) { ButtonSprite::create("Open Folder", "goldFont.fnt", "GJ_button_05.png", .7f); openDirBtnSpr->setScale(.7f); - auto openDirBtn = CCMenuItemSpriteExtra::create( + auto openDirBtn = MenuItemSpriteExtra::create( openDirBtnSpr, this, menu_selector(ModSettingsPopup::onOpenSaveDirectory) ); openDirBtn->setPosition(m_size.width / 2 - 53.f, -m_size.height / 2 + 20.f); diff --git a/loader/src/ui/internal/settings/ModSettingsPopup.hpp b/loader/src/ui/internal/settings/ModSettingsPopup.hpp index 834214d56..d861e2417 100644 --- a/loader/src/ui/internal/settings/ModSettingsPopup.hpp +++ b/loader/src/ui/internal/settings/ModSettingsPopup.hpp @@ -10,7 +10,7 @@ class ModSettingsPopup : public Popup, public SettingNodeDelegate { protected: Mod* m_mod; std::vector m_settings; - CCMenuItemSpriteExtra* m_applyBtn; + MenuItemSpriteExtra* m_applyBtn; ButtonSprite* m_applyBtnSpr; void settingValueChanged(SettingNode*) override; diff --git a/loader/src/ui/nodes/ColorPickPopup.cpp b/loader/src/ui/nodes/ColorPickPopup.cpp index 0fafb50f0..db7b6a101 100644 --- a/loader/src/ui/nodes/ColorPickPopup.cpp +++ b/loader/src/ui/nodes/ColorPickPopup.cpp @@ -157,7 +157,7 @@ bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) { okBtnSpr->setScale(.7f); auto okBtn = - CCMenuItemSpriteExtra::create(okBtnSpr, this, menu_selector(ColorPickPopup::onClose)); + MenuItemSpriteExtra::create(okBtnSpr, this, menu_selector(ColorPickPopup::onClose)); okBtn->setPosition(.0f, -m_size.height / 2 + 20.f); m_buttonMenu->addChild(okBtn); diff --git a/loader/src/ui/nodes/MDPopup.cpp b/loader/src/ui/nodes/MDPopup.cpp index 2f0929da9..39d5153ee 100644 --- a/loader/src/ui/nodes/MDPopup.cpp +++ b/loader/src/ui/nodes/MDPopup.cpp @@ -24,14 +24,14 @@ bool MDPopup::setup( auto btnSpr = ButtonSprite::create(btn1Text); - auto btn = CCMenuItemSpriteExtra::create(btnSpr, this, menu_selector(MDPopup::onBtn)); + auto btn = MenuItemSpriteExtra::create(btnSpr, this, menu_selector(MDPopup::onBtn)); btn->setTag(0); m_buttonMenu->addChild(btn); if (btn2Text) { auto btn2Spr = ButtonSprite::create(btn2Text); - auto btn2 = CCMenuItemSpriteExtra::create(btn2Spr, this, menu_selector(MDPopup::onBtn)); + auto btn2 = MenuItemSpriteExtra::create(btn2Spr, this, menu_selector(MDPopup::onBtn)); btn2->setTag(1); m_buttonMenu->addChild(btn2); diff --git a/loader/src/ui/nodes/MenuItemSprite.cpp b/loader/src/ui/nodes/MenuItemSpriteExtra.cpp similarity index 58% rename from loader/src/ui/nodes/MenuItemSprite.cpp rename to loader/src/ui/nodes/MenuItemSpriteExtra.cpp index cb6ec2a2b..64a71e64e 100644 --- a/loader/src/ui/nodes/MenuItemSprite.cpp +++ b/loader/src/ui/nodes/MenuItemSpriteExtra.cpp @@ -1,19 +1,19 @@ -#include +#include using namespace geode::prelude; -MenuItemSprite* MenuItemSprite::create( +MenuItemSpriteExtra* MenuItemSpriteExtra::create( cocos2d::CCNode* normalSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { - return MenuItemSprite::create(normalSprite, nullptr, target, callback); + return MenuItemSpriteExtra::create(normalSprite, nullptr, target, callback); } -MenuItemSprite* MenuItemSprite::create( +MenuItemSpriteExtra* MenuItemSpriteExtra::create( cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { - auto ret = new MenuItemSprite(); + auto ret = new MenuItemSpriteExtra(); if (ret && ret->init(normalSprite, disabledSprite, target, callback)) { ret->autorelease(); return ret; @@ -22,12 +22,12 @@ MenuItemSprite* MenuItemSprite::create( return nullptr; } -MenuItemSprite::MenuItemSprite() {} +MenuItemSpriteExtra::MenuItemSpriteExtra() : m_scaleSprites(false) {} -MenuItemSprite::~MenuItemSprite() { +MenuItemSpriteExtra::~MenuItemSpriteExtra() { } -void MenuItemSprite::setImage(cocos2d::CCNode* image) { +void MenuItemSpriteExtra::setImage(cocos2d::CCNode* image) { if (image) { image->setAnchorPoint({ 0.5f, 0.5f }); image->setPosition(image->getContentSize() / 2); @@ -35,20 +35,20 @@ void MenuItemSprite::setImage(cocos2d::CCNode* image) { } // why are the members private like what -void MenuItemSprite::setNormalImage(cocos2d::CCNode* image) { +void MenuItemSpriteExtra::setNormalImage(cocos2d::CCNode* image) { CCMenuItemSprite::setNormalImage(image); this->setImage(image); } -void MenuItemSprite::setDisabledImage(cocos2d::CCNode* image) { +void MenuItemSpriteExtra::setDisabledImage(cocos2d::CCNode* image) { CCMenuItemSprite::setDisabledImage(image); this->setImage(image); } -void MenuItemSprite::setSelectedImage(cocos2d::CCNode* image) { +void MenuItemSpriteExtra::setSelectedImage(cocos2d::CCNode* image) { CCMenuItemSprite::setSelectedImage(image); this->setImage(image); } -bool MenuItemSprite::init( +bool MenuItemSpriteExtra::init( cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { @@ -67,32 +67,41 @@ bool MenuItemSprite::init( return true; } -void MenuItemSprite::runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator) { +void MenuItemSpriteExtra::runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator) { if (sprite) { sprite->stopAllActions(); if (generator) sprite->runAction(generator); } } -void MenuItemSprite::runActionOnSprites(MiniFunction generator) { - this->runActionOnSprite(this->getNormalImage(), generator()); - this->runActionOnSprite(this->getDisabledImage(), generator()); - this->runActionOnSprite(this->getSelectedImage(), generator()); +void MenuItemSpriteExtra::runActionOnSprites(MiniFunction generator) { + if (m_scaleSprites) { + this->runActionOnSprite(this->getNormalImage(), generator()); + this->runActionOnSprite(this->getDisabledImage(), generator()); + this->runActionOnSprite(this->getSelectedImage(), generator()); + } + else { + if (auto action = generator()) this->runAction(action); + } } -void MenuItemSprite::activate() { +void MenuItemSpriteExtra::activate() { this->runActionOnSprites(m_activateAction); CCMenuItem::activate(); } -void MenuItemSprite::selected() { +void MenuItemSpriteExtra::selected() { if (!m_bEnabled) return; CCMenuItem::selected(); this->runActionOnSprites(m_selectedAction); } -void MenuItemSprite::unselected() { +void MenuItemSpriteExtra::unselected() { if (!m_bEnabled) return; CCMenuItem::unselected(); this->runActionOnSprites(m_unselectedAction); +} + +void MenuItemSpriteExtra::setScaleSprites(bool scale) { + m_scaleSprites = scale; } \ No newline at end of file diff --git a/loader/test/dependency/main.cpp b/loader/test/dependency/main.cpp index 2f6bd35df..4a2713b67 100644 --- a/loader/test/dependency/main.cpp +++ b/loader/test/dependency/main.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include "main.hpp" @@ -92,7 +92,7 @@ class MySettingNode : public SettingNode { } else { btnSpr->setColor({ 200, 200, 200 }); } - auto btn = CCMenuItemSpriteExtra::create( + auto btn = MenuItemSpriteExtra::create( btnSpr, this, menu_selector(MySettingNode::onSelect) ); btn->setTag(static_cast(icon)); @@ -113,7 +113,7 @@ class MySettingNode : public SettingNode { } m_currentIcon = static_cast(sender->getTag()); static_cast( - static_cast(sender)->getNormalImage() + static_cast(sender)->getNormalImage() )->setColor({ 0, 255, 0 }); this->dispatchChanged(); } From dcc40f11e1161cfd6e7dcb6512e3b2be72e6068f Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:37:30 +0300 Subject: [PATCH 055/135] Revert "Fix some stuff related to menuitemspriteextra but gonna revert" This reverts commit e8b98e48f558af95ea14fc902a0a26967be24fc5. --- loader/include/Geode/UI.hpp | 1 - ...ItemSpriteExtra.hpp => MenuItemSprite.hpp} | 13 ++--- loader/include/Geode/ui/MenuItemToggle.hpp | 14 +++--- loader/src/hooks/MenuLayer.cpp | 2 +- loader/src/ui/internal/info/ModInfoPopup.cpp | 20 ++++---- loader/src/ui/internal/info/ModInfoPopup.hpp | 5 +- .../src/ui/internal/list/InstallListCell.cpp | 5 +- .../src/ui/internal/list/InstallListPopup.cpp | 2 +- loader/src/ui/internal/list/ModListCell.cpp | 17 ++++--- loader/src/ui/internal/list/ModListCell.hpp | 5 +- loader/src/ui/internal/list/ModListLayer.cpp | 16 +++--- loader/src/ui/internal/list/ModListLayer.hpp | 9 ++-- .../src/ui/internal/list/ProblemsListCell.cpp | 4 +- .../ui/internal/settings/GeodeSettingNode.cpp | 12 ++--- .../ui/internal/settings/GeodeSettingNode.hpp | 24 ++++----- .../ui/internal/settings/ModSettingsPopup.cpp | 6 +-- .../ui/internal/settings/ModSettingsPopup.hpp | 2 +- loader/src/ui/nodes/ColorPickPopup.cpp | 2 +- loader/src/ui/nodes/MDPopup.cpp | 4 +- ...ItemSpriteExtra.cpp => MenuItemSprite.cpp} | 49 ++++++++----------- loader/test/dependency/main.cpp | 6 +-- 21 files changed, 103 insertions(+), 115 deletions(-) rename loader/include/Geode/ui/{MenuItemSpriteExtra.hpp => MenuItemSprite.hpp} (81%) rename loader/src/ui/nodes/{MenuItemSpriteExtra.cpp => MenuItemSprite.cpp} (58%) diff --git a/loader/include/Geode/UI.hpp b/loader/include/Geode/UI.hpp index fc326ce63..2330064ca 100644 --- a/loader/include/Geode/UI.hpp +++ b/loader/include/Geode/UI.hpp @@ -10,7 +10,6 @@ #include "ui/ListView.hpp" #include "ui/MDPopup.hpp" #include "ui/MDTextArea.hpp" -#include "ui/MenuItemSpriteExtra.hpp" #include "ui/Notification.hpp" #include "ui/Popup.hpp" #include "ui/SceneManager.hpp" diff --git a/loader/include/Geode/ui/MenuItemSpriteExtra.hpp b/loader/include/Geode/ui/MenuItemSprite.hpp similarity index 81% rename from loader/include/Geode/ui/MenuItemSpriteExtra.hpp rename to loader/include/Geode/ui/MenuItemSprite.hpp index 776519eda..113eb80d5 100644 --- a/loader/include/Geode/ui/MenuItemSpriteExtra.hpp +++ b/loader/include/Geode/ui/MenuItemSprite.hpp @@ -6,20 +6,19 @@ #pragma warning(disable : 4275) namespace geode { - class GEODE_DLL MenuItemSpriteExtra : public cocos2d::CCMenuItemSprite { + class GEODE_DLL MenuItemSprite : public cocos2d::CCMenuItemSprite { protected: - bool m_scaleSprites; - MenuItemSpriteExtra(); - ~MenuItemSpriteExtra() override; + MenuItemSprite(); + ~MenuItemSprite() override; public: - static MenuItemSpriteExtra* create( + static MenuItemSprite* create( cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ); - static MenuItemSpriteExtra* create( + static MenuItemSprite* create( cocos2d::CCNode* normalSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ); @@ -40,8 +39,6 @@ namespace geode { void selected() override; void unselected() override; - void setScaleSprites(bool scale); - void setImage(cocos2d::CCNode* image); void setNormalImage(cocos2d::CCNode* image) override; void setDisabledImage(cocos2d::CCNode* image) override; diff --git a/loader/include/Geode/ui/MenuItemToggle.hpp b/loader/include/Geode/ui/MenuItemToggle.hpp index 2e704c8ac..6399773aa 100644 --- a/loader/include/Geode/ui/MenuItemToggle.hpp +++ b/loader/include/Geode/ui/MenuItemToggle.hpp @@ -1,15 +1,15 @@ #pragma once #include -#include "MenuItemSpriteExtra.hpp" +#include "MenuItemSprite.hpp" #pragma warning(disable : 4275) namespace geode { class GEODE_DLL MenuItemToggle : public cocos2d::CCMenuItem { protected: - MenuItemSpriteExtra* m_offButton; - MenuItemSpriteExtra* m_onButton; + MenuItemSprite* m_offButton; + MenuItemSprite* m_onButton; bool m_toggled; MenuItemToggle(); @@ -26,10 +26,10 @@ namespace geode { cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ); - void setOffButton(MenuItemSpriteExtra* button); - void setOnButton(MenuItemSpriteExtra* button); - MenuItemSpriteExtra* getOffButton() const; - MenuItemSpriteExtra* getOnButton() const; + void setOffButton(MenuItemSprite* button); + void setOnButton(MenuItemSprite* button); + MenuItemSprite* getOffButton() const; + MenuItemSprite* getOnButton() const; bool isToggled() const; void toggle(bool enabled); diff --git a/loader/src/hooks/MenuLayer.cpp b/loader/src/hooks/MenuLayer.cpp index 4bddc8f12..869d1bce2 100644 --- a/loader/src/hooks/MenuLayer.cpp +++ b/loader/src/hooks/MenuLayer.cpp @@ -77,7 +77,7 @@ struct CustomMenuLayer : Modify { auto bottomMenu = static_cast(this->getChildByID("bottom-menu")); - auto btn = MenuItemSpriteExtra::create( + auto btn = CCMenuItemSpriteExtra::create( m_fields->m_geodeButton, this, static_cast(geodeBtnSelector) ); diff --git a/loader/src/ui/internal/info/ModInfoPopup.cpp b/loader/src/ui/internal/info/ModInfoPopup.cpp index d1c5c230a..945e5ec4b 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.cpp +++ b/loader/src/ui/internal/info/ModInfoPopup.cpp @@ -151,13 +151,13 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { auto infoSpr = CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"); infoSpr->setScale(.85f); - m_infoBtn = MenuItemSpriteExtra::create(infoSpr, this, menu_selector(ModInfoPopup::onInfo)); + m_infoBtn = CCMenuItemSpriteExtra::create(infoSpr, this, menu_selector(ModInfoPopup::onInfo)); m_infoBtn->setPosition(LAYER_SIZE.width / 2 - 25.f, LAYER_SIZE.height / 2 - 25.f); m_buttonMenu->addChild(m_infoBtn); // repo button if (metadata.getRepository()) { - auto repoBtn = MenuItemSpriteExtra::create( + auto repoBtn = CCMenuItemSpriteExtra::create( CCSprite::createWithSpriteFrameName("github.png"_spr), this, menu_selector(ModInfoPopup::onRepository) @@ -168,7 +168,7 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { // support button if (metadata.getSupportInfo()) { - auto supportBtn = MenuItemSpriteExtra::create( + auto supportBtn = CCMenuItemSpriteExtra::create( CCSprite::createWithSpriteFrameName("gift.png"_spr), this, menu_selector(ModInfoPopup::onSupport) @@ -181,7 +181,7 @@ bool ModInfoPopup::init(ModMetadata const& metadata, ModListLayer* list) { closeSpr->setScale(.8f); auto closeBtn = - MenuItemSpriteExtra::create(closeSpr, this, menu_selector(ModInfoPopup::onClose)); + CCMenuItemSpriteExtra::create(closeSpr, this, menu_selector(ModInfoPopup::onClose)); closeBtn->setPosition(-LAYER_SIZE.width / 2 + 3.f, LAYER_SIZE.height / 2 - 3.f); m_buttonMenu->addChild(closeBtn); @@ -399,7 +399,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { settingsSpr->setScale(.65f); auto settingsBtn = - MenuItemSpriteExtra::create(settingsSpr, this, menu_selector(LocalModInfoPopup::onSettings)); + CCMenuItemSpriteExtra::create(settingsSpr, this, menu_selector(LocalModInfoPopup::onSettings)); settingsBtn->setPosition(-LAYER_SIZE.width / 2 + 25.f, -LAYER_SIZE.height / 2 + 25.f); m_buttonMenu->addChild(settingsBtn); @@ -410,7 +410,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ); configSpr->setScale(.65f); - auto configBtn = MenuItemSpriteExtra::create( + auto configBtn = CCMenuItemSpriteExtra::create( configSpr, this, menu_selector(LocalModInfoPopup::onOpenConfigDir) ); configBtn->setPosition(-LAYER_SIZE.width / 2 + 65.f, -LAYER_SIZE.height / 2 + 25.f); @@ -451,7 +451,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ButtonSprite::create("Uninstall", "bigFont.fnt", "GJ_button_05.png", .6f); uninstallBtnSpr->setScale(.6f); - auto uninstallBtn = MenuItemSpriteExtra::create( + auto uninstallBtn = CCMenuItemSpriteExtra::create( uninstallBtnSpr, this, menu_selector(LocalModInfoPopup::onUninstall) ); uninstallBtn->setPosition(-85.f, 75.f); @@ -467,7 +467,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ); m_installBtnSpr->setScale(.6f); - m_installBtn = MenuItemSpriteExtra::create(m_installBtnSpr, this, menu_selector(LocalModInfoPopup::onUpdate)); + m_installBtn = CCMenuItemSpriteExtra::create(m_installBtnSpr, this, menu_selector(LocalModInfoPopup::onUpdate)); m_installBtn->setPosition(-8.0f, 75.f); m_buttonMenu->addChild(m_installBtn); @@ -536,7 +536,7 @@ bool LocalModInfoPopup::init(Mod* mod, ModListLayer* list) { ); issuesBtnSpr->setScale(.75f); - auto issuesBtn = MenuItemSpriteExtra::create( + auto issuesBtn = CCMenuItemSpriteExtra::create( issuesBtnSpr, this, menu_selector(LocalModInfoPopup::onIssues) ); issuesBtn->setPosition(0.f, -LAYER_SIZE.height / 2 + 25.f); @@ -726,7 +726,7 @@ bool IndexItemInfoPopup::init(IndexItemHandle item, ModListLayer* list) { ); m_installBtnSpr->setScale(.6f); - m_installBtn = MenuItemSpriteExtra::create( + m_installBtn = CCMenuItemSpriteExtra::create( m_installBtnSpr, this, menu_selector(IndexItemInfoPopup::onInstall) ); m_installBtn->setPosition(-143.0f, 75.f); diff --git a/loader/src/ui/internal/info/ModInfoPopup.hpp b/loader/src/ui/internal/info/ModInfoPopup.hpp index e9ab045af..808cd9181 100644 --- a/loader/src/ui/internal/info/ModInfoPopup.hpp +++ b/loader/src/ui/internal/info/ModInfoPopup.hpp @@ -6,7 +6,6 @@ #include #include #include -#include using namespace geode::prelude; @@ -32,8 +31,8 @@ class ModInfoPopup : public FLAlertLayer { ModListLayer* m_layer = nullptr; DownloadStatusNode* m_installStatus = nullptr; IconButtonSprite* m_installBtnSpr; - MenuItemSpriteExtra* m_installBtn; - MenuItemSpriteExtra* m_infoBtn; + CCMenuItemSpriteExtra* m_installBtn; + CCMenuItemSpriteExtra* m_infoBtn; CCLabelBMFont* m_latestVersionLabel = nullptr; CCLabelBMFont* m_minorVersionLabel = nullptr; MDTextArea* m_detailsArea; diff --git a/loader/src/ui/internal/list/InstallListCell.cpp b/loader/src/ui/internal/list/InstallListCell.cpp index ce309181d..352d8aaf0 100644 --- a/loader/src/ui/internal/list/InstallListCell.cpp +++ b/loader/src/ui/internal/list/InstallListCell.cpp @@ -1,6 +1,7 @@ #include "InstallListCell.hpp" #include "InstallListPopup.hpp" #include +#include #include #include #include @@ -212,7 +213,7 @@ bool IndexItemInstallListCell::init( versionSelectSpr->setScale(.7f); auto versionSelectBtn = - MenuItemSpriteExtra::create(versionSelectSpr, this, menu_selector(IndexItemInstallListCell::onSelectVersion)); + CCMenuItemSpriteExtra::create(versionSelectSpr, this, menu_selector(IndexItemInstallListCell::onSelectVersion)); versionSelectBtn->setAnchorPoint({1.f, .5f}); versionSelectBtn->setPosition({m_toggle->getPositionX() - m_toggle->getContentSize().width - 5, m_height / 2}); m_menu->addChild(versionSelectBtn); @@ -371,7 +372,7 @@ bool SelectVersionCell::init(IndexItemHandle item, SelectVersionPopup* versionPo ); selectSpr->setScale(.6f); - auto selectBtn = MenuItemSpriteExtra::create( + auto selectBtn = CCMenuItemSpriteExtra::create( selectSpr, this, menu_selector(SelectVersionCell::onSelected) ); selectBtn->setAnchorPoint({1.f, .5f}); diff --git a/loader/src/ui/internal/list/InstallListPopup.cpp b/loader/src/ui/internal/list/InstallListPopup.cpp index 2acbb6707..e561ca9b9 100644 --- a/loader/src/ui/internal/list/InstallListPopup.cpp +++ b/loader/src/ui/internal/list/InstallListPopup.cpp @@ -22,7 +22,7 @@ bool InstallListPopup::setup(IndexItemHandle item, MiniFunctionsetScale(.6f); - auto installBtn = MenuItemSpriteExtra::create( + auto installBtn = CCMenuItemSpriteExtra::create( installBtnSpr, this, menu_selector(InstallListPopup::onInstall) diff --git a/loader/src/ui/internal/list/ModListCell.cpp b/loader/src/ui/internal/list/ModListCell.cpp index b1614011b..061e6dcb3 100644 --- a/loader/src/ui/internal/list/ModListCell.cpp +++ b/loader/src/ui/internal/list/ModListCell.cpp @@ -2,6 +2,7 @@ #include "ModListLayer.hpp" #include "../info/ModInfoPopup.hpp" #include +#include #include #include #include @@ -143,7 +144,7 @@ void ModListCell::setupInfo( creatorLabel->setColor({ 163, 163, 163 }); } - m_developerBtn = MenuItemSpriteExtra::create( + m_developerBtn = CCMenuItemSpriteExtra::create( creatorLabel, this, menu_selector(ModListCell::onViewDev) ); m_columnMenu->addChild(m_developerBtn); @@ -291,7 +292,7 @@ bool ModCell::init( exMark->setScale(.5f); m_unresolvedExMark = - MenuItemSpriteExtra::create(exMark, this, menu_selector(ModCell::onUnresolvedInfo)); + CCMenuItemSpriteExtra::create(exMark, this, menu_selector(ModCell::onUnresolvedInfo)); m_unresolvedExMark->setVisible(false); m_menu->addChild(m_unresolvedExMark); @@ -299,7 +300,7 @@ bool ModCell::init( auto restartSpr = ButtonSprite::create("Restart", "bigFont.fnt", "GJ_button_03.png", .8f); restartSpr->setScale(.65f); - auto restartBtn = MenuItemSpriteExtra::create(restartSpr, this, menu_selector(ModCell::onRestart)); + auto restartBtn = CCMenuItemSpriteExtra::create(restartSpr, this, menu_selector(ModCell::onRestart)); m_menu->addChild(restartBtn); } else { @@ -334,7 +335,7 @@ bool ModCell::init( } } - auto viewBtn = MenuItemSpriteExtra::create(viewSpr, this, menu_selector(ModCell::onInfo)); + auto viewBtn = CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ModCell::onInfo)); m_menu->addChild(viewBtn); } @@ -394,7 +395,7 @@ bool IndexItemCell::init( auto restartSpr = ButtonSprite::create("Restart", "bigFont.fnt", "GJ_button_03.png", .8f); restartSpr->setScale(.65f); - auto restartBtn = MenuItemSpriteExtra::create(restartSpr, this, menu_selector(IndexItemCell::onRestart)); + auto restartBtn = CCMenuItemSpriteExtra::create(restartSpr, this, menu_selector(IndexItemCell::onRestart)); m_menu->addChild(restartBtn); } else { @@ -402,7 +403,7 @@ bool IndexItemCell::init( viewSpr->setScale(.65f); auto viewBtn = - MenuItemSpriteExtra::create(viewSpr, this, menu_selector(IndexItemCell::onInfo)); + CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(IndexItemCell::onInfo)); m_menu->addChild(viewBtn); } @@ -516,7 +517,7 @@ bool InvalidGeodeFileCell::init( whySpr->setScale(.65f); auto viewBtn = - MenuItemSpriteExtra::create(whySpr, this, menu_selector(InvalidGeodeFileCell::onInfo)); + CCMenuItemSpriteExtra::create(whySpr, this, menu_selector(InvalidGeodeFileCell::onInfo)); menu->addChild(viewBtn); return true; @@ -634,7 +635,7 @@ bool ProblemsCell::init( viewSpr->setScale(.65f); auto viewBtn = - MenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsCell::onInfo)); + CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsCell::onInfo)); m_menu->addChild(viewBtn); m_menu->updateLayout(); diff --git a/loader/src/ui/internal/list/ModListCell.hpp b/loader/src/ui/internal/list/ModListCell.hpp index 446f5b067..28e253d9d 100644 --- a/loader/src/ui/internal/list/ModListCell.hpp +++ b/loader/src/ui/internal/list/ModListCell.hpp @@ -5,7 +5,6 @@ #include #include #include -#include using namespace geode::prelude; @@ -23,8 +22,8 @@ class ModListCell : public CCLayer { CCMenu* m_menu; CCLabelBMFont* m_description; CCMenuItemToggler* m_enableToggle = nullptr; - MenuItemSpriteExtra* m_unresolvedExMark; - MenuItemSpriteExtra* m_developerBtn; + CCMenuItemSpriteExtra* m_unresolvedExMark; + CCMenuItemSpriteExtra* m_developerBtn; SpacerNode* m_spacer = nullptr; CCMenu* m_columnMenu = nullptr; CCMenu* m_labelMenu = nullptr; diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index 7f44d9ae3..e950a5211 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -16,6 +16,8 @@ #include #include +#include + #define FTS_FUZZY_MATCH_IMPLEMENTATION #include @@ -259,7 +261,7 @@ bool ModListLayer::init() { m_topMenu = CCMenu::create(); // add back button - auto backBtn = MenuItemSpriteExtra::create( + auto backBtn = MenuItemSprite::create( CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"), this, menu_selector(ModListLayer::onExit) ); @@ -270,7 +272,7 @@ bool ModListLayer::init() { auto reloadSpr = CCSprite::createWithSpriteFrameName("GJ_updateBtn_001.png"); reloadSpr->setScale(.8f); auto reloadBtn = - MenuItemSpriteExtra::create(reloadSpr, this, menu_selector(ModListLayer::onReload)); + CCMenuItemSpriteExtra::create(reloadSpr, this, menu_selector(ModListLayer::onReload)); reloadBtn->setPosition(-winSize.width / 2 + 30.0f, -winSize.height / 2 + 30.0f); m_menu->addChild(reloadBtn); @@ -279,7 +281,7 @@ bool ModListLayer::init() { "gj_folderBtn_001.png", .7f, CircleBaseColor::Green, CircleBaseSize::Small ); auto openBtn = - MenuItemSpriteExtra::create(openSpr, this, menu_selector(ModListLayer::onOpenFolder)); + CCMenuItemSpriteExtra::create(openSpr, this, menu_selector(ModListLayer::onOpenFolder)); openBtn->setPosition(-winSize.width / 2 + 30.0f, -winSize.height / 2 + 80.0f); m_menu->addChild(openBtn); @@ -394,7 +396,7 @@ void ModListLayer::createSearchControl() { filterSpr->setScale(.7f); m_filterBtn = - MenuItemSpriteExtra::create(filterSpr, this, menu_selector(ModListLayer::onFilters)); + CCMenuItemSpriteExtra::create(filterSpr, this, menu_selector(ModListLayer::onFilters)); m_filterBtn->setPosition(-10.f, 0.f); menu->addChild(m_filterBtn); @@ -402,14 +404,14 @@ void ModListLayer::createSearchControl() { auto searchSpr = CCSprite::createWithSpriteFrameName("gj_findBtn_001.png"); searchSpr->setScale(.7f); - m_searchBtn = MenuItemSpriteExtra::create(searchSpr, this, nullptr); + m_searchBtn = CCMenuItemSpriteExtra::create(searchSpr, this, nullptr); m_searchBtn->setPosition(-35.f, 0.f); menu->addChild(m_searchBtn); auto searchClearSpr = CCSprite::createWithSpriteFrameName("gj_findBtnOff_001.png"); searchClearSpr->setScale(.7f); - m_searchClearBtn = MenuItemSpriteExtra::create( + m_searchClearBtn = CCMenuItemSpriteExtra::create( searchClearSpr, this, menu_selector(ModListLayer::onResetSearch) ); m_searchClearBtn->setPosition(-35.f, 0.f); @@ -561,7 +563,7 @@ void ModListLayer::reloadList(bool keepScroll, std::optional const if (!m_checkForUpdatesBtn) { auto checkSpr = ButtonSprite::create("Check for Updates"); checkSpr->setScale(.7f); - m_checkForUpdatesBtn = MenuItemSpriteExtra::create( + m_checkForUpdatesBtn = CCMenuItemSpriteExtra::create( checkSpr, this, menu_selector(ModListLayer::onCheckForUpdates) ); m_checkForUpdatesBtn->setPosition(0, -winSize.height / 2 + 40.f); diff --git a/loader/src/ui/internal/list/ModListLayer.hpp b/loader/src/ui/internal/list/ModListLayer.hpp index f9a3780af..0afa2839f 100644 --- a/loader/src/ui/internal/list/ModListLayer.hpp +++ b/loader/src/ui/internal/list/ModListLayer.hpp @@ -1,7 +1,6 @@ #pragma once #include -#include #include using namespace geode::prelude; @@ -55,13 +54,13 @@ class ModListLayer : public CCLayer, public TextInputDelegate { CCMenuItemToggler* m_installedTabBtn; CCMenuItemToggler* m_downloadTabBtn; CCMenuItemToggler* m_featuredTabBtn; - MenuItemSpriteExtra* m_searchBtn; - MenuItemSpriteExtra* m_searchClearBtn; - MenuItemSpriteExtra* m_checkForUpdatesBtn = nullptr; + CCMenuItemSpriteExtra* m_searchBtn; + CCMenuItemSpriteExtra* m_searchClearBtn; + CCMenuItemSpriteExtra* m_checkForUpdatesBtn = nullptr; CCNode* m_searchBG = nullptr; CCTextInputNode* m_searchInput = nullptr; LoadingCircle* m_loadingCircle = nullptr; - MenuItemSpriteExtra* m_filterBtn; + CCMenuItemSpriteExtra* m_filterBtn; ModListQuery m_query; ModListDisplay m_display = ModListDisplay::Concise; EventListener m_indexListener; diff --git a/loader/src/ui/internal/list/ProblemsListCell.cpp b/loader/src/ui/internal/list/ProblemsListCell.cpp index 4b545b701..faa2086b6 100644 --- a/loader/src/ui/internal/list/ProblemsListCell.cpp +++ b/loader/src/ui/internal/list/ProblemsListCell.cpp @@ -1,7 +1,7 @@ #include "ProblemsListCell.hpp" #include "ProblemsListPopup.hpp" #include -#include +#include #include #include #include @@ -115,7 +115,7 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize viewSpr->setScale(.65f); auto viewBtn = - MenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsListCell::onMore)); + CCMenuItemSpriteExtra::create(viewSpr, this, menu_selector(ProblemsListCell::onMore)); m_menu->addChild(viewBtn); } diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.cpp b/loader/src/ui/internal/settings/GeodeSettingNode.cpp index 4f603e5d1..28a37e1e2 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.cpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.cpp @@ -74,7 +74,7 @@ Slider* createSlider(C* node, GeodeSettingValue* setting, float width) { template std::pair< - MenuItemSpriteExtra*, MenuItemSpriteExtra* + CCMenuItemSpriteExtra*, CCMenuItemSpriteExtra* > createArrows(C* node, GeodeSettingValue* setting, float width, bool big) { auto yPos = setting->castDefinition().controls.slider ? 5.f : 0.f; auto decArrowSpr = CCSprite::createWithSpriteFrameName( @@ -83,7 +83,7 @@ std::pair< decArrowSpr->setFlipX(true); decArrowSpr->setScale(.3f); - auto decArrow = MenuItemSpriteExtra::create( + auto decArrow = CCMenuItemSpriteExtra::create( decArrowSpr, node, menu_selector(C::onArrow) ); decArrow->setPosition(-width / 2 + (big ? 65.f : 80.f), yPos); @@ -97,7 +97,7 @@ std::pair< ); incArrowSpr->setScale(.3f); - auto incArrow = MenuItemSpriteExtra::create( + auto incArrow = CCMenuItemSpriteExtra::create( incArrowSpr, node, menu_selector(C::onArrow) ); incArrow->setTag(big ? @@ -377,7 +377,7 @@ bool FileSettingNode::setup(FileSettingValue* setting, float width) { auto fileBtnSpr = CCSprite::createWithSpriteFrameName("gj_folderBtn_001.png"); fileBtnSpr->setScale(.5f); - auto fileBtn = MenuItemSpriteExtra::create( + auto fileBtn = CCMenuItemSpriteExtra::create( fileBtnSpr, this, menu_selector(FileSettingNode::onPickFile) ); fileBtn->setPosition(.0f, .0f); @@ -410,7 +410,7 @@ bool ColorSettingNode::setup(ColorSettingValue* setting, float width) { m_colorSpr->setColor(m_uncommittedValue); m_colorSpr->setScale(.65f); - auto button = MenuItemSpriteExtra::create( + auto button = CCMenuItemSpriteExtra::create( m_colorSpr, this, menu_selector(ColorSettingNode::onSelectColor) ); button->setPositionX(-10.f); @@ -445,7 +445,7 @@ bool ColorAlphaSettingNode::setup(ColorAlphaSettingValue* setting, float width) m_colorSpr->updateOpacity(m_uncommittedValue.a / 255.f); m_colorSpr->setScale(.65f); - auto button = MenuItemSpriteExtra::create( + auto button = CCMenuItemSpriteExtra::create( m_colorSpr, this, menu_selector(ColorAlphaSettingNode::onSelectColor) ); button->setPositionX(-10.f); diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.hpp b/loader/src/ui/internal/settings/GeodeSettingNode.hpp index 2a320b532..c32a6066d 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.hpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.hpp @@ -1,6 +1,6 @@ #pragma once -#include +#include #include #include #include @@ -40,7 +40,7 @@ class GeodeSettingNode : public SettingNode { CCMenu* m_menu; CCLabelBMFont* m_nameLabel; CCLabelBMFont* m_errorLabel; - MenuItemSpriteExtra* m_resetBtn; + CCMenuItemSpriteExtra* m_resetBtn; bool init(GeodeSettingValue* setting, float width) { if (!SettingNode::init(setting)) @@ -81,7 +81,7 @@ class GeodeSettingNode : public SettingNode { auto infoSpr = CCSprite::createWithSpriteFrameName("GJ_infoIcon_001.png"); infoSpr->setScale(.6f); - auto infoBtn = MenuItemSpriteExtra::create( + auto infoBtn = CCMenuItemSpriteExtra::create( infoSpr, this, menu_selector(GeodeSettingNode::onDescription) ); infoBtn->setPosition( @@ -97,7 +97,7 @@ class GeodeSettingNode : public SettingNode { auto resetBtnSpr = CCSprite::createWithSpriteFrameName("reset-gold.png"_spr); resetBtnSpr->setScale(.5f); - m_resetBtn = MenuItemSpriteExtra::create( + m_resetBtn = CCMenuItemSpriteExtra::create( resetBtnSpr, this, menu_selector(GeodeSettingNode::onReset) ); m_resetBtn->setPosition( @@ -210,10 +210,10 @@ class IntSettingNode : InputNode* m_input = nullptr; CCLabelBMFont* m_label = nullptr; Slider* m_slider = nullptr; - MenuItemSpriteExtra* m_decArrow = nullptr; - MenuItemSpriteExtra* m_incArrow = nullptr; - MenuItemSpriteExtra* m_bigDecArrow = nullptr; - MenuItemSpriteExtra* m_bigIncArrow = nullptr; + CCMenuItemSpriteExtra* m_decArrow = nullptr; + CCMenuItemSpriteExtra* m_incArrow = nullptr; + CCMenuItemSpriteExtra* m_bigDecArrow = nullptr; + CCMenuItemSpriteExtra* m_bigIncArrow = nullptr; void valueChanged(bool updateText) override; void textChanged(CCTextInputNode* input) override; @@ -239,10 +239,10 @@ class FloatSettingNode : InputNode* m_input = nullptr; CCLabelBMFont* m_label = nullptr; Slider* m_slider = nullptr; - MenuItemSpriteExtra* m_decArrow = nullptr; - MenuItemSpriteExtra* m_incArrow = nullptr; - MenuItemSpriteExtra* m_bigDecArrow = nullptr; - MenuItemSpriteExtra* m_bigIncArrow = nullptr; + CCMenuItemSpriteExtra* m_decArrow = nullptr; + CCMenuItemSpriteExtra* m_incArrow = nullptr; + CCMenuItemSpriteExtra* m_bigDecArrow = nullptr; + CCMenuItemSpriteExtra* m_bigIncArrow = nullptr; void valueChanged(bool updateText) override; void textChanged(CCTextInputNode* input) override; diff --git a/loader/src/ui/internal/settings/ModSettingsPopup.cpp b/loader/src/ui/internal/settings/ModSettingsPopup.cpp index 369041a13..60f4b6f67 100644 --- a/loader/src/ui/internal/settings/ModSettingsPopup.cpp +++ b/loader/src/ui/internal/settings/ModSettingsPopup.cpp @@ -90,7 +90,7 @@ bool ModSettingsPopup::setup(Mod* mod) { m_applyBtnSpr = ButtonSprite::create("Apply", "goldFont.fnt", "GJ_button_01.png", .7f); m_applyBtnSpr->setScale(.7f); - m_applyBtn = MenuItemSpriteExtra::create( + m_applyBtn = CCMenuItemSpriteExtra::create( m_applyBtnSpr, this, menu_selector(ModSettingsPopup::onApply) ); m_applyBtn->setPosition(.0f, -m_size.height / 2 + 20.f); @@ -99,7 +99,7 @@ bool ModSettingsPopup::setup(Mod* mod) { auto resetBtnSpr = ButtonSprite::create("Reset All", "goldFont.fnt", "GJ_button_05.png", .7f); resetBtnSpr->setScale(.7f); - auto resetBtn = MenuItemSpriteExtra::create( + auto resetBtn = CCMenuItemSpriteExtra::create( resetBtnSpr, this, menu_selector(ModSettingsPopup::onResetAll) ); resetBtn->setPosition(-m_size.width / 2 + 45.f, -m_size.height / 2 + 20.f); @@ -109,7 +109,7 @@ bool ModSettingsPopup::setup(Mod* mod) { ButtonSprite::create("Open Folder", "goldFont.fnt", "GJ_button_05.png", .7f); openDirBtnSpr->setScale(.7f); - auto openDirBtn = MenuItemSpriteExtra::create( + auto openDirBtn = CCMenuItemSpriteExtra::create( openDirBtnSpr, this, menu_selector(ModSettingsPopup::onOpenSaveDirectory) ); openDirBtn->setPosition(m_size.width / 2 - 53.f, -m_size.height / 2 + 20.f); diff --git a/loader/src/ui/internal/settings/ModSettingsPopup.hpp b/loader/src/ui/internal/settings/ModSettingsPopup.hpp index d861e2417..834214d56 100644 --- a/loader/src/ui/internal/settings/ModSettingsPopup.hpp +++ b/loader/src/ui/internal/settings/ModSettingsPopup.hpp @@ -10,7 +10,7 @@ class ModSettingsPopup : public Popup, public SettingNodeDelegate { protected: Mod* m_mod; std::vector m_settings; - MenuItemSpriteExtra* m_applyBtn; + CCMenuItemSpriteExtra* m_applyBtn; ButtonSprite* m_applyBtnSpr; void settingValueChanged(SettingNode*) override; diff --git a/loader/src/ui/nodes/ColorPickPopup.cpp b/loader/src/ui/nodes/ColorPickPopup.cpp index db7b6a101..0fafb50f0 100644 --- a/loader/src/ui/nodes/ColorPickPopup.cpp +++ b/loader/src/ui/nodes/ColorPickPopup.cpp @@ -157,7 +157,7 @@ bool ColorPickPopup::setup(ccColor4B const& color, bool isRGBA) { okBtnSpr->setScale(.7f); auto okBtn = - MenuItemSpriteExtra::create(okBtnSpr, this, menu_selector(ColorPickPopup::onClose)); + CCMenuItemSpriteExtra::create(okBtnSpr, this, menu_selector(ColorPickPopup::onClose)); okBtn->setPosition(.0f, -m_size.height / 2 + 20.f); m_buttonMenu->addChild(okBtn); diff --git a/loader/src/ui/nodes/MDPopup.cpp b/loader/src/ui/nodes/MDPopup.cpp index 39d5153ee..2f0929da9 100644 --- a/loader/src/ui/nodes/MDPopup.cpp +++ b/loader/src/ui/nodes/MDPopup.cpp @@ -24,14 +24,14 @@ bool MDPopup::setup( auto btnSpr = ButtonSprite::create(btn1Text); - auto btn = MenuItemSpriteExtra::create(btnSpr, this, menu_selector(MDPopup::onBtn)); + auto btn = CCMenuItemSpriteExtra::create(btnSpr, this, menu_selector(MDPopup::onBtn)); btn->setTag(0); m_buttonMenu->addChild(btn); if (btn2Text) { auto btn2Spr = ButtonSprite::create(btn2Text); - auto btn2 = MenuItemSpriteExtra::create(btn2Spr, this, menu_selector(MDPopup::onBtn)); + auto btn2 = CCMenuItemSpriteExtra::create(btn2Spr, this, menu_selector(MDPopup::onBtn)); btn2->setTag(1); m_buttonMenu->addChild(btn2); diff --git a/loader/src/ui/nodes/MenuItemSpriteExtra.cpp b/loader/src/ui/nodes/MenuItemSprite.cpp similarity index 58% rename from loader/src/ui/nodes/MenuItemSpriteExtra.cpp rename to loader/src/ui/nodes/MenuItemSprite.cpp index 64a71e64e..cb6ec2a2b 100644 --- a/loader/src/ui/nodes/MenuItemSpriteExtra.cpp +++ b/loader/src/ui/nodes/MenuItemSprite.cpp @@ -1,19 +1,19 @@ -#include +#include using namespace geode::prelude; -MenuItemSpriteExtra* MenuItemSpriteExtra::create( +MenuItemSprite* MenuItemSprite::create( cocos2d::CCNode* normalSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { - return MenuItemSpriteExtra::create(normalSprite, nullptr, target, callback); + return MenuItemSprite::create(normalSprite, nullptr, target, callback); } -MenuItemSpriteExtra* MenuItemSpriteExtra::create( +MenuItemSprite* MenuItemSprite::create( cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { - auto ret = new MenuItemSpriteExtra(); + auto ret = new MenuItemSprite(); if (ret && ret->init(normalSprite, disabledSprite, target, callback)) { ret->autorelease(); return ret; @@ -22,12 +22,12 @@ MenuItemSpriteExtra* MenuItemSpriteExtra::create( return nullptr; } -MenuItemSpriteExtra::MenuItemSpriteExtra() : m_scaleSprites(false) {} +MenuItemSprite::MenuItemSprite() {} -MenuItemSpriteExtra::~MenuItemSpriteExtra() { +MenuItemSprite::~MenuItemSprite() { } -void MenuItemSpriteExtra::setImage(cocos2d::CCNode* image) { +void MenuItemSprite::setImage(cocos2d::CCNode* image) { if (image) { image->setAnchorPoint({ 0.5f, 0.5f }); image->setPosition(image->getContentSize() / 2); @@ -35,20 +35,20 @@ void MenuItemSpriteExtra::setImage(cocos2d::CCNode* image) { } // why are the members private like what -void MenuItemSpriteExtra::setNormalImage(cocos2d::CCNode* image) { +void MenuItemSprite::setNormalImage(cocos2d::CCNode* image) { CCMenuItemSprite::setNormalImage(image); this->setImage(image); } -void MenuItemSpriteExtra::setDisabledImage(cocos2d::CCNode* image) { +void MenuItemSprite::setDisabledImage(cocos2d::CCNode* image) { CCMenuItemSprite::setDisabledImage(image); this->setImage(image); } -void MenuItemSpriteExtra::setSelectedImage(cocos2d::CCNode* image) { +void MenuItemSprite::setSelectedImage(cocos2d::CCNode* image) { CCMenuItemSprite::setSelectedImage(image); this->setImage(image); } -bool MenuItemSpriteExtra::init( +bool MenuItemSprite::init( cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback ) { @@ -67,41 +67,32 @@ bool MenuItemSpriteExtra::init( return true; } -void MenuItemSpriteExtra::runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator) { +void MenuItemSprite::runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator) { if (sprite) { sprite->stopAllActions(); if (generator) sprite->runAction(generator); } } -void MenuItemSpriteExtra::runActionOnSprites(MiniFunction generator) { - if (m_scaleSprites) { - this->runActionOnSprite(this->getNormalImage(), generator()); - this->runActionOnSprite(this->getDisabledImage(), generator()); - this->runActionOnSprite(this->getSelectedImage(), generator()); - } - else { - if (auto action = generator()) this->runAction(action); - } +void MenuItemSprite::runActionOnSprites(MiniFunction generator) { + this->runActionOnSprite(this->getNormalImage(), generator()); + this->runActionOnSprite(this->getDisabledImage(), generator()); + this->runActionOnSprite(this->getSelectedImage(), generator()); } -void MenuItemSpriteExtra::activate() { +void MenuItemSprite::activate() { this->runActionOnSprites(m_activateAction); CCMenuItem::activate(); } -void MenuItemSpriteExtra::selected() { +void MenuItemSprite::selected() { if (!m_bEnabled) return; CCMenuItem::selected(); this->runActionOnSprites(m_selectedAction); } -void MenuItemSpriteExtra::unselected() { +void MenuItemSprite::unselected() { if (!m_bEnabled) return; CCMenuItem::unselected(); this->runActionOnSprites(m_unselectedAction); -} - -void MenuItemSpriteExtra::setScaleSprites(bool scale) { - m_scaleSprites = scale; } \ No newline at end of file diff --git a/loader/test/dependency/main.cpp b/loader/test/dependency/main.cpp index 4a2713b67..2f6bd35df 100644 --- a/loader/test/dependency/main.cpp +++ b/loader/test/dependency/main.cpp @@ -2,7 +2,7 @@ #include #include #include -#include +#include #include #include "main.hpp" @@ -92,7 +92,7 @@ class MySettingNode : public SettingNode { } else { btnSpr->setColor({ 200, 200, 200 }); } - auto btn = MenuItemSpriteExtra::create( + auto btn = CCMenuItemSpriteExtra::create( btnSpr, this, menu_selector(MySettingNode::onSelect) ); btn->setTag(static_cast(icon)); @@ -113,7 +113,7 @@ class MySettingNode : public SettingNode { } m_currentIcon = static_cast(sender->getTag()); static_cast( - static_cast(sender)->getNormalImage() + static_cast(sender)->getNormalImage() )->setColor({ 0, 255, 0 }); this->dispatchChanged(); } From a43dcc84cbd6aaab508e38273cfca1597e1dbae0 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 20 Sep 2023 17:37:42 +0300 Subject: [PATCH 056/135] Revert "Add MenuItemSprite" This reverts commit 152dc7edcf31691cd5d9a923b70387b4a562d40c. --- bindings/Cocos2d.bro | 5 - loader/include/Geode/ui/MenuItemSprite.hpp | 47 ---------- loader/include/Geode/ui/MenuItemToggle.hpp | 43 --------- loader/include/Geode/utils/MiniFunction.hpp | 24 ----- loader/src/ui/internal/list/ModListLayer.cpp | 4 +- loader/src/ui/nodes/MenuItemSprite.cpp | 98 -------------------- 6 files changed, 1 insertion(+), 220 deletions(-) delete mode 100644 loader/include/Geode/ui/MenuItemSprite.hpp delete mode 100644 loader/include/Geode/ui/MenuItemToggle.hpp delete mode 100644 loader/src/ui/nodes/MenuItemSprite.cpp diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index 6f617e769..bde65aff0 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -264,11 +264,6 @@ class cocos2d::CCEaseOut { static cocos2d::CCEaseOut* create(cocos2d::CCActionInterval*, float) = mac 0x2a1b70; } -[[link(win)]] -class cocos2d::CCEaseBounceOut { - static cocos2d::CCEaseBounceOut* create(cocos2d::CCActionInterval*) = mac 0x2a3b40; -} - [[link(win)]] class cocos2d::CCEGLView { CCEGLView(); diff --git a/loader/include/Geode/ui/MenuItemSprite.hpp b/loader/include/Geode/ui/MenuItemSprite.hpp deleted file mode 100644 index 113eb80d5..000000000 --- a/loader/include/Geode/ui/MenuItemSprite.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once - -#include -#include "../utils/MiniFunction.hpp" - -#pragma warning(disable : 4275) - -namespace geode { - class GEODE_DLL MenuItemSprite : public cocos2d::CCMenuItemSprite { - protected: - - MenuItemSprite(); - ~MenuItemSprite() override; - - public: - static MenuItemSprite* create( - cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback - ); - - static MenuItemSprite* create( - cocos2d::CCNode* normalSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback - ); - - bool init( - cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback - ); - - void runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator); - void runActionOnSprites(utils::MiniFunction generator); - - utils::MiniFunction m_selectedAction; - utils::MiniFunction m_unselectedAction; - utils::MiniFunction m_activateAction; - - void activate() override; - void selected() override; - void unselected() override; - - void setImage(cocos2d::CCNode* image); - void setNormalImage(cocos2d::CCNode* image) override; - void setDisabledImage(cocos2d::CCNode* image) override; - void setSelectedImage(cocos2d::CCNode* image) override; - }; -} diff --git a/loader/include/Geode/ui/MenuItemToggle.hpp b/loader/include/Geode/ui/MenuItemToggle.hpp deleted file mode 100644 index 6399773aa..000000000 --- a/loader/include/Geode/ui/MenuItemToggle.hpp +++ /dev/null @@ -1,43 +0,0 @@ -#pragma once - -#include -#include "MenuItemSprite.hpp" - -#pragma warning(disable : 4275) - -namespace geode { - class GEODE_DLL MenuItemToggle : public cocos2d::CCMenuItem { - protected: - MenuItemSprite* m_offButton; - MenuItemSprite* m_onButton; - bool m_toggled; - - MenuItemToggle(); - ~MenuItemToggle() override; - - public: - static MenuItemToggle* create( - cocos2d::CCNode* onSprite, cocos2d::CCNode* offSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback - ); - - bool init( - cocos2d::CCNode* onSprite, cocos2d::CCNode* offSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback - ); - - void setOffButton(MenuItemSprite* button); - void setOnButton(MenuItemSprite* button); - MenuItemSprite* getOffButton() const; - MenuItemSprite* getOnButton() const; - - bool isToggled() const; - void toggle(bool enabled); - - void setScale(float scale) override; - void activate() override; - void selected() override; - void unselected() override; - void setEnabled(bool enabled) override; - }; -} diff --git a/loader/include/Geode/utils/MiniFunction.hpp b/loader/include/Geode/utils/MiniFunction.hpp index 72cf1e19c..edb660526 100644 --- a/loader/include/Geode/utils/MiniFunction.hpp +++ b/loader/include/Geode/utils/MiniFunction.hpp @@ -123,30 +123,6 @@ namespace geode::utils { return *this; } - template - requires(MiniFunctionCallable && !std::is_same_v, MiniFunction>) - MiniFunction& operator=(Callable&& func) { - delete m_state; - m_state = new MiniFunctionState, Ret, Args...>(std::forward(func)); - return *this; - } - - template - requires(!MiniFunctionCallable && std::is_pointer_v && std::is_function_v>) - MiniFunction& operator=(FunctionPointer func) { - delete m_state; - m_state = new MiniFunctionStatePointer(func); - return *this; - } - - template - requires(std::is_member_function_pointer_v) - MiniFunction& operator=(MemberFunctionPointer func) { - delete m_state; - m_state = new MiniFunctionStateMemberPointer(func); - return *this; - } - Ret operator()(Args... args) const { if (!m_state) return Ret(); return m_state->call(args...); diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index e950a5211..a06e745c7 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -16,8 +16,6 @@ #include #include -#include - #define FTS_FUZZY_MATCH_IMPLEMENTATION #include @@ -261,7 +259,7 @@ bool ModListLayer::init() { m_topMenu = CCMenu::create(); // add back button - auto backBtn = MenuItemSprite::create( + auto backBtn = CCMenuItemSpriteExtra::create( CCSprite::createWithSpriteFrameName("GJ_arrow_01_001.png"), this, menu_selector(ModListLayer::onExit) ); diff --git a/loader/src/ui/nodes/MenuItemSprite.cpp b/loader/src/ui/nodes/MenuItemSprite.cpp deleted file mode 100644 index cb6ec2a2b..000000000 --- a/loader/src/ui/nodes/MenuItemSprite.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include - -using namespace geode::prelude; - -MenuItemSprite* MenuItemSprite::create( - cocos2d::CCNode* normalSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback -) { - return MenuItemSprite::create(normalSprite, nullptr, target, callback); -} - -MenuItemSprite* MenuItemSprite::create( - cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback -) { - auto ret = new MenuItemSprite(); - if (ret && ret->init(normalSprite, disabledSprite, target, callback)) { - ret->autorelease(); - return ret; - } - CC_SAFE_DELETE(ret); - return nullptr; -} - -MenuItemSprite::MenuItemSprite() {} - -MenuItemSprite::~MenuItemSprite() { -} - -void MenuItemSprite::setImage(cocos2d::CCNode* image) { - if (image) { - image->setAnchorPoint({ 0.5f, 0.5f }); - image->setPosition(image->getContentSize() / 2); - } -} - -// why are the members private like what -void MenuItemSprite::setNormalImage(cocos2d::CCNode* image) { - CCMenuItemSprite::setNormalImage(image); - this->setImage(image); -} -void MenuItemSprite::setDisabledImage(cocos2d::CCNode* image) { - CCMenuItemSprite::setDisabledImage(image); - this->setImage(image); -} -void MenuItemSprite::setSelectedImage(cocos2d::CCNode* image) { - CCMenuItemSprite::setSelectedImage(image); - this->setImage(image); -} - -bool MenuItemSprite::init( - cocos2d::CCNode* normalSprite, cocos2d::CCNode* disabledSprite, - cocos2d::CCObject* target, cocos2d::SEL_MenuHandler callback -) { - if (!CCMenuItemSprite::initWithNormalSprite(normalSprite, disabledSprite, nullptr, target, callback)) return false; - - m_selectedAction = []() -> cocos2d::CCAction* { - return cocos2d::CCEaseBounceOut::create(cocos2d::CCScaleTo::create(0.3f, 1.26f)); - }; - m_unselectedAction = []() -> cocos2d::CCAction* { - return cocos2d::CCEaseBounceOut::create(cocos2d::CCScaleTo::create(0.4f, 1.0f)); - }; - m_activateAction = []() -> cocos2d::CCAction* { - return cocos2d::CCScaleTo::create(0.f, 1.0f); - }; - - return true; -} - -void MenuItemSprite::runActionOnSprite(cocos2d::CCNode* sprite, cocos2d::CCAction* generator) { - if (sprite) { - sprite->stopAllActions(); - if (generator) sprite->runAction(generator); - } -} - -void MenuItemSprite::runActionOnSprites(MiniFunction generator) { - this->runActionOnSprite(this->getNormalImage(), generator()); - this->runActionOnSprite(this->getDisabledImage(), generator()); - this->runActionOnSprite(this->getSelectedImage(), generator()); -} - -void MenuItemSprite::activate() { - this->runActionOnSprites(m_activateAction); - CCMenuItem::activate(); -} -void MenuItemSprite::selected() { - if (!m_bEnabled) return; - CCMenuItem::selected(); - - this->runActionOnSprites(m_selectedAction); -} -void MenuItemSprite::unselected() { - if (!m_bEnabled) return; - CCMenuItem::unselected(); - - this->runActionOnSprites(m_unselectedAction); -} \ No newline at end of file From fed73fefd6d6174d47d2f771633e13494c0ff0aa Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:23:48 +0300 Subject: [PATCH 057/135] Revert loading layer --- loader/src/hooks/LoadingLayer.cpp | 43 ++++++++++++++----------------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 27c158243..00c5e80e2 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -108,7 +108,7 @@ struct CustomLoadingLayer : Modify { } int getTotalStep() { - return 17; + return 18; } void updateLoadingBar() { @@ -137,28 +137,23 @@ struct CustomLoadingLayer : Modify { } // hook - void loadAssets() { - if (m_loadStep == 14) { - switch (m_fields->m_geodeLoadStep) { - case 0: - if (this->skipOnRefresh()) this->setupLoadingMods(); - break; - case 1: - if (this->skipOnRefresh()) this->setupLoaderResources(); - break; - case 2: - this->setupModResources(); - break; - case 3: - default: - LoadingLayer::loadAssets(); - this->updateLoadingBar(); - break; - } - return; - } - this->setSmallText("Loading game resources"); - LoadingLayer::loadAssets(); + void loadAssets() { + switch (m_fields->m_geodeLoadStep) { + case 0: + if (this->skipOnRefresh()) this->setupLoadingMods(); + break; + case 1: + if (this->skipOnRefresh()) this->setupLoaderResources(); + break; + case 2: + this->setupModResources(); + break; + case 3: + default: + this->setSmallText("Loading game resources"); + LoadingLayer::loadAssets(); + break; + } this->updateLoadingBar(); } -}; +}; \ No newline at end of file From 506bb05c4c7693a276bc6c0b0e3250da984a952e Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:42:54 +0300 Subject: [PATCH 058/135] Implement the new broma codege --- bindings/GeometryDash.bro | 9 --------- codegen/CMakeLists.txt | 2 +- codegen/src/AddressGen.cpp | 6 +++++- codegen/src/BindingGen.cpp | 14 +++++++++++--- codegen/src/ModifyGen.cpp | 8 ++++++-- codegen/src/Shared.hpp | 17 +++++++++++------ codegen/src/SourceGen.cpp | 6 +++++- loader/test/members/Android.cpp | 10 +++++----- 8 files changed, 44 insertions(+), 28 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 64d3b1513..3df5611da 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -4264,15 +4264,6 @@ class LevelSettingsDelegate { virtual void levelSettingsUpdated() {} } -class SecretLayer2 : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, DialogDelegate { - static SecretLayer2* create() = win 0x21FD70; - - bool init() = win 0x21FE10, mac 0x25fe70; - bool onSubmit(cocos2d::CCObject*) = win 0x221ac0, mac 0x2611a0; - void updateSearchLabel(const char* text) = win 0x222FC0, mac 0x260e10; - void showCompletedLevel() = win 0x220C10; -} - [[link(android)]] class SecretLayer2 : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, DialogDelegate { static SecretLayer2* create() = win 0x21FD70; diff --git a/codegen/CMakeLists.txt b/codegen/CMakeLists.txt index 2e3833a5f..35ee9b315 100644 --- a/codegen/CMakeLists.txt +++ b/codegen/CMakeLists.txt @@ -4,7 +4,7 @@ project(Codegen LANGUAGES C CXX) include(../cmake/CPM.cmake) CPMAddPackage("gh:fmtlib/fmt#9.1.0") -CPMAddPackage("gh:geode-sdk/Broma#460f82d") +CPMAddPackage("gh:geode-sdk/Broma#93f401a") file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp diff --git a/codegen/src/AddressGen.cpp b/codegen/src/AddressGen.cpp index 9acb8c78d..7adc690b5 100644 --- a/codegen/src/AddressGen.cpp +++ b/codegen/src/AddressGen.cpp @@ -79,6 +79,8 @@ std::string generateAddressHeader(Root const& root) { output += format_strings::address_begin; for (auto& f : root.functions) { + if (codegen::getStatus(f) == BindStatus::Missing) continue; + std::string address_str; if (codegen::getStatus(f) == BindStatus::Binded) { @@ -104,6 +106,8 @@ std::string generateAddressHeader(Root const& root) { for (auto& c : root.classes) { for (auto& field : c.fields) { + if (codegen::getStatus(field) == BindStatus::Missing) continue; + std::string address_str; auto fn = field.get_as(); @@ -112,7 +116,7 @@ std::string generateAddressHeader(Root const& root) { continue; } - if (codegen::getStatus(field) == BindStatus::NeedsBinding || codegen::platformNumber(field)) { + if (codegen::getStatus(field) == BindStatus::NeedsBinding || codegen::platformNumber(field) != -1) { if (is_cocos_class(field.parent) && codegen::platform == Platform::Windows) { address_str = fmt::format("base::getCocos() + 0x{:x}", codegen::platformNumber(fn->binds)); } diff --git a/codegen/src/BindingGen.cpp b/codegen/src/BindingGen.cpp index 5d8f7c8e4..2fe4d5f9b 100644 --- a/codegen/src/BindingGen.cpp +++ b/codegen/src/BindingGen.cpp @@ -131,6 +131,8 @@ std::string generateBindingHeader(Root const& root, ghc::filesystem::path const& single_output += format_strings::class_includes; for (auto& f : root.functions) { + if (codegen::getStatus(f) == BindStatus::Missing) continue; + FunctionProto const* fb = &f.prototype; char const* used_format = format_strings::function_definition; @@ -202,6 +204,8 @@ std::string generateBindingHeader(Root const& root, ghc::filesystem::path const& bool unimplementedField = false; for (auto field : cls.fields) { + if (codegen::getStatus(field) == BindStatus::Missing) continue; + MemberFunctionProto* fb; char const* used_format = format_strings::function_definition; @@ -221,9 +225,13 @@ std::string generateBindingHeader(Root const& root, ghc::filesystem::path const& } else if (auto p = field.get_as()) { auto hardcode = codegen::platformNumber(p->amount); - if (hardcode) { + if (hardcode > 0) { single_output += fmt::format(format_strings::pad_definition, fmt::arg("hardcode", hardcode)); - } else { + } + else if (hardcode == 0) { + single_output += " // no padding\n"; + } + else { unimplementedField = true; } continue; @@ -234,7 +242,7 @@ std::string generateBindingHeader(Root const& root, ghc::filesystem::path const& } else if (auto fn = field.get_as()) { fb = &fn->prototype; - if (!codegen::platformNumber(fn->binds) && codegen::getStatus(field) != BindStatus::Binded) { + if (codegen::platformNumber(fn->binds) == -1 && codegen::getStatus(field) != BindStatus::Binded) { used_format = format_strings::error_definition; if (fb->type != FunctionType::Normal) diff --git a/codegen/src/ModifyGen.cpp b/codegen/src/ModifyGen.cpp index 937cd527c..9bf5ea16d 100644 --- a/codegen/src/ModifyGen.cpp +++ b/codegen/src/ModifyGen.cpp @@ -57,7 +57,7 @@ namespace geode::modifier {{ std::string generateModifyHeader(Root const& root, ghc::filesystem::path const& singleFolder) { std::string output; - for (auto& c : root.classes) { + for (auto& c : root.classes) { if (c.name == "cocos2d") continue; std::string filename = (codegen::getUnqualifiedClassName(c.name) + ".hpp"); @@ -83,6 +83,8 @@ std::string generateModifyHeader(Root const& root, ghc::filesystem::path const& std::string statics; std::set used; for (auto& f : c.fields) { + if (codegen::getStatus(f) == BindStatus::Missing) continue; + if (auto fn = f.get_as()) { if (fn->prototype.type == FunctionType::Normal && !used.count(fn->prototype.name)) { used.insert(fn->prototype.name); @@ -102,13 +104,15 @@ std::string generateModifyHeader(Root const& root, ghc::filesystem::path const& // modify for (auto& f : c.fields) { + if (codegen::getStatus(f) == BindStatus::Missing) continue; + auto fn = f.get_as(); if (!fn) { continue; } - if (codegen::getStatus(f) == BindStatus::NeedsBinding || codegen::platformNumber(f)) { + if (codegen::getStatus(f) == BindStatus::NeedsBinding || codegen::platformNumber(f) != -1) { } else if (codegen::getStatus(f) == BindStatus::Binded && fn->prototype.type == FunctionType::Normal) { diff --git a/codegen/src/Shared.hpp b/codegen/src/Shared.hpp index a2a694434..ef0e41a0b 100644 --- a/codegen/src/Shared.hpp +++ b/codegen/src/Shared.hpp @@ -51,7 +51,8 @@ inline bool is_cocos_class(std::string const& str) { enum class BindStatus { Binded, NeedsBinding, - Unbindable + Unbindable, + Missing, }; struct codegen_error : std::runtime_error { @@ -91,7 +92,7 @@ namespace codegen { inline Platform platform; - inline uintptr_t platformNumberWithPlatform(Platform p, PlatformNumber const& pn) { + inline ptrdiff_t platformNumberWithPlatform(Platform p, PlatformNumber const& pn) { switch (p) { case Platform::Mac: return pn.mac; case Platform::Windows: return pn.win; @@ -102,7 +103,7 @@ namespace codegen { } } - inline uintptr_t platformNumber(PlatformNumber const& p) { + inline ptrdiff_t platformNumber(PlatformNumber const& p) { return platformNumberWithPlatform(codegen::platform, p); } @@ -114,17 +115,21 @@ namespace codegen { } inline BindStatus getStatusWithPlatform(Platform p, Field const& field) { + if ((field.missing & p) != Platform::None) return BindStatus::Missing; + if (auto fn = field.get_as()) { - if ((fn->links & p) != Platform::None) return BindStatus::Binded; - if (platformNumberWithPlatform(p, fn->binds)) return BindStatus::NeedsBinding; + if ((field.links & p) != Platform::None) return BindStatus::Binded; + if (platformNumberWithPlatform(p, fn->binds) != -1) return BindStatus::NeedsBinding; } return BindStatus::Unbindable; } inline BindStatus getStatusWithPlatform(Platform p, Function const& f) { + if ((f.missing & p) != Platform::None) return BindStatus::Missing; + if ((f.links & p) != Platform::None) return BindStatus::Binded; - if (platformNumberWithPlatform(p, f.binds)) return BindStatus::NeedsBinding; + if (platformNumberWithPlatform(p, f.binds) != -1) return BindStatus::NeedsBinding; return BindStatus::Unbindable; } diff --git a/codegen/src/SourceGen.cpp b/codegen/src/SourceGen.cpp index 230a31fcd..ddba3630d 100644 --- a/codegen/src/SourceGen.cpp +++ b/codegen/src/SourceGen.cpp @@ -135,6 +135,8 @@ std::string generateBindingSource(Root const& root) { std::string output(format_strings::source_start); for (auto& f : root.functions) { + if (codegen::getStatus(f) == BindStatus::Missing) continue; + if (codegen::getStatus(f) != BindStatus::NeedsBinding) { continue; } @@ -153,6 +155,8 @@ std::string generateBindingSource(Root const& root) { for (auto& c : root.classes) { for (auto& f : c.fields) { + if (codegen::getStatus(f) == BindStatus::Missing) continue; + if (auto i = f.get_as()) { // yeah there are no inlines on cocos } @@ -193,7 +197,7 @@ std::string generateBindingSource(Root const& root) { if ( codegen::getStatus(f) == BindStatus::Unbindable && - !codegen::platformNumber(fn->binds) && + codegen::platformNumber(fn->binds) == -1 && fn->prototype.is_virtual && fn->prototype.type != FunctionType::Dtor ) { used_declare_format = format_strings::declare_virtual_error; diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index ed8129cbc..47871bc7c 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -11,10 +11,10 @@ GEODE_MEMBER_CHECK(GameManager, m_levelEditorLayer, 0x13c); static_assert(sizeof(GJBaseGameLayer) == 0x2cc); -// GEODE_MEMBER_CHECK(PlayLayer, unknown4e8, 0x2e8); -// GEODE_MEMBER_CHECK(PlayLayer, m_endPortal, 0x324); -// GEODE_MEMBER_CHECK(PlayLayer, m_bottomGround, 0x37c); -// GEODE_MEMBER_CHECK(PlayLayer, m_topGround, 0x380); -// GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); +GEODE_MEMBER_CHECK(PlayLayer, unknown4e8, 0x2e8); +GEODE_MEMBER_CHECK(PlayLayer, m_endPortal, 0x324); +GEODE_MEMBER_CHECK(PlayLayer, m_bottomGround, 0x37c); +GEODE_MEMBER_CHECK(PlayLayer, m_topGround, 0x380); +GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); #endif \ No newline at end of file From a0deb6ab964234b9403af9afee599763a3d983dd Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:54:11 +0300 Subject: [PATCH 059/135] Fix the missing stuff and fix playlayer --- bindings/GeometryDash.bro | 6 +++++- codegen/CMakeLists.txt | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 3df5611da..62ade59f5 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -4897,11 +4897,15 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, bool unused4cc; bool m_hasCheated; geode::SeedValueRS m_dontSave; + [[missing(android)]] int unknown4d8; + [[missing(android)]] bool m_debugPauseOff; + [[missing(android)]] bool m_shouldSmoothCamera; + [[missing(android)]] float unused_4e0; - PAD = mac 0x4, win 0x4, android 0x4; + PAD = mac 0x4, win 0x4, android 0x0; cocos2d::CCDrawNode* unknown4e8; float m_camera4f0; int unused4f4; diff --git a/codegen/CMakeLists.txt b/codegen/CMakeLists.txt index 35ee9b315..2bd4a39d3 100644 --- a/codegen/CMakeLists.txt +++ b/codegen/CMakeLists.txt @@ -4,7 +4,7 @@ project(Codegen LANGUAGES C CXX) include(../cmake/CPM.cmake) CPMAddPackage("gh:fmtlib/fmt#9.1.0") -CPMAddPackage("gh:geode-sdk/Broma#93f401a") +CPMAddPackage("gh:geode-sdk/Broma#38a3bba") file(GLOB SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp From a50b48791e7423c6be1fea2c7168ef68dfa8b7f5 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:58:16 +0300 Subject: [PATCH 060/135] fix GJAccountManager on android --- bindings/GeometryDash.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 62ade59f5..e11ba2b9b 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1884,7 +1884,7 @@ class GJAccountManager : cocos2d::CCNode { } gd::string getGJP() = mac 0x89520, win 0x10abb0; - PAD = mac 0x8, win 0x4; + PAD = mac 0x8, win 0x4, android 0x4; gd::string m_password; gd::string m_username; int m_accountID; From b0ab2f95f6dd2bf2aa878e2e205f9adc0521261b Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 16:00:38 +0300 Subject: [PATCH 061/135] fix the funny wrong signatures --- bindings/GeometryDash.bro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index e11ba2b9b..abf408c78 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -955,7 +955,7 @@ class CommentUploadDelegate { [[link(android)]] class ConfigureHSVWidget : cocos2d::CCNode { - bool init(int abs, cocos2d::ccHSVValue val) = win 0x4a3f0, mac 0x237310; + bool init(cocos2d::ccHSVValue val, bool abs) = win 0x4a3f0, mac 0x237310; void updateLabels() = win 0x4adf0, mac 0x237df0; cocos2d::CCLabelBMFont* m_hueLabel; cocos2d::CCLabelBMFont* m_saturationLabel; @@ -1711,7 +1711,7 @@ class EndLevelLayer : cocos2d::CCLayer { static EndLevelLayer* create() = mac 0x2787d0, win 0x94b50; void customSetup() = win 0x94cb0; - const char* getCoinString(void* p0) = win 0x96270; + const char* getCoinString() = win 0x96270; const char* getEndText() = win 0x964A0; void onMenu(cocos2d::CCObject* sender) = mac 0x27a500, win 0x96c10; void onEdit(cocos2d::CCObject* sender) = mac 0x27a640, win 0x96d30; From fc58ab79efea50babce4f5cafc5113fd31c3c277 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:36:44 +0300 Subject: [PATCH 062/135] c++ abi can go burn in gaseous tungsten --- bindings/GeometryDash.bro | 14 ++++++------- codegen/src/AndroidSymbol.hpp | 18 +++++++++++++--- codegen/src/Shared.hpp | 1 + loader/include/Geode/DefaultInclude.hpp | 10 ++++----- .../Geode/cocos/platform/android/CCEGLView.h | 2 ++ loader/include/Geode/modify/Field.hpp | 2 +- loader/src/hooks/LoadingLayer.cpp | 21 +++++++++++++++++++ loader/src/platform/android/main.cpp | 4 ++++ loader/test/members/Android.cpp | 2 ++ 9 files changed, 58 insertions(+), 16 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index abf408c78..edaa70471 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -3611,7 +3611,7 @@ class GameObject : CCSpritePlus { bool m_unk3D9; bool m_isSelected; int m_globalClickCounter; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; bool m_shouldUpdateColorSprite; float m_multiScaleMultiplier; bool m_isGroupParent; @@ -3624,20 +3624,20 @@ class GameObject : CCSpritePlus { int m_editorLayer; int m_editorLayer2; int m_unk414; - PAD = mac 0xc, win 0xc; + PAD = mac 0xc, win 0xc, android 0xc; cocos2d::CCPoint m_firstPosition; bool m_unk42C; bool m_unk42D; - PAD = mac 0x6, win 0x6; + PAD = mac 0x6, win 0x6, android 0x6; bool m_isAnimated; - PAD = mac 0x7, win 0x7; + PAD = mac 0x7, win 0x7, android 0x7; bool m_hasEffectLine; bool m_specialUnk43d; - PAD = mac 0x1, win 0x1; + PAD = mac 0x1, win 0x1, android 0x1; bool m_hasDurationLine; bool m_isTriggerable; bool m_triggeredInEditor; - PAD = mac 0x6, win 0x6; + PAD = mac 0x6, win 0x6, android 0x6; bool m_highDetail; ColorActionSprite* m_colorActionSpriteBase; ColorActionSprite* m_colorActionSpriteDetail; @@ -3646,7 +3646,7 @@ class GameObject : CCSpritePlus { bool m_unk459; bool m_unk45A; bool m_wasForcedRotatedPositionUpdateIdk; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; bool m_orbMultiActivate; } diff --git a/codegen/src/AndroidSymbol.hpp b/codegen/src/AndroidSymbol.hpp index dbb936e54..3917fd1b1 100644 --- a/codegen/src/AndroidSymbol.hpp +++ b/codegen/src/AndroidSymbol.hpp @@ -7,9 +7,9 @@ #include #include -std::string mangleIdent(std::string_view str) { +std::string mangleIdent(std::string_view str, bool ne = true) { if (str.find("::") != -1) { - std::string result = "N"; + std::string result = ne ? "N" : ""; auto s = str; do { const auto i = s.find("::"); @@ -19,7 +19,7 @@ std::string mangleIdent(std::string_view str) { else s = s.substr(i + 2); } while(s.size()); - return result + "E"; + return result + (ne ? "E" : ""); } else { return std::to_string(str.size()) + std::string(str); } @@ -125,6 +125,18 @@ std::string mangleType(std::vector& seen, std::string name, bool su std::string generateAndroidSymbol(const Class& clazz, const FunctionBindField* fn) { auto& decl = fn->prototype; + if (decl.type != FunctionType::Normal) { + // ctor and dtor + switch (decl.type) { + case FunctionType::Ctor: + return "_ZN" + mangleIdent(clazz.name, false) + "C2Ev"; + case FunctionType::Dtor: + return "_ZN" + mangleIdent(clazz.name, false) + "D2Ev"; + default: + throw std::runtime_error("Unknown function type"); + } + } + std::string mangledSymbol = "_Z" + mangleIdent(clazz.name + "::" + decl.name); if (decl.args.empty()) { mangledSymbol += "v"; diff --git a/codegen/src/Shared.hpp b/codegen/src/Shared.hpp index ef0e41a0b..c4e572785 100644 --- a/codegen/src/Shared.hpp +++ b/codegen/src/Shared.hpp @@ -136,6 +136,7 @@ namespace codegen { inline bool shouldAndroidBind(const FunctionBindField* fn) { if (codegen::platform == Platform::Android) { + if (fn->prototype.type != FunctionType::Normal) return true; for (auto& [type, name] : fn->prototype.args) { if (can_find(type.name, "gd::")) return true; } diff --git a/loader/include/Geode/DefaultInclude.hpp b/loader/include/Geode/DefaultInclude.hpp index 523aa876e..87d7b1a69 100644 --- a/loader/include/Geode/DefaultInclude.hpp +++ b/loader/include/Geode/DefaultInclude.hpp @@ -81,8 +81,7 @@ namespace geode { GEODE_IOS(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) \ GEODE_WINDOWS(Class_(geode::CutoffConstructorType, size_t fill) \ : Class_() {}) \ - GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \ - : Class_() {}) + GEODE_ANDROID(GEODE_FILL_CONSTRUCTOR(Class_, 0){}) #define GEODE_CUTOFF_CONSTRUCTOR_COCOS(Class_, Base_) \ GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \ @@ -91,8 +90,8 @@ namespace geode { : Base_(geode::CutoffConstructor, fill){}) \ GEODE_WINDOWS(Class_(geode::CutoffConstructorType, size_t fill) \ : Class_() {}) \ - GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \ - : Class_() {}) + GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \ + : Base_(geode::CutoffConstructor, fill){}) #define GEODE_CUTOFF_CONSTRUCTOR_GD(Class_, Base_) \ GEODE_WINDOWS(Class_(geode::CutoffConstructorType, size_t fill) \ @@ -106,7 +105,8 @@ namespace geode { #define GEODE_CUTOFF_CONSTRUCTOR_CUTOFF(Class_, Base_) \ GEODE_WINDOWS(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \ - GEODE_ANDROID(GEODE_FILL_CONSTRUCTOR(Class_, sizeof(Base_)) : Base_(){}) \ + GEODE_ANDROID(Class_(geode::CutoffConstructorType, size_t fill) \ + : Base_(geode::CutoffConstructor, fill){}) \ GEODE_MACOS(Class_(geode::CutoffConstructorType, size_t fill) \ : Base_(geode::CutoffConstructor, fill){}) \ GEODE_IOS(Class_(geode::CutoffConstructorType, size_t fill) \ diff --git a/loader/include/Geode/cocos/platform/android/CCEGLView.h b/loader/include/Geode/cocos/platform/android/CCEGLView.h index a45d16ad7..eed2465da 100644 --- a/loader/include/Geode/cocos/platform/android/CCEGLView.h +++ b/loader/include/Geode/cocos/platform/android/CCEGLView.h @@ -34,6 +34,8 @@ class CC_DLL CCEGLView : public CCEGLViewProtocol { GEODE_FRIEND_MODIFY public: + GEODE_CUSTOM_CONSTRUCTOR_COCOS(CCEGLView, CCEGLViewProtocol) + CCEGLView(); virtual ~CCEGLView(); diff --git a/loader/include/Geode/modify/Field.hpp b/loader/include/Geode/modify/Field.hpp index 7a140f7de..8cf95adde 100644 --- a/loader/include/Geode/modify/Field.hpp +++ b/loader/include/Geode/modify/Field.hpp @@ -58,7 +58,7 @@ namespace geode::modifier { using Intermediate = Modify; // Padding used for guaranteeing any member of parents // will be in between sizeof(Intermediate) and sizeof(Parent) - uintptr_t m_padding; + alignas(Base) uintptr_t m_padding; public: // the constructor that constructs the fields. diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 00c5e80e2..c8d246809 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -156,4 +156,25 @@ struct CustomLoadingLayer : Modify { } this->updateLoadingBar(); } +}; + +#include +struct FieldTest : Modify { + int field = 0x10101010; + + bool init(GJGameLevel* level) { + if (!PlayLayer::init(level)) return false; + log::debug("GameManager 1 {}", GameManager::sharedState()); + log::debug("PlayLayer 1 {}", PlayLayer::get()); + m_fields->field += 0x20202020; + log::debug("GameManager 2 {}", GameManager::sharedState()); + log::debug("PlayLayer 2 {}", PlayLayer::get()); + return true; + } + + void update(float dt) { + log::debug("GameManager {}", GameManager::sharedState()); + log::debug("PlayLayer {}", PlayLayer::get()); + PlayLayer::update(dt); + } }; \ No newline at end of file diff --git a/loader/src/platform/android/main.cpp b/loader/src/platform/android/main.cpp index 3fd948b8d..471b162ed 100644 --- a/loader/src/platform/android/main.cpp +++ b/loader/src/platform/android/main.cpp @@ -20,4 +20,8 @@ extern "C" [[gnu::visibility("default")]] jint JNI_OnLoad(JavaVM* vm, void* rese return JNI_VERSION_1_1; } +extern "C" [[gnu::visibility("default")]] void emptyFunction(void*) { + // empty +} + #endif \ No newline at end of file diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index 47871bc7c..563735568 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -17,4 +17,6 @@ GEODE_MEMBER_CHECK(PlayLayer, m_bottomGround, 0x37c); GEODE_MEMBER_CHECK(PlayLayer, m_topGround, 0x380); GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); +static_assert(sizeof(GameObject) == 0x42c); + #endif \ No newline at end of file From 90d55d05268d396c4de7fc0047cdd5457e241501 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:37:26 +0300 Subject: [PATCH 063/135] revert web --- loader/src/utils/web.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 88569b3eb..7675f46cf 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -214,8 +214,6 @@ SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const return this->error("Curl not initialized", -1); } - log::debug("curl init {}", curl); - // resulting byte array ByteVector ret; // output file if downloading to file. unique_ptr because not always @@ -308,28 +306,17 @@ SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const } ); curl_easy_setopt(curl, CURLOPT_PROGRESSDATA, &data); - log::debug("curl opts"); auto res = curl_easy_perform(curl); - log::debug("curl perform"); - if (res != CURLE_OK) { long code = 0; - log::debug("curl fail"); curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &code); - log::debug("curl cleanup"); curl_easy_cleanup(curl); - log::debug("end"); return this->error("Fetch failed: " + std::string(curl_easy_strerror(res)), code); } - log::debug("curl cleanup 2"); curl_easy_cleanup(curl); - log::debug("end 2"); - AWAIT_RESUME(); - log::debug("end 3"); - // if something is still holding a handle to this // request, then they may still cancel it m_finished = true; @@ -595,4 +582,4 @@ AsyncWebResult AsyncWebResponse::json() { return Err(std::string(e.what())); } }); -} +} \ No newline at end of file From c950787693b747736caf68c97aa94734c6ab2f62 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 17:38:50 +0300 Subject: [PATCH 064/135] remove the field tests --- loader/src/hooks/LoadingLayer.cpp | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index c8d246809..93e82f077 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -157,24 +157,3 @@ struct CustomLoadingLayer : Modify { this->updateLoadingBar(); } }; - -#include -struct FieldTest : Modify { - int field = 0x10101010; - - bool init(GJGameLevel* level) { - if (!PlayLayer::init(level)) return false; - log::debug("GameManager 1 {}", GameManager::sharedState()); - log::debug("PlayLayer 1 {}", PlayLayer::get()); - m_fields->field += 0x20202020; - log::debug("GameManager 2 {}", GameManager::sharedState()); - log::debug("PlayLayer 2 {}", PlayLayer::get()); - return true; - } - - void update(float dt) { - log::debug("GameManager {}", GameManager::sharedState()); - log::debug("PlayLayer {}", PlayLayer::get()); - PlayLayer::update(dt); - } -}; \ No newline at end of file From d964048f2de08df77fe102c8e218136f74f7ab00 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 18:29:59 +0300 Subject: [PATCH 065/135] fix ctor mangling with params --- codegen/src/AndroidSymbol.hpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/codegen/src/AndroidSymbol.hpp b/codegen/src/AndroidSymbol.hpp index 3917fd1b1..a00fb0c31 100644 --- a/codegen/src/AndroidSymbol.hpp +++ b/codegen/src/AndroidSymbol.hpp @@ -125,19 +125,19 @@ std::string mangleType(std::vector& seen, std::string name, bool su std::string generateAndroidSymbol(const Class& clazz, const FunctionBindField* fn) { auto& decl = fn->prototype; - if (decl.type != FunctionType::Normal) { - // ctor and dtor - switch (decl.type) { - case FunctionType::Ctor: - return "_ZN" + mangleIdent(clazz.name, false) + "C2Ev"; - case FunctionType::Dtor: - return "_ZN" + mangleIdent(clazz.name, false) + "D2Ev"; - default: - throw std::runtime_error("Unknown function type"); - } - } - std::string mangledSymbol = "_Z" + mangleIdent(clazz.name + "::" + decl.name); + std::string mangledSymbol; + switch (decl.type) { + case FunctionType::Ctor: + mangledSymbol = "_ZN" + mangleIdent(clazz.name, false) + "C2E"; + break; + case FunctionType::Dtor: + mangledSymbol = "_ZN" + mangleIdent(clazz.name, false) + "D2E"; + break; + default: + mangledSymbol = "_Z" + mangleIdent(clazz.name + "::" + decl.name); + break; + } if (decl.args.empty()) { mangledSymbol += "v"; } else { From 6bd6c6b3202b719ea281be6d0a0307c88557434f Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 18:40:04 +0300 Subject: [PATCH 066/135] reenable persist --- loader/src/hooks/persist.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/loader/src/hooks/persist.cpp b/loader/src/hooks/persist.cpp index 7be7ca061..3f216069d 100644 --- a/loader/src/hooks/persist.cpp +++ b/loader/src/hooks/persist.cpp @@ -4,9 +4,9 @@ using namespace geode::prelude; #include -// struct SceneSwitch : Modify { -// void willSwitchToScene(CCScene* scene) { -// AchievementNotifier::willSwitchToScene(scene); -// SceneManager::get()->willSwitchToScene(scene); -// } -// }; +struct SceneSwitch : Modify { + void willSwitchToScene(CCScene* scene) { + AchievementNotifier::willSwitchToScene(scene); + SceneManager::get()->willSwitchToScene(scene); + } +}; From 8f342440230d91086c4706d3f61d8c5bbc416b9f Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:07:33 +0300 Subject: [PATCH 067/135] android m_shouldTryToKick --- bindings/GeometryDash.bro | 2 +- loader/test/members/Android.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index edaa70471..dd93183f4 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5030,7 +5030,7 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, bool m_delayedResetLevel; int m_lastDeathPercent; bool unk4C4; - PAD = mac 0xb, win 0xb; + PAD = mac 0xb, win 0xb, android 0xb; bool unk4D0; bool unk4D1; cocos2d::CCArray* unk4D4; diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index 563735568..893242bb6 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -16,6 +16,7 @@ GEODE_MEMBER_CHECK(PlayLayer, m_endPortal, 0x324); GEODE_MEMBER_CHECK(PlayLayer, m_bottomGround, 0x37c); GEODE_MEMBER_CHECK(PlayLayer, m_topGround, 0x380); GEODE_MEMBER_CHECK(PlayLayer, m_level, 0x470); +GEODE_MEMBER_CHECK(PlayLayer, m_shouldTryToKick, 0x4e0); static_assert(sizeof(GameObject) == 0x42c); From 238d1b7de9e8820954fa9db764aea0a6e245ddd0 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:18:40 +0300 Subject: [PATCH 068/135] implement android game::exit --- bindings/GeometryDash.bro | 1 + loader/src/platform/android/util.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index dd93183f4..d1b6e9496 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -4501,6 +4501,7 @@ class MenuLayer : cocos2d::CCLayer, FLAlertLayerProtocol, GooglePlayDelegate { void onFacebook(cocos2d::CCObject*) = win 0x191960; void onTwitter(cocos2d::CCObject*) = win 0x191980; void onYouTube(cocos2d::CCObject*) = win 0x1919A0; + void endGame(); static cocos2d::CCScene* scene(bool) = mac 0x1d12d0, win 0x190720, ios 0x19e57c; cocos2d::CCSprite* m_googlePlaySprite; diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 8145a529e..6135b77a1 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -50,8 +50,11 @@ void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) { } void geode::utils::game::exit() { - // Not implemented - log::error("Exiting the game is not implemented on android"); + CCDirector::get()->getActionManager()->addAction(CCSequence::create( + CCDelayTime::create(0.5f), + CCCallFunc::create(nullptr, callfunc_selector(MenuLayer::endGame)), + nullptr + ), CCDirector::get()->getRunningScene(), false);; } void geode::utils::game::restart() { From 7de21d91772c030aa703e7dbdaa472500f7d31b6 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 19:41:25 +0300 Subject: [PATCH 069/135] Fix latest resources downloading --- loader/src/hooks/LoadingLayer.cpp | 4 ++++ loader/src/loader/LoaderImpl.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 93e82f077..5bc171bb1 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -57,12 +57,14 @@ struct CustomLoadingLayer : Modify { void setupLoaderResources() { // verify loader resources if (!LoaderImpl::get()->verifyLoaderResources()) { + log::debug("Downloading Loader Resources"); this->setSmallText("Downloading Loader Resources"); this->addChild(EventListenerNode::create( this, &CustomLoadingLayer::updateResourcesProgress )); } else { + log::debug("Loading Loader Resources"); this->setSmallText("Loading Loader Resources"); LoaderImpl::get()->updateSpecialFiles(); this->continueLoadAssets(); @@ -77,10 +79,12 @@ struct CustomLoadingLayer : Modify { )); }, [&](UpdateFinished) { + log::debug("Downloaded Loader Resources"); this->setSmallText("Downloaded Loader Resources"); this->continueLoadAssets(); }, [&](UpdateFailed const& error) { + log::debug("Failed Loader Resources"); LoaderImpl::get()->platformMessageBox( "Error updating resources", error + ".\n" diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 44ae6c774..8c2e056d7 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -814,6 +814,7 @@ void Loader::Impl::downloadLoaderResources(bool useLatestRelease) { ).post(); } ); + return; } else { log::debug("Loader version {} does not exist on Github, not downloading the resources", this->getVersion().toString()); From fedf96edd9dd07ad00412a386fd0c5e43c71c3c5 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 20:21:23 +0300 Subject: [PATCH 070/135] enable editorpause ids --- loader/src/ids/EditorPauseLayer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/loader/src/ids/EditorPauseLayer.cpp b/loader/src/ids/EditorPauseLayer.cpp index c1284360d..7c44a3f7e 100644 --- a/loader/src/ids/EditorPauseLayer.cpp +++ b/loader/src/ids/EditorPauseLayer.cpp @@ -2,8 +2,6 @@ #include -#if !defined(GEODE_IS_ANDROID) - using namespace geode::prelude; // special class for this because making it a CCMenuItemToggler would be very UB @@ -274,5 +272,3 @@ struct EditorPauseLayerIDs : Modify { return true; } }; - -#endif \ No newline at end of file From 2a0c08c5d1eb021d93c644ba45aed663a3423faa Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 20:44:37 +0300 Subject: [PATCH 071/135] some broma stuff --- bindings/GeometryDash.bro | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index d1b6e9496..fb38211bd 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1212,7 +1212,7 @@ class DrawGridLayer : cocos2d::CCLayer { m_player2NodePoints->removeAllObjects(); } - void loadTimeMarkers(gd::string guidelines) = mac 0x94010; + void loadTimeMarkers(gd::string guidelines) = mac 0x94010, win 0x16cab0; std::array* m_commonLines; std::array* m_yellowGuidelines; @@ -4358,7 +4358,7 @@ class LevelSettingsObject : cocos2d::CCNode { bool m_isFlipped; GJGameLevel* m_level; gd::string m_guidelineString; - int m_unknown; + int m_defaultSongID; int m_colorPage; int m_groundLineIndex; } From 63940f2ce93fcf29926f7a7fcb6b7ea9ff1fef68 Mon Sep 17 00:00:00 2001 From: Cvolton Date: Sun, 1 Oct 2023 17:29:42 +0200 Subject: [PATCH 072/135] Improve Android bindings --- bindings/GeometryDash.bro | 29 ++++++++++++++-------------- loader/src/ids/LevelBrowserLayer.cpp | 6 +----- loader/src/ids/LevelInfoLayer.cpp | 6 +----- loader/test/members/Android.cpp | 6 ++++++ 4 files changed, 23 insertions(+), 24 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index fb38211bd..2cb6d72a6 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -981,7 +981,8 @@ class CountTriggerAction : cocos2d::CCNode { class CreateGuidelinesLayer : FLAlertLayer, FLAlertLayerProtocol { void doClearGuidelines() = win 0x4cf60, mac 0x299690; void onStop(cocos2d::CCObject* sender) = win 0x4d2c0, mac 0x2990f0; - PAD = win 0x4, mac 0x8; + + void* m_unk; LevelSettingsObject* m_levelSettings; PAD = win 0x1c; gd::string m_guidelineString; @@ -1139,10 +1140,10 @@ class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDele class DailyLevelPage : FLAlertLayer, FLAlertLayerProtocol, GJDailyLevelDelegate, LevelDownloadDelegate { static DailyLevelPage* create(bool weekly) = win 0x6a860; bool init(bool weekly) = mac 0x108C90, win 0x6a900; - virtual void updateTimers(float) = mac 0x109780, win 0x6bef0; + void updateTimers(float) = mac 0x109780, win 0x6bef0; virtual void show() = mac 0x10a4b0, win 0x3f360; - PAD = mac 0x29, win 0x15; + PAD = mac 0x29, win 0x15, android 0x15; bool m_weekly; } @@ -3015,7 +3016,7 @@ class GameLevelManager : cocos2d::CCNode { int m_dailyTimeLeft; int m_dailyID; int m_dailyIDUnk; - PAD = mac 0x10, win 0x4; + PAD = mac 0x10, win 0x4, android 0x4; int m_weeklyTimeLeft; int m_weeklyID; int m_weeklyIDUnk; @@ -3283,7 +3284,7 @@ class GameManager : GManager { bool m_showedRateDiffDialog; bool m_showedRateStarDialog; bool m_showedLowDetailDialog; - PAD = mac 0x3c, win 0x30; + PAD = mac 0x3c, win 0x30, android 0x30; int m_bootups; bool m_hasRatedGame; bool m_unk0; @@ -3706,14 +3707,14 @@ class GameStatsManager : cocos2d::CCNode { void storeUserCoin(char const*) = mac 0x42890; bool isItemUnlocked(UnlockType type, int id) = win 0xfbb80; - PAD = mac 0x50, win 0x28; + PAD = mac 0x50, win 0x28, android 0x24; cocos2d::CCDictionary* m_dailyChests; cocos2d::CCDictionary* m_worldAdvertChests; cocos2d::CCDictionary* m_activeChallenges; cocos2d::CCDictionary* m_upcomingChallenges; - PAD = mac 0x18, win 0xc; + PAD = mac 0x18, win 0xc, android 0xc; cocos2d::CCDictionary* m_playerStats; - PAD = mac 0x50, win 0x10; + PAD = mac 0x50, win 0x10, android 0x34; cocos2d::CCDictionary* m_completedLevels; cocos2d::CCDictionary* m_verifiedUserCoins; cocos2d::CCDictionary* m_pendingUserCoins; @@ -3917,7 +3918,7 @@ class LevelBrowserLayer : cocos2d::CCLayer, LevelManagerDelegate, FLAlertLayerPr void onNew(cocos2d::CCObject* sender) = win 0x15cbf0, mac 0x252ac0; static LevelBrowserLayer* create(GJSearchObject* search) = mac 0x251210, win 0x159fa0, ios 0x2d0a00; - PAD = win 0x4, mac 0x8; + void* m_unk; TextArea* m_noInternet; GJListLayer* m_list; CCMenuItemSpriteExtra* m_rightArrow; @@ -4192,14 +4193,14 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg void showUpdateAlert(UpdateResponse) = mac 0x164ED0, win 0x179300; void updateLabelValues() = mac 0x164090, win 0x17b170; - PAD = win 0x4, mac 0x8; + void* m_unk1; cocos2d::CCMenu* m_playBtnMenu; GJGameLevel* m_level; cocos2d::CCArray* m_unknown; CCMenuItemSpriteExtra* m_likeBtn; CCMenuItemSpriteExtra* m_starRateBtn; CCMenuItemSpriteExtra* m_demonRateBtn; - PAD = win 0x4, mac 0x8; + void* m_unk2; CCMenuItemToggler* m_ldmToggler; cocos2d::CCLabelBMFont* m_ldmLabel; cocos2d::CCLabelBMFont* m_lengthLabel; @@ -4208,7 +4209,7 @@ class LevelInfoLayer : cocos2d::CCLayer, LevelDownloadDelegate, LevelUpdateDeleg cocos2d::CCLabelBMFont* m_orbsLabel; cocos2d::CCLabelBMFont* m_folderLabel; CCMenuItemSpriteExtra* m_cloneBtn; - PAD = win 0x4, mac 0x8; + void* m_unk3; } [[link(android)]] @@ -4232,7 +4233,7 @@ class LevelManagerDelegate { [[link(android)]] class LevelPage : cocos2d::CCLayer, DialogDelegate { - PAD = mac 0x8, win 0x4; + void* m_unk; GJGameLevel* m_level; void onInfo(cocos2d::CCObject* sender) = mac 0x23AAE0, win 0x189070; @@ -5425,7 +5426,7 @@ class RetryLevelLayer { [[link(android)]] class RewardsPage : FLAlertLayer { - bool init() = mac 0xf3800, win 0x2178F0; + virtual bool init() = mac 0xf3800, win 0x2178F0; } [[link(android)]] diff --git a/loader/src/ids/LevelBrowserLayer.cpp b/loader/src/ids/LevelBrowserLayer.cpp index 7723454b8..ddd701bff 100644 --- a/loader/src/ids/LevelBrowserLayer.cpp +++ b/loader/src/ids/LevelBrowserLayer.cpp @@ -4,8 +4,6 @@ #include #include -#if !defined(GEODE_IS_ANDROID) - using namespace geode::prelude; $register_ids(LevelBrowserLayer) { @@ -172,6 +170,4 @@ struct LevelBrowserLayerIDs : Modify { return true; } -}; - -#endif \ No newline at end of file +}; \ No newline at end of file diff --git a/loader/src/ids/LevelInfoLayer.cpp b/loader/src/ids/LevelInfoLayer.cpp index 5edfe2526..ecaea7ace 100644 --- a/loader/src/ids/LevelInfoLayer.cpp +++ b/loader/src/ids/LevelInfoLayer.cpp @@ -3,8 +3,6 @@ #include #include -#if !defined(GEODE_IS_ANDROID) - $register_ids(LevelInfoLayer) { auto winSize = CCDirector::get()->getWinSize(); @@ -136,6 +134,4 @@ struct LevelInfoLayerIDs : Modify { return true; } -}; - -#endif \ No newline at end of file +}; \ No newline at end of file diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index 893242bb6..740e938d5 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -8,6 +8,7 @@ GEODE_MEMBER_CHECK(GameManager, m_playLayer, 0x138); GEODE_MEMBER_CHECK(GameManager, m_levelEditorLayer, 0x13c); +GEODE_MEMBER_CHECK(GameManager, m_canGetLevelSaveData, 0x28c); static_assert(sizeof(GJBaseGameLayer) == 0x2cc); @@ -20,4 +21,9 @@ GEODE_MEMBER_CHECK(PlayLayer, m_shouldTryToKick, 0x4e0); static_assert(sizeof(GameObject) == 0x42c); +GEODE_MEMBER_CHECK(GameStatsManager, m_dailyChests, 0x110); +GEODE_MEMBER_CHECK(GameStatsManager, m_completedLevels, 0x164); + +GEODE_MEMBER_CHECK(DailyLevelPage, m_weekly, 0x1ed); + #endif \ No newline at end of file From 728dc22c7a93076e33a1e6210f95c50338216b0e Mon Sep 17 00:00:00 2001 From: matcool <26722564+matcool@users.noreply.github.com> Date: Sun, 1 Oct 2023 15:41:43 -0300 Subject: [PATCH 073/135] some missing paddings --- bindings/GeometryDash.bro | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 2cb6d72a6..ba5855e54 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5043,12 +5043,12 @@ class PlayLayer : GJBaseGameLayer, CCCircleWaveDelegate, CurrencyRewardDelegate, bool m_shouldTryToKick; float m_kickCheckDeltaSnapshot; int m_accumulatedKickCounter; - PAD = mac 0x4, win 0x4; + PAD = mac 0x4, win 0x4, android 0x8; double unk508; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; double unk518; double unk520; - PAD = mac 0x4, win 0x4; + PAD = mac 0x4, win 0x4, android 0x4; bool m_hasGlitter; bool m_isBgEffectOff; bool unk52F; From 2847beed8ffbf29ff51ebd81d388fbf3cb442b90 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 22:45:17 +0300 Subject: [PATCH 074/135] most requested feature of all time --- loader/src/ui/internal/list/ModListLayer.cpp | 4 ++++ loader/src/ui/internal/list/ModListLayer.hpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/loader/src/ui/internal/list/ModListLayer.cpp b/loader/src/ui/internal/list/ModListLayer.cpp index a06e745c7..5783d15c4 100644 --- a/loader/src/ui/internal/list/ModListLayer.cpp +++ b/loader/src/ui/internal/list/ModListLayer.cpp @@ -638,6 +638,10 @@ void ModListLayer::onExit(CCObject*) { ); } +void ModListLayer::keyBackClicked() { + this->onExit(nullptr); +} + void ModListLayer::onReload(CCObject*) { this->reloadList(); } diff --git a/loader/src/ui/internal/list/ModListLayer.hpp b/loader/src/ui/internal/list/ModListLayer.hpp index 0afa2839f..1d2b7a983 100644 --- a/loader/src/ui/internal/list/ModListLayer.hpp +++ b/loader/src/ui/internal/list/ModListLayer.hpp @@ -82,6 +82,9 @@ class ModListLayer : public CCLayer, public TextInputDelegate { void createSearchControl(); void onIndexUpdate(IndexUpdateEvent* event); + // most requested feature of all time + void keyBackClicked() override; + CCArray* createModCells(ModListType type, ModListQuery const& query); CCSize getCellSize() const; CCSize getListSize() const; From 9fa9284726ff440f2a313227a2fbe968f9e227d2 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:25:13 +0300 Subject: [PATCH 075/135] add not working clipboard --- bindings/GeometryDash.bro | 18 +++++++++--------- loader/src/platform/android/util.cpp | 8 ++++++++ loader/test/members/Android.cpp | 2 ++ 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index ba5855e54..ee4b2a042 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1502,10 +1502,10 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ bool m_isPlayingMusic; EditButtonBar* m_buttonBar; - PAD = mac 0x8, win 0x4; + PAD = mac 0x8, win 0x4, android 0x4; cocos2d::CCArray* m_hideableUIElementArray; float m_gridSize; - PAD = mac 0x18, win 0x14; + PAD = mac 0x18, win 0x14, android 0x14; bool m_moveModifier; bool m_swipeModifier; int m_rotationTouchID; @@ -1579,7 +1579,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ CCMenuItemSpriteExtra* m_layerNextBtn; CCMenuItemSpriteExtra* m_layerPrevBtn; CCMenuItemSpriteExtra* m_goToBaseBtn; - PAD = mac 0x10, win 0x8; + PAD = mac 0x10, win 0x8, android 0x8; int m_selectedCreateObjectID; cocos2d::CCArray* m_createButtonArray; cocos2d::CCArray* m_customObjectButtonArray; @@ -1588,16 +1588,16 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ LevelEditorLayer* m_editorLayer; cocos2d::CCPoint m_swipeStart; cocos2d::CCPoint m_swipeEnd; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; cocos2d::CCPoint m_lastTouchPoint; cocos2d::CCPoint m_cameraTest; - PAD = mac 0x8, win 0x8; + PAD = mac 0x8, win 0x8, android 0x8; GameObject* m_selectedObject; - PAD = mac 0x8, win 0x4; + PAD = mac 0x8, win 0x4, android 0x4; bool m_unk2cc; bool m_freeMovingObject; gd::string m_clipboard; - PAD = mac 0x10, win 0x8; + PAD = mac 0x10, win 0x8, android 0x8; int m_selectedTab; int m_timesSelected; PAD = win 0x20; @@ -1704,7 +1704,7 @@ class EffectGameObject : GameObject { bool m_dynamicBlock; int m_itemBlockAID; int m_pickupMode; - PAD = mac 0x28, win 0x24; + PAD = mac 0x28, win 0x24, android 0x24; } [[link(android)]] @@ -5950,7 +5950,7 @@ class TableViewDelegate { [[link(android)]] class TeleportPortalObject : GameObject { - PAD = mac 0x8, win 0x4; + PAD = mac 0x8, win 0x4, android 0x4; TeleportPortalObject* m_orangePortal; bool m_isYellowPortal; float m_teleportYOffset; diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 6135b77a1..8da055a5c 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -9,6 +9,14 @@ using namespace geode::prelude; #include #include +bool utils::clipboard::write(std::string const& data) { + return false; +} + +std::string utils::clipboard::read() { + return ""; +} + ghc::filesystem::path dirs::getGameDir() { return ghc::filesystem::path( "/storage/emulated/0/Android/data/com.geode.launcher/files/game" diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index 740e938d5..6e6220391 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -26,4 +26,6 @@ GEODE_MEMBER_CHECK(GameStatsManager, m_completedLevels, 0x164); GEODE_MEMBER_CHECK(DailyLevelPage, m_weekly, 0x1ed); +GEODE_MEMBER_CHECK(TeleportPortalObject, m_orangePortal, 0x430); + #endif \ No newline at end of file From c4af616a2a5c8ce9e689f3def8fb91ee32529692 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:44:17 +0300 Subject: [PATCH 076/135] fix editorui android --- bindings/GeometryDash.bro | 18 +++++++++--------- loader/test/members/Android.cpp | 5 +++++ 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index ee4b2a042..58835641d 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -416,9 +416,9 @@ class CCMenuItemSpriteExtra : cocos2d::CCMenuItemSprite { return true; } - void activate() = mac 0x125730, win 0x191c0; - void selected() = mac 0x125840, win 0x19270; - void unselected() = mac 0x125a70, win 0x19430; + virtual void activate() = mac 0x125730, win 0x191c0; + virtual void selected() = mac 0x125840, win 0x19270; + virtual void unselected() = mac 0x125a70, win 0x19430; float m_scaleMultiplier; float m_baseScale; @@ -474,10 +474,10 @@ class CCMenuItemToggler : cocos2d::CCMenuItem { void setSizeMult(float) = mac 0x38a40, win 0x19850; void toggle(bool) = mac 0x38950, win 0x199b0, ios 0xf5848; bool init(cocos2d::CCNode* off, cocos2d::CCNode* on, cocos2d::CCObject* target, cocos2d::SEL_MenuHandler handler) = mac 0x38500, win 0x196e0; - void activate() = mac 0x38bc0, win 0x198d0, ios 0xf59ac; - void selected() = mac 0x38b80, win 0x198a0; - void unselected() = mac 0x38c00, win 0x19900; - void setEnabled(bool enabled) = mac 0x38c40, win 0x19930; + virtual void activate() = mac 0x38bc0, win 0x198d0, ios 0xf59ac; + virtual void selected() = mac 0x38b80, win 0x198a0; + virtual void unselected() = mac 0x38c00, win 0x19900; + virtual void setEnabled(bool enabled) = mac 0x38c40, win 0x19930; CCMenuItemSpriteExtra* m_offButton; CCMenuItemSpriteExtra* m_onButton; @@ -1530,7 +1530,7 @@ class EditorUI : cocos2d::CCLayer, FLAlertLayerProtocol, ColorSelectDelegate, GJ bool m_unkSwipeRelated; PAD = mac 0x2, win 0x2, android 0x2; bool m_updateTimeMarkers; - PAD = mac 0x8, win 0x8, android 0x2; + PAD = mac 0x8, win 0x8, android 0x8; cocos2d::CCArray* m_unknownArray2; PAD = mac 0x8, win 0x8, android 0x8; cocos2d::CCArray* m_selectedObjects; @@ -3823,7 +3823,7 @@ class HardStreak : cocos2d::CCDrawNode { [[link(android)]] class InfoAlertButton : CCMenuItemSpriteExtra { bool init(gd::string title, gd::string text, float scale) = win 0x14ef50; - void activate() = win 0x14f050; + virtual void activate() = win 0x14f050; inline InfoAlertButton() {} static InfoAlertButton* create(gd::string title, gd::string text, float scale) = win 0x14ed20, mac 0x2ecad0; } diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index 6e6220391..dd8ff7b51 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -28,4 +28,9 @@ GEODE_MEMBER_CHECK(DailyLevelPage, m_weekly, 0x1ed); GEODE_MEMBER_CHECK(TeleportPortalObject, m_orangePortal, 0x430); +GEODE_MEMBER_CHECK(EditorUI, m_rotationControl, 0x16c); +GEODE_MEMBER_CHECK(EditorUI, m_updateTimeMarkers, 0x1a4); +GEODE_MEMBER_CHECK(EditorUI, m_selectedObjects, 0x1bc); +GEODE_MEMBER_CHECK(EditorUI, m_selectedObject, 0x2c4); + #endif \ No newline at end of file From 877b6449626078783abde9cb13ecb04e75c1ea74 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:58:16 +0300 Subject: [PATCH 077/135] fix ccmenuitemsprite virtuals --- loader/include/Geode/platform/android.hpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/loader/include/Geode/platform/android.hpp b/loader/include/Geode/platform/android.hpp index e19402bcf..149d6bb26 100644 --- a/loader/include/Geode/platform/android.hpp +++ b/loader/include/Geode/platform/android.hpp @@ -2,6 +2,8 @@ #include +#include "ItaniumCast.hpp" + namespace geode { struct PlatformInfo { void* m_so; @@ -11,11 +13,3 @@ namespace geode { namespace geode::base { /*GEODE_NOINLINE inline*/ uintptr_t get(); } - -namespace geode::cast { - template - After typeinfo_cast(Before ptr) { - // yall have symbols smh - return dynamic_cast(ptr); - } -} From 7f277a77e1f7b6c9223684cf026de7b14389dc7c Mon Sep 17 00:00:00 2001 From: SMJS <38814077+SMJSGaming@users.noreply.github.com> Date: Sun, 1 Oct 2023 23:59:44 +0200 Subject: [PATCH 078/135] Added a simple text area UI node (#277) --- loader/include/Geode/ui/TextArea.hpp | 60 +++++++ loader/src/ui/nodes/TextArea.cpp | 228 +++++++++++++++++++++++++++ 2 files changed, 288 insertions(+) create mode 100644 loader/include/Geode/ui/TextArea.hpp create mode 100644 loader/src/ui/nodes/TextArea.cpp diff --git a/loader/include/Geode/ui/TextArea.hpp b/loader/include/Geode/ui/TextArea.hpp new file mode 100644 index 000000000..0ac0cf313 --- /dev/null +++ b/loader/include/Geode/ui/TextArea.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include +#include + +namespace geode { + /** + * A class which provides a textarea with proper alignment and some extra features like: + * + * - Max lines + * - Changing all aspects after creation + * - Custom text alignment + * - Automatic line wrapping and cutoff + * - Line padding + * + * Contact me on Discord (\@smjs) if you have any questions, suggestions or bugs. + */ + class GEODE_DLL SimpleTextArea : public cocos2d::CCNode { + cocos2d::CCMenu* m_container; + std::string m_font; + std::string m_text; + std::vector m_lines; + cocos2d::CCTextAlignment m_alignment; + size_t m_maxLines; + float m_scale; + float m_lineHeight; + float m_linePadding; + bool m_artificialWidth; + public: + static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale); + static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale, const float width); + + void setFont(const std::string& font); + std::string getFont(); + void setAlignment(const cocos2d::CCTextAlignment alignment); + cocos2d::CCTextAlignment getAlignment(); + void setText(const std::string& text); + std::string getText(); + void setMaxLines(const size_t maxLines); + size_t getMaxLines(); + void setWidth(const float width); + float getWidth(); + void setScale(const float scale); + float getScale(); + void setLinePadding(const float padding); + float getLinePadding(); + std::vector getLines(); + float getHeight(); + float getLineHeight(); + private: + static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth); + + SimpleTextArea(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth); + cocos2d::CCLabelBMFont* createLabel(const std::string& text, const float top); + cocos2d::CCLabelBMFont* moveOverflow(cocos2d::CCLabelBMFont* line, const char c, const float top); + float calculateOffset(cocos2d::CCLabelBMFont* label); + void updateLines(); + void updateContents(); + }; +} \ No newline at end of file diff --git a/loader/src/ui/nodes/TextArea.cpp b/loader/src/ui/nodes/TextArea.cpp new file mode 100644 index 000000000..4af0518b5 --- /dev/null +++ b/loader/src/ui/nodes/TextArea.cpp @@ -0,0 +1,228 @@ +#include + +using namespace geode::prelude; + +SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale = 1) { + return SimpleTextArea::create(font, text, scale, 500, false); +} + +SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale, const float width) { + return SimpleTextArea::create(font, text, scale, width, true); +} + +SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth) { + SimpleTextArea* instance = new SimpleTextArea(font, text, scale, width, artificialWidth); + + if (instance && instance->init()) { + instance->autorelease(); + + return instance; + } else { + CC_SAFE_DELETE(instance); + + return nullptr; + } +} + +SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth) { + m_font = font; + m_text = text; + m_maxLines = 0; + m_scale = scale; + m_linePadding = 0; + m_artificialWidth = artificialWidth; + m_container = CCMenu::create(); + + this->setAnchorPoint({ 0.5f, 0.5f }); + m_container->setPosition({ 0, 0 }); + m_container->setAnchorPoint({ 0, 1 }); + m_container->setContentSize({ width, 0 }); + + this->addChild(m_container); + this->updateContents(); +} + +void SimpleTextArea::setFont(const std::string& font) { + m_font = font; + + this->updateContents(); +} + +std::string SimpleTextArea::getFont() { + return m_font; +} + +void SimpleTextArea::setAlignment(const CCTextAlignment alignment) { + m_alignment = alignment; + + this->updateContents(); +} + +CCTextAlignment SimpleTextArea::getAlignment() { + return m_alignment; +} + +void SimpleTextArea::setText(const std::string& text) { + m_text = text; + + this->updateContents(); +} + +std::string SimpleTextArea::getText() { + return m_text; +} + +void SimpleTextArea::setMaxLines(const size_t maxLines) { + m_maxLines = maxLines; + + this->updateContents(); +} + +size_t SimpleTextArea::getMaxLines() { + return m_maxLines; +} + +void SimpleTextArea::setWidth(const float width) { + m_artificialWidth = true; + + this->setContentSize({ width, this->getContentSize().height }); + m_container->setContentSize(this->getContentSize()); +} + +float SimpleTextArea::getWidth() { + return m_container->getContentSize().width; +} + +void SimpleTextArea::setScale(const float scale) { + m_scale = scale; + + this->updateContents(); +} + +float SimpleTextArea::getScale() { + return m_scale; +} + +void SimpleTextArea::setLinePadding(const float padding) { + m_linePadding = padding; + + this->updateContents(); +} + +float SimpleTextArea::getLinePadding() { + return m_linePadding; +} + +std::vector SimpleTextArea::getLines() { + return m_lines; +} + +float SimpleTextArea::getHeight() { + return m_container->getContentSize().height; +} + +float SimpleTextArea::getLineHeight() { + return m_lineHeight; +} + +CCLabelBMFont* SimpleTextArea::createLabel(const std::string& text, const float top) { + CCLabelBMFont* label = CCLabelBMFont::create(text.c_str(), m_font.c_str()); + + label->setScale(m_scale); + label->setAnchorPoint({ 0, 0 }); + label->setPosition({ 0, top }); + + return label; +} + +CCLabelBMFont* SimpleTextArea::moveOverflow(CCLabelBMFont* line, const char c, const float top) { + const std::string text = line->getString(); + const char back = text.back(); + const bool lastIsSpace = back == ' '; + CCLabelBMFont* newLine = this->createLabel(std::string(!lastIsSpace, back).append(std::string(c != ' ', c)), top); + + if (!lastIsSpace) { + if (text[text.size() - 2] == ' ') { + line->setString(text.substr(0, text.size() - 1).c_str()); + } else { + line->setString((text.substr(0, text.size() - 1) + '-').c_str()); + } + } + + m_lines.push_back(newLine); + + return newLine; +} + +float SimpleTextArea::calculateOffset(CCLabelBMFont* label) { + return m_linePadding + label->getContentSize().height * m_scale; +} + +void SimpleTextArea::updateLines() { + float top = 0; + CCLabelBMFont* line = this->createLabel("", top); + m_lines = { line }; + + for (const char c : m_text) { + if (m_maxLines && m_lines.size() > m_maxLines) { + CCLabelBMFont* last = m_lines.at(m_maxLines - 1); + const std::string text = last->getString(); + + m_lines.pop_back(); + last->setString(text.substr(0, text.size() - 3).append("...").c_str()); + + break; + } else if (c == '\n') { + line = this->createLabel("", top -= this->calculateOffset(line)); + + m_lines.push_back(line); + } else if (m_artificialWidth && line->getContentSize().width >= this->getWidth()) { + line = this->moveOverflow(line, c, top -= this->calculateOffset(line)); + } else { + const std::string text = line->getString(); + + line->setString((text + c).c_str()); + } + } +} + +void SimpleTextArea::updateContents() { + this->updateLines(); + const size_t lineCount = m_lines.size(); + const float width = this->getWidth(); + + if (lineCount > 0) { + m_lineHeight = m_lines.back()->getContentSize().height * m_scale; + } else { + m_lineHeight = 0; + } + + float height = m_lineHeight * lineCount + m_linePadding * (lineCount - 1); + + this->setContentSize({ width, height }); + m_container->setContentSize(this->getContentSize()); + m_container->removeAllChildren(); + + height -= m_lineHeight; + + for (CCLabelBMFont* line : m_lines) { + const float y = height + line->getPositionY(); + + switch (m_alignment) { + case kCCTextAlignmentLeft: { + line->setAnchorPoint({ 0, 0 }); + line->setPosition({ 0, y }); + } break; + case kCCTextAlignmentCenter: { + line->setAnchorPoint({ 0.5f, 0 }); + line->setPosition({ width / 2, y }); + } break; + case kCCTextAlignmentRight: { + line->setAnchorPoint({ 1, 0 }); + line->setPosition({ width, y }); + } break; + } + + m_container->addChild(line); + } +} \ No newline at end of file From 777cf38df09b06b23060690277b89b069d3b977a Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 13:37:09 +0300 Subject: [PATCH 079/135] implement threaded unzipping and revert typeinfo cast (but its ugly) --- loader/include/Geode/loader/Loader.hpp | 3 +- loader/include/Geode/platform/android.hpp | 10 +- loader/src/hooks/LoadingLayer.cpp | 27 ++++-- loader/src/loader/LoaderImpl.cpp | 93 +++++++++++++++---- loader/src/loader/LoaderImpl.hpp | 7 +- loader/src/loader/ModImpl.cpp | 18 ++-- loader/src/loader/ModImpl.hpp | 3 + .../src/ui/internal/list/ProblemsListCell.cpp | 5 + 8 files changed, 131 insertions(+), 35 deletions(-) diff --git a/loader/include/Geode/loader/Loader.hpp b/loader/include/Geode/loader/Loader.hpp index f9dd18150..030dc0ca5 100644 --- a/loader/include/Geode/loader/Loader.hpp +++ b/loader/include/Geode/loader/Loader.hpp @@ -32,7 +32,8 @@ namespace geode { LoadFailed, EnableFailed, MissingDependency, - PresentIncompatibility + PresentIncompatibility, + UnzipFailed }; Type type; std::variant cause; diff --git a/loader/include/Geode/platform/android.hpp b/loader/include/Geode/platform/android.hpp index 149d6bb26..e19402bcf 100644 --- a/loader/include/Geode/platform/android.hpp +++ b/loader/include/Geode/platform/android.hpp @@ -2,8 +2,6 @@ #include -#include "ItaniumCast.hpp" - namespace geode { struct PlatformInfo { void* m_so; @@ -13,3 +11,11 @@ namespace geode { namespace geode::base { /*GEODE_NOINLINE inline*/ uintptr_t get(); } + +namespace geode::cast { + template + After typeinfo_cast(Before ptr) { + // yall have symbols smh + return dynamic_cast(ptr); + } +} diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index 5bc171bb1..c765def56 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -9,30 +9,38 @@ using namespace geode::prelude; struct CustomLoadingLayer : Modify { CCLabelBMFont* m_smallLabel = nullptr; + CCLabelBMFont* m_smallLabel2 = nullptr; int m_geodeLoadStep = 0; + int m_totalMods = 0; void updateLoadedModsLabel() { auto allMods = Loader::get()->getAllMods(); auto count = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) { return item->isEnabled(); }); - auto totalCount = std::count_if(allMods.begin(), allMods.end(), [&](auto& item) { - return item->shouldLoad(); - }); - auto str = fmt::format("Geode: Loaded {}/{} mods", count, totalCount); + auto str = fmt::format("Geode: Loaded {}/{} mods", count, m_totalMods); this->setSmallText(str); + auto currentMod = LoaderImpl::get()->m_currentlyLoadingMod; + auto modName = currentMod ? currentMod->getName() : "Unknown"; + this->setSmallText2(modName); } void setSmallText(std::string const& text) { m_fields->m_smallLabel->setString(text.c_str()); } + void setSmallText2(std::string const& text) { + m_fields->m_smallLabel2->setString(text.c_str()); + } + // hook bool init(bool fromReload) { CCFileUtils::get()->updatePaths(); if (!LoadingLayer::init(fromReload)) return false; + m_totalMods = Loader::get()->getAllMods().size(); + auto winSize = CCDirector::sharedDirector()->getWinSize(); m_fields->m_smallLabel = CCLabelBMFont::create("", "goldFont.fnt"); @@ -41,6 +49,12 @@ struct CustomLoadingLayer : Modify { m_fields->m_smallLabel->setID("geode-small-label"); this->addChild(m_fields->m_smallLabel); + m_fields->m_smallLabel2 = CCLabelBMFont::create("", "goldFont.fnt"); + m_fields->m_smallLabel2->setPosition(winSize.width / 2, 15.f); + m_fields->m_smallLabel2->setScale(.45f); + m_fields->m_smallLabel2->setID("geode-small-label"); + this->addChild(m_fields->m_smallLabel2); + return true; } @@ -51,6 +65,7 @@ struct CustomLoadingLayer : Modify { } else { this->continueLoadAssets(); + this->setSmallText2(""); } } @@ -108,11 +123,11 @@ struct CustomLoadingLayer : Modify { } int getCurrentStep() { - return m_fields->m_geodeLoadStep + m_loadStep + 1; + return m_fields->m_geodeLoadStep + m_loadStep + 1 + LoaderImpl::get()->m_refreshedModCount; } int getTotalStep() { - return 18; + return 18 + m_totalMods; } void updateLoadingBar() { diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 8c2e056d7..529e327c3 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -388,7 +388,7 @@ void Loader::Impl::buildModGraph() { void Loader::Impl::loadModGraph(Mod* node, bool early) { if (early && !node->needsEarlyLoad()) { - m_modsToLoad.push(node); + m_modsToLoad.push_back(node); return; } @@ -402,32 +402,82 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) { if (node->isEnabled()) { for (auto const& dep : node->m_impl->m_dependants) { - this->loadModGraph(dep, early); + m_modsToLoad.push_front(dep); } log::popNest(); return; } - if (node->shouldLoad()) { - log::debug("Load"); - auto res = node->m_impl->loadBinary(); + m_currentlyLoadingMod = node; + m_refreshingModCount += 1; + m_refreshedModCount += 1; + + auto unzipFunction = [this, node]() { + log::debug("Unzip"); + auto res = node->m_impl->unzipGeodeFile(node->getMetadata()); + return res; + }; + + auto loadFunction = [this, node, early]() { + if (node->shouldLoad()) { + log::debug("Load"); + auto res = node->m_impl->loadBinary(); + if (!res) { + m_problems.push_back({ + LoadProblem::Type::LoadFailed, + node, + res.unwrapErr() + }); + log::error("Failed to load binary: {}", res.unwrapErr()); + log::popNest(); + m_refreshingModCount -= 1; + return; + } + + for (auto const& dep : node->m_impl->m_dependants) { + m_modsToLoad.push_front(dep); + } + } + + m_refreshingModCount -= 1; + + log::popNest(); + }; + + if (early) { + auto res = unzipFunction(); if (!res) { m_problems.push_back({ - LoadProblem::Type::LoadFailed, + LoadProblem::Type::UnzipFailed, node, res.unwrapErr() }); - log::error("Failed to load binary: {}", res.unwrapErr()); + log::error("Failed to unzip: {}", res.unwrapErr()); log::popNest(); + m_refreshingModCount -= 1; return; } - - for (auto const& dep : node->m_impl->m_dependants) { - this->loadModGraph(dep, early); - } + loadFunction(); + } + else { + std::thread([=]() { + auto res = unzipFunction(); + queueInMainThread([=]() { + if (!res) { + m_problems.push_back({ + LoadProblem::Type::UnzipFailed, + node, + res.unwrapErr() + }); + log::error("Failed to unzip: {}", res.unwrapErr()); + log::popNest(); + m_refreshingModCount -= 1; + return; + } + loadFunction(); + }); + }).detach(); } - - log::popNest(); } void Loader::Impl::findProblems() { @@ -568,12 +618,19 @@ void Loader::Impl::refreshModGraph() { else m_loadingState = LoadingState::Mods; - queueInMainThread([]() { - Loader::get()->m_impl->continueRefreshModGraph(); + queueInMainThread([&]() { + this->continueRefreshModGraph(); }); } void Loader::Impl::continueRefreshModGraph() { + if (m_refreshingModCount != 0) { + queueInMainThread([&]() { + this->continueRefreshModGraph(); + }); + return; + } + log::info("Continuing mod graph refresh..."); log::pushNest(); @@ -585,7 +642,7 @@ void Loader::Impl::continueRefreshModGraph() { log::pushNest(); this->loadModGraph(m_modsToLoad.front(), false); log::popNest(); - m_modsToLoad.pop(); + m_modsToLoad.pop_front(); if (m_modsToLoad.empty()) m_loadingState = LoadingState::Problems; break; @@ -608,8 +665,8 @@ void Loader::Impl::continueRefreshModGraph() { log::info("Took {}s", static_cast(time) / 1000.f); if (m_loadingState != LoadingState::Done) { - queueInMainThread([]() { - Loader::get()->m_impl->continueRefreshModGraph(); + queueInMainThread([&]() { + this->continueRefreshModGraph(); }); } diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index ab6f4b1a0..af790a5eb 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -58,7 +58,7 @@ namespace geode { std::vector m_modSearchDirectories; std::vector m_problems; std::unordered_map m_mods; - std::queue m_modsToLoad; + std::deque m_modsToLoad; std::vector m_texturePaths; bool m_isSetup = false; @@ -83,6 +83,11 @@ namespace geode { std::mutex m_nextModAccessMutex; Mod* m_nextMod = nullptr; + Mod* m_currentlyLoadingMod = nullptr; + + int m_refreshingModCount = 0; + int m_refreshedModCount = 0; + void provideNextMod(Mod* mod); Mod* takeNextMod(); void releaseNextMod(); diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 393916cfe..d97c5b0f6 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -568,17 +568,21 @@ Result<> Mod::Impl::createTempDir() { return Err("Unable to create mod runtime directory"); } + // Mark temp dir creation as succesful + m_tempDirName = tempPath; + + return Ok(); +} + +Result<> Mod::Impl::unzipGeodeFile(ModMetadata metadata) { // Unzip .geode file into temp dir - GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(m_metadata.getPath())); - if (!unzip.hasEntry(m_metadata.getBinaryName())) { + GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(metadata.getPath())); + if (!unzip.hasEntry(metadata.getBinaryName())) { return Err( - fmt::format("Unable to find platform binary under the name \"{}\"", m_metadata.getBinaryName()) + fmt::format("Unable to find platform binary under the name \"{}\"", metadata.getBinaryName()) ); } - GEODE_UNWRAP(unzip.extractAllTo(tempPath)); - - // Mark temp dir creation as succesful - m_tempDirName = tempPath; + GEODE_UNWRAP(unzip.extractAllTo(dirs::getModRuntimeDir() / metadata.getID())); return Ok(); } diff --git a/loader/src/loader/ModImpl.hpp b/loader/src/loader/ModImpl.hpp index 55e5c88d0..598d3388e 100644 --- a/loader/src/loader/ModImpl.hpp +++ b/loader/src/loader/ModImpl.hpp @@ -75,6 +75,9 @@ namespace geode { Result<> unloadPlatformBinary(); Result<> createTempDir(); + // called on a separate thread + Result<> unzipGeodeFile(ModMetadata metadata); + void setupSettings(); std::string getID() const; diff --git a/loader/src/ui/internal/list/ProblemsListCell.cpp b/loader/src/ui/internal/list/ProblemsListCell.cpp index faa2086b6..fbca79442 100644 --- a/loader/src/ui/internal/list/ProblemsListCell.cpp +++ b/loader/src/ui/internal/list/ProblemsListCell.cpp @@ -87,6 +87,11 @@ bool ProblemsListCell::init(LoadProblem problem, ProblemsListPopup* list, CCSize icon = "info-alert.png"_spr; message = fmt::format("{} is incompatible with {}", cause, problem.message); break; + case LoadProblem::Type::UnzipFailed: + icon = "info-alert.png"_spr; + message = fmt::format("{} has failed unzipping", cause); + m_longMessage = problem.message; + break; } m_problem = std::move(problem); From 5c765c6798299d260ecf864d298a24ce15238203 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:15:20 +0300 Subject: [PATCH 080/135] Implement modified date check on geode files for unzip --- loader/src/loader/LoaderImpl.cpp | 21 +++++++++++++-------- loader/src/loader/LoaderImpl.hpp | 3 +++ loader/src/loader/ModImpl.cpp | 28 +++++++++++++++++++++++++++- 3 files changed, 43 insertions(+), 9 deletions(-) diff --git a/loader/src/loader/LoaderImpl.cpp b/loader/src/loader/LoaderImpl.cpp index 529e327c3..d652d5e71 100644 --- a/loader/src/loader/LoaderImpl.cpp +++ b/loader/src/loader/LoaderImpl.cpp @@ -41,9 +41,6 @@ void Loader::Impl::createDirectories() { ghc::filesystem::create_directory(dirs::getSaveDir()); #endif - // try deleting geode/unzipped if it already exists - try { ghc::filesystem::remove_all(dirs::getModRuntimeDir()); } catch(...) {} - (void) utils::file::createDirectoryAll(dirs::getGeodeResourcesDir()); (void) utils::file::createDirectoryAll(dirs::getModConfigDir()); (void) utils::file::createDirectoryAll(dirs::getModsDir()); @@ -411,6 +408,7 @@ void Loader::Impl::loadModGraph(Mod* node, bool early) { m_currentlyLoadingMod = node; m_refreshingModCount += 1; m_refreshedModCount += 1; + m_lateRefreshedModCount += early ? 0 : 1; auto unzipFunction = [this, node]() { log::debug("Unzip"); @@ -631,10 +629,16 @@ void Loader::Impl::continueRefreshModGraph() { return; } + if (m_lateRefreshedModCount > 0) { + auto end = std::chrono::high_resolution_clock::now(); + auto time = std::chrono::duration_cast(end - m_timerBegin).count(); + log::info("Took {}s", static_cast(time) / 1000.f); + } + log::info("Continuing mod graph refresh..."); log::pushNest(); - auto begin = std::chrono::high_resolution_clock::now(); + m_timerBegin = std::chrono::high_resolution_clock::now(); switch (m_loadingState) { case LoadingState::Mods: @@ -652,6 +656,11 @@ void Loader::Impl::continueRefreshModGraph() { this->findProblems(); log::popNest(); m_loadingState = LoadingState::Done; + { + auto end = std::chrono::high_resolution_clock::now(); + auto time = std::chrono::duration_cast(end - m_timerBegin).count(); + log::info("Took {}s", static_cast(time) / 1000.f); + } break; default: m_loadingState = LoadingState::Done; @@ -660,10 +669,6 @@ void Loader::Impl::continueRefreshModGraph() { break; } - auto end = std::chrono::high_resolution_clock::now(); - auto time = std::chrono::duration_cast(end - begin).count(); - log::info("Took {}s", static_cast(time) / 1000.f); - if (m_loadingState != LoadingState::Done) { queueInMainThread([&]() { this->continueRefreshModGraph(); diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index af790a5eb..e697edd2c 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -87,6 +87,9 @@ namespace geode { int m_refreshingModCount = 0; int m_refreshedModCount = 0; + int m_lateRefreshedModCount = 0; + + std::chrono::time_point m_timerBegin; void provideNextMod(Mod* mod); Mod* takeNextMod(); diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index d97c5b0f6..7075349fb 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -3,6 +3,7 @@ #include "ModMetadataImpl.hpp" #include "about.hpp" +#include #include #include #include @@ -576,13 +577,38 @@ Result<> Mod::Impl::createTempDir() { Result<> Mod::Impl::unzipGeodeFile(ModMetadata metadata) { // Unzip .geode file into temp dir + auto tempDir = dirs::getModRuntimeDir() / metadata.getID(); + + auto datePath = tempDir / "modified-at"; + std::string currentHash = file::readString(datePath).unwrapOr(""); + + auto modifiedDate = ghc::filesystem::last_write_time(metadata.getPath()); + auto modifiedCount = std::chrono::duration_cast(modifiedDate.time_since_epoch()); + auto modifiedHash = std::to_string(modifiedCount.count()); + if (currentHash == modifiedHash) { + log::debug("Same hash detected, skipping unzip"); + return Ok(); + } + log::debug("Hash mismatch detected, unzipping"); + + std::error_code ec; + ghc::filesystem::remove_all(tempDir, ec); + if (ec) { + return Err("Unable to delete temp dir: " + ec.message()); + } + + auto res = file::writeString(datePath, modifiedHash); + if (!res) { + log::warn("Failed to write modified date of geode zip"); + } + GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(metadata.getPath())); if (!unzip.hasEntry(metadata.getBinaryName())) { return Err( fmt::format("Unable to find platform binary under the name \"{}\"", metadata.getBinaryName()) ); } - GEODE_UNWRAP(unzip.extractAllTo(dirs::getModRuntimeDir() / metadata.getID())); + GEODE_UNWRAP(unzip.extractAllTo(tempDir)); return Ok(); } From 0ed1a41426bb5bead62af93e6eb76e7b41168954 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 14:37:02 +0300 Subject: [PATCH 081/135] Fix unzip modify date & add verifying text --- loader/src/hooks/LoadingLayer.cpp | 30 +++++++++++++++++------------- loader/src/loader/ModImpl.cpp | 6 ++++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/loader/src/hooks/LoadingLayer.cpp b/loader/src/hooks/LoadingLayer.cpp index c765def56..3cdf20e76 100644 --- a/loader/src/hooks/LoadingLayer.cpp +++ b/loader/src/hooks/LoadingLayer.cpp @@ -70,20 +70,24 @@ struct CustomLoadingLayer : Modify { } void setupLoaderResources() { + log::debug("Verifying Loader Resources"); + this->setSmallText("Verifying Loader Resources"); // verify loader resources - if (!LoaderImpl::get()->verifyLoaderResources()) { - log::debug("Downloading Loader Resources"); - this->setSmallText("Downloading Loader Resources"); - this->addChild(EventListenerNode::create( - this, &CustomLoadingLayer::updateResourcesProgress - )); - } - else { - log::debug("Loading Loader Resources"); - this->setSmallText("Loading Loader Resources"); - LoaderImpl::get()->updateSpecialFiles(); - this->continueLoadAssets(); - } + Loader::get()->queueInMainThread([&]() { + if (!LoaderImpl::get()->verifyLoaderResources()) { + log::debug("Downloading Loader Resources"); + this->setSmallText("Downloading Loader Resources"); + this->addChild(EventListenerNode::create( + this, &CustomLoadingLayer::updateResourcesProgress + )); + } + else { + log::debug("Loading Loader Resources"); + this->setSmallText("Loading Loader Resources"); + LoaderImpl::get()->updateSpecialFiles(); + this->continueLoadAssets(); + } + }); } void updateResourcesProgress(ResourceDownloadEvent* event) { diff --git a/loader/src/loader/ModImpl.cpp b/loader/src/loader/ModImpl.cpp index 7075349fb..adf335f58 100644 --- a/loader/src/loader/ModImpl.cpp +++ b/loader/src/loader/ModImpl.cpp @@ -596,11 +596,13 @@ Result<> Mod::Impl::unzipGeodeFile(ModMetadata metadata) { if (ec) { return Err("Unable to delete temp dir: " + ec.message()); } - + + (void)utils::file::createDirectoryAll(tempDir); auto res = file::writeString(datePath, modifiedHash); if (!res) { - log::warn("Failed to write modified date of geode zip"); + log::warn("Failed to write modified date of geode zip: {}", res.unwrapErr()); } + GEODE_UNWRAP_INTO(auto unzip, file::Unzip::create(metadata.getPath())); if (!unzip.hasEntry(metadata.getBinaryName())) { From 8dd2e15c383f7829a4e5db0a3c5a54b32dc2076f Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 16:50:10 +0300 Subject: [PATCH 082/135] fix dynamic cast --- loader/include/Geode/platform/ItaniumCast.hpp | 42 +++++++------------ loader/include/Geode/platform/android.hpp | 8 +--- loader/src/hooks/DynamicCastFix.cpp | 21 +++++----- 3 files changed, 28 insertions(+), 43 deletions(-) diff --git a/loader/include/Geode/platform/ItaniumCast.hpp b/loader/include/Geode/platform/ItaniumCast.hpp index 93cd024e1..8f90d1797 100644 --- a/loader/include/Geode/platform/ItaniumCast.hpp +++ b/loader/include/Geode/platform/ItaniumCast.hpp @@ -1,8 +1,6 @@ #pragma once namespace geode::cast { - using uinthalf_t = uint32_t; - using inthalf_t = int32_t; struct DummyClass { virtual ~DummyClass() {} @@ -14,8 +12,10 @@ namespace geode::cast { struct DummyMultipleClass : DummySingleClass, DummyClass2 {}; + struct VtableType; + struct ClassTypeinfoType { - void** m_typeinfoVtable; + VtableType* m_typeinfoVtable; char const* m_typeinfoName; }; @@ -23,16 +23,17 @@ namespace geode::cast { ClassTypeinfoType* m_baseClassTypeinfo; }; -#pragma pack(push, 1) - struct MultipleClassSingleEntryType { ClassTypeinfoType* m_baseClassTypeinfo; - uint8_t m_visibilityFlag; - inthalf_t m_offset; - uint8_t m_padding[sizeof(inthalf_t) - 1]; - }; + intptr_t m_metadata; -#pragma pack(pop) + uint8_t visibilityFlag() const { + return m_metadata & 0xFF; + } + intptr_t offset() const { + return m_metadata >> 8; + } + }; struct MultipleClassTypeinfoType : ClassTypeinfoType { uint32_t m_flags; @@ -41,7 +42,7 @@ namespace geode::cast { }; struct VtableTypeinfoType { - inthalf_t m_offset; + intptr_t m_offset; ClassTypeinfoType* m_typeinfo; }; @@ -51,36 +52,25 @@ namespace geode::cast { struct CompleteVtableType : VtableTypeinfoType, VtableType {}; - inline void** typeinfoVtableOf(void* ptr) { - auto vftable = *reinterpret_cast(ptr); - - auto typeinfoPtr = - static_cast(static_cast(vftable)); - - return typeinfoPtr->m_typeinfo->m_typeinfoVtable; - } - inline void* traverseTypeinfoFor( void* ptr, ClassTypeinfoType const* typeinfo, char const* afterIdent ) { - DummySingleClass dummySingleClass; - DummyMultipleClass dummyMultipleClass; - { auto optionIdent = typeinfo->m_typeinfoName; if (std::strcmp(optionIdent, afterIdent) == 0) { return ptr; } } - if (typeinfo->m_typeinfoVtable == typeinfoVtableOf(&dummySingleClass)) { + auto typeinfoVtableName = static_cast(typeinfo->m_typeinfoVtable)->m_typeinfo->m_typeinfoName; + if (std::strcmp(typeinfoVtableName, "N10__cxxabiv120__si_class_type_infoE") == 0) { auto siTypeinfo = static_cast(typeinfo); return traverseTypeinfoFor(ptr, siTypeinfo->m_baseClassTypeinfo, afterIdent); } - else if (typeinfo->m_typeinfoVtable == typeinfoVtableOf(&dummyMultipleClass)) { + else if (std::strcmp(typeinfoVtableName, "N10__cxxabiv121__vmi_class_type_infoE") == 0) { auto vmiTypeinfo = static_cast(typeinfo); for (int i = 0; i < vmiTypeinfo->m_numBaseClass; ++i) { auto& entry = vmiTypeinfo->m_baseClasses[i]; - auto optionPtr = reinterpret_cast(ptr) + entry.m_offset; + auto optionPtr = reinterpret_cast(ptr) + entry.offset(); auto ret = traverseTypeinfoFor(optionPtr, entry.m_baseClassTypeinfo, afterIdent); if (ret != nullptr) return ret; } diff --git a/loader/include/Geode/platform/android.hpp b/loader/include/Geode/platform/android.hpp index e19402bcf..31c7edeb9 100644 --- a/loader/include/Geode/platform/android.hpp +++ b/loader/include/Geode/platform/android.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include "ItaniumCast.hpp" namespace geode { struct PlatformInfo { @@ -12,10 +13,3 @@ namespace geode::base { /*GEODE_NOINLINE inline*/ uintptr_t get(); } -namespace geode::cast { - template - After typeinfo_cast(Before ptr) { - // yall have symbols smh - return dynamic_cast(ptr); - } -} diff --git a/loader/src/hooks/DynamicCastFix.cpp b/loader/src/hooks/DynamicCastFix.cpp index 3986eeae4..5a17e56fa 100644 --- a/loader/src/hooks/DynamicCastFix.cpp +++ b/loader/src/hooks/DynamicCastFix.cpp @@ -1,19 +1,20 @@ #include - -#ifdef GEODE_IS_MACOS +#include using namespace geode::prelude; - #include - #include - $execute { // this replaces the call to __dynamic_cast with a call to our own // this is needed because the transitions in cocos uses dynamic cast to check // layers, which fail on user layers due to typeinfo not matching - (void)Mod::get()->patch( - reinterpret_cast(base::get() + 0x603948), toByteArray(&cast::typeinfoCastInternal) - ); -} -#endif \ No newline at end of file + #if defined(GEODE_IS_MACOS) + (void)Mod::get()->patch( + reinterpret_cast(base::get() + 0x603948), toByteArray(&cast::typeinfoCastInternal) + ); + #elif defined(GEODE_IS_ANDROID) + (void)Mod::get()->addHook(reinterpret_cast(base::get() + 0x519a8c), &cast::typeinfoCastInternal, "__dynamic_cast"); + #endif + + +} \ No newline at end of file From d3235663ae6beef8269f76d1ece95f14bb0a843a Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 17:01:01 +0300 Subject: [PATCH 083/135] update tuliphook --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a6ce0923f..dfcd33fab 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -96,7 +96,7 @@ if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) set(TULIP_LINK_SOURCE ON) endif() set(CMAKE_WARN_DEPRECATED OFF CACHE BOOL "" FORCE) -CPMAddPackage("gh:geode-sdk/TulipHook#41a18a1") +CPMAddPackage("gh:geode-sdk/TulipHook#d2132de") set(CMAKE_WARN_DEPRECATED ON CACHE BOOL "" FORCE) # Silence warnings from dependencies From 03673606440a3e0f47fe9be615fc6a4a8ab8c888 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:03:58 +0300 Subject: [PATCH 084/135] Add text input node fix --- loader/src/hooks/TextInputNodeFix.cpp | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 loader/src/hooks/TextInputNodeFix.cpp diff --git a/loader/src/hooks/TextInputNodeFix.cpp b/loader/src/hooks/TextInputNodeFix.cpp new file mode 100644 index 000000000..73aa60518 --- /dev/null +++ b/loader/src/hooks/TextInputNodeFix.cpp @@ -0,0 +1,18 @@ +#include + +#ifdef GEODE_IS_ANDROID + +using namespace geode::prelude; + +struct TextNodeFix : Modify { + bool onTextFieldInsertText(cocos2d::CCTextFieldTTF* field, char const* text, int count) { + auto change = count >= this->m_maxLabelLength ? 1 : 0; + + this->m_maxLabelLength += change; + auto ret = CCTextInputNode::onTextFieldInsertText(field, text, count); + this->m_maxLabelLength -= change; + return ret; + } +}; + +#endif \ No newline at end of file From d194cbe3b7b6595db93ba278f7abce864c5b0a07 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 2 Oct 2023 19:05:27 +0300 Subject: [PATCH 085/135] remove this-> --- loader/src/hooks/TextInputNodeFix.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/loader/src/hooks/TextInputNodeFix.cpp b/loader/src/hooks/TextInputNodeFix.cpp index 73aa60518..185417614 100644 --- a/loader/src/hooks/TextInputNodeFix.cpp +++ b/loader/src/hooks/TextInputNodeFix.cpp @@ -6,11 +6,11 @@ using namespace geode::prelude; struct TextNodeFix : Modify { bool onTextFieldInsertText(cocos2d::CCTextFieldTTF* field, char const* text, int count) { - auto change = count >= this->m_maxLabelLength ? 1 : 0; + auto change = count >= m_maxLabelLength ? 1 : 0; - this->m_maxLabelLength += change; + m_maxLabelLength += change; auto ret = CCTextInputNode::onTextFieldInsertText(field, text, count); - this->m_maxLabelLength -= change; + m_maxLabelLength -= change; return ret; } }; From a985d5a8c564dc2a8d5a36577d3c33b8495dffe9 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 3 Oct 2023 17:51:12 +0300 Subject: [PATCH 086/135] implement utils except file utils but i tried ok --- loader/src/platform/android/main.cpp | 2 +- loader/src/platform/android/util.cpp | 77 ++++++++++++++++++++++++++-- loader/src/platform/mac/util.mm | 2 +- 3 files changed, 76 insertions(+), 5 deletions(-) diff --git a/loader/src/platform/android/main.cpp b/loader/src/platform/android/main.cpp index 471b162ed..f15001461 100644 --- a/loader/src/platform/android/main.cpp +++ b/loader/src/platform/android/main.cpp @@ -17,7 +17,7 @@ extern "C" [[gnu::visibility("default")]] jint JNI_OnLoad(JavaVM* vm, void* rese glDeleteVertexArraysOESEXT = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); geodeEntry(nullptr); - return JNI_VERSION_1_1; + return JNI_VERSION_1_6; } extern "C" [[gnu::visibility("default")]] void emptyFunction(void*) { diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 8da055a5c..dacc4a844 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -9,14 +9,41 @@ using namespace geode::prelude; #include #include +#include +#include + bool utils::clipboard::write(std::string const& data) { + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "writeClipboard", "(Ljava/lang/String;)V")) { + jstring stringArg1 = t.env->NewStringUTF(data.c_str()); + + t.env->CallStaticVoidMethod(t.classID, t.methodID, stringArg1); + + t.env->DeleteLocalRef(stringArg1); + t.env->DeleteLocalRef(t.classID); + return true; + } return false; } std::string utils::clipboard::read() { + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "readClipboard", "()Ljava/lang/String;")) { + jstring stringResult = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID); + + std::string result = JniHelper::jstring2string(stringResult); + + t.env->DeleteLocalRef(stringResult); + t.env->DeleteLocalRef(t.classID); + return result; + } return ""; } +CCPoint cocos::getMousePos() { + return CCPoint(0, 0); +} + ghc::filesystem::path dirs::getGameDir() { return ghc::filesystem::path( "/storage/emulated/0/Android/data/com.geode.launcher/files/game" @@ -44,7 +71,17 @@ void utils::web::openLinkInBrowser(std::string const& url) { CCApplication::sharedApplication()->openURL(url.c_str()); } -bool utils::file::openFolder(ghc::filesystem::path const&) { +bool utils::file::openFolder(ghc::filesystem::path const& path) { + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "openFolder", "(Ljava/lang/String;)Z")) { + jstring stringArg1 = t.env->NewStringUTF(path.string().c_str()); + + jboolean result = t.env->CallStaticBooleanMethod(t.classID, t.methodID, stringArg1); + + t.env->DeleteLocalRef(stringArg1); + t.env->DeleteLocalRef(t.classID); + return result; + } return false; } @@ -58,16 +95,50 @@ void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) { } void geode::utils::game::exit() { + if (CCApplication::sharedApplication() && + (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { + log::error("Cannot exit in PlayLayer or LevelEditorLayer!"); + return; + } + AppDelegate::get()->trySaveGame(); + // AppDelegate::get()->showLoadingCircle(false, true); + CCDirector::get()->getActionManager()->addAction(CCSequence::create( CCDelayTime::create(0.5f), CCCallFunc::create(nullptr, callfunc_selector(MenuLayer::endGame)), nullptr - ), CCDirector::get()->getRunningScene(), false);; + ), CCDirector::get()->getRunningScene(), false); } void geode::utils::game::restart() { + if (CCApplication::sharedApplication() && + (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { + log::error("Cannot restart in PlayLayer or LevelEditorLayer!"); + return; + } + + class Exit : public CCObject { + public: + void restart() { + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "restartGame", "()V")) { + t.env->CallStaticVoidMethod(t.classID, t.methodID); + + t.env->DeleteLocalRef(t.classID); + } + } + }; // Not implemented - log::error("Restarting the game is not implemented on android"); + // log::error("Restarting the game is not implemented on android"); + + AppDelegate::get()->trySaveGame(); + // AppDelegate::get()->showLoadingCircle(false, true); + + CCDirector::get()->getActionManager()->addAction(CCSequence::create( + CCDelayTime::create(0.5f), + CCCallFunc::create(nullptr, callfunc_selector(Exit::restart)), + nullptr + ), CCDirector::get()->getRunningScene(), false); } #endif diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm index 31111cfa5..e09712659 100644 --- a/loader/src/platform/mac/util.mm +++ b/loader/src/platform/mac/util.mm @@ -207,7 +207,7 @@ @implementation FileDialog void geode::utils::game::exit() { if (CCApplication::sharedApplication() && (GameManager::get()->m_playLayer || GameManager::get()->m_levelEditorLayer)) { - log::error("Cannot restart in PlayLayer or LevelEditorLayer!"); + log::error("Cannot exit in PlayLayer or LevelEditorLayer!"); return; } From 0e8865546c8ab96cbb182ce13b316df40fbfc72c Mon Sep 17 00:00:00 2001 From: SMJS <38814077+SMJSGaming@users.noreply.github.com> Date: Tue, 3 Oct 2023 22:28:15 +0200 Subject: [PATCH 087/135] Fixed alignment issues caused by unallocated memory and bad anchor points Simply put, alignment had no default assignment, causing undefined behavior, this also revealed some bad anchor points which could be optimized --- loader/src/ui/nodes/TextArea.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/loader/src/ui/nodes/TextArea.cpp b/loader/src/ui/nodes/TextArea.cpp index 4af0518b5..9dce696fa 100644 --- a/loader/src/ui/nodes/TextArea.cpp +++ b/loader/src/ui/nodes/TextArea.cpp @@ -30,6 +30,7 @@ SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text, m_maxLines = 0; m_scale = scale; m_linePadding = 0; + m_alignment = kCCTextAlignmentLeft; m_artificialWidth = artificialWidth; m_container = CCMenu::create(); @@ -129,7 +130,6 @@ CCLabelBMFont* SimpleTextArea::createLabel(const std::string& text, const float CCLabelBMFont* label = CCLabelBMFont::create(text.c_str(), m_font.c_str()); label->setScale(m_scale); - label->setAnchorPoint({ 0, 0 }); label->setPosition({ 0, top }); return label; @@ -203,26 +203,24 @@ void SimpleTextArea::updateContents() { m_container->setContentSize(this->getContentSize()); m_container->removeAllChildren(); - height -= m_lineHeight; - for (CCLabelBMFont* line : m_lines) { const float y = height + line->getPositionY(); switch (m_alignment) { case kCCTextAlignmentLeft: { - line->setAnchorPoint({ 0, 0 }); + line->setAnchorPoint({ 0, 1 }); line->setPosition({ 0, y }); } break; case kCCTextAlignmentCenter: { - line->setAnchorPoint({ 0.5f, 0 }); + line->setAnchorPoint({ 0.5f, 1 }); line->setPosition({ width / 2, y }); } break; case kCCTextAlignmentRight: { - line->setAnchorPoint({ 1, 0 }); + line->setAnchorPoint({ 1, 1 }); line->setPosition({ width, y }); } break; } m_container->addChild(line); } -} \ No newline at end of file +} From 36c461ace47e2939c1f37709ee4514cb0c08d5ba Mon Sep 17 00:00:00 2001 From: SMJS <38814077+SMJSGaming@users.noreply.github.com> Date: Tue, 3 Oct 2023 22:33:59 +0200 Subject: [PATCH 088/135] Fixed alignment issues caused by unallocated memory and bad anchor points (#282) --- loader/src/ui/nodes/TextArea.cpp | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/loader/src/ui/nodes/TextArea.cpp b/loader/src/ui/nodes/TextArea.cpp index 4af0518b5..9dce696fa 100644 --- a/loader/src/ui/nodes/TextArea.cpp +++ b/loader/src/ui/nodes/TextArea.cpp @@ -30,6 +30,7 @@ SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text, m_maxLines = 0; m_scale = scale; m_linePadding = 0; + m_alignment = kCCTextAlignmentLeft; m_artificialWidth = artificialWidth; m_container = CCMenu::create(); @@ -129,7 +130,6 @@ CCLabelBMFont* SimpleTextArea::createLabel(const std::string& text, const float CCLabelBMFont* label = CCLabelBMFont::create(text.c_str(), m_font.c_str()); label->setScale(m_scale); - label->setAnchorPoint({ 0, 0 }); label->setPosition({ 0, top }); return label; @@ -203,26 +203,24 @@ void SimpleTextArea::updateContents() { m_container->setContentSize(this->getContentSize()); m_container->removeAllChildren(); - height -= m_lineHeight; - for (CCLabelBMFont* line : m_lines) { const float y = height + line->getPositionY(); switch (m_alignment) { case kCCTextAlignmentLeft: { - line->setAnchorPoint({ 0, 0 }); + line->setAnchorPoint({ 0, 1 }); line->setPosition({ 0, y }); } break; case kCCTextAlignmentCenter: { - line->setAnchorPoint({ 0.5f, 0 }); + line->setAnchorPoint({ 0.5f, 1 }); line->setPosition({ width / 2, y }); } break; case kCCTextAlignmentRight: { - line->setAnchorPoint({ 1, 0 }); + line->setAnchorPoint({ 1, 1 }); line->setPosition({ width, y }); } break; } m_container->addChild(line); } -} \ No newline at end of file +} From f563c4678e2a278b67ae059f30f2c13e77b0d9dd Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:50:16 +0300 Subject: [PATCH 089/135] Only hash markdown files --- cmake/GeodeFile.cmake | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index f44b7d263..8f1a8ddd7 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -294,9 +294,10 @@ function(package_geode_resources_now proname src dest header_dest) # "LOADER_RESOURCE_FILES {\n" ) - list(APPEND HASHED_EXTENSIONS ".png") - list(APPEND HASHED_EXTENSIONS ".mp3") - list(APPEND HASHED_EXTENSIONS ".ogg") + # yeah don't think we need to check too many stuff + # list(APPEND HASHED_EXTENSIONS ".png") + # list(APPEND HASHED_EXTENSIONS ".mp3") + # list(APPEND HASHED_EXTENSIONS ".ogg") list(APPEND HASHED_EXTENSIONS ".md") foreach(file ${RESOURCE_FILES}) From 66e36b3a389700bb953534f916ae89fa728f7689 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:09:42 +0300 Subject: [PATCH 090/135] this handler sometimes doesnt work --- .../platform/android/backtrace/ScopedFd.hpp | 55 +++ .../platform/android/backtrace/execinfo.hpp | 191 +++++++++ loader/src/platform/android/crashlog.cpp | 376 +++++++++++++++++- 3 files changed, 618 insertions(+), 4 deletions(-) create mode 100644 loader/src/platform/android/backtrace/ScopedFd.hpp create mode 100644 loader/src/platform/android/backtrace/execinfo.hpp diff --git a/loader/src/platform/android/backtrace/ScopedFd.hpp b/loader/src/platform/android/backtrace/ScopedFd.hpp new file mode 100644 index 000000000..701d7ebc6 --- /dev/null +++ b/loader/src/platform/android/backtrace/ScopedFd.hpp @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2019 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#pragma once + +#include + +class ScopedFd final { + public: + explicit ScopedFd(int fd) : fd_(fd) { + } + + ScopedFd() : fd_(-1) { + } + + ~ScopedFd() { + reset(-1); + } + + void reset(int fd = -1) { + fd_ = fd; + } + + int get() const { + return fd_; + } + + private: + int fd_; +}; diff --git a/loader/src/platform/android/backtrace/execinfo.hpp b/loader/src/platform/android/backtrace/execinfo.hpp new file mode 100644 index 000000000..893cac934 --- /dev/null +++ b/loader/src/platform/android/backtrace/execinfo.hpp @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2012 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ScopedFd.hpp" + +struct StackState { + void** frames; + int frame_count; + int cur_frame = 0; + + StackState(void** frames, int frame_count) : frames(frames), frame_count(frame_count) {} +}; + +static _Unwind_Reason_Code TraceFunction(_Unwind_Context* context, void* arg) { + // The instruction pointer is pointing at the instruction after the return + // call on all architectures. + // Modify the pc to point at the real function. + uintptr_t ip = _Unwind_GetIP(context); + if (ip != 0) { +#if defined(__arm__) + // If the ip is suspiciously low, do nothing to avoid a segfault trying + // to access this memory. + if (ip >= 4096) { + // Check bits [15:11] of the first halfword assuming the instruction + // is 32 bits long. If the bits are any of these values, then our + // assumption was correct: + // b11101 + // b11110 + // b11111 + // Otherwise, this is a 16 bit instruction. + uint16_t value = (*reinterpret_cast(ip - 2)) >> 11; + if (value == 0x1f || value == 0x1e || value == 0x1d) { + ip -= 4; + } else { + ip -= 2; + } + } +#elif defined(__aarch64__) + // All instructions are 4 bytes long, skip back one instruction. + ip -= 4; +#elif defined(__i386__) || defined(__x86_64__) + // It's difficult to decode exactly where the previous instruction is, + // so subtract 1 to estimate where the instruction lives. + ip--; +#endif + } + + StackState* state = static_cast(arg); + state->frames[state->cur_frame++] = reinterpret_cast(ip); + return (state->cur_frame >= state->frame_count) ? _URC_END_OF_STACK : _URC_NO_REASON; +} + +int backtrace(void** buffer, int size) { + if (size <= 0) { + return 0; + } + + StackState state(buffer, size); + _Unwind_Backtrace(TraceFunction, &state); + return state.cur_frame; +} + +void backtrace_symbols_fd(void* const* buffer, int size, int fd); + +char** backtrace_symbols(void* const* buffer, int size) { + if (size <= 0) { + return nullptr; + } + // Do this calculation first in case the user passes in a bad value. + size_t ptr_size; + if (__builtin_mul_overflow(sizeof(char*), size, &ptr_size)) { + return nullptr; + } + ScopedFd fd(syscall(SYS_memfd_create, "backtrace_symbols_fd", MFD_CLOEXEC)); + // ScopedFd fd(memfd_create("backtrace_symbols_fd", MFD_CLOEXEC)); + if (fd.get() == -1) { + return nullptr; + } + backtrace_symbols_fd(buffer, size, fd.get()); + + // Get the size of the file. + off_t file_size = lseek(fd.get(), 0, SEEK_END); + if (file_size <= 0) { + return nullptr; + } + + // The interface for backtrace_symbols indicates that only the single + // returned pointer must be freed by the caller. Therefore, allocate a + // buffer that includes the memory for the strings and all of the pointers. + // Add one byte at the end just in case the file didn't end with a '\n'. + size_t symbol_data_size; + if (__builtin_add_overflow(ptr_size, file_size, &symbol_data_size) || + __builtin_add_overflow(symbol_data_size, 1, &symbol_data_size)) { + return nullptr; + } + + uint8_t* symbol_data = reinterpret_cast(malloc(symbol_data_size)); + if (symbol_data == nullptr) { + return nullptr; + } + + // Copy the string data into the buffer. + char* cur_string = reinterpret_cast(&symbol_data[ptr_size]); + // If this fails, the read won't read back the correct number of bytes. + lseek(fd.get(), 0, SEEK_SET); + ssize_t num_read = read(fd.get(), cur_string, file_size); + fd.reset(-1); + if (num_read != file_size) { + free(symbol_data); + return nullptr; + } + + // Make sure the last character in the file is '\n'. + if (cur_string[file_size] != '\n') { + cur_string[file_size++] = '\n'; + } + + for (int i = 0; i < size; i++) { + (reinterpret_cast(symbol_data))[i] = cur_string; + cur_string = strchr(cur_string, '\n'); + if (cur_string == nullptr) { + free(symbol_data); + return nullptr; + } + cur_string[0] = '\0'; + cur_string++; + } + return reinterpret_cast(symbol_data); +} + +// This function should do no allocations if possible. +void backtrace_symbols_fd(void* const* buffer, int size, int fd) { + if (size <= 0 || fd < 0) { + return; + } + + for (int frame_num = 0; frame_num < size; frame_num++) { + void* address = buffer[frame_num]; + Dl_info info; + if (dladdr(address, &info) != 0) { + if (info.dli_fname != nullptr) { + write(fd, info.dli_fname, strlen(info.dli_fname)); + } + if (info.dli_sname != nullptr) { + dprintf(fd, "(%s+0x%" PRIxPTR ") ", info.dli_sname, + reinterpret_cast(address) - reinterpret_cast(info.dli_saddr)); + } else { + dprintf(fd, "(+%p) ", info.dli_saddr); + } + } + + dprintf(fd, "[%p]\n", address); + } +} diff --git a/loader/src/platform/android/crashlog.cpp b/loader/src/platform/android/crashlog.cpp index 2f83c5cfa..6f1812e82 100644 --- a/loader/src/platform/android/crashlog.cpp +++ b/loader/src/platform/android/crashlog.cpp @@ -2,16 +2,384 @@ #ifdef GEODE_IS_ANDROID -ghc::filesystem::path crashlog::getCrashLogDirectory() { - return geode::dirs::getSaveDir(); +using namespace geode::prelude; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "backtrace/execinfo.hpp" + +static constexpr size_t FRAME_SIZE = 64; +static std::mutex s_mutex; +static std::condition_variable s_cv; +static int s_signal = 0; +static siginfo_t* s_siginfo = nullptr; +static ucontext_t* s_context = nullptr; +static size_t s_backtraceSize = 0; +static std::array s_backtrace; + +static std::string_view getSignalCodeString() { + switch(s_signal) { + case SIGSEGV: return "SIGSEGV: Segmentation Fault"; + case SIGINT: return "SIGINT: Interactive attention signal, (usually ctrl+c)"; + case SIGFPE: + switch(s_siginfo->si_code) { + case FPE_INTDIV: return "SIGFPE: (integer divide by zero)"; + case FPE_INTOVF: return "SIGFPE: (integer overflow)"; + case FPE_FLTDIV: return "SIGFPE: (floating-point divide by zero)"; + case FPE_FLTOVF: return "SIGFPE: (floating-point overflow)"; + case FPE_FLTUND: return "SIGFPE: (floating-point underflow)"; + case FPE_FLTRES: return "SIGFPE: (floating-point inexact result)"; + case FPE_FLTINV: return "SIGFPE: (floating-point invalid operation)"; + case FPE_FLTSUB: return "SIGFPE: (subscript out of range)"; + default: return "SIGFPE: Arithmetic Exception"; + } + case SIGILL: + switch(s_siginfo->si_code) { + case ILL_ILLOPC: return "SIGILL: (illegal opcode)"; + case ILL_ILLOPN: return "SIGILL: (illegal operand)"; + case ILL_ILLADR: return "SIGILL: (illegal addressing mode)"; + case ILL_ILLTRP: return "SIGILL: (illegal trap)"; + case ILL_PRVOPC: return "SIGILL: (privileged opcode)"; + case ILL_PRVREG: return "SIGILL: (privileged register)"; + case ILL_COPROC: return "SIGILL: (coprocessor error)"; + case ILL_BADSTK: return "SIGILL: (internal stack error)"; + default: return "SIGILL: Illegal Instruction"; + } + case SIGTERM: return "SIGTERM: a termination request was sent to the program"; + case SIGABRT: return "SIGABRT: usually caused by an abort() or assert()"; + case SIGBUS: return "SIGBUS: Bus error (bad memory access)"; + default: return "Unknown signal code"; + } +} + +static std::string getImageName(Elf32_Phdr const* image) { + if (image == nullptr) { + return ""; + } + std::string imageName;// = image->imageFilePath; + if (imageName.empty()) { + imageName = ""; + } + return imageName; +} + +// static std::vector getAllImages() { +// std::vector images; +// struct task_dyld_info dyldInfo; +// mach_msg_type_number_t count = TASK_DYLD_INFO_COUNT; +// if (task_info(mach_task_self(), TASK_DYLD_INFO, (task_info_t)&dyldInfo, &count) == KERN_SUCCESS) { +// struct dyld_all_image_infos* imageInfos = (struct dyld_all_image_infos*)dyldInfo.all_image_info_addr; + +// for (size_t i = 0; i < imageInfos->infoArrayCount; ++i) { +// images.push_back(&imageInfos->infoArray[i]); +// } +// } + +// return images; +// } + +static Elf32_Phdr const* imageFromAddress(void const* addr) { + if (addr == nullptr) { + return nullptr; + } + + // auto loadedImages = getAllImages(); + // std::sort(loadedImages.begin(), loadedImages.end(), [](auto const a, auto const b) { + // return (uintptr_t)a->imageLoadAddress < (uintptr_t)b->imageLoadAddress; + // }); + // auto iter = std::upper_bound(loadedImages.begin(), loadedImages.end(), addr, [](auto const addr, auto const image) { + // return (uintptr_t)addr < (uintptr_t)image->imageLoadAddress; + // }); + + // if (iter == loadedImages.begin()) { + // return nullptr; + // } + // --iter; + + // auto image = *iter; + // // auto imageSize = getImageSize((struct mach_header_64 const*)image->imageLoadAddress); + // auto imageAddress = (uintptr_t)image->imageLoadAddress; + // if ((uintptr_t)addr >= imageAddress/* && (uintptr_t)addr < imageAddress + imageSize*/) { + // return image; + // } + return nullptr; +} + +static Mod* modFromAddress(void const* addr) { + if (addr == nullptr) { + return nullptr; + } + // auto image = imageFromAddress(addr); + // if (image == nullptr) { + // return nullptr; + // } + + // ghc::filesystem::path imagePath = getImageName(image); + // if (!ghc::filesystem::exists(imagePath)) { + // return nullptr; + // } + // auto geodePath = dirs::getGameDir() / "Frameworks" / "Geode.dylib"; + // if (ghc::filesystem::equivalent(imagePath, geodePath)) { + // return Mod::get(); + // } + + // for (auto& mod : Loader::get()->getAllMods()) { + // if (!mod->isEnabled() || !ghc::filesystem::exists(mod->getBinaryPath())) { + // continue; + // } + // if (ghc::filesystem::equivalent(imagePath, mod->getBinaryPath())) { + // return mod; + // } + // } + return nullptr; +} + +static std::string getInfo(void* address, Mod* faultyMod) { + std::stringstream stream; + stream << "Faulty Lib: " << getImageName(imageFromAddress(address)) << "\n"; + stream << "Faulty Mod: " << (faultyMod ? faultyMod->getID() : "") << "\n"; + stream << "Instruction Address: " << address << "\n"; + stream << "Signal Code: " << std::hex << s_signal << " (" << getSignalCodeString() << ")" << std::dec << "\n"; + return stream.str(); +} + +static struct sigaction oldActionSEGV; +static struct sigaction oldActionBUS; +static struct sigaction oldActionILL; + +extern "C" void signalHandler(int signal, siginfo_t* signalInfo, void* vcontext) { + auto context = reinterpret_cast(vcontext); + s_backtraceSize = 0; + // s_backtraceSize = backtrace(s_backtrace.data(), FRAME_SIZE); + + // for some reason this is needed, dont ask me why + // s_backtrace[1] = reinterpret_cast(context->uc_mcontext.fault_address); + // if (s_backtraceSize < FRAME_SIZE) { + // s_backtrace[s_backtraceSize] = nullptr; + // } + + { + std::unique_lock lock(s_mutex); + s_signal = signal; + s_siginfo = signalInfo; + s_context = context; + } + + s_cv.notify_all(); + std::unique_lock lock(s_mutex); + s_cv.wait(lock, [] { return s_signal == 0; }); + // std::_Exit(EXIT_FAILURE); + + switch (signal) { + case SIGSEGV: + sigaction(signal, &oldActionSEGV, nullptr); + oldActionSEGV.sa_sigaction(signal, signalInfo, vcontext); + break; + case SIGBUS: + sigaction(signal, &oldActionBUS, nullptr); + oldActionBUS.sa_sigaction(signal, signalInfo, vcontext); + break; + case SIGILL: + sigaction(signal, &oldActionILL, nullptr); + oldActionILL.sa_sigaction(signal, signalInfo, vcontext); + break; + } } +static std::string getStacktrace() { + std::stringstream stacktrace; + + if (s_backtraceSize == 0) { + return stacktrace.str(); + } + + auto messages = backtrace_symbols(s_backtrace.data(), s_backtraceSize); + if (s_backtraceSize < FRAME_SIZE) { + messages[s_backtraceSize] = nullptr; + } + + + for (int i = 1; i < s_backtraceSize; ++i) { + auto message = std::string(messages[i]); + + // TODO: parse the message + stacktrace << message << "\n"; + + + // auto stream = std::stringstream(message); + // int index; + // std::string binary; + // uintptr_t address; + // std::string function; + // uintptr_t offset; + // std::string line; + + // stream >> index; + + // if (!lines.eof()) { + // std::getline(lines, line); + // } + // std::getline(stream, binary); + // auto cutoff = binary.find("0x"); + // stream = std::stringstream(binary.substr(cutoff)); + // binary = geode::utils::string::trim(binary.substr(0, cutoff)); + // stream >> std::hex >> address >> std::dec; + + // if (!line.empty()) { + // // log::debug("address: {}", address); + // auto image = imageFromAddress(reinterpret_cast(address)); + // // log::debug("image: {}", image); + // stacktrace << " - " << std::showbase << std::hex; + + // if (image) { + // auto baseAddress = image->imageLoadAddress; + // auto imageName = getImageName(image); + // stacktrace << imageName << " + " << (address - (uintptr_t)baseAddress); + // } + // else { + // stacktrace << address; + // } + // stacktrace << std::dec; + // stacktrace << ": " << line << "\n"; + // } + // else { + // std::getline(stream, function); + // cutoff = function.find("+"); + // stream = std::stringstream(function.substr(cutoff)); + // stream >> offset; + // function = geode::utils::string::trim(function.substr(0, cutoff)); + + // { + // int status; + // auto demangle = abi::__cxa_demangle(function.c_str(), 0, 0, &status); + // if (status == 0) { + // function = demangle; + // } + // free(demangle); + // } + + // stacktrace << "- " << binary; + // stacktrace << " @ " << std::showbase << std::hex << address << std::dec; + // stacktrace << " (" << function << " + " << offset << ")\n"; + // } + } + + free(messages); + + return stacktrace.str(); +} + +static std::string getRegisters() { + std::stringstream registers; + + auto context = s_context; + auto& ctx = context->uc_mcontext; + + // geez + registers << std::showbase << std::hex /*<< std::setfill('0') << std::setw(16) */; + registers << "r0: " << ctx.arm_r0 << "\n"; + registers << "r1: " << ctx.arm_r1 << "\n"; + registers << "r2: " << ctx.arm_r2 << "\n"; + registers << "r3: " << ctx.arm_r3 << "\n"; + registers << "r4: " << ctx.arm_r4 << "\n"; + registers << "r5: " << ctx.arm_r5 << "\n"; + registers << "r6: " << ctx.arm_r6 << "\n"; + registers << "r7: " << ctx.arm_r7 << "\n"; + registers << "r8: " << ctx.arm_r8 << "\n"; + registers << "r9: " << ctx.arm_r9 << "\n"; + registers << "r10: " << ctx.arm_r10 << "\n"; + registers << "r11: " << ctx.arm_fp << "\n"; + registers << "r12: " << ctx.arm_ip << "\n"; + registers << "sp: " << ctx.arm_sp << "\n"; + registers << "lr: " << ctx.arm_lr << "\n"; + registers << "pc: " << ctx.arm_pc << "\n"; + registers << "cpsr: " << ctx.arm_cpsr << "\n"; + + return registers.str(); +} + +static void handlerThread() { + std::unique_lock lock(s_mutex); + s_cv.wait(lock, [] { return s_signal != 0; }); + + auto signalAddress = reinterpret_cast(s_context->uc_mcontext.fault_address); + // Mod* faultyMod = nullptr; + // for (int i = 1; i < s_backtraceSize; ++i) { + // auto mod = modFromAddress(s_backtrace[i]); + // if (mod != nullptr) { + // faultyMod = mod; + // break; + // } + // } + Mod* faultyMod = modFromAddress(signalAddress); + + auto text = crashlog::writeCrashlog(faultyMod, getInfo(signalAddress, faultyMod), getStacktrace(), getRegisters()); + + log::error("Geode crashed!\n{}", text); + + s_signal = 0; + s_cv.notify_all(); + + log::debug("Notified"); +} + +static bool s_lastLaunchCrashed; + bool crashlog::setupPlatformHandler() { - return false; + struct sigaction action; + action.sa_sigaction = &signalHandler; + action.sa_flags = SA_SIGINFO; + sigemptyset(&action.sa_mask); + sigaction(SIGSEGV, &action, &oldActionSEGV); + // I'd rather not track interrupt lol + // sigaction(SIGINT, &action, nullptr); + // sigaction(SIGFPE, &action, nullptr); + sigaction(SIGILL, &action, &oldActionILL); + // sigaction(SIGTERM, &action, nullptr); + // sigaction(SIGABRT, &action, nullptr); + sigaction(SIGBUS, &action, &oldActionBUS); + + std::thread(&handlerThread).detach(); + + auto lastCrashedFile = crashlog::getCrashLogDirectory() / "last-crashed"; + if (ghc::filesystem::exists(lastCrashedFile)) { + s_lastLaunchCrashed = true; + try { + ghc::filesystem::remove(lastCrashedFile); + } + catch (...) { + } + } + return true; } bool crashlog::didLastLaunchCrash() { - return false; + return s_lastLaunchCrashed; +} + +ghc::filesystem::path crashlog::getCrashLogDirectory() { + return dirs::getGeodeDir() / "crashlogs"; } +// ghc::filesystem::path crashlog::getCrashLogDirectory() { +// return geode::dirs::getSaveDir(); +// } + +// bool crashlog::setupPlatformHandler() { +// return false; +// } + +// bool crashlog::didLastLaunchCrash() { +// return false; +// } + #endif From 35c018e66145289ced0fea6534de10701c452beb Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Thu, 5 Oct 2023 17:02:59 +0300 Subject: [PATCH 091/135] even more broken --- loader/src/platform/android/crashlog.cpp | 145 ++++++++++++++++++++--- 1 file changed, 126 insertions(+), 19 deletions(-) diff --git a/loader/src/platform/android/crashlog.cpp b/loader/src/platform/android/crashlog.cpp index 6f1812e82..8c4f4f82f 100644 --- a/loader/src/platform/android/crashlog.cpp +++ b/loader/src/platform/android/crashlog.cpp @@ -335,28 +335,135 @@ static void handlerThread() { static bool s_lastLaunchCrashed; bool crashlog::setupPlatformHandler() { - struct sigaction action; - action.sa_sigaction = &signalHandler; - action.sa_flags = SA_SIGINFO; - sigemptyset(&action.sa_mask); - sigaction(SIGSEGV, &action, &oldActionSEGV); - // I'd rather not track interrupt lol - // sigaction(SIGINT, &action, nullptr); - // sigaction(SIGFPE, &action, nullptr); - sigaction(SIGILL, &action, &oldActionILL); - // sigaction(SIGTERM, &action, nullptr); - // sigaction(SIGABRT, &action, nullptr); - sigaction(SIGBUS, &action, &oldActionBUS); - - std::thread(&handlerThread).detach(); + auto pidFile = crashlog::getCrashLogDirectory() / "last-pid"; + + int lastPid = 0; + + if (ghc::filesystem::exists(pidFile)) { + + auto res = file::readString(pidFile); + if (!res) { + log::warn("Failed to read last-pid file: {}", res.error()); + } + else { + lastPid = std::stoi(res.unwrap()); + } + + std::error_code ec; + ghc::filesystem::remove(pidFile, ec); + + if (ec) { + log::warn("Failed to remove last-pid file: {}", ec.message()); + } + } + + auto res = file::writeString(pidFile, std::to_string(getpid())); + if (!res) { + log::warn("Failed to write last-pid file: {}", res.error()); + } + + lastPid = 1513; + + + if (lastPid == 0) { + return true; + } + + // TODO: get logcat crash + + std::string logcatCrash = R"RAW( +F/libc (31506): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xccb00000 in tid 31584 (GLThread 215445), pid 31506 (.geode.launcher) +F/DEBUG (31618): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** +F/DEBUG (31618): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' +F/DEBUG (31618): Revision: '7' +F/DEBUG (31618): ABI: 'arm' +F/DEBUG (31618): pid: 31506, tid: 31584, name: GLThread 215445 >>> com.geode.launcher <<< +F/DEBUG (31618): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xccb00000 +F/DEBUG (31618): r0 ccafffe0 r1 ccafffe4 r2 ffefb73c r3 00000000 +F/DEBUG (31618): r4 00000000 r5 c7e4af50 r6 c7e49400 r7 3c888889 +F/DEBUG (31618): r8 c2dcf000 r9 cf8a7000 r10 cd1c6800 r11 cf8a7000 +F/DEBUG (31618): ip eff2b5f0 sp cd1c6680 lr c921095d pc efe9ef2c +F/DEBUG (31618): +F/DEBUG (31618): backtrace: +F/DEBUG (31618): #00 pc 00019f2c /system/lib/libc.so (memcpy+96) +F/DEBUG (31618): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) +F/DEBUG (31618): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) +F/DEBUG (31618): #03 pc 00000617 +F/libc ( 836): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xcd680000 in tid 901 (GLThread 215582), pid 836 (.geode.launcher) +F/DEBUG ( 933): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** +F/DEBUG ( 933): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' +F/DEBUG ( 933): Revision: '7' +F/DEBUG ( 933): ABI: 'arm' +F/DEBUG ( 933): pid: 836, tid: 901, name: GLThread 215582 >>> com.geode.launcher <<< +F/DEBUG ( 933): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xcd680000 +F/DEBUG ( 933): r0 cd67ffd0 r1 cd67fff4 r2 ffe935fc r3 00000000 +F/DEBUG ( 933): r4 00000000 r5 cc6fa350 r6 cc6f8800 r7 3c888889 +F/DEBUG ( 933): r8 c2990300 r9 ed1e0600 r10 caec3800 r11 ed1e0600 +F/DEBUG ( 933): ip eff2b5f0 sp caec3680 lr c94fe95d pc efe9ef30 +F/DEBUG ( 933): +F/DEBUG ( 933): backtrace: +F/DEBUG ( 933): #00 pc 00019f30 /system/lib/libc.so (memcpy+100) +F/DEBUG ( 933): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) +F/DEBUG ( 933): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) +F/DEBUG ( 933): #03 pc 00000617 +F/libc ( 1071): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc9c00000 in tid 1228 (GLThread 215607), pid 1071 (.geode.launcher) +F/DEBUG ( 1377): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** +F/DEBUG ( 1377): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' +F/DEBUG ( 1377): Revision: '7' +F/DEBUG ( 1377): ABI: 'arm' +F/DEBUG ( 1377): pid: 1071, tid: 1228, name: GLThread 215607 >>> com.geode.launcher <<< +F/DEBUG ( 1377): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc9c00000 +F/DEBUG ( 1377): r0 c9bfffe0 r1 c9bfffe4 r2 ffb862fc r3 00000000 +F/DEBUG ( 1377): r4 00000000 r5 c1bf2b50 r6 c1bf1000 r7 3c888889 +F/DEBUG ( 1377): r8 c7d34200 r9 ed1e6e00 r10 cd0d2800 r11 ed1e6e00 +F/DEBUG ( 1377): ip eff2b5f0 sp cd0d2680 lr c900c95d pc efe9ef2c +F/DEBUG ( 1377): +F/DEBUG ( 1377): backtrace: +F/DEBUG ( 1377): #00 pc 00019f2c /system/lib/libc.so (memcpy+96) +F/DEBUG ( 1377): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) +F/DEBUG ( 1377): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) +F/DEBUG ( 1377): #03 pc 00000617 +F/libc ( 1513): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc8500000 in tid 1658 (GLThread 215649), pid 1513 (.geode.launcher) +F/DEBUG ( 1752): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** +F/DEBUG ( 1752): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' +F/DEBUG ( 1752): Revision: '7' +F/DEBUG ( 1752): ABI: 'arm' +F/DEBUG ( 1752): pid: 1513, tid: 1658, name: GLThread 215649 >>> com.geode.launcher <<< +F/DEBUG ( 1752): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc8500000 +F/DEBUG ( 1752): r0 c84fffc0 r1 c84fffe4 r2 ffb13634 r3 00000008 +F/DEBUG ( 1752): r4 00000000 r5 c83e0750 r6 c83dec00 r7 3c888889 +F/DEBUG ( 1752): r8 e41cad00 r9 ed9fbc00 r10 cd38f800 r11 ed9fbc00 +F/DEBUG ( 1752): ip 00000000 sp cd38f680 lr c951195d pc efe9ef30 +F/DEBUG ( 1752): +F/DEBUG ( 1752): backtrace: +F/DEBUG ( 1752): #00 pc 00019f30 /system/lib/libc.so (memcpy+100) +F/DEBUG ( 1752): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) +F/DEBUG ( 1752): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) +F/DEBUG ( 1752): #03 pc 00000617 + )RAW"; + + std::string crashTrace; + auto findLast = logcatCrash.find_last_of(fmt::format("pid {} (.geode.launcher)", lastPid)); + if (findLast != std::string::npos) { + auto begin = logcatCrash.substr(0, findLast).find_last_of("F/libc"); + if (begin != std::string::npos) { + crashTrace = logcatCrash.substr(begin); + } + } + else { + return true; + } + + auto text = crashlog::writeCrashlog(nullptr, "", crashTrace, ""); + s_lastLaunchCrashed = true; auto lastCrashedFile = crashlog::getCrashLogDirectory() / "last-crashed"; if (ghc::filesystem::exists(lastCrashedFile)) { - s_lastLaunchCrashed = true; - try { - ghc::filesystem::remove(lastCrashedFile); - } - catch (...) { + std::error_code ec; + ghc::filesystem::remove(lastCrashedFile, ec); + + if (ec) { + log::warn("Failed to remove last-crashed file: {}", ec.message()); } } return true; From f57601d0b5c955d9182c6c3077d62c52f1979a6d Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 8 Oct 2023 16:38:17 +0300 Subject: [PATCH 092/135] file picker --- CMakeLists.txt | 2 +- cmake/GeodeFile.cmake | 3 + loader/include/Geode/utils/file.hpp | 15 ++ loader/src/platform/android/crashlog.cpp | 201 ++++++------------ loader/src/platform/android/util.cpp | 115 +++++++++- .../ui/internal/settings/GeodeSettingNode.cpp | 11 +- 6 files changed, 203 insertions(+), 144 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index dfcd33fab..1244fb93f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -71,8 +71,8 @@ set(GEODE_BIN_PATH ${CMAKE_CURRENT_SOURCE_DIR}/bin) set(GEODE_LOADER_PATH ${CMAKE_CURRENT_SOURCE_DIR}/loader) set(GEODE_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) -include(cmake/GeodeFile.cmake) include(cmake/Platform.cmake) +include(cmake/GeodeFile.cmake) include(cmake/CPM.cmake) if (PROJECT_IS_TOP_LEVEL AND NOT GEODE_BUILDING_DOCS) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index 8f1a8ddd7..4c3fe779d 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -188,6 +188,9 @@ function(setup_geode_mod proname) elseif (APPLE) file(GLOB libs ${dir}/*.dylib) list(APPEND libs_to_link ${libs}) + elseif (ANDROID) + file(GLOB libs ${dir}/*.so) + list(APPEND libs_to_link ${libs}) else() message(FATAL_ERROR "Library extension not defined on this platform") endif() diff --git a/loader/include/Geode/utils/file.hpp b/loader/include/Geode/utils/file.hpp index 9e932c570..495d2d50d 100644 --- a/loader/include/Geode/utils/file.hpp +++ b/loader/include/Geode/utils/file.hpp @@ -244,16 +244,31 @@ namespace geode::utils::file { /** * Prompt the user to pick a file using the system's file system picker + * @note Will not work on Android, use the callback version instead * @param mode Type of file selection prompt to show * @param options Picker options */ GEODE_DLL Result pickFile(PickMode mode, FilePickOptions const& options); + + GEODE_DLL void pickFile( + PickMode mode, FilePickOptions const& options, + utils::MiniFunction callback, + utils::MiniFunction failed = {} + ); + /** * Prompt the user to pick a bunch of files for opening using the system's file system picker + * @note Will not work on Android, use the callback version instead * @param options Picker options */ GEODE_DLL Result> pickFiles(FilePickOptions const& options); + GEODE_DLL void pickFiles( + FilePickOptions const& options, + utils::MiniFunction)> callback, + utils::MiniFunction failed = {} + ); + class GEODE_DLL FileWatchEvent : public Event { protected: ghc::filesystem::path m_path; diff --git a/loader/src/platform/android/crashlog.cpp b/loader/src/platform/android/crashlog.cpp index 8c4f4f82f..e1ed7bd9c 100644 --- a/loader/src/platform/android/crashlog.cpp +++ b/loader/src/platform/android/crashlog.cpp @@ -334,159 +334,90 @@ static void handlerThread() { static bool s_lastLaunchCrashed; -bool crashlog::setupPlatformHandler() { - auto pidFile = crashlog::getCrashLogDirectory() / "last-pid"; +// bool crashlog::setupPlatformHandler() { +// auto pidFile = crashlog::getCrashLogDirectory() / "last-pid"; - int lastPid = 0; +// int lastPid = 0; - if (ghc::filesystem::exists(pidFile)) { +// if (ghc::filesystem::exists(pidFile)) { - auto res = file::readString(pidFile); - if (!res) { - log::warn("Failed to read last-pid file: {}", res.error()); - } - else { - lastPid = std::stoi(res.unwrap()); - } +// auto res = file::readString(pidFile); +// if (!res) { +// log::warn("Failed to read last-pid file: {}", res.error()); +// } +// else { +// lastPid = std::stoi(res.unwrap()); +// } - std::error_code ec; - ghc::filesystem::remove(pidFile, ec); +// std::error_code ec; +// ghc::filesystem::remove(pidFile, ec); - if (ec) { - log::warn("Failed to remove last-pid file: {}", ec.message()); - } - } +// if (ec) { +// log::warn("Failed to remove last-pid file: {}", ec.message()); +// } +// } - auto res = file::writeString(pidFile, std::to_string(getpid())); - if (!res) { - log::warn("Failed to write last-pid file: {}", res.error()); - } +// auto res = file::writeString(pidFile, std::to_string(getpid())); +// if (!res) { +// log::warn("Failed to write last-pid file: {}", res.error()); +// } - lastPid = 1513; +// lastPid = 1513; - if (lastPid == 0) { - return true; - } +// if (lastPid == 0) { +// return true; +// } - // TODO: get logcat crash - - std::string logcatCrash = R"RAW( -F/libc (31506): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xccb00000 in tid 31584 (GLThread 215445), pid 31506 (.geode.launcher) -F/DEBUG (31618): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** -F/DEBUG (31618): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' -F/DEBUG (31618): Revision: '7' -F/DEBUG (31618): ABI: 'arm' -F/DEBUG (31618): pid: 31506, tid: 31584, name: GLThread 215445 >>> com.geode.launcher <<< -F/DEBUG (31618): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xccb00000 -F/DEBUG (31618): r0 ccafffe0 r1 ccafffe4 r2 ffefb73c r3 00000000 -F/DEBUG (31618): r4 00000000 r5 c7e4af50 r6 c7e49400 r7 3c888889 -F/DEBUG (31618): r8 c2dcf000 r9 cf8a7000 r10 cd1c6800 r11 cf8a7000 -F/DEBUG (31618): ip eff2b5f0 sp cd1c6680 lr c921095d pc efe9ef2c -F/DEBUG (31618): -F/DEBUG (31618): backtrace: -F/DEBUG (31618): #00 pc 00019f2c /system/lib/libc.so (memcpy+96) -F/DEBUG (31618): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) -F/DEBUG (31618): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) -F/DEBUG (31618): #03 pc 00000617 -F/libc ( 836): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xcd680000 in tid 901 (GLThread 215582), pid 836 (.geode.launcher) -F/DEBUG ( 933): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** -F/DEBUG ( 933): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' -F/DEBUG ( 933): Revision: '7' -F/DEBUG ( 933): ABI: 'arm' -F/DEBUG ( 933): pid: 836, tid: 901, name: GLThread 215582 >>> com.geode.launcher <<< -F/DEBUG ( 933): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xcd680000 -F/DEBUG ( 933): r0 cd67ffd0 r1 cd67fff4 r2 ffe935fc r3 00000000 -F/DEBUG ( 933): r4 00000000 r5 cc6fa350 r6 cc6f8800 r7 3c888889 -F/DEBUG ( 933): r8 c2990300 r9 ed1e0600 r10 caec3800 r11 ed1e0600 -F/DEBUG ( 933): ip eff2b5f0 sp caec3680 lr c94fe95d pc efe9ef30 -F/DEBUG ( 933): -F/DEBUG ( 933): backtrace: -F/DEBUG ( 933): #00 pc 00019f30 /system/lib/libc.so (memcpy+100) -F/DEBUG ( 933): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) -F/DEBUG ( 933): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) -F/DEBUG ( 933): #03 pc 00000617 -F/libc ( 1071): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc9c00000 in tid 1228 (GLThread 215607), pid 1071 (.geode.launcher) -F/DEBUG ( 1377): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** -F/DEBUG ( 1377): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' -F/DEBUG ( 1377): Revision: '7' -F/DEBUG ( 1377): ABI: 'arm' -F/DEBUG ( 1377): pid: 1071, tid: 1228, name: GLThread 215607 >>> com.geode.launcher <<< -F/DEBUG ( 1377): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc9c00000 -F/DEBUG ( 1377): r0 c9bfffe0 r1 c9bfffe4 r2 ffb862fc r3 00000000 -F/DEBUG ( 1377): r4 00000000 r5 c1bf2b50 r6 c1bf1000 r7 3c888889 -F/DEBUG ( 1377): r8 c7d34200 r9 ed1e6e00 r10 cd0d2800 r11 ed1e6e00 -F/DEBUG ( 1377): ip eff2b5f0 sp cd0d2680 lr c900c95d pc efe9ef2c -F/DEBUG ( 1377): -F/DEBUG ( 1377): backtrace: -F/DEBUG ( 1377): #00 pc 00019f2c /system/lib/libc.so (memcpy+96) -F/DEBUG ( 1377): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) -F/DEBUG ( 1377): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) -F/DEBUG ( 1377): #03 pc 00000617 -F/libc ( 1513): Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc8500000 in tid 1658 (GLThread 215649), pid 1513 (.geode.launcher) -F/DEBUG ( 1752): *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** -F/DEBUG ( 1752): Build fingerprint: 'samsung/j7y17ltexx/j7y17lte:9/PPR1.180610.011/J730FXWU8CUG1:user/release-keys' -F/DEBUG ( 1752): Revision: '7' -F/DEBUG ( 1752): ABI: 'arm' -F/DEBUG ( 1752): pid: 1513, tid: 1658, name: GLThread 215649 >>> com.geode.launcher <<< -F/DEBUG ( 1752): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xc8500000 -F/DEBUG ( 1752): r0 c84fffc0 r1 c84fffe4 r2 ffb13634 r3 00000008 -F/DEBUG ( 1752): r4 00000000 r5 c83e0750 r6 c83dec00 r7 3c888889 -F/DEBUG ( 1752): r8 e41cad00 r9 ed9fbc00 r10 cd38f800 r11 ed9fbc00 -F/DEBUG ( 1752): ip 00000000 sp cd38f680 lr c951195d pc efe9ef30 -F/DEBUG ( 1752): -F/DEBUG ( 1752): backtrace: -F/DEBUG ( 1752): #00 pc 00019f30 /system/lib/libc.so (memcpy+100) -F/DEBUG ( 1752): #01 pc 00336959 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x336000) (GJEffectManager::updateSpawnTriggers(float)+64) -F/DEBUG ( 1752): #02 pc 0021b279 /data/app/com.robtopx.geometryjump-xzzAmj1_bAwPLWKGJk5srA==/lib/arm/libcocos2dcpp.so (offset 0x219000) (PlayLayer::update(float)+480) -F/DEBUG ( 1752): #03 pc 00000617 - )RAW"; - - std::string crashTrace; - auto findLast = logcatCrash.find_last_of(fmt::format("pid {} (.geode.launcher)", lastPid)); - if (findLast != std::string::npos) { - auto begin = logcatCrash.substr(0, findLast).find_last_of("F/libc"); - if (begin != std::string::npos) { - crashTrace = logcatCrash.substr(begin); - } - } - else { - return true; - } +// // TODO: get logcat crash - auto text = crashlog::writeCrashlog(nullptr, "", crashTrace, ""); - s_lastLaunchCrashed = true; - - auto lastCrashedFile = crashlog::getCrashLogDirectory() / "last-crashed"; - if (ghc::filesystem::exists(lastCrashedFile)) { - std::error_code ec; - ghc::filesystem::remove(lastCrashedFile, ec); - - if (ec) { - log::warn("Failed to remove last-crashed file: {}", ec.message()); - } - } - return true; -} +// std::string logcatCrash = R"RAW()RAW"; -bool crashlog::didLastLaunchCrash() { - return s_lastLaunchCrashed; -} +// std::string crashTrace; +// auto findLast = logcatCrash.find_last_of(fmt::format("pid {} (.geode.launcher)", lastPid)); +// if (findLast != std::string::npos) { +// auto begin = logcatCrash.substr(0, findLast).find_last_of("F/libc"); +// if (begin != std::string::npos) { +// crashTrace = logcatCrash.substr(begin); +// } +// } +// else { +// return true; +// } -ghc::filesystem::path crashlog::getCrashLogDirectory() { - return dirs::getGeodeDir() / "crashlogs"; -} +// auto text = crashlog::writeCrashlog(nullptr, "", crashTrace, ""); +// s_lastLaunchCrashed = true; + +// auto lastCrashedFile = crashlog::getCrashLogDirectory() / "last-crashed"; +// if (ghc::filesystem::exists(lastCrashedFile)) { +// std::error_code ec; +// ghc::filesystem::remove(lastCrashedFile, ec); -// ghc::filesystem::path crashlog::getCrashLogDirectory() { -// return geode::dirs::getSaveDir(); +// if (ec) { +// log::warn("Failed to remove last-crashed file: {}", ec.message()); +// } +// } +// return true; // } -// bool crashlog::setupPlatformHandler() { -// return false; +// bool crashlog::didLastLaunchCrash() { +// return s_lastLaunchCrashed; // } -// bool crashlog::didLastLaunchCrash() { -// return false; +// ghc::filesystem::path crashlog::getCrashLogDirectory() { +// return dirs::getGeodeDir() / "crashlogs"; // } +ghc::filesystem::path crashlog::getCrashLogDirectory() { + return geode::dirs::getSaveDir(); +} + +bool crashlog::setupPlatformHandler() { + return false; +} + +bool crashlog::didLastLaunchCrash() { + return false; +} + #endif diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index dacc4a844..05175cf29 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -85,9 +85,118 @@ bool utils::file::openFolder(ghc::filesystem::path const& path) { return false; } -geode::Result utils::file:: - pickFile(geode::utils::file::PickMode, geode::utils::file::FilePickOptions const&) { - return geode::Err("This function is currently unimplemented"); + +static utils::MiniFunction s_fileCallback; +static utils::MiniFunction)> s_filesCallback; +static utils::MiniFunction s_failedCallback; + +extern "C" +JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_selectFileCallback( + JNIEnv *env, + jobject, + jstring data +) { + auto isCopy = jboolean(); + auto dataStr = env->GetStringUTFChars(data, &isCopy); + + log::debug("Selected file: {}", dataStr); + + s_fileCallback(dataStr); +} + +extern "C" +JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_selectFilesCallback( + JNIEnv *env, + jobject, + jobjectArray datas +) { + auto isCopy = jboolean(); + auto count = env->GetArrayLength(datas); + auto result = std::vector(); + for (int i = 0; i < count; i++) { + auto data = (jstring)env->GetObjectArrayElement(datas, i); + auto dataStr = env->GetStringUTFChars(data, &isCopy); + result.push_back(dataStr); + + log::debug("Selected file {}: {}", i, dataStr); + } + + s_filesCallback(result); +} + +extern "C" +JNIEXPORT void JNICALL Java_com_geode_launcher_utils_GeodeUtils_failedCallback( + JNIEnv *env, + jobject +) { + if (s_failedCallback) s_failedCallback(); +} + +Result file::pickFile(file::PickMode mode, file::FilePickOptions const& options) { + return Err("Use the callback version"); +} + +void file::pickFile( + PickMode mode, FilePickOptions const& options, + utils::MiniFunction callback, + utils::MiniFunction failed +) { + s_fileCallback = callback; + s_failedCallback = failed; + + std::string method; + switch (mode) { + case file::PickMode::OpenFile: + method = "selectFile"; + break; + case file::PickMode::SaveFile: + method = "createFile"; + break; + case file::PickMode::OpenFolder: + method = "selectFolder"; + break; + } + + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", method.c_str(), "(Ljava/lang/String;)Z")) { + jstring stringArg1 = t.env->NewStringUTF(options.defaultPath.value_or(ghc::filesystem::path()).string().c_str()); + + jboolean result = t.env->CallStaticBooleanMethod(t.classID, t.methodID, stringArg1); + + t.env->DeleteLocalRef(stringArg1); + t.env->DeleteLocalRef(t.classID); + if (result) { + return; + } + } + if (s_failedCallback) s_failedCallback(); +} + +Result> file::pickFiles(file::FilePickOptions const& options) { + return Err("Use the callback version"); +} + +void file::pickFiles( + FilePickOptions const& options, + utils::MiniFunction)> callback, + utils::MiniFunction failed +) { + s_filesCallback = callback; + s_failedCallback = failed; + + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "selectFiles", "(Ljava/lang/String;)Z")) { + jstring stringArg1 = t.env->NewStringUTF(options.defaultPath.value_or(ghc::filesystem::path()).string().c_str()); + + jboolean result = t.env->CallStaticBooleanMethod(t.classID, t.methodID, stringArg1); + + t.env->DeleteLocalRef(stringArg1); + t.env->DeleteLocalRef(t.classID); + if (result) { + return; + } + } + if (s_failedCallback) s_failedCallback(); } void geode::utils::game::launchLoaderUninstaller(bool deleteSaveData) { diff --git a/loader/src/ui/internal/settings/GeodeSettingNode.cpp b/loader/src/ui/internal/settings/GeodeSettingNode.cpp index 28a37e1e2..f9e7da30a 100644 --- a/loader/src/ui/internal/settings/GeodeSettingNode.cpp +++ b/loader/src/ui/internal/settings/GeodeSettingNode.cpp @@ -355,16 +355,17 @@ void FileSettingNode::valueChanged(bool updateText) { } void FileSettingNode::onPickFile(CCObject*) { - if (auto path = file::pickFile( + file::pickFile( file::PickMode::OpenFile, { dirs::getGameDir(), setting()->castDefinition().controls.filters + }, + [&](auto path) { + m_uncommittedValue = path; + this->valueChanged(true); } - )) { - m_uncommittedValue = path.unwrap(); - this->valueChanged(true); - } + ); } bool FileSettingNode::setup(FileSettingValue* setting, float width) { From df459dec3cf16dad069507162b455f492c4162e5 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 8 Oct 2023 17:11:32 +0300 Subject: [PATCH 093/135] new pick files to other platforms --- loader/src/platform/android/util.cpp | 8 +++---- loader/src/platform/mac/util.mm | 32 ++++++++++++++++++++++++++-- loader/src/platform/windows/util.cpp | 28 ++++++++++++++++++++++++ 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/loader/src/platform/android/util.cpp b/loader/src/platform/android/util.cpp index 05175cf29..29f2c547a 100644 --- a/loader/src/platform/android/util.cpp +++ b/loader/src/platform/android/util.cpp @@ -138,8 +138,8 @@ Result file::pickFile(file::PickMode mode, file::FilePick void file::pickFile( PickMode mode, FilePickOptions const& options, - utils::MiniFunction callback, - utils::MiniFunction failed + MiniFunction callback, + MiniFunction failed ) { s_fileCallback = callback; s_failedCallback = failed; @@ -178,8 +178,8 @@ Result> file::pickFiles(file::FilePickOptions void file::pickFiles( FilePickOptions const& options, - utils::MiniFunction)> callback, - utils::MiniFunction failed + MiniFunction)> callback, + MiniFunction failed ) { s_filesCallback = callback; s_failedCallback = failed; diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm index e09712659..9c1ec5903 100644 --- a/loader/src/platform/mac/util.mm +++ b/loader/src/platform/mac/util.mm @@ -145,7 +145,7 @@ @implementation FileDialog } @end -Result utils::file::pickFile( +Result file::pickFile( file::PickMode mode, file::FilePickOptions const& options ) { auto result = [FileDialog filePickerWithMode:mode options:options multiple: false]; @@ -157,13 +157,41 @@ @implementation FileDialog } } -Result> utils::file::pickFiles( +GEODE_DLL void file::pickFile( + PickMode mode, FilePickOptions const& options, + MiniFunction callback, + MiniFunction failed +) { + auto result = file::pickFile(mode, options); + + if (result.isOk()) { + callback(std::move(result.unwrap())); + } else { + failed(); + } +} + +Result> file::pickFiles( file::FilePickOptions const& options ) { //return Err("utils::file::pickFiles is not implemented"); return [FileDialog filePickerWithMode: file::PickMode::OpenFile options:options multiple:true]; } +GEODE_DLL void file::pickFiles( + FilePickOptions const& options, + MiniFunction callback, + MiniFunction failed +) { + auto result = file::pickFiles(options); + + if (result.isOk()) { + callback(std::move(result.unwrap())); + } else { + failed(); + } +} + CCPoint cocos::getMousePos() { auto windowFrame = NSApp.mainWindow.frame; auto viewFrame = NSApp.mainWindow.contentView.frame; diff --git a/loader/src/platform/windows/util.cpp b/loader/src/platform/windows/util.cpp index 68e7ad526..c779bef52 100644 --- a/loader/src/platform/windows/util.cpp +++ b/loader/src/platform/windows/util.cpp @@ -97,6 +97,20 @@ Result utils::file::pickFile( return Ok(path); } +GEODE_DLL void file::pickFile( + PickMode mode, FilePickOptions const& options, + MiniFunction callback, + MiniFunction failed +) { + auto result = file::pickFile(mode, options); + + if (result.isOk()) { + callback(std::move(result.unwrap())); + } else { + failed(); + } +} + Result> utils::file::pickFiles( file::FilePickOptions const& options ) { @@ -105,6 +119,20 @@ Result> utils::file::pickFiles( return Ok(paths); } +GEODE_DLL void file::pickFiles( + FilePickOptions const& options, + MiniFunction callback, + MiniFunction failed +) { + auto result = file::pickFiles(options); + + if (result.isOk()) { + callback(std::move(result.unwrap())); + } else { + failed(); + } +} + void utils::web::openLinkInBrowser(std::string const& url) { ShellExecuteA(0, 0, url.c_str(), 0, 0, SW_SHOW); } From a08c8e6b6f2842d9eaad9dc2d840f252f9be9147 Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Sat, 7 Oct 2023 16:00:03 +0200 Subject: [PATCH 094/135] add android paddings to PlayerObject same as windows except for the first pad --- bindings/GeometryDash.bro | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 6ab08b3c6..04a6ea0c8 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5236,18 +5236,18 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate { void yStartDown() = mac 0x22e9b0; void yStartUp() = mac 0x22e990; - PAD = mac 0x14, win 0x14; + PAD = mac 0x14, win 0x14, android 0x10; bool m_unk480; cocos2d::CCNode* m_unk484; cocos2d::CCDictionary* m_collisionLog; cocos2d::CCDictionary* m_collisionLog1; GameObject* m_collidedSlope; - PAD = mac 0x30, win 0x1c; + PAD = mac 0x30, win 0x1c, android 0x1c; bool m_unk4B0; cocos2d::CCSprite* m_unk4B4; int m_collidedGroundObjectUniqueID; int m_collidedCeilObjectUniqueID; - PAD = mac 0x14, win 0x14; + PAD = mac 0x14, win 0x14, android 0x14; bool m_unk4D4; cocos2d::CCArray* m_particleSystems; bool m_unk4DC; @@ -5279,13 +5279,13 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate { bool m_unk53E; bool m_unk53F; bool m_isCheckpointQueued; - PAD = mac 0xf, win 0xf; + PAD = mac 0xf, win 0xf, android 0xf; double m_lastJumpTime; double m_unk558; double m_unk560; - PAD = mac 0x1c, win 0x1c; + PAD = mac 0x1c, win 0x1c, android 0x1c; float m_decelerationRate; - PAD = mac 0x13, win 0x13; + PAD = mac 0x13, win 0x13, android 0x13; bool m_hasHitRing; GameObject* m_objectSnappedTo; CheckpointObject* m_checkpoint; @@ -5303,14 +5303,14 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate { void* m_unk5D0; cocos2d::CCParticleSystemQuad* m_unk5D4; cocos2d::CCParticleSystemQuad* m_unk5D8; - PAD = mac 0x20, win 0x20; + PAD = mac 0x20, win 0x20, android 0x20; // int m_streakID; // float m_wellIdk; // PAD = win 0x10; bool m_unk5FC; bool m_unk5FD; bool m_hasHitPortal; - PAD = mac 0xb, win 0xb; + PAD = mac 0xb, win 0xb, android 0xb; bool m_unknown73d; cocos2d::_ccColor3B m_unknown73e; cocos2d::_ccColor3B m_unknown741; @@ -5357,13 +5357,13 @@ class PlayerObject : GameObject, AnimatedSpriteDelegate { bool m_unk684; bool m_unk685; double m_unk688; - PAD = win 0x4; + PAD = win 0x4, android 0x4; float m_meteringValue; float m_groundHeight; float m_unk69C; - PAD = win 0x4; + PAD = win 0x4, android 0x4; std::array m_unk6A4; - PAD = win 0x1c; + PAD = win 0x1c, android 0x1c; } [[link(android)]] From 42a1a33c532a4c86546ee0b0eb55dcfd3b9f0382 Mon Sep 17 00:00:00 2001 From: SMJSGaming Date: Tue, 10 Oct 2023 19:19:12 +0200 Subject: [PATCH 095/135] Added word wrappers, colors and optimizations to text area --- loader/include/Geode/ui/TextArea.hpp | 33 ++++-- loader/src/ui/nodes/TextArea.cpp | 164 +++++++++++++++++++-------- 2 files changed, 144 insertions(+), 53 deletions(-) diff --git a/loader/include/Geode/ui/TextArea.hpp b/loader/include/Geode/ui/TextArea.hpp index 0ac0cf313..c923d4e4e 100644 --- a/loader/include/Geode/ui/TextArea.hpp +++ b/loader/include/Geode/ui/TextArea.hpp @@ -4,36 +4,47 @@ #include namespace geode { + enum WrappingMode { + NO_WRAP, + WORD_WRAP, + CUTOFF_WRAP + }; + /** * A class which provides a textarea with proper alignment and some extra features like: * * - Max lines * - Changing all aspects after creation * - Custom text alignment - * - Automatic line wrapping and cutoff + * - Configurable and automatic word wrapping * - Line padding * * Contact me on Discord (\@smjs) if you have any questions, suggestions or bugs. */ class GEODE_DLL SimpleTextArea : public cocos2d::CCNode { + static SimpleTextArea* create(const std::string& text, const std::string& font = "chatFont.fnt", const float scale = 1); + static SimpleTextArea* create(const std::string& text, const std::string& font, const float scale, const float width); + cocos2d::CCMenu* m_container; std::string m_font; std::string m_text; std::vector m_lines; + cocos2d::ccColor4B m_color; cocos2d::CCTextAlignment m_alignment; + WrappingMode m_wrappingMode; size_t m_maxLines; float m_scale; float m_lineHeight; float m_linePadding; - bool m_artificialWidth; - public: - static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale); - static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale, const float width); void setFont(const std::string& font); std::string getFont(); + void setColor(const cocos2d::ccColor4B& color); + cocos2d::ccColor4B getColor(); void setAlignment(const cocos2d::CCTextAlignment alignment); cocos2d::CCTextAlignment getAlignment(); + void setWrappingMode(const WrappingMode mode); + WrappingMode getWrappingMode(); void setText(const std::string& text); std::string getText(); void setMaxLines(const size_t maxLines); @@ -50,11 +61,17 @@ namespace geode { private: static SimpleTextArea* create(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth); + bool m_shouldUpdate; + bool m_artificialWidth; + SimpleTextArea(const std::string& font, const std::string& text, const float scale, const float width, const bool artificialWidth); cocos2d::CCLabelBMFont* createLabel(const std::string& text, const float top); - cocos2d::CCLabelBMFont* moveOverflow(cocos2d::CCLabelBMFont* line, const char c, const float top); float calculateOffset(cocos2d::CCLabelBMFont* label); - void updateLines(); - void updateContents(); + void charIteration(const std::function& overflowHandling); + void updateLinesNoWrap(); + void updateLinesWordWrap(); + void updateLinesCutoffWrap(); + void updateContainer(); + virtual void draw() override; }; } \ No newline at end of file diff --git a/loader/src/ui/nodes/TextArea.cpp b/loader/src/ui/nodes/TextArea.cpp index 9dce696fa..a2b747175 100644 --- a/loader/src/ui/nodes/TextArea.cpp +++ b/loader/src/ui/nodes/TextArea.cpp @@ -2,11 +2,11 @@ using namespace geode::prelude; -SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale = 1) { - return SimpleTextArea::create(font, text, scale, 500, false); +SimpleTextArea* SimpleTextArea::create(const std::string& text, const std::string& font, const float scale) { + return SimpleTextArea::create(font, text, scale, CCDirector::sharedDirector()->getWinSize().width / 2, false); } -SimpleTextArea* SimpleTextArea::create(const std::string& font, const std::string& text, const float scale, const float width) { +SimpleTextArea* SimpleTextArea::create(const std::string& text, const std::string& font, const float scale, const float width) { return SimpleTextArea::create(font, text, scale, width, true); } @@ -30,9 +30,12 @@ SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text, m_maxLines = 0; m_scale = scale; m_linePadding = 0; + m_color = { 0xFF, 0xFF, 0xFF, 0xFF }; m_alignment = kCCTextAlignmentLeft; + m_wrappingMode = WORD_WRAP; m_artificialWidth = artificialWidth; m_container = CCMenu::create(); + m_shouldUpdate = true; this->setAnchorPoint({ 0.5f, 0.5f }); m_container->setPosition({ 0, 0 }); @@ -40,33 +43,47 @@ SimpleTextArea::SimpleTextArea(const std::string& font, const std::string& text, m_container->setContentSize({ width, 0 }); this->addChild(m_container); - this->updateContents(); } void SimpleTextArea::setFont(const std::string& font) { m_font = font; - - this->updateContents(); + m_shouldUpdate = true; } std::string SimpleTextArea::getFont() { return m_font; } +void SimpleTextArea::setColor(const ccColor4B& color) { + m_color = color; + m_shouldUpdate = true; +} + +ccColor4B SimpleTextArea::getColor() { + return m_color; +} + void SimpleTextArea::setAlignment(const CCTextAlignment alignment) { m_alignment = alignment; - - this->updateContents(); + m_shouldUpdate = true; } CCTextAlignment SimpleTextArea::getAlignment() { return m_alignment; } +void SimpleTextArea::setWrappingMode(const WrappingMode mode) { + m_wrappingMode = mode; + m_shouldUpdate = true; +} + +WrappingMode SimpleTextArea::getWrappingMode() { + return m_wrappingMode; +} + void SimpleTextArea::setText(const std::string& text) { m_text = text; - - this->updateContents(); + m_shouldUpdate = true; } std::string SimpleTextArea::getText() { @@ -75,8 +92,7 @@ std::string SimpleTextArea::getText() { void SimpleTextArea::setMaxLines(const size_t maxLines) { m_maxLines = maxLines; - - this->updateContents(); + m_shouldUpdate = true; } size_t SimpleTextArea::getMaxLines() { @@ -85,6 +101,7 @@ size_t SimpleTextArea::getMaxLines() { void SimpleTextArea::setWidth(const float width) { m_artificialWidth = true; + m_shouldUpdate = true; this->setContentSize({ width, this->getContentSize().height }); m_container->setContentSize(this->getContentSize()); @@ -96,8 +113,7 @@ float SimpleTextArea::getWidth() { void SimpleTextArea::setScale(const float scale) { m_scale = scale; - - this->updateContents(); + m_shouldUpdate = true; } float SimpleTextArea::getScale() { @@ -106,8 +122,7 @@ float SimpleTextArea::getScale() { void SimpleTextArea::setLinePadding(const float padding) { m_linePadding = padding; - - this->updateContents(); + m_shouldUpdate = true; } float SimpleTextArea::getLinePadding() { @@ -131,34 +146,17 @@ CCLabelBMFont* SimpleTextArea::createLabel(const std::string& text, const float label->setScale(m_scale); label->setPosition({ 0, top }); + label->setColor({ m_color.r, m_color.g, m_color.b }); + label->setOpacity(m_color.a); return label; } -CCLabelBMFont* SimpleTextArea::moveOverflow(CCLabelBMFont* line, const char c, const float top) { - const std::string text = line->getString(); - const char back = text.back(); - const bool lastIsSpace = back == ' '; - CCLabelBMFont* newLine = this->createLabel(std::string(!lastIsSpace, back).append(std::string(c != ' ', c)), top); - - if (!lastIsSpace) { - if (text[text.size() - 2] == ' ') { - line->setString(text.substr(0, text.size() - 1).c_str()); - } else { - line->setString((text.substr(0, text.size() - 1) + '-').c_str()); - } - } - - m_lines.push_back(newLine); - - return newLine; -} - float SimpleTextArea::calculateOffset(CCLabelBMFont* label) { return m_linePadding + label->getContentSize().height * m_scale; } -void SimpleTextArea::updateLines() { +void SimpleTextArea::charIteration(const std::function& overflowHandling) { float top = 0; CCLabelBMFont* line = this->createLabel("", top); m_lines = { line }; @@ -173,21 +171,87 @@ void SimpleTextArea::updateLines() { break; } else if (c == '\n') { - line = this->createLabel("", top -= this->calculateOffset(line)); + m_lines.push_back(line = this->createLabel("", top -= this->calculateOffset(line))); + } else if (m_artificialWidth && line->getContentSize().width * m_scale >= this->getWidth()) { + m_lines.push_back(line = overflowHandling(line, c, top -= this->calculateOffset(line))); + } else { + line->setString((std::string(line->getString()) + c).c_str()); + } + } +} - m_lines.push_back(line); - } else if (m_artificialWidth && line->getContentSize().width >= this->getWidth()) { - line = this->moveOverflow(line, c, top -= this->calculateOffset(line)); +void SimpleTextArea::updateLinesNoWrap() { + std::stringstream stream(m_text); + std::string part; + float top = 0; + + while (std::getline(stream, part)) { + if (m_maxLines && m_lines.size() >= m_maxLines) { + CCLabelBMFont* last = m_lines.at(m_maxLines - 1); + const std::string text = last->getString(); + + last->setString(text.substr(0, text.size() - 3).append("...").c_str()); + + break; } else { - const std::string text = line->getString(); + CCLabelBMFont* line = this->createLabel(part, 0); + + top -= this->calculateOffset(line); - line->setString((text + c).c_str()); + m_lines.push_back(line); } } } -void SimpleTextArea::updateContents() { - this->updateLines(); +void SimpleTextArea::updateLinesWordWrap() { + this->charIteration([this](CCLabelBMFont* line, const char c, const float top) { + static std::string delimiters(" `~!@#$%^&*()-_=+[{}];:'\",<.>/?\\|"); + + if (delimiters.find(c) == std::string_view::npos) { + const std::string text = line->getString(); + const size_t position = text.find_last_of(delimiters) + 1; + + line->setString(text.substr(0, position).c_str()); + + return this->createLabel(text.substr(position) + c, top); + } else { + return this->createLabel(std::string(c, c != ' '), top); + } + }); +} + +void SimpleTextArea::updateLinesCutoffWrap() { + this->charIteration([this](CCLabelBMFont* line, const char c, const float top) { + const std::string text = line->getString(); + const char back = text.back(); + const bool lastIsSpace = back == ' '; + CCLabelBMFont* newLine = this->createLabel(std::string(!lastIsSpace, back).append(std::string(c != ' ', c)), top); + + if (!lastIsSpace) { + if (text[text.size() - 2] == ' ') { + line->setString(text.substr(0, text.size() - 1).c_str()); + } else { + line->setString((text.substr(0, text.size() - 1) + '-').c_str()); + } + } + + return newLine; + }); +} + +void SimpleTextArea::updateContainer() { + switch (m_wrappingMode) { + case NO_WRAP: { + this->updateLinesNoWrap(); + } break; + case WORD_WRAP: { + this->updateLinesWordWrap(); + } break; + case CUTOFF_WRAP: { + this->updateLinesCutoffWrap(); + } break; + } + const size_t lineCount = m_lines.size(); const float width = this->getWidth(); @@ -212,7 +276,7 @@ void SimpleTextArea::updateContents() { line->setPosition({ 0, y }); } break; case kCCTextAlignmentCenter: { - line->setAnchorPoint({ 0.5f, 1 }); + line->setAnchorPoint({ 0, 1 }); line->setPosition({ width / 2, y }); } break; case kCCTextAlignmentRight: { @@ -224,3 +288,13 @@ void SimpleTextArea::updateContents() { m_container->addChild(line); } } + +void SimpleTextArea::draw() { + CCNode::draw(); + + if (m_shouldUpdate) { + this->updateContainer(); + + m_shouldUpdate = false; + } +} \ No newline at end of file From 449ee464bec4583a7a042776996f4de09ff253b0 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Wed, 11 Oct 2023 21:02:06 +0300 Subject: [PATCH 096/135] fix pickfiles --- loader/src/platform/mac/util.mm | 2 +- loader/src/platform/windows/util.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/src/platform/mac/util.mm b/loader/src/platform/mac/util.mm index 9c1ec5903..13ef876ff 100644 --- a/loader/src/platform/mac/util.mm +++ b/loader/src/platform/mac/util.mm @@ -180,7 +180,7 @@ @implementation FileDialog GEODE_DLL void file::pickFiles( FilePickOptions const& options, - MiniFunction callback, + MiniFunction)> callback, MiniFunction failed ) { auto result = file::pickFiles(options); diff --git a/loader/src/platform/windows/util.cpp b/loader/src/platform/windows/util.cpp index c779bef52..e84c71abb 100644 --- a/loader/src/platform/windows/util.cpp +++ b/loader/src/platform/windows/util.cpp @@ -121,7 +121,7 @@ Result> utils::file::pickFiles( GEODE_DLL void file::pickFiles( FilePickOptions const& options, - MiniFunction callback, + MiniFunction)> callback, MiniFunction failed ) { auto result = file::pickFiles(options); From 451c2b10f6b31ec4130220e94bcb7932328eb86e Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Fri, 13 Oct 2023 06:18:15 -0500 Subject: [PATCH 097/135] symbols --- bindings/Cocos2d.bro | 1 + bindings/GeometryDash.bro | 10 +++++----- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index b26400b2b..991a69880 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -1232,6 +1232,7 @@ class cocos2d::extension::CCScale9Sprite { class cocos2d::extension::CCScrollView { CCScrollView() = mac 0x214800; virtual ~CCScrollView() = mac 0x214c30; + static auto create(cocos2d::CCSize, cocos2d::CCNode*) = mac 0x214cd0; virtual auto init() = mac 0x214fb0; virtual auto setContentSize(cocos2d::CCSize const&) = mac 0x215eb0; virtual auto getContentSize() const = mac 0x215e90; diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index ab336f385..f31be6d12 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1724,7 +1724,7 @@ class FMODAudioEngine : cocos2d::CCNode { virtual void update(float) = win 0x23b20; cocos2d::CCDictionary* m_dictionary; - std::string m_filePath; + gd::string m_filePath; float m_backgroundMusicVolume; float m_effectsVolume; float m_pulse1; @@ -2432,9 +2432,9 @@ class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, cocos2d::CCSprite* m_colorSelector2; CCMenuItemSpriteExtra* m_unkButton0x148; CCMenuItemSpriteExtra* m_unkButton0x14c; - PAD = win 0x8; + PAD = win 0x8, mac 0x10; cocos2d::CCArray* m_pagesArray; - PAD = win 0x8; + PAD = win 0x8, mac 0x10; CCMenuItemToggler* m_tabToggleCube; CCMenuItemToggler* m_tabToggleShip; CCMenuItemToggler* m_tabToggleBall; @@ -2444,7 +2444,7 @@ class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, CCMenuItemToggler* m_tabToggleSpider; CCMenuItemToggler* m_tabToggleSpecial; CCMenuItemToggler* m_tabToggleDeathEffect; - PAD = win 0x4; + PAD = win 0x4, mac 0x8; bool m_updateSelector; } @@ -4071,7 +4071,7 @@ class LevelSearchLayer : cocos2d::CCLayer { virtual bool init() = mac 0x384770, win 0x17da60; GJSearchObject* getSearchObject(SearchType, gd::string) = mac 0x388a50, win 0x1805f0; void onMoreOptions(cocos2d::CCObject*) = win 0x17f500; - void onSearch(cocos2d::CCObject*) = win 0x180fc0; + void onSearch(cocos2d::CCObject*) = mac 0x386a70, win 0x180fc0; PAD = mac 0x18, win 0xC; CCTextInputNode* m_searchInput; From c12a64f93b1a40d3842e6f401490a6daf40fd0b3 Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Sun, 15 Oct 2023 10:01:21 -0300 Subject: [PATCH 098/135] update ndk to r26b --- .github/workflows/build-android.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml index d15024039..c74d522ae 100644 --- a/.github/workflows/build-android.yml +++ b/.github/workflows/build-android.yml @@ -18,7 +18,7 @@ jobs: - uses: nttld/setup-ndk@v1 id: setup-ndk with: - ndk-version: r25c + ndk-version: r26b add-to-path: false - name: Download CLI From 6a3a2c9714e00ad7b5519af85beb0c2f0cf3fab1 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:12:32 +0300 Subject: [PATCH 099/135] fix bros and remove update dir on start --- bindings/Cocos2d.bro | 5 ----- bindings/GeometryDash.bro | 12 ++++++------ loader/src/platform/android/main.cpp | 7 +++++++ 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/bindings/Cocos2d.bro b/bindings/Cocos2d.bro index 9e85414ba..c873de2a6 100644 --- a/bindings/Cocos2d.bro +++ b/bindings/Cocos2d.bro @@ -94,11 +94,6 @@ class cocos2d::CCCallFuncND { static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFuncND, void*) = mac 0x455470; } -[[link(win, android)]] -class cocos2d::CCCallFuncND { - static auto create(cocos2d::CCObject*, cocos2d::SEL_CallFuncND, void*) = mac 0x455470; -} - [[link(win, android)]] class cocos2d::CCClippingNode { CCClippingNode() { diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 76b62e67f..bc74d6882 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1078,12 +1078,12 @@ class CustomSongWidget : cocos2d::CCNode, MusicDownloadDelegate, FLAlertLayerPro void updatePlaybackBtn() = win 0x69970; void updateSongInfo() = win 0x69bf0; void updateSongObject(SongInfoObject* song) = win 0x69280, mac 0x37d690; - void onCancelDownload(CCObject*) = win 0x693b0; - void onDownload(CCObject*) = win 0x69540; - void onGetSongInfo(CCObject*) = win 0x69490; - void onMore(CCObject*) = win 0x68e20; - void onPlayback(CCObject*) = win 0x697b0; - void onSelect(CCObject*) = win 0x69760; + void onCancelDownload(cocos2d::CCObject*) = win 0x693b0; + void onDownload(cocos2d::CCObject*) = win 0x69540; + void onGetSongInfo(cocos2d::CCObject*) = win 0x69490; + void onMore(cocos2d::CCObject*) = win 0x68e20; + void onPlayback(cocos2d::CCObject*) = win 0x697b0; + void onSelect(cocos2d::CCObject*) = win 0x69760; SongInfoObject* m_songInfo; cocos2d::CCMenu* m_buttonMenu; diff --git a/loader/src/platform/android/main.cpp b/loader/src/platform/android/main.cpp index f15001461..b8015ef46 100644 --- a/loader/src/platform/android/main.cpp +++ b/loader/src/platform/android/main.cpp @@ -16,6 +16,13 @@ extern "C" [[gnu::visibility("default")]] jint JNI_OnLoad(JavaVM* vm, void* rese glBindVertexArrayOESEXT = (PFNGLBINDVERTEXARRAYOESPROC)eglGetProcAddress("glBindVertexArrayOES"); glDeleteVertexArraysOESEXT = (PFNGLDELETEVERTEXARRAYSOESPROC)eglGetProcAddress("glDeleteVertexArraysOES"); + auto updatePath = geode::dirs::getGameDir() / "update"; + std::error_code ec; + ghc::filesystem::remove_all(updatePath, ec); + if (ec) { + geode::log::warn("Failed to remove update directory: {}", ec.message()); + } + geodeEntry(nullptr); return JNI_VERSION_1_6; } From 4acca436e81fa543f97b13fbd7c0d0b7421bb745 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:17:29 +0300 Subject: [PATCH 100/135] who named these functions please use the android signatures i beg you --- bindings/GeometryDash.bro | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index bc74d6882..9ded142be 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -2565,14 +2565,14 @@ class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, void onDartIcon(cocos2d::CCObject* sender) = win 0x128420; void onRobotIcon(cocos2d::CCObject* sender) = win 0x1286d0; void onSpiderIcon(cocos2d::CCObject* sender) = win 0x128890; - void onPlayerDeathEffect(cocos2d::CCObject* sender) = win 0x128a50; - void onPlayerTrail(cocos2d::CCObject* sender) = win 0x128af0; + void onDeathEffect(cocos2d::CCObject* sender) = win 0x128a50; + void onTrail(cocos2d::CCObject* sender) = win 0x128af0; void onShards(cocos2d::CCObject* sender) = win 0x12ad70; void onBack(cocos2d::CCObject* sender) = win 0x12adf0; void onShop(cocos2d::CCObject* sender) = win 0x12ad90; void setupColorSelect() = mac 0x1b7500; - void showCircleWave() = win 0x12aad0; - void showBlackCircleWave() = win 0x12a9d0; + void playRainbowEffect() = win 0x12aad0; + void playShadowEffect() = win 0x12a9d0; PAD = mac 0x10, win 0x8; CCTextInputNode* m_nameInput; SimplePlayer* m_playerPreview; @@ -3810,7 +3810,7 @@ class GaragePage : cocos2d::CCLayer, ListButtonBarDelegate { return nullptr; } - void listButtonBarSwitchedPage(ListButtonBar* bar, int idk) = win 0x12bb40; + virtual void listButtonBarSwitchedPage(ListButtonBar* bar, int idk) = win 0x12bb40; inline GaragePage() {} bool init(IconType type, GJGarageLayer* pGarage, cocos2d::SEL_MenuHandler pSelectCallback) = mac 0x1bb710, win 0x12af70, ios 0x225d5c; @@ -4445,7 +4445,7 @@ class LikeItemLayer : FLAlertLayer { [[link(android)]] class ListButtonBar : cocos2d::CCNode { BoomScrollLayer* m_scrollLayer; - void switchedPage(int page) = win 0x29c50; + void goToPage(int page) = win 0x29c50; } [[link(android)]] @@ -5878,7 +5878,7 @@ class SpeedObject : cocos2d::CCNode { float m_xPos; GameObject* m_object; - static SpeedObject* create(GameObject* object, Speed speed, float x) = win 0x20de70; + static SpeedObject* create(GameObject* object, int speed, float x) = win 0x20de70; } [[link(android)]] From cd012df57e4551d38c57ab6e5d45f28da70694df Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:26:24 +0300 Subject: [PATCH 101/135] i missed this one alphaaaaaa --- bindings/GeometryDash.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 9ded142be..608fd6efa 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -2566,7 +2566,7 @@ class GJGarageLayer : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, void onRobotIcon(cocos2d::CCObject* sender) = win 0x1286d0; void onSpiderIcon(cocos2d::CCObject* sender) = win 0x128890; void onDeathEffect(cocos2d::CCObject* sender) = win 0x128a50; - void onTrail(cocos2d::CCObject* sender) = win 0x128af0; + void onSpecialIcon(cocos2d::CCObject* sender) = win 0x128af0; void onShards(cocos2d::CCObject* sender) = win 0x12ad70; void onBack(cocos2d::CCObject* sender) = win 0x12adf0; void onShop(cocos2d::CCObject* sender) = win 0x12ad90; From 57a475b3b78ea6bff5e3ec38f11ce35f753b5ddf Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 16:43:21 +0300 Subject: [PATCH 102/135] add the logcat writer --- loader/src/internal/crashlog.cpp | 2 +- loader/src/internal/crashlog.hpp | 2 ++ loader/src/platform/android/crashlog.cpp | 17 +++++++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/loader/src/internal/crashlog.cpp b/loader/src/internal/crashlog.cpp index 7f698616c..76459efc8 100644 --- a/loader/src/internal/crashlog.cpp +++ b/loader/src/internal/crashlog.cpp @@ -3,7 +3,7 @@ using namespace geode::prelude; -static std::string getDateString(bool filesafe) { +std::string crashlog::getDateString(bool filesafe) { auto const now = std::time(nullptr); auto const tm = *std::localtime(&now); std::ostringstream oss; diff --git a/loader/src/internal/crashlog.hpp b/loader/src/internal/crashlog.hpp index 4ed85293a..4590bbc3c 100644 --- a/loader/src/internal/crashlog.hpp +++ b/loader/src/internal/crashlog.hpp @@ -26,4 +26,6 @@ namespace crashlog { ghc::filesystem::path GEODE_DLL getCrashLogDirectory(); std::string GEODE_DLL writeCrashlog(geode::Mod* faultyMod, std::string const& info, std::string const& stacktrace, std::string const& registers); + + std::string getDateString(bool filesafe); } diff --git a/loader/src/platform/android/crashlog.cpp b/loader/src/platform/android/crashlog.cpp index e1ed7bd9c..2ceac82ea 100644 --- a/loader/src/platform/android/crashlog.cpp +++ b/loader/src/platform/android/crashlog.cpp @@ -15,6 +15,10 @@ using namespace geode::prelude; #include #include + +#include +#include + #include "backtrace/execinfo.hpp" static constexpr size_t FRAME_SIZE = 64; @@ -413,6 +417,19 @@ ghc::filesystem::path crashlog::getCrashLogDirectory() { } bool crashlog::setupPlatformHandler() { + auto path = crashlog::getCrashLogDirectory() / (getDateString(true) + ".log"); + + JniMethodInfo t; + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "writeLogcatCrashBuffer", "(Ljava/lang/String;)Z")) { + jstring stringArg1 = t.env->NewStringUTF(path.string().c_str()); + + jboolean result = t.env->CallStaticBooleanMethod(t.classID, t.methodID, stringArg1); + + t.env->DeleteLocalRef(stringArg1); + t.env->DeleteLocalRef(t.classID); + return result; + } + return false; } From 241fed492ca829e4a7cb363681d50b3d501a5b56 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 17:31:30 +0300 Subject: [PATCH 103/135] android crashlog implemented gg --- loader/src/internal/crashlog.cpp | 6 +- loader/src/internal/crashlog.hpp | 11 +++ loader/src/load.cpp | 2 + loader/src/platform/android/crashlog.cpp | 106 ++++++++++++++++++++--- loader/src/platform/mac/crashlog.mm | 2 + loader/src/platform/windows/crashlog.cpp | 2 + 6 files changed, 115 insertions(+), 14 deletions(-) diff --git a/loader/src/internal/crashlog.cpp b/loader/src/internal/crashlog.cpp index 76459efc8..60240c7d2 100644 --- a/loader/src/internal/crashlog.cpp +++ b/loader/src/internal/crashlog.cpp @@ -16,13 +16,13 @@ std::string crashlog::getDateString(bool filesafe) { return oss.str(); } -static void printGeodeInfo(std::stringstream& stream) { +void crashlog::printGeodeInfo(std::stringstream& stream) { stream << "Loader Version: " << Loader::get()->getVersion().toString() << "\n" << "Installed mods: " << Loader::get()->getAllMods().size() << "\n" << "Problems: " << Loader::get()->getProblems().size() << "\n"; } -static void printMods(std::stringstream& stream) { +void crashlog::printMods(std::stringstream& stream) { auto mods = Loader::get()->getAllMods(); if (mods.empty()) { stream << "\n"; @@ -30,7 +30,7 @@ static void printMods(std::stringstream& stream) { using namespace std::string_view_literals; for (auto& mod : mods) { stream << fmt::format("{} | [{}] {}\n", - mod->isEnabled() ? "x"sv : " "sv, + mod->isEnabled() ? "x"sv : mod->shouldLoad() ? "~"sv : " "sv, mod->getVersion().toString(), mod->getID() ); } diff --git a/loader/src/internal/crashlog.hpp b/loader/src/internal/crashlog.hpp index 4590bbc3c..8174758fd 100644 --- a/loader/src/internal/crashlog.hpp +++ b/loader/src/internal/crashlog.hpp @@ -13,6 +13,12 @@ namespace crashlog { * @returns True if the handler was successfully installed, false otherwise */ bool GEODE_DLL setupPlatformHandler(); + + /** + * Setup platform-specific crashlog handler for post-launch + */ + void GEODE_DLL setupPlatformHandlerPost(); + /** * Check if previous launch of GD crashed unexpectedly * @returns True if the launch crashed, false otherwise or if indeterminate @@ -28,4 +34,9 @@ namespace crashlog { std::string GEODE_DLL writeCrashlog(geode::Mod* faultyMod, std::string const& info, std::string const& stacktrace, std::string const& registers); std::string getDateString(bool filesafe); + + void printGeodeInfo(std::stringstream& stream); + void printMods(std::stringstream& stream); + + } diff --git a/loader/src/load.cpp b/loader/src/load.cpp index 85e05d422..09586af7c 100644 --- a/loader/src/load.cpp +++ b/loader/src/load.cpp @@ -88,6 +88,8 @@ int geodeEntry(void* platformData) { return 1; } + crashlog::setupPlatformHandlerPost(); + log::info("Set up loader"); // download and install new loader update in the background diff --git a/loader/src/platform/android/crashlog.cpp b/loader/src/platform/android/crashlog.cpp index 2ceac82ea..41c4e2721 100644 --- a/loader/src/platform/android/crashlog.cpp +++ b/loader/src/platform/android/crashlog.cpp @@ -336,7 +336,7 @@ static void handlerThread() { log::debug("Notified"); } -static bool s_lastLaunchCrashed; +static bool s_lastLaunchCrashed = false; // bool crashlog::setupPlatformHandler() { // auto pidFile = crashlog::getCrashLogDirectory() / "last-pid"; @@ -413,28 +413,112 @@ static bool s_lastLaunchCrashed; // } ghc::filesystem::path crashlog::getCrashLogDirectory() { - return geode::dirs::getSaveDir(); + return dirs::getGeodeDir() / "crashlogs"; } -bool crashlog::setupPlatformHandler() { - auto path = crashlog::getCrashLogDirectory() / (getDateString(true) + ".log"); +int writeAndGetPid() { + auto pidFile = crashlog::getCrashLogDirectory() / "last-pid"; + + int lastPid = 0; + + if (ghc::filesystem::exists(pidFile)) { + + auto res = file::readString(pidFile); + if (!res) { + log::warn("Failed to read last-pid file: {}", res.error()); + } + else { + lastPid = std::stoi(res.unwrap()); + } + + std::error_code ec; + ghc::filesystem::remove(pidFile, ec); + + if (ec) { + log::warn("Failed to remove last-pid file: {}", ec.message()); + } + } + + auto res = file::writeString(pidFile, std::to_string(getpid())); + if (!res) { + log::warn("Failed to write last-pid file: {}", res.error()); + } + + return lastPid; +} + +void printModsAndroid(std::stringstream& stream) { + auto mods = Loader::get()->getAllMods(); + if (mods.empty()) { + stream << "\n"; + } + using namespace std::string_view_literals; + for (auto& mod : mods) { + stream << fmt::format("{} | [{}] {}\n", + mod->shouldLoad() ? "x"sv : " "sv, + mod->getVersion().toString(), mod->getID() + ); + } +} +static std::string s_result; +bool crashlog::setupPlatformHandler() { JniMethodInfo t; - if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "writeLogcatCrashBuffer", "(Ljava/lang/String;)Z")) { - jstring stringArg1 = t.env->NewStringUTF(path.string().c_str()); + + if (JniHelper::getStaticMethodInfo(t, "com/geode/launcher/utils/GeodeUtils", "getLogcatCrashBuffer", "()Ljava/lang/String;")) { + jstring stringResult = (jstring)t.env->CallStaticObjectMethod(t.classID, t.methodID); - jboolean result = t.env->CallStaticBooleanMethod(t.classID, t.methodID, stringArg1); + s_result = JniHelper::jstring2string(stringResult); - t.env->DeleteLocalRef(stringArg1); + t.env->DeleteLocalRef(stringResult); t.env->DeleteLocalRef(t.classID); - return result; + + if (s_result.empty()) { + return false; + } + } + else return false; + + auto lastPid = writeAndGetPid(); + + auto index = s_result.rfind(fmt::format("pid {}", lastPid)); + if (index != std::string::npos) { + auto begin = s_result.substr(0, index).rfind("F/libc"); + if (begin != std::string::npos) { + s_result = s_result.substr(begin); + } + s_lastLaunchCrashed = true; + } - return false; + return true; +} + +void crashlog::setupPlatformHandlerPost() { + if (s_result.empty()) return; + + std::stringstream ss; + ss << "Geode crashed!\n"; + ss << "Please submit this crash report to the developer of the mod that caused it.\n"; + ss << "\n== Geode Information ==\n"; + crashlog::printGeodeInfo(ss); + + ss << "\n== Installed Mods ==\n"; + printModsAndroid(ss); + + ss << "\n== Crash Report (Logcat) ==\n"; + ss << s_result; + + std::ofstream actualFile; + actualFile.open( + crashlog::getCrashLogDirectory() / (crashlog::getDateString(true) + ".log"), std::ios::app + ); + actualFile << ss.rdbuf() << std::flush; + actualFile.close(); } bool crashlog::didLastLaunchCrash() { - return false; + return s_lastLaunchCrashed; } #endif diff --git a/loader/src/platform/mac/crashlog.mm b/loader/src/platform/mac/crashlog.mm index 7a104e86d..882f29611 100644 --- a/loader/src/platform/mac/crashlog.mm +++ b/loader/src/platform/mac/crashlog.mm @@ -382,6 +382,8 @@ static void handlerThread() { return true; } +void crashlog::setupPlatformHandlerPost() {} + bool crashlog::didLastLaunchCrash() { return s_lastLaunchCrashed; } diff --git a/loader/src/platform/windows/crashlog.cpp b/loader/src/platform/windows/crashlog.cpp index 19784522e..fb43eaa4b 100644 --- a/loader/src/platform/windows/crashlog.cpp +++ b/loader/src/platform/windows/crashlog.cpp @@ -252,6 +252,8 @@ bool crashlog::didLastLaunchCrash() { return g_lastLaunchCrashed; } +void crashlog::setupPlatformHandlerPost() {} + ghc::filesystem::path crashlog::getCrashLogDirectory() { return dirs::getGeodeDir() / "crashlogs"; } From 69ac4649606742f9a12d433cba33efe0373fcc46 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 17:44:41 +0300 Subject: [PATCH 104/135] Add profilepage virtuals --- bindings/GeometryDash.bro | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 608fd6efa..77653256e 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5437,6 +5437,22 @@ class ProfilePage : FLAlertLayer, FLAlertLayerProtocol, LevelCommentDelegate, Co virtual void keyBackClicked() = mac 0x464A60, win 0x49C80; void loadPageFromUserInfo(GJUserScore* score) = mac 0x460480, win 0x210040; + virtual void FLAlert_Clicked(FLAlertLayer*, bool) = mac 0x463340; + virtual void commentDeleteFailed(int, int) = mac 0x4648e0; + virtual void commentUploadFailed(int, CommentError) = mac 0x464800; + virtual void commentUploadFinished(int) = mac 0x464770; + virtual void getUserInfoFinished(GJUserScore*) = mac 0x463cd0; + virtual void loadCommentsFailed(char const*) = mac 0x464340; + virtual void loadCommentsFinished(cocos2d::CCArray*, char const*) = mac 0x464250; + virtual void onClosePopup(UploadActionPopup*) = mac 0x463510; + virtual void registerWithTouchDispatcher() = mac 0x464a60; + virtual void setupPageInfo(gd::string, char const*) = mac 0x464410; + virtual void show() = mac 0x4639c0; + virtual void updateUserScoreFailed() = mac 0x463920; + virtual void updateUserScoreFinished() = mac 0x463850; + virtual void uploadActionFailed(int, int) = mac 0x463710; + virtual void uploadActionFinished(int, int) = mac 0x463570; + GJUserScore* m_score; int m_accountID; PAD = mac 0x44, win 0x38, android 0x24; From 944ab383b48112ba5cd7def34a2100e6e0af0f09 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 17:48:40 +0300 Subject: [PATCH 105/135] funny virtual warning --- loader/include/Geode/ui/TextArea.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/include/Geode/ui/TextArea.hpp b/loader/include/Geode/ui/TextArea.hpp index c923d4e4e..1fb1eea51 100644 --- a/loader/include/Geode/ui/TextArea.hpp +++ b/loader/include/Geode/ui/TextArea.hpp @@ -51,8 +51,8 @@ namespace geode { size_t getMaxLines(); void setWidth(const float width); float getWidth(); - void setScale(const float scale); - float getScale(); + void setScale(const float scale) override; + float getScale() override; void setLinePadding(const float padding); float getLinePadding(); std::vector getLines(); From bfe9e8d945a0e976952a2c0353f7d85cf46f309c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 17:59:43 +0300 Subject: [PATCH 106/135] windows profilepage virtuals --- bindings/GeometryDash.bro | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 77653256e..5619fab3c 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5437,21 +5437,21 @@ class ProfilePage : FLAlertLayer, FLAlertLayerProtocol, LevelCommentDelegate, Co virtual void keyBackClicked() = mac 0x464A60, win 0x49C80; void loadPageFromUserInfo(GJUserScore* score) = mac 0x460480, win 0x210040; - virtual void FLAlert_Clicked(FLAlertLayer*, bool) = mac 0x463340; - virtual void commentDeleteFailed(int, int) = mac 0x4648e0; - virtual void commentUploadFailed(int, CommentError) = mac 0x464800; - virtual void commentUploadFinished(int) = mac 0x464770; - virtual void getUserInfoFinished(GJUserScore*) = mac 0x463cd0; - virtual void loadCommentsFailed(char const*) = mac 0x464340; - virtual void loadCommentsFinished(cocos2d::CCArray*, char const*) = mac 0x464250; - virtual void onClosePopup(UploadActionPopup*) = mac 0x463510; - virtual void registerWithTouchDispatcher() = mac 0x464a60; - virtual void setupPageInfo(gd::string, char const*) = mac 0x464410; - virtual void show() = mac 0x4639c0; - virtual void updateUserScoreFailed() = mac 0x463920; - virtual void updateUserScoreFinished() = mac 0x463850; - virtual void uploadActionFailed(int, int) = mac 0x463710; - virtual void uploadActionFinished(int, int) = mac 0x463570; + virtual void FLAlert_Clicked(FLAlertLayer*, bool) = mac 0x463340, win 0x2128B0; + virtual void commentDeleteFailed(int, int) = mac 0x4648e0, win 0x213D20; + virtual void commentUploadFailed(int, CommentError) = mac 0x464800, win 0x213C40; + virtual void commentUploadFinished(int) = mac 0x464770, win 0x213B90; + virtual void getUserInfoFinished(GJUserScore*) = mac 0x463cd0, win 0x213350; + virtual void loadCommentsFailed(char const*) = mac 0x464340, win 0x2139A0; + virtual void loadCommentsFinished(cocos2d::CCArray*, char const*) = mac 0x464250, win 0x213940; + virtual void onClosePopup(UploadActionPopup*) = mac 0x463510, win 0x2129F0; + virtual void registerWithTouchDispatcher() = mac 0x464a60, win 0x16990; + virtual void setupPageInfo(gd::string, char const*) = mac 0x464410, win 0x213A00; + virtual void show() = mac 0x4639c0, win 0x212d60; + virtual void updateUserScoreFailed() = mac 0x463920, win 0x212D20; + virtual void updateUserScoreFinished() = mac 0x463850, win 0x212C30; + virtual void uploadActionFailed(int, int) = mac 0x463710, win 0x212B20; + virtual void uploadActionFinished(int, int) = mac 0x463570, win 0x212A30; GJUserScore* m_score; int m_accountID; From 6a01f9bebbbb93a61336f9567f494f33c6465f14 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:16:46 +0300 Subject: [PATCH 107/135] Add changelog for 1.4.0 but i probably missed like 20 million things --- CHANGELOG.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 094bce59e..96e27d02c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,32 @@ # Geode Changelog +## v1.4.0 + * Add Android support !!!! + * Implement every Geode functionality except openFolder + * Requires the Geode launcher in order to be used + * Fixes the text input node allowing typing for 1 less character + * Uses `logcat` in order to get crash reports, so reopening the game is required to generate them + * Broma requires classes to be added `[[link(android)]]` in order to be linked + * All Geode and GD files are stored in `Android/data/com.geode.launcher/files` + * Game files in `games`, save files in `save` + * Allow logging to be disabled per mod (6d599a5) + * Mod cells use layouts (114fa46) + * MacOS console is now separate (182984d) + * Add uninstall button to Geode mod (Only functional in Windows currently) (a738320) + * Make new version label invisible on download (0f179da) + * Fix the toggling of disabled dependencies (cd89ef1) + * Fix spritesheet issues (ef47647) + * Change `LoadingLayer` (ef47647) + * Make mod info popup top a layout (dd806e0) + * Add `GEODE_HIDDEN` to inline unique functions (71a79ab) + * Fix big mod icons (26a6c7e) + * Fix `CCNode::removeChildByID` export (23cd456) + * Make `MDTextArea` fit its size (140f38b) + * Enable ESC/Back to go back in Geode mod list (2847bee) + * Add `SimpleTextArea` (7f277a7) + * Check modified date when unzipping `.geode` files (5c765c6) + * Only hash markdown files on resource checking (f563c46) + ## v1.3.5 * Follow redirect in web::utils functions (a942a45) * Lots of bindings From 6cc010f43f2f6a1610b6ce6482c1ffd960d3e37d Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:17:28 +0300 Subject: [PATCH 108/135] the funny no break space --- CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96e27d02c..3d61cbbca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Geode Changelog -## v1.4.0 +## v1.4.0 * Add Android support !!!! * Implement every Geode functionality except openFolder * Requires the Geode launcher in order to be used @@ -248,7 +248,7 @@ Thank you to [Fleeym](https://github.com/Fleeym/Fleeym) for contributing to this * Fix recursive comparison in VersionTag * `geode/unzipped` is now deleted on startup if it exists -## v1.0.0-beta.9 +## v1.0.0-beta.9 * Fix multiple modifiers not being able to have fields on same class due to having same field index * Add `Result::ok` and `Result::err` for converting the `Result` into `std::optional` @@ -316,7 +316,7 @@ Thank you to [Fleeym](https://github.com/Fleeym/Fleeym) for contributing to this - Something related to codegen and addresser? I have no clue what it does, so you probably won't have either - MacOS minimum version bumped to 10.14 -## v1.0.0-beta.2 +## v1.0.0-beta.2 * Fixed bug where `Mod::getSavedValue` would cause a crash due to trying operator on a null JSON value * Fixed bug where loading would crash if one of the mods' binaries failed to load From 089303345e1ba5adf1cb9c286e0d6a694dad941c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:19:17 +0300 Subject: [PATCH 109/135] fix the typo --- CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d61cbbca..33df95f34 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,13 +2,13 @@ ## v1.4.0 * Add Android support !!!! - * Implement every Geode functionality except openFolder + * Implement every Geode functionality except `utils::file::openFolder` * Requires the Geode launcher in order to be used * Fixes the text input node allowing typing for 1 less character * Uses `logcat` in order to get crash reports, so reopening the game is required to generate them * Broma requires classes to be added `[[link(android)]]` in order to be linked * All Geode and GD files are stored in `Android/data/com.geode.launcher/files` - * Game files in `games`, save files in `save` + * Game files in `game`, save files in `save` * Allow logging to be disabled per mod (6d599a5) * Mod cells use layouts (114fa46) * MacOS console is now separate (182984d) From 9558afa8a912dd453ae37bb1c15cdf66f35c477c Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 18:51:08 +0300 Subject: [PATCH 110/135] remove unused codegen code in android --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1244fb93f..317af9efa 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -191,6 +191,9 @@ target_compile_features(GeodeCodegenSources PUBLIC cxx_std_20) if (APPLE) target_compile_options(GeodeCodegenSources PUBLIC -ffunction-sections -fdata-sections) target_link_options(GeodeCodegenSources PUBLIC -dead_strip) +elseif(ANDROID) + target_compile_options(GeodeCodegenSources PUBLIC -ffunction-sections -fdata-sections) + target_link_options(GeodeCodegenSources PUBLIC -Wl,--gc-sections) endif() if (NOT GEODE_DISABLE_PRECOMPILED_HEADERS) From f8c5e9748b1455c512e70022eaa95235ff6c1f10 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:05:08 +0300 Subject: [PATCH 111/135] Strip debug symbols on release for android --- cmake/GeodeFile.cmake | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index a77f175a5..401b46160 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -208,6 +208,17 @@ function(setup_geode_mod proname) set_target_properties(${proname} PROPERTIES PREFIX "") set_target_properties(${proname} PROPERTIES OUTPUT_NAME ${MOD_ID}) + if (ANDROID) + if (CMAKE_BUILD_TYPE STREQUAL "Release") + add_custom_command( + TARGET "${PROJECT_NAME}" POST_BUILD + DEPENDS "${PROJECT_NAME}" + COMMAND $<$:${CMAKE_STRIP}> + ARGS -S $ + ) + endif() + endif() + endfunction() function(create_geode_file proname) From cac2cbc7742cdf4b1dc3da0004d0bfc93e8f2e87 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:20:47 +0300 Subject: [PATCH 112/135] fix field alignment by doing max --- loader/include/Geode/modify/Field.hpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/loader/include/Geode/modify/Field.hpp b/loader/include/Geode/modify/Field.hpp index 8cf95adde..82a7e7514 100644 --- a/loader/include/Geode/modify/Field.hpp +++ b/loader/include/Geode/modify/Field.hpp @@ -1,9 +1,9 @@ #pragma once +#include "../utils/MiniFunction.hpp" #include "Traits.hpp" #include -#include "../utils/MiniFunction.hpp" #include #include @@ -49,8 +49,7 @@ namespace geode::modifier { } }; - [[deprecated("Will be removed in 1.0.0")]] - GEODE_DLL size_t getFieldIndexForClass(size_t hash); + [[deprecated("Will be removed in 1.0.0")]] GEODE_DLL size_t getFieldIndexForClass(size_t hash); GEODE_DLL size_t getFieldIndexForClass(char const* name); template @@ -58,7 +57,7 @@ namespace geode::modifier { using Intermediate = Modify; // Padding used for guaranteeing any member of parents // will be in between sizeof(Intermediate) and sizeof(Parent) - alignas(Base) uintptr_t m_padding; + alignas(std::max(alignof(Base), alignof(uintptr_t))) uintptr_t m_padding; public: // the constructor that constructs the fields. @@ -120,7 +119,7 @@ namespace geode::modifier { reinterpret_cast(offsetField) - sizeof(Intermediate) ); } - + Parent* self() { return this->operator Parent*(); } From 18a5dc706f58518548593fa48c193648e1562e85 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:27:00 +0300 Subject: [PATCH 113/135] remove the bandaid that no one knows what it does --- cmake/GeodeFile.cmake | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index 401b46160..d4a59375b 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -130,27 +130,14 @@ function(setup_geode_mod proname) set(HAS_HEADERS Off) endif() - # todo: figure out how to either not make cmake shit itself and print out --binary path/to/dll "" or - # make cli not shit itself when it sees that - if (HAS_HEADERS) - add_custom_target(${proname}_PACKAGE ALL - DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json - COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} - --binary $ $ - --output ${CMAKE_CURRENT_BINARY_DIR}/${MOD_ID}.geode - ${INSTALL_ARG} - VERBATIM USES_TERMINAL - ) - else() - add_custom_target(${proname}_PACKAGE ALL - DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json - COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} - --binary $ - --output ${CMAKE_CURRENT_BINARY_DIR}/${MOD_ID}.geode - ${INSTALL_ARG} - VERBATIM USES_TERMINAL - ) - endif() + add_custom_target(${proname}_PACKAGE ALL + DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json + COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} + --binary $ + --output ${CMAKE_CURRENT_BINARY_DIR}/${MOD_ID}.geode + ${INSTALL_ARG} + VERBATIM USES_TERMINAL + ) # Add dependency dir to include path if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/geode-deps") From 94b8b327669347c39fba3260468cddd77a8a8f7e Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Sun, 15 Oct 2023 13:37:34 -0300 Subject: [PATCH 114/135] add android build to main workflow --- .github/workflows/build-android.yml | 57 ----------------------------- .github/workflows/build.yml | 48 ++++++++++++++++++++++-- .github/workflows/draft.yml | 2 + 3 files changed, 47 insertions(+), 60 deletions(-) delete mode 100644 .github/workflows/build-android.yml diff --git a/.github/workflows/build-android.yml b/.github/workflows/build-android.yml deleted file mode 100644 index c74d522ae..000000000 --- a/.github/workflows/build-android.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: Build Android - -on: - workflow_dispatch: - push: - branches: - - '**' # every branch - - '!no-build-**' # unless marked as no-build - -jobs: - build: - name: Build Android - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v3 - - - uses: nttld/setup-ndk@v1 - id: setup-ndk - with: - ndk-version: r26b - add-to-path: false - - - name: Download CLI - uses: robinraju/release-downloader@v1.8 - with: - repository: geode-sdk/cli - latest: true - fileName: '*-linux.zip' - tarBall: false - zipBall: false - out-file-path: "cli" - - - name: Setup CLI - run: | - 7z x "${{ github.workspace }}/cli/*-linux.zip" -o"${{ github.workspace }}/cli" - chmod +x $GITHUB_WORKSPACE/cli/geode - echo "${{ github.workspace }}/cli" >> $GITHUB_PATH - - - name: Configure - env: - NDK_HOME: ${{ steps.setup-ndk.outputs.ndk-path }} - ANDROID_ABI: armeabi-v7a - MIN_SDK_VERSION: 24 - run: | - sudo apt install ninja-build - cmake -DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake -DANDROID_ABI=$ANDROID_ABI -DANDROID_PLATFORM=android-$MIN_SDK_VERSION -DCMAKE_BUILD_TYPE=Debug -DGEODE_DONT_BUILD_TEST_MODS=1 -G Ninja -B build - - - name: Build - run: | - cmake --build build --config Debug - - - name: Upload Artifacts - uses: actions/upload-artifact@v3 - with: - name: geode-android - path: ./bin/nightly/*.so diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a0cdd5865..fd54c88e7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,6 +20,7 @@ jobs: - name: Windows os: windows-latest id: win + cli_id: win extra_flags: -T host=x64 -A win32 -DCMAKE_BUILD_TYPE=RelWithDebInfo -DGEODE_DEBUG=On # uncomment to use vs clang-cl and ninja #extra_flags: > @@ -34,6 +35,7 @@ jobs: - name: macOS os: macos-latest id: mac + cli_id: mac extra_flags: > -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ @@ -43,6 +45,21 @@ jobs: cli_cmd: 'chmod +x $GITHUB_WORKSPACE/cli/geode' package_cmd: './installer/mac/package.sh ./bin/nightly ./installer/mac/geode-installer-mac.pkg' installer_path: './installer/mac/geode-installer-mac.pkg' + + - name: Android + os: ubuntu-latest + id: android + cli_id: linux + extra_flags: > + -DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake + -DANDROID_ABI=$ANDROID_ABI + -DANDROID_PLATFORM=android-$MIN_SDK_VERSION + -DGEODE_DONT_BUILD_TEST_MODS=1 + -G Ninja + cli_cmd: 'chmod +x $GITHUB_WORKSPACE/cli/geode' + package_cmd: '' + installer_path: '' + name: Build ${{ matrix.config.name }} runs-on: ${{ matrix.config.os }} @@ -57,7 +74,7 @@ jobs: uses: hendrikmuhs/ccache-action@v1 with: key: ${{ matrix.config.os }} - if: matrix.config.id == 'mac' + if: matrix.config.id != 'win' - name: Setup MSVC uses: ilammy/msvc-dev-cmd@v1.12.1 @@ -65,22 +82,38 @@ jobs: arch: amd64_x86 if: matrix.config.id == 'win' + - name: Setup NDK + uses: nttld/setup-ndk@v1 + id: setup-ndk + with: + ndk-version: r26b + add-to-path: false + if: matrix.config.id == 'android' + - name: Download CLI uses: robinraju/release-downloader@v1.8 with: repository: geode-sdk/cli latest: true - fileName: '*-${{ matrix.config.id }}.zip' + fileName: '*-${{ matrix.config.cli_id }}.zip' tarBall: false zipBall: false out-file-path: "cli" - name: Setup CLI run: | - 7z x "${{ github.workspace }}/cli/*-${{ matrix.config.id }}.zip" -o"${{ github.workspace }}/cli" + 7z x "${{ github.workspace }}/cli/*-${{ matrix.config.cli_id }}.zip" -o"${{ github.workspace }}/cli" ${{ matrix.config.cli_cmd }} echo "${{ github.workspace }}/cli" >> $GITHUB_PATH + - name: Setup Android Env + run: | + echo "NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >> "$GITHUB_ENV" + echo "ANDROID_ABI=armeabi-v7a" >> "$GITHUB_ENV" + echo "MIN_SDK_VERSION=24" >> "$GITHUB_ENV" + sudo apt install ninja-build + if: matrix.config.id == 'android' + - name: Configure run: > cmake -B ${{ github.workspace }}/build @@ -101,12 +134,14 @@ jobs: - name: Package Installer run: ${{ matrix.config.package_cmd }} + if: matrix.config.id != 'android' - name: Upload Installer uses: actions/upload-artifact@v3 with: name: geode-installer-${{ matrix.config.id }} path: ${{ matrix.config.installer_path }} + if: matrix.config.id != 'android' publish: name: Publish @@ -146,6 +181,12 @@ jobs: files: geode-win/XInput9_1_0.dll geode-win/Geode.dll geode-win/GeodeUpdater.exe geode-win/Geode.lib geode-win/Geode.pdb dest: geode-${{ steps.ref.outputs.hash }}-win.zip + - name: Zip Android Artifacts + uses: vimtor/action-zip@v1.1 + with: + files: geode-android/Geode.so + dest: geode-${{ steps.ref.outputs.hash }}-android.zip + - name: Zip Resources uses: vimtor/action-zip@v1.1 with: @@ -166,4 +207,5 @@ jobs: ./geode-installer-${{ steps.ref.outputs.hash }}-win.exe ./geode-${{ steps.ref.outputs.hash }}-mac.zip ./geode-${{ steps.ref.outputs.hash }}-win.zip + ./geode-${{ steps.ref.outputs.hash }}-android.zip ./resources.zip diff --git a/.github/workflows/draft.yml b/.github/workflows/draft.yml index d6051f79d..f6bc76049 100644 --- a/.github/workflows/draft.yml +++ b/.github/workflows/draft.yml @@ -28,6 +28,7 @@ jobs: mv dev/geode-installer-*-win.exe geode-installer-v${{ steps.ref.outputs.version }}-win.exe mv dev/geode-*-mac.zip geode-v${{ steps.ref.outputs.version }}-mac.zip mv dev/geode-*-win.zip geode-v${{ steps.ref.outputs.version }}-win.zip + mv dev/geode-*-android.zip geode-v${{ steps.ref.outputs.version }}-android.zip mv dev/resources.zip resources.zip - name: Create Draft Release @@ -48,4 +49,5 @@ jobs: ./geode-installer-v${{ steps.ref.outputs.version }}-win.exe ./geode-v${{ steps.ref.outputs.version }}-mac.zip ./geode-v${{ steps.ref.outputs.version }}-win.zip + ./geode-v${{ steps.ref.outputs.version }}-android.zip ./resources.zip From 5ec0a6ad7f2e0dda2be2ad2104d8868294c6223b Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:40:24 +0300 Subject: [PATCH 115/135] Readd fod's thing that apparently adds the .lib --- cmake/GeodeFile.cmake | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index d4a59375b..b11d5e9c3 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -130,14 +130,26 @@ function(setup_geode_mod proname) set(HAS_HEADERS Off) endif() - add_custom_target(${proname}_PACKAGE ALL - DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json - COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} - --binary $ - --output ${CMAKE_CURRENT_BINARY_DIR}/${MOD_ID}.geode - ${INSTALL_ARG} - VERBATIM USES_TERMINAL - ) + if (HAS_HEADERS AND WIN32) + # this adds the .lib file on windows, which is needed for linking with the headers + add_custom_target(${proname}_PACKAGE ALL + DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json + COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} + --binary $ $ + --output ${CMAKE_CURRENT_BINARY_DIR}/${MOD_ID}.geode + ${INSTALL_ARG} + VERBATIM USES_TERMINAL + ) + else() + add_custom_target(${proname}_PACKAGE ALL + DEPENDS ${proname} ${CMAKE_CURRENT_SOURCE_DIR}/mod.json + COMMAND ${GEODE_CLI} package new ${CMAKE_CURRENT_SOURCE_DIR} + --binary $ + --output ${CMAKE_CURRENT_BINARY_DIR}/${MOD_ID}.geode + ${INSTALL_ARG} + VERBATIM USES_TERMINAL + ) + endif() # Add dependency dir to include path if (EXISTS "${CMAKE_CURRENT_BINARY_DIR}/geode-deps") From 2f95a133bece84097ac63dacfc9a329340eafabc Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Sun, 15 Oct 2023 14:08:20 -0300 Subject: [PATCH 116/135] change min sdk version to 23 --- .github/workflows/build.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index fd54c88e7..f0ae16bdb 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -52,8 +52,8 @@ jobs: cli_id: linux extra_flags: > -DCMAKE_TOOLCHAIN_FILE=$NDK_HOME/build/cmake/android.toolchain.cmake - -DANDROID_ABI=$ANDROID_ABI - -DANDROID_PLATFORM=android-$MIN_SDK_VERSION + -DANDROID_ABI=armeabi-v7a + -DANDROID_PLATFORM=android-23 -DGEODE_DONT_BUILD_TEST_MODS=1 -G Ninja cli_cmd: 'chmod +x $GITHUB_WORKSPACE/cli/geode' @@ -109,8 +109,6 @@ jobs: - name: Setup Android Env run: | echo "NDK_HOME=${{ steps.setup-ndk.outputs.ndk-path }}" >> "$GITHUB_ENV" - echo "ANDROID_ABI=armeabi-v7a" >> "$GITHUB_ENV" - echo "MIN_SDK_VERSION=24" >> "$GITHUB_ENV" sudo apt install ninja-build if: matrix.config.id == 'android' From 619fb6aa6966a98cd3a3b6fe1df83acf886a9a4a Mon Sep 17 00:00:00 2001 From: Cvolton Date: Sun, 15 Oct 2023 18:47:32 +0200 Subject: [PATCH 117/135] Bindings: Fix ProfilePage and CommentCell virtuals --- bindings/GeometryDash.bro | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 5619fab3c..29cd7568f 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -937,8 +937,8 @@ class CommentCell : TableViewCell, LikeItemDelegate, FLAlertLayerProtocol { void loadFromComment(GJComment*) = mac 0x111c70, win 0x5f3d0; void onConfirmDelete(cocos2d::CCObject* sender) = mac 0x11d100, win 0x61140; void onLike(cocos2d::CCObject* sender) = mac 0x11d000, win 0x60F90; - virtual void FLAlert_Clicked(FLAlertLayer* layer, bool btn) = mac 0x11d540, win 0x61260; virtual void likedItem(LikeItemType type, int id, bool special) = mac 0x11d340, win 0x61070; + virtual void FLAlert_Clicked(FLAlertLayer* layer, bool btn) = mac 0x11d540, win 0x61260; cocos2d::CCSprite* m_iconSprite; cocos2d::CCLabelBMFont* m_likeLabel; @@ -5428,30 +5428,30 @@ class PointNode : cocos2d::CCObject { [[link(android)]] class ProfilePage : FLAlertLayer, FLAlertLayerProtocol, LevelCommentDelegate, CommentUploadDelegate, UserInfoDelegate, UploadActionDelegate, UploadPopupDelegate, LeaderboardManagerDelegate { static ProfilePage* create(int accountID, bool idk) = mac 0x45eed0, win 0x20ee50; - virtual void getUserInfoFailed(int) = mac 0x463FB0, win 0x2133e0; - virtual void userInfoChanged(GJUserScore*) = mac 0x464070, win 0x213430; bool init(int accountID, bool idk) = mac 0x45f170, win 0x20ef00; void onMyLevels(cocos2d::CCObject*) = mac 0x462d70, win 0x211bb0; void onUpdate(cocos2d::CCObject*) = mac 0x460150, win 0x20fa20; void onClose(cocos2d::CCObject*) = mac 0x45fd20, win 0x49C60; - virtual void keyBackClicked() = mac 0x464A60, win 0x49C80; void loadPageFromUserInfo(GJUserScore* score) = mac 0x460480, win 0x210040; + virtual void registerWithTouchDispatcher() = mac 0x464a60, win 0x16990; + virtual void keyBackClicked() = mac 0x464A60, win 0x49C80; + virtual void show() = mac 0x4639c0, win 0x212d60; virtual void FLAlert_Clicked(FLAlertLayer*, bool) = mac 0x463340, win 0x2128B0; - virtual void commentDeleteFailed(int, int) = mac 0x4648e0, win 0x213D20; - virtual void commentUploadFailed(int, CommentError) = mac 0x464800, win 0x213C40; - virtual void commentUploadFinished(int) = mac 0x464770, win 0x213B90; + virtual void updateUserScoreFinished() = mac 0x463850, win 0x212C30; + virtual void updateUserScoreFailed() = mac 0x463920, win 0x212D20; virtual void getUserInfoFinished(GJUserScore*) = mac 0x463cd0, win 0x213350; - virtual void loadCommentsFailed(char const*) = mac 0x464340, win 0x2139A0; + virtual void getUserInfoFailed(int) = mac 0x463FB0, win 0x2133e0; + virtual void userInfoChanged(GJUserScore*) = mac 0x464070, win 0x213430; virtual void loadCommentsFinished(cocos2d::CCArray*, char const*) = mac 0x464250, win 0x213940; - virtual void onClosePopup(UploadActionPopup*) = mac 0x463510, win 0x2129F0; - virtual void registerWithTouchDispatcher() = mac 0x464a60, win 0x16990; + virtual void loadCommentsFailed(char const*) = mac 0x464340, win 0x2139A0; virtual void setupPageInfo(gd::string, char const*) = mac 0x464410, win 0x213A00; - virtual void show() = mac 0x4639c0, win 0x212d60; - virtual void updateUserScoreFailed() = mac 0x463920, win 0x212D20; - virtual void updateUserScoreFinished() = mac 0x463850, win 0x212C30; - virtual void uploadActionFailed(int, int) = mac 0x463710, win 0x212B20; + virtual void commentUploadFinished(int) = mac 0x464770, win 0x213B90; + virtual void commentUploadFailed(int, CommentError) = mac 0x464800, win 0x213C40; + virtual void commentDeleteFailed(int, int) = mac 0x4648e0, win 0x213D20; + virtual void onClosePopup(UploadActionPopup*) = mac 0x463510, win 0x2129F0; virtual void uploadActionFinished(int, int) = mac 0x463570, win 0x212A30; + virtual void uploadActionFailed(int, int) = mac 0x463710, win 0x212B20; GJUserScore* m_score; int m_accountID; From c783a02f3fcfbb8b22ef679b54a10f2444bc0dfb Mon Sep 17 00:00:00 2001 From: dankmeme01 <42031238+dankmeme01@users.noreply.github.com> Date: Sun, 15 Oct 2023 20:02:28 +0200 Subject: [PATCH 118/135] add virtual CCBlockLayer::customSetup --- bindings/GeometryDash.bro | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 29cd7568f..688919ee3 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -308,6 +308,7 @@ class CCBlockLayer : cocos2d::CCLayerColor { virtual bool init() = mac 0x2a59c0, win 0x168d0; virtual void draw() = mac 0x2a5c20, win 0x16a80; // same as GJDropDownLayer virtual void registerWithTouchDispatcher() = mac 0x2a5ad0, win 0x16990; // shared with many + virtual void customSetup() = win 0x7640; virtual void enterLayer() = mac 0x2a5aa0, win 0x16970; virtual void exitLayer() = mac 0x2a5b40, win 0x169e0; // same as PauseLayer, EditorPauseLayer virtual void showLayer(bool) = mac 0x2a5b90, win 0x16a20; // same as PauseLayer, EditorPauseLayer From bbec2c4d732f2ac26c5888792b63141e5d55c4d0 Mon Sep 17 00:00:00 2001 From: Cvolton Date: Mon, 16 Oct 2023 15:10:15 +0200 Subject: [PATCH 119/135] Bindings: Fix DailyLevelPage updateTimers calling convention --- bindings/GeometryDash.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 688919ee3..114afdd17 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1169,7 +1169,7 @@ class CustomizeObjectLayer : FLAlertLayer, TextInputDelegate, HSVWidgetPopupDele class DailyLevelPage : FLAlertLayer, FLAlertLayerProtocol, GJDailyLevelDelegate, LevelDownloadDelegate { static DailyLevelPage* create(bool weekly) = mac 0x108ac0, win 0x6a860; bool init(bool weekly) = mac 0x108C90, win 0x6a900; - void updateTimers(float) = mac 0x109780, win 0x6bef0; + callback void updateTimers(float) = mac 0x109780, win 0x6bef0; virtual void show() = mac 0x10a4b0, win 0x3f360; PAD = mac 0x29, win 0x15, android 0x15; From 6f2044ca92c070045104d7efe0a1f81fb313828d Mon Sep 17 00:00:00 2001 From: Cvolton Date: Mon, 16 Oct 2023 17:15:05 +0200 Subject: [PATCH 120/135] add missing GJRewardTypes --- loader/include/Geode/Enums.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/loader/include/Geode/Enums.hpp b/loader/include/Geode/Enums.hpp index c7fd10064..2e0983aaa 100644 --- a/loader/include/Geode/Enums.hpp +++ b/loader/include/Geode/Enums.hpp @@ -295,7 +295,9 @@ enum class GJRewardType { Unknown = 0x0, Small = 0x1, - Large = 0x2 + Large = 0x2, + SmallTreasure = 0x3, + LargeTreasure = 0x4 }; enum class IconType { From 8ca3b9fce2dbaa87a2d75549abc89a46a5303967 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:47:20 +0300 Subject: [PATCH 121/135] thank you cvolton --- loader/src/ui/internal/GeodeUI.cpp | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp index 99d936b27..9a599c1fd 100644 --- a/loader/src/ui/internal/GeodeUI.cpp +++ b/loader/src/ui/internal/GeodeUI.cpp @@ -17,18 +17,13 @@ void geode::openIssueReportPopup(Mod* mod) { if (mod->getMetadata().getIssues()) { MDPopup::create( "Issue Report", - mod->getMetadata().getIssues().value().info + - "\n\n" + "Please report the issue to the mod that caused the crash.\n" "If your issue relates to a game crash, please include the " "latest crash log(s) from `" + dirs::getCrashlogsDir().string() + "`", - "OK", (mod->getMetadata().getIssues().value().url ? "Open URL" : ""), + "OK", "", [mod](bool btn2) { - if (btn2) { - web::openLinkInBrowser( - mod->getMetadata().getIssues().value().url.value() - ); - } + } )->show(); } From 8c74e3357f2b39f0341af3cd2ecbd524bd27ef88 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:48:38 +0300 Subject: [PATCH 122/135] thank you mat --- loader/src/ui/internal/GeodeUI.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp index 9a599c1fd..c6db6ad19 100644 --- a/loader/src/ui/internal/GeodeUI.cpp +++ b/loader/src/ui/internal/GeodeUI.cpp @@ -21,9 +21,9 @@ void geode::openIssueReportPopup(Mod* mod) { "If your issue relates to a game crash, please include the " "latest crash log(s) from `" + dirs::getCrashlogsDir().string() + "`", - "OK", "", + "OK", "Open Folder", [mod](bool btn2) { - + utils::openFolder(dirs::getCrashlogsDir()) } )->show(); } From 17f892169c9822da86302eaa17d098d3ecce3279 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:48:47 +0300 Subject: [PATCH 123/135] i forgot semicolon --- loader/src/ui/internal/GeodeUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp index c6db6ad19..a0622728b 100644 --- a/loader/src/ui/internal/GeodeUI.cpp +++ b/loader/src/ui/internal/GeodeUI.cpp @@ -23,7 +23,7 @@ void geode::openIssueReportPopup(Mod* mod) { dirs::getCrashlogsDir().string() + "`", "OK", "Open Folder", [mod](bool btn2) { - utils::openFolder(dirs::getCrashlogsDir()) + utils::openFolder(dirs::getCrashlogsDir()); } )->show(); } From 902385fd1b9415c7e5a400a8cb8d699fc6f2b281 Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Mon, 16 Oct 2023 18:49:28 +0300 Subject: [PATCH 124/135] fix namespace --- loader/src/ui/internal/GeodeUI.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/src/ui/internal/GeodeUI.cpp b/loader/src/ui/internal/GeodeUI.cpp index a0622728b..e51049891 100644 --- a/loader/src/ui/internal/GeodeUI.cpp +++ b/loader/src/ui/internal/GeodeUI.cpp @@ -23,7 +23,7 @@ void geode::openIssueReportPopup(Mod* mod) { dirs::getCrashlogsDir().string() + "`", "OK", "Open Folder", [mod](bool btn2) { - utils::openFolder(dirs::getCrashlogsDir()); + file::openFolder(dirs::getCrashlogsDir()); } )->show(); } From b17ca9ae4bb3faec3519b1831a9300b5d82c4daf Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Sun, 22 Oct 2023 11:01:14 -0500 Subject: [PATCH 125/135] docs change lmao --- loader/include/Geode/utils/web.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/loader/include/Geode/utils/web.hpp b/loader/include/Geode/utils/web.hpp index f87313d47..b64c63a3c 100644 --- a/loader/include/Geode/utils/web.hpp +++ b/loader/include/Geode/utils/web.hpp @@ -194,7 +194,7 @@ namespace geode::utils::web { * URL to fetch from the internet asynchronously * @param url URL of the data to download. Redirects will be * automatically followed - * @returns Same AsyncWebRequest + * @returns An AsyncWebResponse object */ AsyncWebResponse fetch(std::string const& url); /** From 23bfc22d1159286546f52cece509954fc0e80abb Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Sun, 22 Oct 2023 11:50:58 -0500 Subject: [PATCH 126/135] someone made an oopsie in SentAsyncWebRequest::Impl's constructor --- loader/src/utils/web.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/loader/src/utils/web.cpp b/loader/src/utils/web.cpp index 7675f46cf..6bfea64dc 100644 --- a/loader/src/utils/web.cpp +++ b/loader/src/utils/web.cpp @@ -187,7 +187,7 @@ static std::unordered_map RUNNING_REQUES static std::mutex RUNNING_REQUESTS_MUTEX; SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const& req, std::string const& id) : - m_id(id), m_url(req.m_url), m_target(req.m_target), m_extra(req.extra()), m_httpHeaders(req.m_httpHeaders) { + m_self(self), m_id(id), m_url(req.m_url), m_target(req.m_target), m_extra(req.extra()), m_httpHeaders(req.m_httpHeaders) { #define AWAIT_RESUME() \ {\ @@ -296,6 +296,7 @@ SentAsyncWebRequest::Impl::Impl(SentAsyncWebRequest* self, AsyncWebRequest const } return 1; } + Loader::get()->queueInMainThread([self = data->self, now, total]() { std::lock_guard _(self->m_mutex); for (auto& prog : self->m_progresses) { From 278869ec68fc45e42e949b38e0503bf012e35941 Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Sun, 22 Oct 2023 13:41:20 -0500 Subject: [PATCH 127/135] add my binding --- bindings/GeometryDash.bro | 1 + 1 file changed, 1 insertion(+) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 2bf7c1d36..9ea588aa1 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1061,6 +1061,7 @@ class CustomSongLayer : FLAlertLayer, FLAlertLayerProtocol, TextInputDelegate, G bool init(LevelSettingsObject*) = mac 0xf06f0, win 0x65c10; void onArtists(cocos2d::CCObject*) = mac 0xf1950; void onSongBrowser(cocos2d::CCObject*) = mac 0xf18a0, win 0x67080; + void onSearch(cocos2d::CCObject*) = mac 0xf1ad0, win 0x66de0; LevelSettingsObject* m_levelSettings; CCTextInputNode* m_songIDInput; From 9186ecadc51dcde0ebf85306aaa691552838ff77 Mon Sep 17 00:00:00 2001 From: camila314 <47485054+camila314@users.noreply.github.com> Date: Sun, 22 Oct 2023 14:57:59 -0500 Subject: [PATCH 128/135] add thing --- bindings/GeometryDash.bro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 9ea588aa1..2ae29af04 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1017,7 +1017,7 @@ class CreatorLayer : cocos2d::CCLayer, cocos2d::CCSceneTransitionDelegate, Dialo void onTreasureRoom(cocos2d::CCObject*) = win 0x4f540; virtual void sceneWillResume() = mac 0x1438F0, win 0x4fb50; virtual bool init() = mac 0x141c10, win 0x4de40; - static CreatorLayer* create() = win 0x4dda0; + static CreatorLayer* create() = mac 0x141b10, win 0x4dda0; } [[link(android)]] From 3500ce98967289b543151a5c1bc03c780fdcdcfa Mon Sep 17 00:00:00 2001 From: Cvolton Date: Tue, 31 Oct 2023 19:42:10 +0100 Subject: [PATCH 129/135] Bindings: add SearchButton (#322) --- bindings/GeometryDash.bro | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 2ae29af04..1f774bae3 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -4322,6 +4322,15 @@ class LevelSettingsDelegate { virtual void levelSettingsUpdated() {} } +[[link(android)]] +class SearchButton : cocos2d::CCSprite { + static SearchButton* create(char const* background, char const* text, float scale, char const* icon) = win 0x182120, mac 0x3869A0; + bool init(char const* background, char const* text, float scale, char const* icon) = win 0x182210, mac 0x389290; + + cocos2d::CCLabelBMFont* m_text; + cocos2d::CCSprite* m_icon; +} + [[link(android)]] class SecretLayer2 : cocos2d::CCLayer, TextInputDelegate, FLAlertLayerProtocol, DialogDelegate { static SecretLayer2* create() = win 0x21FD70; From 80539b493b4ca67eefa15b28086d481922fbb618 Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Thu, 9 Nov 2023 22:43:25 -0300 Subject: [PATCH 130/135] fix bindings --- bindings/GeometryDash.bro | 2 -- 1 file changed, 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 0556963cd..563747c0c 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5450,8 +5450,6 @@ class PointNode : cocos2d::CCObject { class ProfilePage : FLAlertLayer, FLAlertLayerProtocol, LevelCommentDelegate, CommentUploadDelegate, UserInfoDelegate, UploadActionDelegate, UploadPopupDelegate, LeaderboardManagerDelegate { static ProfilePage* create(int accountID, bool idk) = mac 0x45eed0, win 0x20ee50; ProfilePage() = win 0x20e920; - virtual void getUserInfoFailed(int) = mac 0x463FB0, win 0x2133e0; - virtual void userInfoChanged(GJUserScore*) = mac 0x464070, win 0x213430; bool init(int accountID, bool idk) = mac 0x45f170, win 0x20ef00; void onYoutube(cocos2d::CCObject*) = mac 0x462360, win 0x212e80; void onTwitter(cocos2d::CCObject*) = mac 0x462500, win 0x212fe0; From 8d8001a65501959a7359a64a5c871c6c25aba276 Mon Sep 17 00:00:00 2001 From: mat <26722564+matcool@users.noreply.github.com> Date: Thu, 9 Nov 2023 22:54:34 -0300 Subject: [PATCH 131/135] ok idc about this class for now --- bindings/GeometryDash.bro | 7 ------- 1 file changed, 7 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 563747c0c..9c63e114b 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5523,13 +5523,6 @@ class RateStarsLayer : FLAlertLayer, UploadPopupDelegate, UploadActionDelegate { bool init(int levelID, bool isModSuggest) = mac 0x136050, win 0x2156a0; } -class RateLevelLayer : FLAlertLayer { - RateLevelLayer() = win 0x214a80; - virtual ~RateLevelLayer() = win 0x214b40; - - bool init(int levelID) = win 0x214cb0; -} - [[link(android)]] class RetryLevelLayer { static RetryLevelLayer* create() = mac 0x28dd60, win 0x216390; From b76eb1245832047dddde0ff313af61dfa4a16faa Mon Sep 17 00:00:00 2001 From: altalk23 <45172705+altalk23@users.noreply.github.com> Date: Tue, 21 Nov 2023 20:34:12 +0300 Subject: [PATCH 132/135] fix onShare --- bindings/GeometryDash.bro | 2 +- loader/src/loader/LoaderImpl.hpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 6a8f1bcf5..09982edf6 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -5809,7 +5809,7 @@ class SetupTouchTogglePopup : FLAlertLayer { class ShareCommentLayer : FLAlertLayer, TextInputDelegate, UploadActionDelegate, UploadPopupDelegate { static ShareCommentLayer* create(gd::string, int, CommentType, int) = win 0x24bac0; bool init(gd::string, int, CommentType, int) = win 0x24bb90; - void onShare(CCObject*) = win 0x24c760; + void onShare(cocos2d::CCObject*) = win 0x24c760; } [[link(android)]] diff --git a/loader/src/loader/LoaderImpl.hpp b/loader/src/loader/LoaderImpl.hpp index 16714e7c2..c9f8c3c7f 100644 --- a/loader/src/loader/LoaderImpl.hpp +++ b/loader/src/loader/LoaderImpl.hpp @@ -71,7 +71,6 @@ namespace geode { std::vector> m_gdThreadQueue; mutable std::mutex m_gdThreadMutex; - bool m_platformConsoleOpen = false; std::vector> m_uninitializedHooks; bool m_readyToHook = false; From cb8f51e86cfcdbd8713ccd9021e2af5fd9ad52bd Mon Sep 17 00:00:00 2001 From: Cvolton Date: Thu, 7 Dec 2023 00:36:17 +0100 Subject: [PATCH 133/135] add DailyLevelNode::init --- bindings/GeometryDash.bro | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 09982edf6..2c3519a5c 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -1177,6 +1177,11 @@ class DailyLevelPage : FLAlertLayer, FLAlertLayerProtocol, GJDailyLevelDelegate, bool m_weekly; } +[[link(android)]] +class DailyLevelNode : cocos2d::CCNode, FLAlertLayerProtocol { + bool init(GJGameLevel* level, DailyLevelPage* page, bool weekly) = mac 0x10ABB0, win 0x6C480; +} + [[link(android)]] class DialogLayer : cocos2d::CCLayerColor { static DialogLayer* create(DialogObject* dialog, int color) { From ffed1df4fc031c1d036bad51fce8d3342dd3283c Mon Sep 17 00:00:00 2001 From: Cvolton Date: Wed, 13 Dec 2023 01:01:58 +0100 Subject: [PATCH 134/135] Fix Android strip not being run without Geode CLI --- cmake/GeodeFile.cmake | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cmake/GeodeFile.cmake b/cmake/GeodeFile.cmake index b11d5e9c3..d3a7d5530 100644 --- a/cmake/GeodeFile.cmake +++ b/cmake/GeodeFile.cmake @@ -51,6 +51,17 @@ function(setup_geode_mod proname) # Link Geode to the mod target_link_libraries(${proname} geode-sdk) + if (ANDROID) + if (CMAKE_BUILD_TYPE STREQUAL "Release") + add_custom_command( + TARGET "${PROJECT_NAME}" POST_BUILD + DEPENDS "${PROJECT_NAME}" + COMMAND $<$:${CMAKE_STRIP}> + ARGS -S $ + ) + endif() + endif() + if (GEODE_DISABLE_CLI_CALLS) message("Skipping setting up geode mod ${proname}") return() @@ -207,17 +218,6 @@ function(setup_geode_mod proname) set_target_properties(${proname} PROPERTIES PREFIX "") set_target_properties(${proname} PROPERTIES OUTPUT_NAME ${MOD_ID}) - if (ANDROID) - if (CMAKE_BUILD_TYPE STREQUAL "Release") - add_custom_command( - TARGET "${PROJECT_NAME}" POST_BUILD - DEPENDS "${PROJECT_NAME}" - COMMAND $<$:${CMAKE_STRIP}> - ARGS -S $ - ) - endif() - endif() - endfunction() function(create_geode_file proname) From d22dc28ad9a00238e517d1a121a889a3f3fcb455 Mon Sep 17 00:00:00 2001 From: Cvolton Date: Sun, 17 Dec 2023 19:38:59 +0100 Subject: [PATCH 135/135] Bindings: Improve song related stuff --- bindings/GeometryDash.bro | 29 +++++++++++++++++++++++++++-- loader/test/members/Android.cpp | 3 +++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/bindings/GeometryDash.bro b/bindings/GeometryDash.bro index 2c3519a5c..7d432bc3c 100644 --- a/bindings/GeometryDash.bro +++ b/bindings/GeometryDash.bro @@ -2442,7 +2442,7 @@ class GJGameLevel : cocos2d::CCNode { void dataLoaded(DS_Dictionary* dict) = mac 0x2dc0e0, win 0xbded0, ios 0x6fca4; GJDifficulty getAverageDifficulty() = win 0xbd9b0; gd::string getUnpackedLevelDescription() = mac 0x2DDB50, win 0xbf890; - gd::string lengthKeyToString(int key) = win 0xbd910; + static gd::string lengthKeyToString(int key) = mac 0x2DBBD0, win 0xbd910; static GJGameLevel* getCurrent() { auto playLayer = PlayLayer::get(); @@ -2823,6 +2823,11 @@ class GJSearchObject : cocos2d::CCNode { bool m_songFilter; } +[[link(android)]] +class GJSongBrowser : GJDropDownLayer, FLAlertLayerProtocol { + static GJSongBrowser* create(LevelSettingsObject* levelSettingsObject) = mac 0x3685D0, win 0x14CB20; +} + [[link(android)]] class GJSpecialColorSelect { static const char* textForColorIdx(int id) = mac 0x383a50, win 0x14e1d0, ios 0x113f6c; @@ -3050,6 +3055,15 @@ class GameLevelManager : cocos2d::CCNode { const char* getAccountCommentKey(int a2, int a3){ return cocos2d::CCString::createWithFormat("a_%i_%i", a2, a3)->getCString(); } + bool getBoolForKey(char const* key) { + return m_searchFilters->valueForKey(key)->boolValue(); + } + int getIntForKey(char const* key) { + return m_searchFilters->valueForKey(key)->intValue(); + } + void setIntForKey(int value, char const* key) { + m_searchFilters->setObject(cocos2d::CCString::createWithFormat("%i", value), key); + } inline static GameLevelManager* get() { return GameLevelManager::sharedState(); @@ -4605,10 +4619,20 @@ class MenuLayer : cocos2d::CCLayer, FLAlertLayerProtocol, GooglePlayDelegate { class MessageListDelegate {} [[link(android)]] -class MoreSearchLayer : FLAlertLayer { +class MoreSearchLayer : FLAlertLayer, TextInputDelegate { static MoreSearchLayer* create() = mac 0x388180, win 0x182520; virtual bool init() = mac 0x3896b0, win 0x1825c0; void onClose(cocos2d::CCObject*) = mac 0x38aa40, win 0x1848f0; + void onSongMode(cocos2d::CCObject*) = mac 0x38b030, win 0x1842d0; + void onSongFilter(cocos2d::CCObject*) = mac 0x38aea0, win 0x183e30; + + cocos2d::CCLabelBMFont* m_audioTrackName; + CCMenuItemSpriteExtra* m_songLeftBtn; + CCMenuItemSpriteExtra* m_songRightBtn; + CCMenuItemSpriteExtra* m_normalBtn; + CCMenuItemSpriteExtra* m_customBtn; + CCTextInputNode* m_enterSongID; + } [[link(android)]] @@ -4647,6 +4671,7 @@ class MusicDownloadManager : cocos2d::CCNode, PlatformDownloadDelegate { cocos2d::CCArray* getDownloadedSongs() = win 0x195640; void songStateChanged() = win 0x194d90; void onGetSongInfoCompleted(gd::string, gd::string) = mac 0x2eec60; + bool isSongDownloaded(int songID) = mac 0x2F0E10, win 0x195FF0; cocos2d::CCDictionary* m_unknownDict; cocos2d::CCArray* m_handlers; diff --git a/loader/test/members/Android.cpp b/loader/test/members/Android.cpp index dd8ff7b51..d7e61a349 100644 --- a/loader/test/members/Android.cpp +++ b/loader/test/members/Android.cpp @@ -33,4 +33,7 @@ GEODE_MEMBER_CHECK(EditorUI, m_updateTimeMarkers, 0x1a4); GEODE_MEMBER_CHECK(EditorUI, m_selectedObjects, 0x1bc); GEODE_MEMBER_CHECK(EditorUI, m_selectedObject, 0x2c4); +GEODE_MEMBER_CHECK(MoreSearchLayer, m_enterSongID, 0x1E4); +GEODE_MEMBER_CHECK(MoreSearchLayer, m_songLeftBtn, 0x1D4); + #endif \ No newline at end of file