@@ -23,19 +23,19 @@ namespace avalanche {
2323 int ACC_PUBLISHER = 31079132 ;
2424 std::string URL_MOD_ISSUES = AVAL_MOD->getMetadataRef ().getIssues().value().url.value_or(URL_AVALANCHE); // URL to the mod's issues page on its GitHub repository
2525
26- matjson::Value fetchedBadges = nullptr ; // Cached profile data
27- matjson::Value fetchedLevels = nullptr ; // Cached project data
26+ matjson::Value fetchedBadges = matjson::Value() ; // Cached profile data
27+ matjson::Value fetchedLevels = matjson::Value() ; // Cached project data
2828
2929 EventListener<web::WebTask> badgeListReq; // Web request listener for team profile data
3030 EventListener<web::WebTask> levelListReq; // Web request listener for team project data
3131
3232 const char * Handler::Badges::getBadgeID (Profile::Badge badge) {
3333 switch (badge) {
34- case Profile::Badge::CUBIC: return teamStrings ::Profiles::Nodes::Cubic;
35- case Profile::Badge::DIRECTOR: return teamStrings ::Profiles::Nodes::Director;
36- case Profile::Badge::MANAGER: return teamStrings ::Profiles::Nodes::Manager;
37- case Profile::Badge::MEMBER: return teamStrings ::Profiles::Nodes::Member;
38- case Profile::Badge::COLLABORATOR: return teamStrings ::Profiles::Nodes::Collaborator;
34+ case Profile::Badge::CUBIC: return values ::Profiles::Nodes::Cubic;
35+ case Profile::Badge::DIRECTOR: return values ::Profiles::Nodes::Director;
36+ case Profile::Badge::MANAGER: return values ::Profiles::Nodes::Manager;
37+ case Profile::Badge::MEMBER: return values ::Profiles::Nodes::Member;
38+ case Profile::Badge::COLLABORATOR: return values ::Profiles::Nodes::Collaborator;
3939
4040 default : return nullptr ;
4141 };
@@ -46,22 +46,22 @@ namespace avalanche {
4646 Profile::Badge Handler::Badges::fromBadgeID (const std::string& id) {
4747 auto i = id.c_str ();
4848
49- if (i == teamStrings ::Profiles::Nodes::Cubic) return Profile::Badge::CUBIC;
50- if (i == teamStrings ::Profiles::Nodes::Director) return Profile::Badge::DIRECTOR;
51- if (i == teamStrings ::Profiles::Nodes::Manager) return Profile::Badge::MANAGER;
52- if (i == teamStrings ::Profiles::Nodes::Member) return Profile::Badge::MEMBER;
53- if (i == teamStrings ::Profiles::Nodes::Collaborator) return Profile::Badge::COLLABORATOR;
49+ if (i == values ::Profiles::Nodes::Cubic) return Profile::Badge::CUBIC;
50+ if (i == values ::Profiles::Nodes::Director) return Profile::Badge::DIRECTOR;
51+ if (i == values ::Profiles::Nodes::Manager) return Profile::Badge::MANAGER;
52+ if (i == values ::Profiles::Nodes::Member) return Profile::Badge::MEMBER;
53+ if (i == values ::Profiles::Nodes::Collaborator) return Profile::Badge::COLLABORATOR;
5454
5555 return Profile::Badge::NONE;
5656 };
5757
5858 const char * Handler::Badges::getSpriteName (Profile::Badge badge) {
5959 switch (badge) {
60- case Profile::Badge::CUBIC: return teamStrings ::Profiles::Sprites::Cubic;
61- case Profile::Badge::DIRECTOR: return teamStrings ::Profiles::Sprites::Director;
62- case Profile::Badge::MANAGER: return teamStrings ::Profiles::Sprites::Manager;
63- case Profile::Badge::MEMBER: return teamStrings ::Profiles::Sprites::Member;
64- case Profile::Badge::COLLABORATOR: return teamStrings ::Profiles::Sprites::Collaborator;
60+ case Profile::Badge::CUBIC: return values ::Profiles::Sprites::Cubic;
61+ case Profile::Badge::DIRECTOR: return values ::Profiles::Sprites::Director;
62+ case Profile::Badge::MANAGER: return values ::Profiles::Sprites::Manager;
63+ case Profile::Badge::MEMBER: return values ::Profiles::Sprites::Member;
64+ case Profile::Badge::COLLABORATOR: return values ::Profiles::Sprites::Collaborator;
6565
6666 default : return nullptr ;
6767 };
@@ -77,39 +77,41 @@ namespace avalanche {
7777 case Profile::Badge::MEMBER: return AVAL_MOD->getSettingValue <ccColor3B>(" com-member" );
7878 case Profile::Badge::COLLABORATOR: return AVAL_MOD->getSettingValue <ccColor3B>(" com-collaborator" );
7979
80- default : return { 255 ,255 ,255 };
80+ default : return { 255 , 255 , 255 };
8181 };
82+
83+ return { 255 , 255 , 255 };
8284 };
8385
8486 constexpr const char * Handler::Badges::apiToBadgeID (const std::string& apiName) {
8587 auto api = apiName.c_str ();
8688
87- if (api == teamStrings ::Profiles::API::Cubic) return getBadgeID (Profile::Badge::CUBIC);
88- if (api == teamStrings ::Profiles::API::Director) return getBadgeID (Profile::Badge::DIRECTOR);
89- if (api == teamStrings ::Profiles::API::Manager) return getBadgeID (Profile::Badge::MANAGER);
90- if (api == teamStrings ::Profiles::API::Member) return getBadgeID (Profile::Badge::MEMBER);
91- if (api == teamStrings ::Profiles::API::Collaborator) return getBadgeID (Profile::Badge::COLLABORATOR);
89+ if (api == values ::Profiles::API::Cubic) return getBadgeID (Profile::Badge::CUBIC);
90+ if (api == values ::Profiles::API::Director) return getBadgeID (Profile::Badge::DIRECTOR);
91+ if (api == values ::Profiles::API::Manager) return getBadgeID (Profile::Badge::MANAGER);
92+ if (api == values ::Profiles::API::Member) return getBadgeID (Profile::Badge::MEMBER);
93+ if (api == values ::Profiles::API::Collaborator) return getBadgeID (Profile::Badge::COLLABORATOR);
9294
9395 return nullptr ;
9496 };
9597
9698 Project::Type Handler::Levels::fromString (const std::string& str) {
9799 auto s = str.c_str ();
98100
99- if (s == teamStrings ::Projects::API::Solo) return Project::Type::SOLO;
100- if (s == teamStrings ::Projects::API::Team) return Project::Type::TEAM;
101- if (s == teamStrings ::Projects::API::Collab) return Project::Type::COLLAB;
102- if (s == teamStrings ::Projects::API::Event) return Project::Type::EVENT;
101+ if (s == values ::Projects::API::Solo) return Project::Type::SOLO;
102+ if (s == values ::Projects::API::Team) return Project::Type::TEAM;
103+ if (s == values ::Projects::API::Collab) return Project::Type::COLLAB;
104+ if (s == values ::Projects::API::Event) return Project::Type::EVENT;
103105
104106 return Project::Type::NONE;
105107 };
106108
107109 constexpr const char * Handler::Levels::toString (Project::Type type) {
108110 switch (type) {
109- case Project::Type::SOLO: return teamStrings ::Projects::API::Solo;
110- case Project::Type::TEAM: return teamStrings ::Projects::API::Team;
111- case Project::Type::COLLAB: return teamStrings ::Projects::API::Collab;
112- case Project::Type::EVENT: return teamStrings ::Projects::API::Event;
111+ case Project::Type::SOLO: return values ::Projects::API::Solo;
112+ case Project::Type::TEAM: return values ::Projects::API::Team;
113+ case Project::Type::COLLAB: return values ::Projects::API::Collab;
114+ case Project::Type::EVENT: return values ::Projects::API::Event;
113115
114116 default : return nullptr ;
115117 };
@@ -119,12 +121,12 @@ namespace avalanche {
119121 badgeListReq.bind ([](web::WebTask::Event* e) {
120122 if (web::WebResponse* avalReqRes = e->getValue ()) {
121123 if (avalReqRes->ok ()) {
122- if (fetchedBadges == nullptr ) {
124+ if (fetchedBadges. isNull () ) {
123125 if (avalReqRes->json ().isOk ()) {
124126 auto jsonRes = avalReqRes->json ().unwrapOr (matjson::Value::object ());
125127
126128 for (auto & [key, value] : jsonRes) {
127- std::string cacheKey = fmt::format (" cache-badge-p{}" , (std::string)key);
129+ auto cacheKey = fmt::format (" cache-badge-p{}" , (std::string)key);
128130 AVAL_MOD->setSavedValue (cacheKey, value);
129131 };
130132
@@ -148,18 +150,18 @@ namespace avalanche {
148150 auto badgeReq = web::WebRequest (); // send the web request
149151 badgeReq.userAgent (" Avalanche Index mod for Geode" );
150152 badgeReq.timeout (std::chrono::seconds (30 ));
151- badgeListReq.setFilter (badgeReq.get (URL_API_BADGES));
153+ badgeListReq.setFilter (badgeReq.get (std::string ( URL_API_BADGES) ));
152154
153155 // fetch data for all projects
154156 levelListReq.bind ([](web::WebTask::Event* e) {
155157 if (web::WebResponse* avalReqRes = e->getValue ()) {
156158 if (avalReqRes->ok ()) {
157- if (fetchedLevels == nullptr ) {
159+ if (fetchedLevels. isNull () ) {
158160 if (avalReqRes->json ().isOk ()) {
159161 auto jsonRes = avalReqRes->json ().unwrapOr (matjson::Value::object ());
160162
161163 for (auto & [key, value] : jsonRes) {
162- std::string cacheKey = fmt::format (" cache-level-p{}" , (std::string)key);
164+ auto cacheKey = fmt::format (" cache-level-p{}" , (std::string)key);
163165 AVAL_MOD->setSavedValue (cacheKey, value);
164166 };
165167
@@ -183,51 +185,87 @@ namespace avalanche {
183185 auto levelReq = web::WebRequest (); // send the web request
184186 levelReq.userAgent (" Avalanche Index mod for Geode" );
185187 levelReq.timeout (std::chrono::seconds (30 ));
186- levelListReq.setFilter (levelReq.get (URL_API_LEVELS));
188+ levelListReq.setFilter (levelReq.get (std::string ( URL_API_LEVELS) ));
187189 };
188190
189191 Profile Handler::GetProfile (int id) {
190192 if (id > 0 ) {
191- std::string cacheKey = fmt::format (" cache-badge-p{}" , (int )id); // format the save key string
193+ auto cacheKey = fmt::format (" cache-badge-p{}" , (int )id); // format the save key string
192194 matjson::Value cacheStd = AVAL_MOD->getSavedValue <matjson::Value>(cacheKey); // gets locally saved badge json
193195
194- auto c_name = cacheStd[" name" ].asString ().unwrapOr (und);
195- auto c_badge = Handler::Badges::fromBadgeID (cacheStd[" badge" ].asString ().unwrapOr (und).c_str ());
196+ if (AVAL_MOD->getSettingValue <bool >(" web-once" )) { // only fetch from cached web data if this setting is on
197+ log::debug (" Fetching badge data from session web cache" );
198+
199+ if (fetchedBadges.isNull ()) {
200+ log::warn (" Session web cache for badge data is unaccessible" );
201+ } else if (fetchedBadges.isObject ()) {
202+ auto key = std::to_string (id);
203+ fetchedBadges.contains (key) ? cacheStd = fetchedBadges[key.c_str ()] : cacheStd = nullptr ;
204+ };
205+ } else {
206+ log::warn (" Fetching badge data directly from saved cache" );
207+ };
208+
209+ if (cacheStd == nullptr ) {
210+ log::error (" Player {} is no longer associated with Avalanche" , (int )id);
211+ return Profile ();
212+ } else {
213+ auto c_name = cacheStd[" name" ].asString ().unwrapOr (und);
214+ auto c_badge = Handler::Badges::fromBadgeID (cacheStd[" badge" ].asString ().unwrapOr (und));
196215
197- Profile res (c_name, c_badge);
198- return res;
216+ Profile res (c_name, c_badge);
217+ return res;
218+ };
199219 } else {
200- log::error (" Profile ID is invalid" );
220+ log::error (" Profile ID {} is invalid" , ( int )id );
201221 return Profile ();
202222 };
203223 };
204224
205225 Project Handler::GetProject (int id) {
206226 if (id > 0 ) {
207- std::string cacheKey = fmt::format (" cache-level-p{}" , (int )id); // format the save key string
227+ auto cacheKey = fmt::format (" cache-level-p{}" , (int )id); // format the save key string
208228 matjson::Value cacheStd = AVAL_MOD->getSavedValue <matjson::Value>(cacheKey); // gets locally saved level json
209229
210- auto c_name = cacheStd[" name" ].asString ().unwrapOr (und);
211- auto c_host = cacheStd[" host" ].asString ().unwrapOr (und);
212- auto c_showcase = cacheStd[" showcase" ].asString ().unwrapOr (und);
213- auto c_thumbnail = cacheStd[" thumbnail" ].asString ().unwrapOr (" " );
214- auto c_type = Handler::Levels::fromString (cacheStd[" type" ].asString ().unwrapOr (und));
215- auto c_fame = cacheStd[" fame" ].asBool ().unwrapOr (false );
216-
217- auto c_linked = cacheStd[" project" ];
218- Project::LinkToMain ltm;
219-
220- if (c_linked.isObject ()) {
221- ltm = Project::LinkToMain (
222- c_linked[" enabled" ].asBool ().unwrapOr (false ),
223- c_linked[" id" ].asInt ().unwrapOr (0 )
224- );
230+ if (AVAL_MOD->getSettingValue <bool >(" web-once" )) { // only fetch from cached web data if this setting is on
231+ log::debug (" Fetching level data from session web cache" );
232+
233+ if (fetchedLevels.isNull ()) {
234+ log::warn (" Session web cache for level data is unaccessible" );
235+ } else if (fetchedLevels.isObject ()) {
236+ auto key = std::to_string (id);
237+ fetchedLevels.contains (key) ? cacheStd = fetchedLevels[key.c_str ()] : cacheStd = nullptr ;
238+ };
225239 } else {
226- ltm = Project::LinkToMain ( );
240+ log::warn ( " Fetching badge data directly from saved cache " );
227241 };
228242
229- Project res (c_name, c_host, c_showcase, c_thumbnail, c_type, c_fame, ltm);
230- return res;
243+ if (cacheStd == nullptr ) {
244+ log::error (" Level {} is no longer part of Avalanche" , (int )id);
245+ return Project ();
246+ } else {
247+ auto c_name = cacheStd[" name" ].asString ().unwrapOr (und);
248+ auto c_host = cacheStd[" host" ].asString ().unwrapOr (und);
249+ auto c_showcase = cacheStd[" showcase" ].asString ().unwrapOr (und);
250+ auto c_thumbnail = cacheStd[" thumbnail" ].asString ().unwrapOr (" " );
251+ auto c_type = Handler::Levels::fromString (cacheStd[" type" ].asString ().unwrapOr (und));
252+ auto c_fame = cacheStd[" fame" ].asBool ().unwrapOr (false );
253+
254+ auto c_linked = cacheStd[" project" ];
255+ Project::LinkToMain ltm;
256+
257+ if (c_linked.isObject ()) {
258+ ltm = Project::LinkToMain (
259+ c_linked[" enabled" ].asBool ().unwrapOr (false ),
260+ c_linked[" id" ].asInt ().unwrapOr (0 )
261+ );
262+ } else {
263+ ltm = Project::LinkToMain ();
264+ };
265+
266+ Project res (c_name, c_host, c_showcase, c_thumbnail, c_type, c_fame, ltm);
267+ return res;
268+ };
231269 } else {
232270 log::error (" Project ID is invalid" );
233271 return Project ();
0 commit comments