Skip to content

Commit

Permalink
Reported by @SorkoPiko
Browse files Browse the repository at this point in the history
  • Loading branch information
hiimjasmine00 committed Nov 5, 2024
1 parent 84d0de4 commit 74b8aa7
Show file tree
Hide file tree
Showing 10 changed files with 79 additions and 50 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64")
set(CMAKE_CXX_VISIBILITY_PRESET hidden)

project(BetterSafe VERSION 1.0.4)
project(BetterSafe VERSION 1.0.5)

add_library(${PROJECT_NAME} SHARED
src/BetterSafe.cpp
Expand Down
3 changes: 3 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
# Better Safe Changelog
## v1.0.5 (2024-11-05)
- Fixed a bug where levels would not load on an empty month

## v1.0.4 (2024-09-21)
- Fixed a bug where the level cache would reload when switching between months

Expand Down
4 changes: 2 additions & 2 deletions mod.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"geode": "3.7.1",
"geode": "3.9.0",
"gd": {
"android": "2.206",
"win": "2.206",
"mac": "2.206"
},
"version": "v1.0.4",
"version": "v1.0.5",
"id": "hiimjustin000.better_safe",
"name": "Better Safe",
"developer": "hiimjustin000",
Expand Down
17 changes: 10 additions & 7 deletions src/BSCalendarPopup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,7 @@ bool BSCalendarPopup::setup(CCObject* obj, SEL_MenuHandler onSafe, bool weekly)
m_loadingCircle->retain();
m_loadingCircle->show();

auto safeButton = CCMenuItemExt::createSpriteExtraWithFrameName("GJ_safeBtn_001.png", 1.0f, [this, obj, onSafe](auto sender) {
(obj->*onSafe)(sender);
});
auto safeButton = CCMenuItemSpriteExtra::create(CCSprite::createWithSpriteFrameName("GJ_safeBtn_001.png"), obj, onSafe);
safeButton->setPosition(340.0f, 25.0f);
safeButton->setTag(91508); // my birthday
m_buttonMenu->addChild(safeButton);
Expand Down Expand Up @@ -221,19 +219,24 @@ void BSCalendarPopup::loadMonth() {
m_lastButton->setVisible(false);

auto levelSafe = BetterSafe::getMonth(m_year, m_month, m_weekly);
if (levelSafe.empty()) {
loadLevelsFinished(CCArray::create(), "");
return;
}
std::vector<std::string> ids;
for (auto& level : levelSafe) ids.push_back(std::to_string(level.id));
auto searchObject = GJSearchObject::create(SearchType::MapPackOnClick, string::join(ids, ","));
auto glm = GameLevelManager::sharedState();
std::string key = searchObject->getKey();
if (auto storedLevels = glm->getStoredOnlineLevels(key.substr(std::max(0, (int)key.size() - 256)).c_str())) loadLevelsFinished(storedLevels, searchObject->getKey());
if (auto storedLevels = glm->getStoredOnlineLevels(key.substr(std::max(0, (int)key.size() - 256)).c_str()))
loadLevelsFinished(storedLevels, searchObject->getKey());
else glm->getOnlineLevels(searchObject);
}

void BSCalendarPopup::loadLevelsFinished(CCArray* levels, const char*) {
CC_SAFE_RELEASE(m_levels);
CC_SAFE_RETAIN(levels);
m_levels = levels;
m_levels->retain();
setupMonth();
}

Expand Down Expand Up @@ -329,7 +332,7 @@ BSCalendarPopup::~BSCalendarPopup() {
if (glm->m_levelManagerDelegate == this) glm->m_levelManagerDelegate = nullptr;
}

BSSelectPopup* BSSelectPopup::create(int year, int month, int minYear, int minMonth, int maxYear, int maxMonth, MiniFunction<void(int, int)> callback) {
BSSelectPopup* BSSelectPopup::create(int year, int month, int minYear, int minMonth, int maxYear, int maxMonth, std::function<void(int, int)> const& callback) {
auto ret = new BSSelectPopup();
if (ret->initAnchored(250.0f, 150.0f, year, month, minYear, minMonth, maxYear, maxMonth, callback)) {
ret->autorelease();
Expand All @@ -339,7 +342,7 @@ BSSelectPopup* BSSelectPopup::create(int year, int month, int minYear, int minMo
return nullptr;
}

bool BSSelectPopup::setup(int year, int month, int minYear, int minMonth, int maxYear, int maxMonth, MiniFunction<void(int, int)> callback) {
bool BSSelectPopup::setup(int year, int month, int minYear, int minMonth, int maxYear, int maxMonth, std::function<void(int, int)> const& callback) {
setTitle("Select Date");

m_noElasticity = true;
Expand Down
25 changes: 12 additions & 13 deletions src/BSCalendarPopup.hpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "BSHoverNode.hpp"

class BSCalendarPopup : public geode::Popup<CCObject*, SEL_MenuHandler, bool>, public LevelManagerDelegate {
class BSCalendarPopup : public geode::Popup<cocos2d::CCObject*, cocos2d::SEL_MenuHandler, bool>, public LevelManagerDelegate {
public:
inline static std::vector<int> DAYS_IN_MONTH = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
inline static std::vector<std::string> MONTHS = {
Expand All @@ -11,17 +11,17 @@ class BSCalendarPopup : public geode::Popup<CCObject*, SEL_MenuHandler, bool>, p
16, 17, 18, 19, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20
};
protected:
EventListener<web::WebTask> m_listener;
geode::EventListener<geode::utils::web::WebTask> m_listener;
bool m_weekly;
int m_year;
int m_firstYear;
int m_currentYear;
int m_month;
int m_firstMonth;
int m_currentMonth;
CCArray* m_levels;
CCMenu* m_calendarMenu;
CCLabelBMFont* m_monthLabel;
cocos2d::CCArray* m_levels;
cocos2d::CCMenu* m_calendarMenu;
cocos2d::CCLabelBMFont* m_monthLabel;
CCMenuItemSpriteExtra* m_monthButton;
BSHoverNode* m_hoverNode;
LoadingCircle* m_loadingCircle;
Expand All @@ -30,37 +30,36 @@ class BSCalendarPopup : public geode::Popup<CCObject*, SEL_MenuHandler, bool>, p
CCMenuItemSpriteExtra* m_firstButton;
CCMenuItemSpriteExtra* m_lastButton;

bool setup(CCObject*, SEL_MenuHandler, bool) override;
bool setup(CCObject*, cocos2d::SEL_MenuHandler, bool) override;

void createWeekdayLabel(const char* text, int idx);
void loadMonth();
void setupMonth();
public:
static BSCalendarPopup* create(CCObject*, SEL_MenuHandler, bool);
static BSCalendarPopup* create(CCObject*, cocos2d::SEL_MenuHandler, bool);

void loadLevelsFinished(CCArray* levels, const char* key, int) override {
void loadLevelsFinished(cocos2d::CCArray* levels, const char* key, int) override {
loadLevelsFinished(levels, key);
}
void loadLevelsFinished(CCArray*, const char*) override;
void loadLevelsFinished(cocos2d::CCArray*, const char*) override;
void loadLevelsFailed(const char* key, int) override {
loadLevelsFailed(key);
}
void loadLevelsFailed(const char*) override {
m_loadingCircle->setVisible(false);
m_loadingCircle->fadeAndRemove();
FLAlertLayer::create("Load Failed", "Failed to load safe levels. Please try again later.", "OK")->show();
}
void setupPageInfo(gd::string, const char*) override {}

~BSCalendarPopup() override;
};

class BSSelectPopup : public geode::Popup<int, int, int, int, int, int, MiniFunction<void(int, int)>> {
class BSSelectPopup : public geode::Popup<int, int, int, int, int, int, std::function<void(int, int)> const&> {
protected:
int m_year;
int m_month;

bool setup(int, int, int, int, int, int, MiniFunction<void(int, int)>) override;
bool setup(int, int, int, int, int, int, std::function<void(int, int)> const&) override;
public:
static BSSelectPopup* create(int, int, int, int, int, int, MiniFunction<void(int, int)>);
static BSSelectPopup* create(int, int, int, int, int, int, std::function<void(int, int)> const&);
};
6 changes: 4 additions & 2 deletions src/BSHoverNode.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "BSHoverNode.hpp"

BSHoverNode* BSHoverNode::create(SafeLevel const& level, GJGameLevel* gameLevel, MiniFunction<void()> callback) {
using namespace geode::prelude;

BSHoverNode* BSHoverNode::create(SafeLevel const& level, GJGameLevel* gameLevel, std::function<void()> const& callback) {
auto ret = new BSHoverNode();
if (ret->init(level, gameLevel, callback)) {
ret->autorelease();
Expand All @@ -10,7 +12,7 @@ BSHoverNode* BSHoverNode::create(SafeLevel const& level, GJGameLevel* gameLevel,
return nullptr;
}

bool BSHoverNode::init(SafeLevel const& level, GJGameLevel* gameLevel, MiniFunction<void()> callback) {
bool BSHoverNode::init(SafeLevel const& level, GJGameLevel* gameLevel, std::function<void()> const& callback) {
if (!CCLayer::init()) return false;

setAnchorPoint({ 0.5f, 0.5f });
Expand Down
12 changes: 6 additions & 6 deletions src/BSHoverNode.hpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
#include "BetterSafe.hpp"

class BSHoverNode : public CCLayer {
class BSHoverNode : public cocos2d::CCLayer {
protected:
CCScale9Sprite* m_background;
MiniFunction<void()> m_callback;
cocos2d::extension::CCScale9Sprite* m_background;
std::function<void()> m_callback;

bool init(SafeLevel const&, GJGameLevel*, MiniFunction<void()>);
bool init(SafeLevel const&, GJGameLevel*, std::function<void()> const&);
public:
static BSHoverNode* create(SafeLevel const&, GJGameLevel*, MiniFunction<void()>);
static BSHoverNode* create(SafeLevel const&, GJGameLevel*, std::function<void()> const&);

void close();
void keyBackClicked() override;
void registerWithTouchDispatcher() override;
bool ccTouchBegan(CCTouch*, CCEvent*) override;
bool ccTouchBegan(cocos2d::CCTouch*, cocos2d::CCEvent*) override;

~BSHoverNode() override;
};
16 changes: 14 additions & 2 deletions src/BetterSafe.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#include "BetterSafe.hpp"

using namespace geode::prelude;

#define DAILY_SAFE_URL "https://raw.githubusercontent.com/hiimjustin000/the-safe/master/daily.json"
#define WEEKLY_SAFE_URL "https://raw.githubusercontent.com/hiimjustin000/the-safe/master/weekly.json"

Expand All @@ -14,7 +16,7 @@ SafeDate BetterSafe::parseDate(const std::string& date) {

#define PROPERTY_OR_DEFAULT(obj, prop, isFunc, asFunc, def) (obj.contains(prop) && obj[prop].isFunc() ? obj[prop].asFunc() : def)

void BetterSafe::loadDailySafe(EventListener<web::WebTask>&& listenerRef, LoadingCircle* circle, MiniFunction<void()> callback) {
void BetterSafe::loadDailySafe(EventListener<web::WebTask>&& listenerRef, LoadingCircle* circle, std::function<void()> const& callback) {
if (DAILY_SAFE.size()) return callback();

auto&& listener = std::move(listenerRef);
Expand All @@ -25,6 +27,11 @@ void BetterSafe::loadDailySafe(EventListener<web::WebTask>&& listenerRef, Loadin
auto str = res->string().value();
std::string error;
auto json = matjson::parse(str, error).value_or(matjson::Array());
if (!error.empty() || !json.is_array()) {
FLAlertLayer::create("Parse Failed", "Failed to parse the daily safe. Please try again later.", "OK")->show();
circle->setVisible(false);
return;
}
for (auto& level : json.as_array()) {
std::vector<SafeDate> dates;
dates.push_back(parseDate(PROPERTY_OR_DEFAULT(level, "date", is_string, as_string, "1970-01-01")));
Expand All @@ -49,7 +56,7 @@ void BetterSafe::loadDailySafe(EventListener<web::WebTask>&& listenerRef, Loadin
listener.setFilter(web::WebRequest().get(DAILY_SAFE_URL));
}

void BetterSafe::loadWeeklySafe(EventListener<web::WebTask>&& listenerRef, LoadingCircle* circle, MiniFunction<void()> callback) {
void BetterSafe::loadWeeklySafe(EventListener<web::WebTask>&& listenerRef, LoadingCircle* circle, std::function<void()> const& callback) {
if (WEEKLY_SAFE.size()) return callback();

auto&& listener = std::move(listenerRef);
Expand All @@ -60,6 +67,11 @@ void BetterSafe::loadWeeklySafe(EventListener<web::WebTask>&& listenerRef, Loadi
auto str = res->string().value();
std::string error;
auto json = matjson::parse(str, error).value_or(matjson::Array());
if (!error.empty() || !json.is_array()) {
FLAlertLayer::create("Parse Failed", "Failed to parse the weekly safe. Please try again later.", "OK")->show();
circle->setVisible(false);
return;
}
for (auto& level : json.as_array()) {
std::vector<SafeDate> dates;
if (level.contains("dates") && level["dates"].is_array()) {
Expand Down
7 changes: 2 additions & 5 deletions src/BetterSafe.hpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
#include <Geode/Geode.hpp>
#include <Geode/utils/web.hpp>

using namespace geode::prelude;

struct SafeDate {
int year;
int month;
Expand All @@ -23,8 +20,8 @@ class BetterSafe {
inline static std::vector<SafeLevel> WEEKLY_SAFE;

static SafeDate parseDate(const std::string&);
static void loadDailySafe(EventListener<web::WebTask>&&, LoadingCircle*, MiniFunction<void()>);
static void loadWeeklySafe(EventListener<web::WebTask>&&, LoadingCircle*, MiniFunction<void()>);
static void loadDailySafe(geode::EventListener<geode::utils::web::WebTask>&&, LoadingCircle*, std::function<void()> const&);
static void loadWeeklySafe(geode::EventListener<geode::utils::web::WebTask>&&, LoadingCircle*, std::function<void()> const&);
static std::vector<SafeLevel> getMonth(int year, int month, bool weekly);
static int getDifficultyFromLevel(GJGameLevel* level);
};
37 changes: 25 additions & 12 deletions src/main.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
#include "BSCalendarPopup.hpp"

using namespace geode::prelude;

#include <Geode/modify/MenuLayer.hpp>
class $modify(BSMenuLayer, MenuLayer) {
struct Fields {
CCObject* m_dailySafeListener;
SEL_MenuHandler m_dailySafeSelector;
CCObject* m_weeklySafeListener;
SEL_MenuHandler m_weeklySafeSelector;
};

static void onModify(auto& self) {
(void)self.setHookPriority("MenuLayer::init", INT_MIN / 2);
}
Expand All @@ -14,32 +23,36 @@ class $modify(BSMenuLayer, MenuLayer) {

auto dailiesMenu = redashMenu->getChildByID("ninxout.redash/dailies-menu");
if (!dailiesMenu) return true;

auto f = m_fields.self();

auto dailyNode = dailiesMenu->getChildByID("daily-node");
auto dailySafeButton = static_cast<CCMenuItemSpriteExtra*>(dailyNode ? dailyNode->getChildByIDRecursive("safe-button") : nullptr);
if (dailyNode && dailySafeButton) dailySafeButton->setTarget(this, menu_selector(BSMenuLayer::onTheDailySafe));
if (dailyNode && dailySafeButton) {
f->m_dailySafeListener = dailySafeButton->m_pListener;
f->m_dailySafeSelector = dailySafeButton->m_pfnSelector;
dailySafeButton->setTarget(this, menu_selector(BSMenuLayer::onTheDailySafe));
}

auto weeklyNode = dailiesMenu->getChildByID("weekly-node");
auto weeklySafeButton = static_cast<CCMenuItemSpriteExtra*>(weeklyNode ? weeklyNode->getChildByIDRecursive("safe-button") : nullptr);
if (weeklyNode && weeklySafeButton) weeklySafeButton->setTarget(this, menu_selector(BSMenuLayer::onTheWeeklySafe));
if (weeklyNode && weeklySafeButton) {
f->m_weeklySafeListener = weeklyNode;
f->m_weeklySafeSelector = weeklySafeButton->m_pfnSelector;
weeklySafeButton->setTarget(this, menu_selector(BSMenuLayer::onTheWeeklySafe));
}

return true;
}

void onTheDailySafe(CCObject*) {
BSCalendarPopup::create(this, menu_selector(BSMenuLayer::onTheOriginalDailySafe), false)->show();
auto f = m_fields.self();
BSCalendarPopup::create(f->m_dailySafeListener, f->m_dailySafeSelector, false)->show();
}

void onTheWeeklySafe(CCObject*) {
BSCalendarPopup::create(this, menu_selector(BSMenuLayer::onTheOriginalWeeklySafe), true)->show();
}

void onTheOriginalDailySafe(CCObject*) {
switchToScene(LevelBrowserLayer::create(GJSearchObject::create(SearchType::DailySafe)));
}

void onTheOriginalWeeklySafe(CCObject*) {
switchToScene(LevelBrowserLayer::create(GJSearchObject::create(SearchType::WeeklySafe)));
auto f = m_fields.self();
BSCalendarPopup::create(f->m_weeklySafeListener, f->m_weeklySafeSelector, true)->show();
}
};

Expand Down

0 comments on commit 74b8aa7

Please sign in to comment.