diff --git a/mod.json b/mod.json index ec822d5..6de2669 100644 --- a/mod.json +++ b/mod.json @@ -1,5 +1,5 @@ { - "geode": "4.0.1", + "geode": "4.1.1", "gd": { "win": "2.2074", "android": "2.2074", diff --git a/src/NodeModding.cpp b/src/NodeModding.cpp index 6a38d0a..dc9840a 100644 --- a/src/NodeModding.cpp +++ b/src/NodeModding.cpp @@ -7,25 +7,66 @@ using namespace geode::prelude; -class $modify(MyCCObject, CCObject) { +class CCAutoreleasePoolHack : public CCObject { +public: + CCArray* m_pManagedObjectArray; +}; - static void onModify(auto& self) { - HOOK_LATEST("cocos2d::CCObject::autorelease"); +class CCPoolManagerHack { +public: + CCArray* m_pReleasePoolStack; + CCAutoreleasePool* m_pCurReleasePool; +}; + +class NodeModding : public CCObject { +public: + static NodeModding* create() { + auto ret = new NodeModding(); + ret->autorelease(); + return ret; + } + + static NodeModding* get() { + static NodeModding* instance = nullptr; + if (!instance) { + instance = NodeModding::create(); + } + return instance; + } + + void handleCurrentNode(CCNode* node) { + std::string className = Utils::getNodeName(node); + UIModding::get()->doUICheckForType(className, node); + } + + void handleArray(CCArray* array) { + auto scene = CCDirector::sharedDirector()->getRunningScene(); + + if (scene && UIModding::get()->doModify && UIModding::get()->finishedLoad && !Callbacks::get()->m_ignoreUICheck) { + + for (auto object : CCArrayExt(array)) { + if (auto node = typeinfo_cast(object)) { + handleCurrentNode(node); + } + } + } } +}; + +#include - CCObject* autorelease() { - if (!UIModding::get()->finishedLoad || !UIModding::get()->doModify || Callbacks::get()->m_ignoreUICheck) - return CCObject::autorelease(); - - if (CCNode* node = typeinfo_cast(this)) { - node->retain(); - std::string className = Utils::getNodeName(this); - queueInMainThread([=] { - UIModding::get()->doUICheckForType(className, node); - node->release(); - }); +class $modify(CCPoolManager) { + void pop() { + auto poolManager = reinterpret_cast(this); + + if (poolManager && poolManager->m_pCurReleasePool) { + auto pool = reinterpret_cast(poolManager->m_pCurReleasePool); + + if (pool->m_pManagedObjectArray) { + NodeModding::get()->handleArray(pool->m_pManagedObjectArray); + } } - - return CCObject::autorelease(); + + return CCPoolManager::pop(); } }; \ No newline at end of file diff --git a/src/nodes/CCScene.h b/src/nodes/CCScene.h index 6f6b383..5758a9f 100644 --- a/src/nodes/CCScene.h +++ b/src/nodes/CCScene.h @@ -8,37 +8,50 @@ using namespace geode::prelude; -class $modify(MyCCScene, CCScene) { - - static void onModify(auto& self) { - HOOK_LATEST("cocos2d::CCScene::create"); +class SceneHandler : public CCObject { +public: + static SceneHandler* create() { + auto ret = new SceneHandler(); + ret->autorelease(); + return ret; } - struct Fields { - int m_currentCount = 0; - bool m_isMenuLayer = false; - }; + CCScene* m_currentScene = nullptr; + + // IMPORTANT: might contain dangling pointers, + // do not use for anything other than checking + std::unordered_set m_handledNodes; - static CCScene* create() { - auto ret = CCScene::create(); - if (UIModding::get()->doModify) { - ret->schedule(schedule_selector(MyCCScene::checkForUpdates)); + void checkForUpdates(CCScene* scene) { + if (Callbacks::get()->m_ignoreUICheck) return; + + if (scene != m_currentScene) { + // we're in a new scene, clear the handled nodes + m_handledNodes.clear(); + m_currentScene = scene; + } + + for (auto node : CCArrayExt(scene->getChildren())) { + if (m_handledNodes.find(node) != m_handledNodes.end()) continue; + m_handledNodes.insert(node); + + if (node->getID() == "MenuLayer") continue; // hardcoded for now + + UIModding::get()->doUICheck(node); } - return ret; } - void checkForUpdates(float dt) { - if (this->getChildrenCount() != m_fields->m_currentCount && (this->getChildrenCount() != 1 || m_fields->m_currentCount == 0)) { - int idx = 0; - - for (CCNode* node : CCArrayExt(this->getChildren())) { - idx++; - if (node->getID() == "MenuLayer" || Callbacks::get()->m_ignoreUICheck) continue; - if (idx > m_fields->m_currentCount) { - UIModding::get()->doUICheck(node); - } - } + void update(float dt) { + auto scene = CCDirector::sharedDirector()->getRunningScene(); + + if (scene && UIModding::get()->doModify) { + this->checkForUpdates(scene); } - m_fields->m_currentCount = this->getChildrenCount(); } -}; \ No newline at end of file +}; + +$execute { + Loader::get()->queueInMainThread([]{ + CCScheduler::get()->scheduleUpdateForTarget(SceneHandler::create(), INT_MAX, false); + }); +} \ No newline at end of file