Skip to content

Commit

Permalink
prepare for geode v4
Browse files Browse the repository at this point in the history
  • Loading branch information
Cvolton committed Nov 10, 2024
1 parent e4d2c72 commit d508a8c
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 125 deletions.
2 changes: 1 addition & 1 deletion mod.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"geode": "3.9.0",
"geode": "4.0.0",
"version": "v4.2.13",
"gd": {
"win": "2.2073",
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/InfoLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class BI_DLL $modify(BIInfoLayer, InfoLayer) {
};

static void onModify(auto& self) {
auto res = self.setHookPriority("InfoLayer::onMore", 99999);
res = self.setHookPriority("InfoLayer::onLevelInfo", 99999);
(void) self.setHookPriority("InfoLayer::onMore", 99999);
(void) self.setHookPriority("InfoLayer::onLevelInfo", 99999);
}

void onJumpToPageLayer(CCObject* sender) {
Expand Down
4 changes: 2 additions & 2 deletions src/hooks/LevelInfoLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ using namespace geode::prelude;

class BI_DLL $modify(LevelInfoLayer) {
static void onModify(auto& self) {
auto res = self.setHookPriority("LevelInfoLayer::onViewProfile", 99999);
res = self.setHookPriority("LevelInfoLayer::onLevelInfo", 99999);
(void) self.setHookPriority("LevelInfoLayer::onViewProfile", 99999);
(void) self.setHookPriority("LevelInfoLayer::onLevelInfo", 99999);
}

bool init(GJGameLevel* level, bool challenge) {
Expand Down
19 changes: 10 additions & 9 deletions src/managers/BaseJsonManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@ Result<> BaseJsonManager::load() {
}

std::string error;
auto parsed = matjson::parse(result.unwrap(), error);
if (!parsed.has_value()) {
return Err("Unable to parse: {}", error);
auto parsed = matjson::parse(result.unwrap());
if (!parsed) {
return Err("Unable to parse: {}", parsed.err());
}
m_json = parsed.value();
m_json = parsed.unwrap();

if (!m_json.is_object()) {
m_json = matjson::Object();
if (!m_json.isObject()) {
m_json = matjson::Value();
return Err("Not an object");
}
}
Expand All @@ -52,7 +52,8 @@ Result<> BaseJsonManager::load() {
Result<> BaseJsonManager::save() {
//std::cout << ("Locking shared_lock save") << std::endl;
std::shared_lock guard(m_jsonMutex);
std::string savedStr = m_json.dump(matjson::NO_INDENTATION);
//TODO: v4 this func will change
std::string savedStr = m_json.dump(matjson::NO_INDENTATION).unwrap();

auto res2 = utils::file::writeString(Mod::get()->getSaveDir() / m_filename, savedStr);
if (!res2) {
Expand Down Expand Up @@ -111,13 +112,13 @@ void BaseJsonManager::validateLoadedData() {

void BaseJsonManager::validateIsObject(const char* key) {
// no mutex because this is only intended to be called from funcs that already lock it
if(!m_json[key].is_object()) m_json[key] = matjson::Object();
if(!m_json[key].isObject()) m_json[key] = matjson::Value();
}

BaseJsonManager::BaseJsonManager(){}

bool BaseJsonManager::objectExists(const char* dict, const std::string& key) {
std::shared_lock guard(m_jsonMutex);

return m_json[dict].as_object().find(key) != m_json[dict].as_object().end();
return m_json[dict].contains(key);
}
2 changes: 1 addition & 1 deletion src/managers/BaseJsonManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class BI_DLL BaseJsonManager {

public:
std::string m_filename;
matjson::Value m_json = matjson::Object();
matjson::Value m_json = matjson::Value();
std::shared_mutex m_jsonMutex;

bool init(const char* filename);
Expand Down
134 changes: 49 additions & 85 deletions src/managers/BetterInfoCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,8 @@ void BetterInfoCache::establishCachedDicts(){
std::shared_lock guard(m_jsonMutex);
std::unique_lock lock(m_coinCountsMutex);

for(auto [key, value] : m_json["coin-count-dict"].as_object()) {
if(value.is_number()) m_coinCounts[BetterInfo::stoi(key)] = value.as_int();
for(auto [key, value] : m_json["coin-count-dict"]) {
if(value.isNumber()) m_coinCounts[BetterInfo::stoi(key)] = value.asInt().unwrapOr(0);
}
}

Expand Down Expand Up @@ -102,15 +102,16 @@ void BetterInfoCache::cacheScoresResult(CCArray* scores) {
}

void BetterInfoCache::cacheScore(GJUserScore* score) {
auto object = matjson::Object();
object["username"] = std::string(score->m_userName);
object["icon-type"] = (int) score->m_iconType;
object["iconID"] = score->m_iconID;
object["color-1"] = score->m_color1;
object["color-2"] = score->m_color2;
object["special"] = score->m_special;
object["accountID"] = score->m_accountID;
object["cached"] = std::time(nullptr);
auto object = matjson::makeObject({
{ "username", score->m_userName },
{ "icon-type", (int) score->m_iconType },
{ "iconID", score->m_iconID },
{ "color-1", score->m_color1 },
{ "color-2", score->m_color2 },
{ "special", score->m_special },
{ "accountID", score->m_accountID },
{ "cached", std::time(nullptr) }
});

std::thread([this, object, accountID = score->m_accountID] {
thread::setName("BI Score Cache");
Expand Down Expand Up @@ -145,24 +146,19 @@ GJUserScore* BetterInfoCache::getCachedScore(int accountID) {
if(!objectExists("user-info-dict", idString)) return nullptr;

std::shared_lock guard(m_jsonMutex);
auto it = m_json["user-info-dict"].as_object().find(idString);
if(it == m_json["user-info-dict"].as_object().end()) return nullptr;
if(!m_json["user-info-dict"].contains(idString)) return nullptr;

auto object = it->second.as_object();
auto object = m_json["user-info-dict"][idString];
if(!object.contains("username") || !object.contains("icon-type") || !object.contains("iconID") || !object.contains("color-1") || !object.contains("color-2") || !object.contains("accountID")) return nullptr;
if(!object["username"].is_string() || !object["icon-type"].is_number() || !object["iconID"].is_number() || !object["color-1"].is_number() || !object["color-2"].is_number() || !object["accountID"].is_number()) return nullptr;

auto score = GJUserScore::create();
score->m_userName = object["username"].as_string();
score->m_iconType = (IconType) object["icon-type"].as_int();
score->m_iconID = object["iconID"].as_int();
score->m_color1 = object["color-1"].as_int();
score->m_color2 = object["color-2"].as_int();
score->m_accountID = object["accountID"].as_int();

if(!object.contains("special") || !object["special"].is_number()) return score;

score->m_special = object["special"].as_int();
score->m_userName = object["username"].asString().unwrapOr(GameLevelManager::sharedState()->tryGetUsername(accountID));
score->m_iconType = (IconType) object["icon-type"].asInt().unwrapOr(0);
score->m_iconID = object["iconID"].asInt().unwrapOr(1);
score->m_color1 = object["color-1"].asInt().unwrapOr(0);
score->m_color2 = object["color-2"].asInt().unwrapOr(0);
score->m_accountID = object["accountID"].asInt().unwrapOr(0);
score->m_special = object["special"].asInt().unwrapOr(0);
return score;
}

Expand Down Expand Up @@ -220,33 +216,24 @@ void BetterInfoCache::checkClaimableLists() {
std::thread([this, completedLevels = std::move(completedLevels)] {
thread::setName("BI Claimable List Checker");

//log::info("Completed levels {}", completedLevels);

std::unordered_set<int> completedLists;

std::shared_lock guard(m_jsonMutex);
for(auto [key, value] : m_json["list-info-dict"].as_object()) {
if(!value.is_object()) continue;
if(!value["diamonds"].is_number()) continue;
if(!value["levels"].is_array()) continue;
if(!value["levels-to-claim"].is_number()) continue;

if(value["diamonds"].as_int() <= 0) continue;
for(auto [key, value] : m_json["list-info-dict"]) {
if(value["diamonds"].asInt().unwrapOr(0) <= 0) continue;

auto listID = BetterInfo::stoi(key);
auto levels = value["levels"].as_array();
auto levelsToClaim = value["levels-to-claim"].as_int();
auto levels = value["levels"].asArray().unwrapOr(std::vector<matjson::Value>());
auto levelsToClaim = value["levels-to-claim"].asInt().unwrapOr(0);

//log::debug("Checking list {} with {} levels", listID, levels.size());
if(levelsToClaim <= 0) continue;

int completed = 0;
for(auto level : levels) {
if(!level.is_number()) continue;
if(completedLevels.find(level.as_int()) != completedLevels.end()) completed++;
if(!level.isNumber()) continue;
if(completedLevels.find(level.asInt().unwrapOr(-1)) != completedLevels.end()) completed++;
}

//log::info("Completed {} out of {} levels from list {}", completed, levelsToClaim, listID);

if(completed >= levelsToClaim) {
completedLists.insert(listID);
}
Expand All @@ -271,7 +258,7 @@ void BetterInfoCache::checkClaimableLists() {
void BetterInfoCache::cacheList(GJLevelList* list) {
std::unique_lock guard(m_jsonMutex);
auto idString = std::to_string(list->m_listID);
if(!m_json["list-info-dict"][idString].is_object()) m_json["list-info-dict"][idString] = matjson::Object();
if(!m_json["list-info-dict"][idString].isObject()) m_json["list-info-dict"][idString] = matjson::Value();

auto name = std::string(list->m_listName);
for(auto it = name.begin(); it < name.end(); it++) {
Expand All @@ -283,7 +270,6 @@ void BetterInfoCache::cacheList(GJLevelList* list) {
m_json["list-info-dict"][idString]["levels-to-claim"] = list->m_levelsToClaim;
m_json["list-info-dict"][idString]["diamonds"] = list->m_diamonds;
guard.unlock();
//std::cout << ("Unlocking unique_lock storeLevelInfo") << std::endl;
doSave();
}

Expand Down Expand Up @@ -526,26 +512,18 @@ std::string BetterInfoCache::getLevelName(int levelID) {
auto idString = std::to_string(levelID);
if(!objectExists("level-name-dict", idString)) return "Unknown";

//std::cout << ("Locking shared_lock getLevelName") << std::endl;
std::shared_lock guard(m_jsonMutex);
//std::cout << ("Unlocking shared_lock getLevelName") << std::endl;
auto it = m_json["level-name-dict"].as_object().find(idString);
if(it == m_json["level-name-dict"].as_object().end()) return "Unknown";
if(!it->second.is_string()) return "Unknown (malformed JSON)";
return it->second.as_string();
if(!m_json["level-name-dict"].contains(idString)) return "Unknown";

return m_json["level-name-dict"][idString].asString().unwrapOr("Unknown (malformed JSON)");
}

int BetterInfoCache::getDemonDifficulty(int levelID) {
auto idString = std::to_string(levelID);
if(!objectExists("demon-difficulty-dict", idString)) return 0;

//std::cout << ("Locking shared_lock getDemonDifficulty") << std::endl;
std::shared_lock guard(m_jsonMutex);
//std::cout << ("Unlocking shared_lock getDemonDifficulty") << std::endl;
auto it = m_json["demon-difficulty-dict"].as_object().find(idString);
if(it == m_json["demon-difficulty-dict"].as_object().end()) return 0;
if(!it->second.is_number()) return 0;
return it->second.as_int();
return m_json["demon-difficulty-dict"][idString].asInt().unwrapOr(0);
}

void BetterInfoCache::storeUserName(int userID, const std::string& username) {
Expand Down Expand Up @@ -579,7 +557,7 @@ void BetterInfoCache::storeLevelInfo(int levelID, const std::string& field, cons
//std::cout << ("Locking unique_lock storeLevelInfo") << std::endl;
std::unique_lock guard(m_jsonMutex);
auto idString = std::to_string(levelID);
if(!m_json["level-info-dict"][idString].is_object()) m_json["level-info-dict"][idString] = matjson::Object();
if(!m_json["level-info-dict"][idString].isObject()) m_json["level-info-dict"][idString] = matjson::Value();

m_json["level-info-dict"][idString][field] = value;
guard.unlock();
Expand All @@ -588,17 +566,10 @@ void BetterInfoCache::storeLevelInfo(int levelID, const std::string& field, cons
}

std::string BetterInfoCache::getLevelInfo(int levelID, const std::string& field) {
//std::cout << ("Locking shared_lock getLevelInfo") << std::endl;
std::shared_lock guard(m_jsonMutex);
//std::cout << ("Unlocking shared_lock getLevelInfo") << std::endl;

auto idString = std::to_string(levelID);
if(m_json["level-info-dict"].as_object().find(idString) == m_json["level-info-dict"].as_object().end()) return "";

auto it = m_json["level-info-dict"][idString].as_object().find(field);
if(it == m_json["level-info-dict"][idString].as_object().end() || !(it->second.is_string())) return "";

return m_json["level-info-dict"][idString][field].as_string();
return m_json["level-info-dict"][idString][field].asString().unwrapOr("");
}

void BetterInfoCache::storeDatesForLevel(GJGameLevel* level) {
Expand Down Expand Up @@ -637,8 +608,7 @@ std::string BetterInfoCache::getUserName(int userID, bool download) {
auto data = json.unwrap();
std::string username;

if(data["non_player_username"].is_string()) username = data["non_player_username"].as_string();
else if(data["username"].is_string()) username = data["username"].as_string();
username = data["non_player_username"].asString().unwrapOr(data["username"].asString().unwrapOr(""));

storeUserName(userID, username);
log::debug("Restored green username for {}: {}", userID, username);
Expand All @@ -652,13 +622,8 @@ std::string BetterInfoCache::getUserName(int userID, bool download) {
return "";
}

//std::cout << ("Locking shared_lock getUserName") << std::endl;
std::shared_lock guard(m_jsonMutex);
//std::cout << ("Unlocking shared_lock getUserName") << std::endl;
auto it = m_json["username-dict"].as_object().find(idString);
if(it == m_json["username-dict"].as_object().end()) return "";
if(!it->second.is_string()) return "";
return it->second.as_string();
return m_json["username-dict"][idString].asString().unwrapOr("");
}

int BetterInfoCache::getCoinCount(int levelID) {
Expand All @@ -671,10 +636,11 @@ int BetterInfoCache::getCoinCount(int levelID) {
auto idString = std::to_string(levelID);
if(!objectExists("coin-count-dict", idString)) return 3;

auto it = m_json["coin-count-dict"].as_object().find(idString);
if(it == m_json["coin-count-dict"].as_object().end()) return 3;
if(!it->second.is_number()) return 3;
return m_coinCounts[levelID] = it->second.as_int();
if(auto res = m_json["coin-count-dict"][idString].asInt()) {
return m_coinCounts[levelID] = res.unwrap();
}

return 3;
}

void BetterInfoCache::storeUploadDate(int levelID, const std::string& date) {
Expand Down Expand Up @@ -720,10 +686,13 @@ std::string BetterInfoCache::getUploadDate(int levelID, UploadDateDelegate* dele
}

auto data = json.unwrap();
if(!data["approx"].is_object()) return *response;
if(!data["approx"]["estimation"].is_string()) return *response;
if(!data["approx"].isObject()) return *response;
if(!data["approx"]["estimation"].isString()) return *response;

auto res = data["approx"]["estimation"].asString();
if(!res) return *response;

storeUploadDate(levelID, data["approx"]["estimation"].as_string());
storeUploadDate(levelID, res.unwrap());
return *response;
}
));
Expand All @@ -733,11 +702,6 @@ std::string BetterInfoCache::getUploadDate(int levelID, UploadDateDelegate* dele
return "";
}

//std::cout << ("Locking unique_lock getUploadDate") << std::endl;
std::shared_lock guard(m_jsonMutex);
//std::cout << ("Unlocking unique_lock getUploadDate") << std::endl;
auto it = m_json["upload-date-dict"].as_object().find(idString);
if(it == m_json["upload-date-dict"].as_object().end()) return "";
if(!it->second.is_string()) return "";
return it->second.as_string();
return m_json["upload-date-dict"][idString].asString().unwrapOr("");
}
17 changes: 10 additions & 7 deletions src/managers/BetterInfoStatsV2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,34 @@ auto& BetterInfoStatsV2::levelObject(GJGameLevel* gjLevel) {

auto idStr = std::to_string(gjLevel->m_levelID.value());
auto& levels = m_json[key];
if(!levels[idStr].is_object()) levels[idStr] = matjson::Object();
if(!levels[idStr].isObject()) levels[idStr] = matjson::Value();
auto& level = levels[idStr];
if(!level["attempts"].is_array()) level["attempts"] = matjson::Array();
if(!level["attempts"].isArray()) level["attempts"] = std::vector<int>();
return level;
}

void BetterInfoStatsV2::logDeath(GJGameLevel* level, bool practice, LevelDeath death) {
if(practice) return;
if(level->m_levelType == GJLevelType::Editor) return;

levelObject(level)["attempts"].as_array().push_back(death);
if(auto array = levelObject(level)["attempts"].asArray()) {
array.unwrap().push_back(death);
}

doSave();
}

std::pair<int, int> BetterInfoStatsV2::getCommonFail(GJGameLevel* gjLevel) {
std::unordered_map<int, int> fails;

auto attempts = levelObject(gjLevel)["attempts"].as_array();
auto attempts = levelObject(gjLevel)["attempts"].asArray().unwrapOr(std::vector<matjson::Value>());
if(attempts.size() == 0) return {0,0};

for(auto& attempt : attempts) {
if(!attempt.is_object()) continue;
if(!attempt["percentage"].is_number()) continue;
if(!attempt.isObject()) continue;
if(!attempt["percentage"].isNumber()) continue;

fails[attempt["percentage"].as_int()] += 1;
fails[attempt["percentage"].asInt().unwrapOr(0)] += 1;
}

auto max = std::max_element(
Expand Down
Loading

0 comments on commit d508a8c

Please sign in to comment.