diff --git a/changelog.md b/changelog.md index b59b19f..b1f27e2 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,8 @@ +## 1.8.5 +- Cleanup filesystem code +- Fix a crash when there is an invalid path (hopefully) +- Fix an issue with CCSpriteWithHue. Do note that changing the wraith textures is still broken and has inconsistent behavior + ## 1.8.4 - Actually fix loading individual sprites from init diff --git a/mod.json b/mod.json index 1a8713a..69cf920 100644 --- a/mod.json +++ b/mod.json @@ -5,7 +5,7 @@ "android": "2.2074", "mac": "2.2074" }, - "version": "v1.8.4", + "version": "v1.8.5", "id": "alphalaneous.happy_textures", "name": "Happy Textures :3", "developer": "Alphalaneous", @@ -16,6 +16,11 @@ "id": "geode.node-ids", "version": ">=v1.15.0", "importance": "required" + }, + { + "id": "geode.texture-loader", + "version": ">=v1.7.0", + "importance": "suggested" } ], "resources": { diff --git a/src/Config.h b/src/Config.h index 56bef2a..0c13d4b 100644 --- a/src/Config.h +++ b/src/Config.h @@ -10,8 +10,8 @@ class Config { bool m_batchNodesEnabled = true; void loadPackJsons() { - for (std::string packPath : Utils::getActivePacks()) { - std::filesystem::path json = std::filesystem::path{packPath} / "pack.json"; + for (std::filesystem::path packPath : Utils::getActivePacks()) { + std::filesystem::path json = packPath / "pack.json"; if (!std::filesystem::exists(json)) continue; std::ifstream inputFile(json); diff --git a/src/FileWatcher.h b/src/FileWatcher.h index 6e44cea..754dbce 100644 --- a/src/FileWatcher.h +++ b/src/FileWatcher.h @@ -19,11 +19,10 @@ enum class FileStatus {created, modified, erased}; class FileWatcher { public: - FileWatcher(std::string pathToWatch, std::chrono::duration delay) : m_pathToWatch(pathToWatch), m_delay{delay} { + FileWatcher(std::filesystem::path pathToWatch, std::chrono::duration delay) : m_pathToWatch(pathToWatch), m_delay{delay} { if (std::filesystem::is_directory(pathToWatch)) { - auto path = std::filesystem::path{utils::string::replace(pathToWatch, "\\", "/")}.lexically_normal().make_preferred(); - for (auto& file : std::filesystem::recursive_directory_iterator(path)) { + for (auto& file : std::filesystem::recursive_directory_iterator(pathToWatch)) { m_paths[file.path()] = std::filesystem::last_write_time(file); } } @@ -67,7 +66,7 @@ class FileWatcher { private: std::unordered_map m_paths; std::chrono::duration m_delay; - std::string m_pathToWatch = ""; + std::filesystem::path m_pathToWatch = ""; bool m_running = true; bool contains(const std::filesystem::path &key) { diff --git a/src/TextureLoader.hpp b/src/TextureLoader.hpp deleted file mode 100644 index f7f1623..0000000 --- a/src/TextureLoader.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include - -#include -#include -#include - -namespace geode::texture_loader { - -inline bool isLoaded() { - return geode::Loader::get()->isModLoaded("geode.texture-loader"); -} - -struct Pack { - std::string id; - std::string name; - VersionInfo version; - std::vector authors; - - /// Path from where the pack originates from. May be a file (apk, zip) or a folder - std::filesystem::path path; - /// Path where the resources are located. This is what is added to the search path - std::filesystem::path resourcesPath; -}; - -namespace impl { - using EventGetAvailablePacks = geode::DispatchEvent*>; - using EventGetAppliedPacks = geode::DispatchEvent*>; -} - -inline std::vector getAvailablePacks() { - std::vector result; - impl::EventGetAvailablePacks("geode.texture-loader/v1/get-available-packs", &result).post(); - return result; -} - -inline std::vector getAppliedPacks() { - std::vector result; - impl::EventGetAppliedPacks("geode.texture-loader/v1/get-applied-packs", &result).post(); - return result; -} - -} \ No newline at end of file diff --git a/src/UIModding.cpp b/src/UIModding.cpp index 61e2892..44626f3 100644 --- a/src/UIModding.cpp +++ b/src/UIModding.cpp @@ -914,16 +914,15 @@ std::vector generateValidSprites(std::string path, matjson::Value s std::vector validSprites; if (!path.empty()) { - std::vector packs = Utils::getActivePacks(); - for (std::string packPath : packs) { - std::string sprPath = fmt::format("{}{}", packPath, path); - if (std::filesystem::is_directory(sprPath)) { - for (const auto& entry : std::filesystem::directory_iterator(sprPath)) { - std::string textureName = utils::string::split(entry.path().filename().string(), ".").at(0); - if (!utils::string::endsWith(textureName, "-hd") && !utils::string::endsWith(textureName, "-uhd")) { - std::string sprName = fmt::format("{}\\{}", path, entry.path().filename().string()); - sprites.push_back(sprName); - } + std::vector packs = Utils::getActivePacks(); + for (std::filesystem::path packPath : packs) { + std::filesystem::path sprPath = packPath / path; + if (!std::filesystem::is_directory(sprPath)) continue; + for (const auto& entry : std::filesystem::directory_iterator(sprPath)) { + std::string textureName = utils::string::split(entry.path().filename().string(), ".").at(0); + if (!utils::string::endsWith(textureName, "-hd") && !utils::string::endsWith(textureName, "-uhd")) { + std::string sprName = fmt::format("{}\\{}", path, entry.path().filename().string()); + sprites.push_back(sprName); } } } @@ -1574,10 +1573,9 @@ void UIModding::startFileListeners() { fw->stop(); } listeners.clear(); - std::vector packs = Utils::getActivePacks(); - for (std::string path : packs) { - - std::string uiPath = fmt::format("{}{}", path, "ui\\"); + std::vector packs = Utils::getActivePacks(); + for (std::filesystem::path path : packs) { + std::filesystem::path uiPath = path / "ui"; FileWatcher* fw = new FileWatcher(uiPath, std::chrono::milliseconds(500)); listeners.push_back(fw); @@ -1624,9 +1622,9 @@ AxisAlignment UIModding::getAxisAlignment(std::string name) { } void UIModding::loadNodeFiles() { - std::vector packs = Utils::getActivePacks(); - for (std::string path : packs) { - std::filesystem::path nodePath = std::filesystem::path{utils::string::replace(fmt::format("{}{}", path, "ui/nodes/"), "\\", "/")}.lexically_normal().make_preferred(); + std::vector packs = Utils::getActivePacks(); + for (std::filesystem::path path : packs) { + std::filesystem::path nodePath = path / "ui" / "nodes"; if (std::filesystem::is_directory(nodePath)) { for (const auto& entry : std::filesystem::directory_iterator(nodePath)) { diff --git a/src/UIModding.h b/src/UIModding.h index 174c9c2..5a58045 100644 --- a/src/UIModding.h +++ b/src/UIModding.h @@ -2,6 +2,7 @@ #include #include "FileWatcher.h" + using namespace geode::prelude; struct ColorData { @@ -18,9 +19,10 @@ class UIModding { std::map uiCache; std::map colorCache; std::map randomSprites; - std::vector activePackCache; + std::vector activePackCache; std::unordered_map filenameCache; std::unordered_map spritesChanged; + std::unordered_map frameToNameMap; std::vector listeners; Ref removalQueue = CCArray::create(); @@ -66,7 +68,7 @@ class UIModding { void loadNodeFiles(); void doUICheck(CCNode* node); void doUICheckForType(std::string name, CCNode* node); - std::vector getActivePacks(); + std::vector getActivePacks(); void startFileListeners(); AxisAlignment getAxisAlignment(std::string name); std::optional getColors(std::string name); diff --git a/src/Utils.h b/src/Utils.h index 8d5709b..fcd2156 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -4,7 +4,7 @@ #include "UIModding.h" #include #include "Macros.h" -#include "TextureLoader.hpp" +#include using namespace geode::prelude; @@ -119,8 +119,6 @@ namespace Utils { #endif } - - static void setColorIfExists(CCRGBAProtocol* node, std::string colorId) { if (!node) return; std::optional dataOpt = UIModding::get()->getColors(colorId); @@ -143,6 +141,17 @@ namespace Utils { return ""; } + static std::string getSpriteName(CCSpriteFrame* spriteFrame) { + if (UIModding::get()->frameToNameMap.contains(spriteFrame)) return UIModding::get()->frameToNameMap[spriteFrame]; + for (auto [key, frame] : CCDictionaryExt(CCSpriteFrameCache::sharedSpriteFrameCache()->m_pSpriteFrames)) { + if (spriteFrame == frame) { + UIModding::get()->frameToNameMap[spriteFrame] = key; + return key; + } + } + return ""; + } + static std::string getHookPrioLatest(const std::string& name) { int minPriority = 0; const Mod* currentMod = Mod::get(); @@ -178,27 +187,28 @@ namespace Utils { UIModding::get()->activePackCache.clear(); } - static std::vector getActivePacks() { + static std::vector getActivePacks() { if (!UIModding::get()->activePackCache.empty()) return UIModding::get()->activePackCache; Mod* textureLoader = Loader::get()->getLoadedMod("geode.texture-loader"); if (textureLoader) { if (textureLoader->getVersion() >= VersionInfo{1, 7, 0}) { - for(geode::texture_loader::Pack pack : geode::texture_loader::getAppliedPacks()) { - UIModding::get()->activePackCache.push_back(pack.resourcesPath.string() + "/"); + for (geode::texture_loader::Pack pack : geode::texture_loader::getAppliedPacks()) { + UIModding::get()->activePackCache.push_back(pack.resourcesPath); } } else { log::info("Using old pack method. Update Texture Loader!"); for (matjson::Value value : textureLoader->getSavedValue>("applied")) { if (value.isObject() && value.contains("path") && value["path"].isString()) { - std::string path = value["path"].asString().unwrapOr(""); - if (utils::string::endsWith(path, ".zip")) { + std::filesystem::path path = std::filesystem::path{utils::string::replace(value["path"].asString().unwrapOr(""), "\\", "/")}; + if (path.extension().string() == ".zip") { std::filesystem::path pathFs{path}; - path = (textureLoader->getSaveDir() / "unzipped" / pathFs.filename()).string(); + path = textureLoader->getSaveDir() / "unzipped" / pathFs.filename(); } - UIModding::get()->activePackCache.push_back(path + "/"); + if (!std::filesystem::is_directory(path)) continue; + UIModding::get()->activePackCache.push_back(path); } } } @@ -209,7 +219,7 @@ namespace Utils { static std::string qualityToNormal(std::string str) { std::vector fileParts = utils::string::split(str, "."); - + if (fileParts.size() < 1) return str; std::string suffix = fileParts[fileParts.size()-1]; std::string prefix = str.substr(0, str.size() - suffix.size() - 1); @@ -225,12 +235,13 @@ namespace Utils { static void reloadFileNames() { UIModding::get()->filenameCache.clear(); - for (std::string packPath : Utils::getActivePacks()) { - + for (std::filesystem::path packPath : Utils::getActivePacks()) { + if (!std::filesystem::is_directory(packPath)) continue; for (const auto& entry : std::filesystem::recursive_directory_iterator(packPath)) { if (entry.is_regular_file()) { std::string pathStr = entry.path().string(); - std::string subStr = pathStr.substr(packPath.size()); + std::string subStr = pathStr.substr(packPath.string().size() + 1); + log::info("subStr: {}", subStr); UIModding::get()->filenameCache[qualityToNormal(utils::string::replace(subStr, "\\", "/"))] = true; } } diff --git a/src/nodes/CCSprite.h b/src/nodes/CCSprite.h index 4fa833f..1138b20 100644 --- a/src/nodes/CCSprite.h +++ b/src/nodes/CCSprite.h @@ -2,8 +2,29 @@ #include #include +#include #include "../Macros.h" +class $modify(MyCCSpriteWithHue, CCSpriteWithHue) { + + static void onModify(auto& self) { + (void) self.setHookPriority("cocos2d::CCSpriteWithHue::initWithSpriteFrame", Priority::VeryEarly); + } + + bool initWithSpriteFrame(cocos2d::CCSpriteFrame* p0) { + std::string frameName = Utils::getSpriteName(p0); + + if (Utils::spriteExistsInPacks(frameName) && !UIModding::get()->spritesChanged[frameName]) { + CCSprite* spr = CCSprite::create(frameName.c_str()); + auto spriteFrame = CCSpriteFrame::createWithTexture(spr->getTexture(), spr->getTextureRect()); + CCSpriteFrameCache::get()->addSpriteFrame(spriteFrame, frameName.c_str()); + UIModding::get()->spritesChanged[frameName] = true; + } + + return CCSpriteWithHue::initWithSpriteFrame(p0); + } +}; + class $modify(MyCCSprite, CCSprite) { static void onModify(auto& self) { @@ -19,7 +40,6 @@ class $modify(MyCCSprite, CCSprite) { CCSpriteFrameCache::get()->addSpriteFrame(spriteFrame, pszSpriteFrameName); UIModding::get()->spritesChanged[pszSpriteFrameName] = true; } - return CCSprite::initWithSpriteFrameName(pszSpriteFrameName); } diff --git a/src/nodes/LoadingLayer.h b/src/nodes/LoadingLayer.h index 6abdeb5..ce44079 100644 --- a/src/nodes/LoadingLayer.h +++ b/src/nodes/LoadingLayer.h @@ -20,6 +20,7 @@ class $modify(MyLoadingLayer, LoadingLayer) { UIModding::get()->uiCache.clear(); UIModding::get()->colorCache.clear(); UIModding::get()->spritesChanged.clear(); + UIModding::get()->frameToNameMap.clear(); queueInMainThread([] { Utils::clearActivePackCache();