Skip to content

Commit

Permalink
Added Pointercrate & AreDL setting for demon placement (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jouca committed Aug 9, 2024
1 parent c285193 commit 0007196
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 19 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# Changelog
## <cj>v1.3.8</c> <cb>(2024-08-06)</c>
* <cg>Added</c> Pointercrate & AreDL setting for demon placement.
* <cg>Added</c> GDUtils GFX and GD Awards badges.
* <cg>Added</c> setting to show buttons for previewing icons colors when they are not unlocked.
* <cy>Changed</c> badges for GDUtils Developer and GDUtils collaborator badges.
Expand Down
5 changes: 5 additions & 0 deletions mod.json
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,11 @@
"type": "bool",
"default": true
},
"demonListSelection": {
"name": "Demon List Selection",
"description": "Whether or not to select between <cg>Pointercrate</c> or <cg>AreDL</c> for placements.",
"type": "custom"
},
"levelsProtocol": {
"name": "Allow Levels Protocol",
"description": "Whether or not to allow <cg>Geometry Dash</c> to <cy>redirect to a level</c> if you were to use a <cy>https://gdutils.com/</c> url, or <cy>gdutils:</c> protocol.",
Expand Down
3 changes: 3 additions & 0 deletions src/Settings/CustomSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ SettingNode* SettingAppValue::createNode(float width) {
SettingNode* SettingPosValue::createNode(float width) {
return SettingPosNode::create(this, width);
}
SettingNode* SettingDLPosValue::createNode(float width) {
return SettingDLNode::create(this, width);
}
SettingNode* SettingCreditsValue::createNode(float width) {
return SettingCreditsNode::create(this, width);
}
Expand Down
170 changes: 170 additions & 0 deletions src/Settings/CustomSettings.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,176 @@ class SettingSectionNode : public SettingNode {
}
};

// Pointercrate / AreDL setting

const int DEFAULT_DL_POS = 2;

struct SettingDLPosStruct {
int m_pos;
};

class SettingDLPosValue;

class SettingDLPosValue : public SettingValue {
protected:
int m_pos;
public:
SettingDLPosValue(std::string const& key, std::string const& modID, int const& position)
: SettingValue(key, modID), m_pos(position) {}

bool load(matjson::Value const& json) override {
try {
m_pos = static_cast<int>(json.as<int>());
return true;
} catch(...) {
return false;
}
}
bool save(matjson::Value& json) const override {
json = static_cast<int>(m_pos);
return true;
}
SettingNode* createNode(float width) override;
void setPos(int pos) {
m_pos = pos;
}
int getPos() const {
return m_pos;
}
};
template<>
struct SettingValueSetter<SettingDLPosStruct> {
static SettingDLPosStruct get(SettingValue* setting) {
auto posSetting = static_cast<SettingDLPosValue*>(setting);
struct SettingDLPosStruct defaultStruct = { posSetting->getPos() };
return defaultStruct;
};
static void set(SettingDLPosValue* setting, SettingDLPosStruct const& value) {
setting->setPos(value.m_pos);
};
};

class SettingDLNode : public SettingNode {
protected:
int m_currentPos;
CCMenuItemToggler* pcBtn;
CCMenuItemToggler* aredlBtn;

int getActiveCornerTag(int corner) {
switch (corner) {
case 1: // AreDL
return 2008;
case 2: // Pointercrate
default:
return 2009;
}
}

int tagToCorner(int tag) {
switch (tag) {
case 2008: // AreDL
return 1;
default:
case 2009: // Pointercrate
return 2;
}
}

bool init(SettingDLPosValue* value, float width) {
if (!SettingNode::init(value))
return false;

auto pointercrate_text = CCLabelBMFont::create("Pointercrate", "goldFont.fnt");
pointercrate_text->setScale(.6F);
pointercrate_text->setPosition(161, 16);
this->addChild(pointercrate_text);

auto aredl_text = CCLabelBMFont::create("AreDL", "goldFont.fnt");
aredl_text->setScale(.6F);
aredl_text->setPosition(276, 16);
this->addChild(aredl_text);

m_currentPos = value->getPos();
this->setContentSize({ width, 30.f });
auto menu = CCMenu::create();
CCSprite* toggleOn = CCSprite::createWithSpriteFrameName("GJ_checkOn_001.png");
CCSprite* toggleOff = CCSprite::createWithSpriteFrameName("GJ_checkOff_001.png");
toggleOn->setScale(.7F);
toggleOff->setScale(.7F);
menu->setPosition(width / 2, 23.f);
pcBtn = CCMenuItemToggler::create(
toggleOn,
toggleOff,
this,
menu_selector(SettingDLNode::onCornerClick)
);
aredlBtn = CCMenuItemToggler::create(
toggleOn,
toggleOff,
this,
menu_selector(SettingDLNode::onCornerClick)
);
pcBtn->setPosition({ -80, -8 });
aredlBtn->setPosition({ 60, -8 });

pcBtn->setTag(getActiveCornerTag(2));
aredlBtn->setTag(getActiveCornerTag(1));
int currentCorner = m_currentPos;
pcBtn->toggle(!(pcBtn->getTag() == getActiveCornerTag(currentCorner)));
aredlBtn->toggle(!(aredlBtn->getTag() == getActiveCornerTag(currentCorner)));

menu->addChild(pcBtn);
menu->addChild(aredlBtn);

this->addChild(menu);
return true;
}

void onCornerClick(CCObject* sender) {
pcBtn->toggle(true);
aredlBtn->toggle(true);
m_currentPos = tagToCorner(sender->getTag());
this->dispatchChanged();
};

void onInfoBtn(CCObject* sender) {
FLAlertLayer::create(
Mod::get()->getSettingDefinition(this->m_value->getKey())->get<CustomSetting>()->json->get<std::string>("name").c_str(),
Mod::get()->getSettingDefinition(this->m_value->getKey())->get<CustomSetting>()->json->get<std::string>("description").c_str(),
"OK"
)->show();
}
public:
void commit() override {
static_cast<SettingDLPosValue*>(m_value)->setPos(m_currentPos);
this->dispatchCommitted();
}

bool hasUncommittedChanges() override {
return m_currentPos != static_cast<SettingDLPosValue*>(m_value)->getPos();
}

bool hasNonDefaultValue() override {
return m_currentPos != DEFAULT_DL_POS;
}

void resetToDefault() override {
pcBtn->toggle(true);
aredlBtn->toggle(false);
m_currentPos = DEFAULT_DL_POS;
}

static SettingDLNode* create(SettingDLPosValue* value, float width) {
auto ret = new SettingDLNode;
if (ret && ret->init(value, width)) {
ret->autorelease();
return ret;
}
CC_SAFE_DELETE(ret);
return nullptr;
}
};

/*
Notification Position
*/
Expand Down
68 changes: 49 additions & 19 deletions src/Utils/DemonList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#include <string>
#include <Geode/modify/LevelInfoLayer.hpp>
#include <Geode/utils/web.hpp>
#include "../Settings/CustomSettings.hpp"


// demon list
Expand Down Expand Up @@ -103,45 +104,74 @@ class $modify(LevelInfoLayer) {
const geode::utils::MiniFunction<void(Result<matjson::Value>)> then = [this, level, levelID, loading_circle, positionLabel, demonSpr, winSize](Result<matjson::Value> const& result_json) {
matjson::Value json = result_json.value();

if (loading_circle != nullptr) {
loading_circle->fadeAndRemove();
}
auto scene = CCDirector::sharedDirector()->getRunningScene();
if (json.dump() == "[]") { //idk how to check size, doing .count crashes
log::info("Level not found in pointercrate.");
this->release();
int listId = Mod::get()->getSettingValue<SettingDLPosStruct>("demonListSelection").m_pos;

if (listId == 2) {
if (loading_circle != nullptr) {
loading_circle->fadeAndRemove();
}
auto scene = CCDirector::sharedDirector()->getRunningScene();
if (json.dump() == "[]") { //idk how to check size, doing .count crashes
log::info("Level not found in Pointercrate.");
this->release();
} else {
auto info = json.get<matjson::Value>(0);
auto position = info.get<int>("position");
positionLabel->setString(fmt::format("#{}", position).c_str());
positionLabel->setScale(getScaleBasedPos(position));
positionLabel->setVisible(true);
demonSpr->setVisible(true);
set(levelID, position);
log::info("Level found in Pointercrate! {} at #{}", level->m_levelName.c_str(), position);
this->release();
}
} else {
auto info = json.get<matjson::Value>(0);
auto position = info.get<int>("position");
positionLabel->setString(fmt::format("#{}", position).c_str());
positionLabel->setScale(getScaleBasedPos(position));
positionLabel->setVisible(true);
demonSpr->setVisible(true);
set(levelID, position);
log::info("Level found in Pointercrate! {} at #{}", level->m_levelName.c_str(), position);
this->release();
if (loading_circle != nullptr) {
loading_circle->fadeAndRemove();
}
auto scene = CCDirector::sharedDirector()->getRunningScene();
if (json.contains("code")) {
this->release();
} else {
auto position = json.get<int>("position");
positionLabel->setString(fmt::format("#{}", position).c_str());
positionLabel->setScale(getScaleBasedPos(position));
positionLabel->setVisible(true);
demonSpr->setVisible(true);
set(levelID, position);
log::info("Level found in AREDL! {} at #{}", level->m_levelName.c_str(), position);
this->release();
}
}
};
const geode::utils::MiniFunction<void(std::string const&)> expect = [this, loading_circle](std::string const& error) {
if (loading_circle != nullptr) {
loading_circle->fadeAndRemove();
}
log::error("Error while sending a request to Pointercrate: {}", error);
log::error("Error while sending a request to Demon List: {}", error);
FLAlertLayer::create(nullptr,
"Error",
"Failed to make a request to <cy>Pointercrate</c>. Please either <cg>try again later</c>, look at the error logs to see what might have happened, or report this to the developers.",
"Failed to make a request to <cy>Demon List</c>. Please either <cg>try again later</c>, look at the error logs to see what might have happened, or report this to the developers.",
"OK",
nullptr,
350.0F
)->show();
this->release();
};

int listId = Mod::get()->getSettingValue<SettingDLPosStruct>("demonListSelection").m_pos;
std::string url = "";
if (listId == 2) {
url = fmt::format("https://pointercrate.com/api/v2/demons/listed/?name={}", url_encode(level->m_levelName).c_str());
} else {
url = fmt::format("https://api.aredl.net/api/aredl/levels/{}", levelID);
}

geode::utils::web::WebRequest request = web::WebRequest();
const std::lock_guard<std::mutex> lock(lock_var);
RUNNING_REQUESTS.emplace(
"@loaderDemonListLevelInfo",
request.get(fmt::format("https://pointercrate.com/api/v2/demons/listed/?name={}", url_encode(level->m_levelName).c_str())).map(
request.get(url.c_str()).map(
[expect = std::move(expect), then = std::move(then)](web::WebResponse* response) {
const std::lock_guard<std::mutex> lock(lock_var);
if (response->ok()) {
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,7 @@ class $modify(MenuLayer) {

Mod::get()->addCustomSetting<SettingTestValue>("test-notification", "none");
Mod::get()->addCustomSetting<SettingPosValue>("notificationPlacement", 4);
Mod::get()->addCustomSetting<SettingDLPosValue>("demonListSelection", 2);
// Sections
Mod::get()->addCustomSetting<SettingSectionValue>("notification-section", "none");
Mod::get()->addCustomSetting<SettingSectionValue>("notification-placement-section", "none");
Expand Down

0 comments on commit 0007196

Please sign in to comment.