the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1081 lines 29 kB view raw
1#include "stdafx.h" 2 3#include "OrbisLeaderboardManager.h" 4 5#include "base64.h" 6 7#include "..\Orbis_App.h" 8#include "..\..\Common\Consoles_App.h" 9 10#include "Common\Network\Sony\SQRNetworkManager.h" 11 12#include "..\..\..\Minecraft.World\StringHelpers.h" 13 14#include <cstdlib> 15 16#include <np.h> 17//#include <sys/ppu_thread.h> 18 19#include "Orbis\OrbisExtras\ShutdownManager.h" 20 21 22LeaderboardManager *LeaderboardManager::m_instance = new OrbisLeaderboardManager(); //Singleton instance of the LeaderboardManager 23 24OrbisLeaderboardManager::OrbisLeaderboardManager() 25{ 26 m_eStatsState = eStatsState_Idle; 27 28 m_titleContext = -1; 29 30 m_myXUID = INVALID_XUID; 31 32 m_scores = NULL; //m_stats = NULL; 33 34 m_statsType = eStatsType_Kills; 35 m_difficulty = 0; 36 37 m_requestId = 0; 38 39 m_openSessions = 0; 40 41 InitializeCriticalSection(&m_csViewsLock); 42 43 m_running = false; 44 m_threadScoreboard = NULL; 45} 46 47OrbisLeaderboardManager::~OrbisLeaderboardManager() 48{ 49 m_running = false; 50 51 // 4J-JEV: Wait for thread to stop and hope it doesn't take too long. 52 long long startShutdown = System::currentTimeMillis(); 53 while (m_threadScoreboard->isRunning()) 54 { 55 Sleep(1); 56 assert( (System::currentTimeMillis() - startShutdown) < 16 ); 57 } 58 59 delete m_threadScoreboard; 60 61 DeleteCriticalSection(&m_csViewsLock); 62} 63 64int OrbisLeaderboardManager::scoreboardThreadEntry(LPVOID lpParam) 65{ 66 ShutdownManager::HasStarted(ShutdownManager::eLeaderboardThread); 67 OrbisLeaderboardManager *self = reinterpret_cast<OrbisLeaderboardManager *>(lpParam); 68 69 self->m_running = true; 70 app.DebugPrintf("[LeaderboardManager] Thread started.\n"); 71 72 bool needsWriting = false; 73 do 74 { 75 if (self->m_openSessions > 0 || needsWriting) 76 { 77 self->scoreboardThreadInternal(); 78 } 79 80 EnterCriticalSection(&self->m_csViewsLock); 81 needsWriting = self->m_views.size() > 0; 82 LeaveCriticalSection(&self->m_csViewsLock); 83 84 // 4J Stu - We can't write while we aren't signed in to live 85 if (!ProfileManager.IsSignedInLive(ProfileManager.GetPrimaryPad())) 86 { 87 needsWriting = false; 88 } 89 90 if ( (!needsWriting) && (self->m_eStatsState != eStatsState_Getting) ) 91 { 92 Sleep(50); // 4J-JEV: When we're not reading or writing. 93 } 94 95 } while ( (self->m_running || self->m_eStatsState == eStatsState_Getting || needsWriting) 96 && ShutdownManager::ShouldRun(ShutdownManager::eLeaderboardThread) 97 ); 98 99 // 4J-JEV, moved this here so setScore can finish up. 100 sceNpScoreDestroyTitleCtx(self->m_titleContext); 101 // TODO sceNpScoreTerm(); 102 app.DebugPrintf("[LeaderboardManager] Thread closed.\n"); 103 ShutdownManager::HasFinished(ShutdownManager::eLeaderboardThread); 104 return 0; 105} 106 107void OrbisLeaderboardManager::scoreboardThreadInternal() 108{ 109 // 4J-JEV: Just initialise the context the once now. 110 if (m_titleContext == -1) 111 { 112 int primaryPad = ProfileManager.GetPrimaryPad(); 113 114 if (!ProfileManager.IsSignedInLive(primaryPad)) return; 115 116 SceNpId npId; 117 ProfileManager.GetSceNpId(primaryPad,&npId); 118 119 int ret = sceNpScoreCreateNpTitleCtx(primaryPad, &npId); 120 121 if (ret < 0) return; 122 else m_titleContext = ret; 123 } 124 else assert( m_titleContext > 0 ); //Paranoia 125 126 127 switch (m_eStatsState) 128 { 129 case eStatsState_Getting: 130 // Player starts using async multiplayer feature 131 // 4J-PB - Fix for SCEA FQA #4 - TRC R4064 - Incorrect usage of AsyncMultiplay 132 // Note 1: 133 // The following NP call should be reserved for asynchronous multiplayer modes that require PS Plus to be accessed. 134 // 135 // Note 2: 136 // The message is not displayed with a user without PlayStation�Plus subscription and they are able to access the Leaderboards. 137 138 // NotifyAsyncPlusFeature(); 139 140 switch(m_eFilterMode) 141 { 142 case eFM_MyScore: 143 case eFM_Friends: 144 getScoreByIds(); 145 break; 146 case eFM_TopRank: 147 getScoreByRange(); 148 break; 149 } 150 break; 151 152 case eStatsState_Canceled: 153 case eStatsState_Failed: 154 case eStatsState_Ready: 155 case eStatsState_Idle: 156 157 // 4J-JEV: Moved this here, I don't want reading and 158 // writing going on at the same time. 159 // -- 160 // 4J-JEV: Writing no longer changes the manager state, 161 // we'll manage the write queue seperately. 162 163 EnterCriticalSection(&m_csViewsLock); 164 bool hasWork = !m_views.empty(); 165 LeaveCriticalSection(&m_csViewsLock); 166 167 if (hasWork) 168 { 169 setScore(); 170 } 171 172 break; 173 } 174} 175 176bool OrbisLeaderboardManager::getScoreByIds() 177{ 178 if (m_eStatsState == eStatsState_Canceled) return false; 179 180 // ---------------------------- 181 SceRtcTick last_sort_date; 182 SceNpScoreRankNumber mTotalRecord; 183 184 SceNpId *npIds = NULL; 185 186 187 int ret; 188 uint32_t num = 0; 189 190 SceNpScorePlayerRankData *ptr; 191 SceNpScoreComment *comments; 192 // ---------------------------- 193 194 // Check for invalid LManager state. 195 assert( m_eFilterMode == eFM_Friends 196 || m_eFilterMode == eFM_MyScore); 197 198 SceNpId myNpId; 199 // 4J-PB - should it be user 0? 200 if(!ProfileManager.IsSignedInLive(0)) 201 { 202 app.DebugPrintf("[LeaderboardManager] OpenSession() fail: User isn't signed in to PSN\n"); 203 return false; 204 } 205 ProfileManager.GetSceNpId(0,&myNpId); 206 207 // Get queried users. 208 if (m_eFilterMode == eFM_Friends) 209 { 210 211 sce::Toolkit::NP::Utilities::Future<sce::Toolkit::NP::FriendsList> s_friendList; 212 sce::Toolkit::NP::FriendInfoRequest request; 213 214 memset(&request, 0, sizeof(request)); 215 request.userInfo.userId = ProfileManager.getUserID(ProfileManager.GetPrimaryPad()); 216 request.flag = SCE_TOOLKIT_NP_FRIENDS_LIST_ALL; 217 ret = sce::Toolkit::NP::Friends::Interface::getFriendslist(&s_friendList, &request, false); 218 219 if(ret != SCE_TOOLKIT_NP_SUCCESS) 220 { 221 // Error handling 222 if (m_eStatsState != eStatsState_Canceled) m_eStatsState = eStatsState_Failed; 223 app.DebugPrintf("[LeaderboardManager] getFriendslist fail\n"); 224 return false; 225 } 226 else if (s_friendList.hasResult()) 227 { 228 // 4J-JEV: Friends list doesn't include player, leave space for them. 229 num = s_friendList.get()->size() + 1; 230 231 npIds = new SceNpId[num]; 232 233 int i = 0; 234 235 sce::Toolkit::NP::FriendsList::const_iterator itr; 236 for (itr = s_friendList.get()->begin(); itr != s_friendList.get()->end(); itr++) 237 { 238 npIds[i] = itr->npid; 239 i++; 240 } 241 242 npIds[num-1] = myNpId; // 4J-JEV: Append player to end of query. 243 } 244 else 245 { 246 // 4J-JEV: Something terrible must have happend, 247 // 'getFriendslist' was supposed to be a synchronous operation. 248 __debugbreak(); 249 250 // 4J-JEV: We can at least fall-back to just the players score. 251 num = 1; 252 npIds = new SceNpId[1]; 253 npIds[0] = myNpId; 254 } 255 } 256 else if (m_eFilterMode == eFM_MyScore) 257 { 258 num = 1; 259 npIds = new SceNpId[1]; 260 npIds[0] = myNpId; 261 } 262 263 ptr = new SceNpScorePlayerRankData[num]; 264 comments = new SceNpScoreComment[num]; 265 266 ZeroMemory(ptr, sizeof(SceNpScorePlayerRankData) * num); 267 ZeroMemory(comments, sizeof(SceNpScoreComment) * num); 268 269 /* app.DebugPrintf("sceNpScoreGetRankingByNpId(\n\t transaction=%i,\n\t boardID=0,\n\t npId=%i,\n\t friendCount*sizeof(SceNpId)=%i*%i=%i,\ 270 rankData=%i,\n\t friendCount*sizeof(SceNpScorePlayerRankData)=%i,\n\t NULL, 0, NULL, 0,\n\t friendCount=%i,\n...\n", 271 transaction, npId, friendCount, sizeof(SceNpId), friendCount*sizeof(SceNpId), 272 rankData, friendCount*sizeof(SceNpScorePlayerRankData), friendCount 273 ); */ 274 275 int boardId = getBoardId(m_difficulty, m_statsType); 276 277 for (int batch=0; batch<num; batch+=100) 278 { 279 ret = sceNpScoreCreateTransactionCtx(m_titleContext); 280 if (m_eStatsState == eStatsState_Canceled) 281 { 282 // Cancel operation has been called, abort. 283 app.DebugPrintf("[LeaderboardManager]\tgetScoreByIds() - m_eStatsState == eStatsState_Canceled.\n"); 284 285 sceNpScoreDestroyTransactionCtx(ret); 286 287 if (npIds != NULL) delete [] npIds; 288 if (ptr != NULL) delete [] ptr; 289 if (comments != NULL) delete [] comments; 290 291 return false; 292 } 293 else if (ret < 0) 294 { 295 // Error occurred creating a transacion, abort. 296 app.DebugPrintf("[LeaderboardManager]\tgetScoreByIds() - createTransaction failed, ret=0x%X\n", ret); 297 298 m_eStatsState = eStatsState_Failed; 299 300 if (npIds != NULL) delete [] npIds; 301 if (ptr != NULL) delete [] ptr; 302 if (comments != NULL) delete [] comments; 303 304 return false; 305 } 306 else 307 { 308 // Transaction created successfully, continue. 309 m_requestId = ret; 310 } 311 312 int tmpNum = min( num - batch, (unsigned int) 100 ); 313 314 app.DebugPrintf("[LeaderboardManager]\t Requesting ids %i-%i of %i.\n", batch, batch+tmpNum, num); 315 316 ret = sceNpScoreGetRankingByNpId( 317 m_requestId, 318 boardId, // BoardId 319 320 batch + npIds, sizeof(SceNpId) * tmpNum, //IN: Player IDs 321 batch + ptr, sizeof(SceNpScorePlayerRankData) * tmpNum, //OUT: Rank Data 322 323 batch + comments, sizeof(SceNpScoreComment) * tmpNum, //OUT: Comments 324 325 NULL, 0, // GameData. (unused) 326 327 tmpNum, 328 329 &last_sort_date, 330 &mTotalRecord, 331 332 NULL // Reserved, specify null. 333 ); 334 335 if (ret == SCE_NP_COMMUNITY_ERROR_ABORTED) 336 { 337 ret = sceNpScoreDestroyTransactionCtx(m_requestId); 338 app.DebugPrintf("[LeaderboardManager] getScoreByIds(): 'sceNpScoreGetRankingByRange' aborted (0x%X).\n", ret); 339 340 delete [] ptr; 341 delete [] comments; 342 delete [] npIds; 343 344 return false; 345 } 346 else if (ret == SCE_NP_COMMUNITY_SERVER_ERROR_GAME_RANKING_NOT_FOUND) 347 { 348 // 4J-JEV: Keep going, other batches might have scores. 349 } 350 else if (ret<0) goto error3; 351 352 // Return. 353 sceNpScoreDestroyTransactionCtx(m_requestId); 354 m_requestId = 0; 355 } 356 357 m_readCount = num; 358 359 // Filter scorers and construct output structure. 360 if (m_scores != NULL) delete [] m_scores; 361 m_scores = new ReadScore[m_readCount]; 362 convertToOutput(m_readCount, m_scores, ptr, comments); 363 m_maxRank = m_readCount; 364 365 app.DebugPrintf( 366 "[LeaderboardManager] getScoreByIds(), Success!\n" 367 "\t Board %i\n" 368 "\t %i of %i results have an entry\n" 369 "1stScore=%i\n", 370 boardId, 371 m_readCount, num, 372 ptr->rankData.scoreValue 373 ); 374 375 // Sort scores 376 std::sort(m_scores, m_scores + m_readCount, SortByRank); 377 378 delete [] ptr; 379 delete [] comments; 380 delete [] npIds; 381 382 m_eStatsState = eStatsState_Ready; 383 return true; 384 385 // Error. 386error3: 387 if (ret!=SCE_NP_COMMUNITY_ERROR_ABORTED) //0x8002a109 388 sceNpScoreDestroyTransactionCtx(m_requestId); 389 m_requestId = 0; 390 delete [] ptr; 391 delete [] comments; 392error2: 393 if (npIds != NULL) delete [] npIds; 394error1: 395 if (m_eStatsState != eStatsState_Canceled) m_eStatsState = eStatsState_Failed; 396 app.DebugPrintf("[LeaderboardManger] getScoreByIds() FAILED, ret=0x%X\n", ret); 397 return false; 398} 399 400bool OrbisLeaderboardManager::getScoreByRange() 401{ 402 SceRtcTick last_sort_date; 403 SceNpScoreRankNumber mTotalRecord; 404 405 unsigned int num = m_readCount; 406 SceNpScoreRankData *ptr; 407 SceNpScoreComment *comments; 408 409 assert(m_eFilterMode == eFM_TopRank); 410 411 int ret = sceNpScoreCreateTransactionCtx(m_titleContext); 412 if (m_eStatsState == eStatsState_Canceled) 413 { 414 // Cancel operation has been called, abort. 415 app.DebugPrintf("[LeaderboardManager]\tgetScoreByRange() - m_eStatsState == eStatsState_Canceled.\n"); 416 sceNpScoreDestroyTransactionCtx(ret); 417 return false; 418 } 419 else if (ret < 0) 420 { 421 // Error occurred creating a transacion, abort. 422 m_eStatsState = eStatsState_Failed; 423 app.DebugPrintf("[LeaderboardManager]\tgetScoreByRange() - createTransaction failed, ret=0x%X\n", ret); 424 return false; 425 } 426 else 427 { 428 // Transaction created successfully, continue. 429 m_requestId = ret; 430 } 431 432 ptr = new SceNpScoreRankData[num]; 433 comments = new SceNpScoreComment[num]; 434 435 int boardId = getBoardId(m_difficulty, m_statsType); 436 ret = sceNpScoreGetRankingByRange( 437 m_requestId, 438 boardId, // BoardId 439 440 m_startIndex, 441 442 ptr, sizeof(SceNpScoreRankData) * num, //OUT: Rank Data 443 444 comments, sizeof(SceNpScoreComment) * num, //OUT: Comment Data 445 446 NULL, 0, // GameData. 447 448 num, 449 450 &last_sort_date, 451 &m_maxRank, // 'Total number of players registered in the target scoreboard.' 452 453 NULL // Reserved, specify null. 454 ); 455 456 if (ret == SCE_NP_COMMUNITY_ERROR_ABORTED) 457 { 458 ret = sceNpScoreDestroyTransactionCtx(m_requestId); 459 app.DebugPrintf("[LeaderboardManager] getScoreByRange(): 'sceNpScoreGetRankingByRange' aborted (0x%X).\n", ret); 460 461 delete [] ptr; 462 delete [] comments; 463 464 return false; 465 } 466 else if (ret == SCE_NP_COMMUNITY_SERVER_ERROR_GAME_RANKING_NOT_FOUND) 467 { 468 ret = sceNpScoreDestroyTransactionCtx(m_requestId); 469 app.DebugPrintf("[LeaderboardManager] getScoreByRange(): Game ranking not found."); 470 471 delete [] ptr; 472 delete [] comments; 473 474 m_scores = NULL; 475 m_readCount = 0; 476 477 m_eStatsState = eStatsState_Ready; 478 return false; 479 } 480 else if (ret<0) goto error2; 481 else 482 { 483 app.DebugPrintf("[LeaderboardManager] getScoreByRange(), success, 1stScore=%i.\n", ptr->scoreValue); 484 } 485 486 // Return. 487 sceNpScoreDestroyTransactionCtx(m_requestId); 488 m_requestId = 0; 489 490 //m_stats = ptr; //Maybe: addPadding(num,ptr); 491 492 if (m_scores != NULL) delete [] m_scores; 493 m_readCount = ret; 494 m_scores = new ReadScore[m_readCount]; 495 for (int i=0; i<m_readCount; i++) 496 { 497 //memcpy(m_scores+i, ptr+i, sizeof(SceNpScoreRankData)); 498 initReadScoreStruct(m_scores[i], ptr[i]); 499 //fromBase32(m_scores+i, comments+i); 500 fillReadScoreStruct(m_scores[i], comments[i]); 501 } 502 503 m_eStatsState = eStatsState_Ready; 504 return true; 505 506 // Error. 507error2: 508 if (ret!=SCE_NP_COMMUNITY_ERROR_ABORTED) //0x8002a109 509 sceNpScoreDestroyTransactionCtx(m_requestId); 510 m_requestId = 0; 511 512 delete [] ptr; 513 delete [] comments; 514error1: 515 if (m_eStatsState != eStatsState_Canceled) m_eStatsState = eStatsState_Failed; 516 app.DebugPrintf("[LeaderboardManager]\tgetScoreByRange() failed, ret=0x%X\n", ret); 517 return false; 518} 519 520bool OrbisLeaderboardManager::setScore() 521{ 522 int ret; 523 SceNpId npId; 524 int32_t writeTitleContext = 0; 525 SceNpScoreRankNumber tmp = 0; 526 SceNpScoreComment comment; 527 528 // Get next job. 529 530 EnterCriticalSection(&m_csViewsLock); 531 RegisterScore rscore = m_views.front(); 532 m_views.pop(); 533 LeaveCriticalSection(&m_csViewsLock); 534 535 if ( ProfileManager.IsGuest(rscore.m_iPad) ) 536 { 537 app.DebugPrintf("[LeaderboardManager] setScore(): m_iPad[%i] is guest.\n", rscore.m_iPad); 538 return true; 539 } 540 541 ProfileManager.GetSceNpId(rscore.m_iPad, &npId); 542 writeTitleContext = sceNpScoreCreateNpTitleCtx( 0, &npId); 543 if (writeTitleContext < 0) 544 { 545 app.DebugPrintf("[LeaderboardManager] setScore(): sceNpScoreCreateTitleCtx FAILED, ret == %X.\n", ret); 546 return false; 547 } 548 549 ret = sceNpScoreCreateTransactionCtx(writeTitleContext); 550 551 // Start emptying queue if leaderboards has been closed. 552 if (ret == SCE_NP_COMMUNITY_ERROR_NOT_INITIALIZED) 553 { 554 EnterCriticalSection(&m_csViewsLock); 555 m_views.pop(); 556 LeaveCriticalSection(&m_csViewsLock); 557 } 558 559 // Error handling. 560 if (ret<0) 561 { 562 app.DebugPrintf("[LeaderboardManager] setScore() FAILED, ret=0x%X\n", ret); 563 sceNpScoreDestroyTitleCtx(writeTitleContext); 564 return false; 565 } 566 m_requestId = ret; 567 568 toBase32(&comment, (void *) &rscore.m_commentData); 569 570 int boardId = getBoardId(rscore.m_difficulty, rscore.m_commentData.m_statsType); 571 ret = sceNpScoreRecordScore( 572 m_requestId, // transId, 573 boardId, // boardId, 574 rscore.m_score, //IN: new score, 575 576 &comment, // Comments 577 NULL, // GameInfo 578 579 &tmp, //OUT: current rank, 580 NULL, //compareDate 581 582 NULL // Reserved, specify null. 583 ); 584 585 if (ret==SCE_NP_COMMUNITY_SERVER_ERROR_NOT_BEST_SCORE) //0x8002A415 586 app.DebugPrintf("[LeaderboardManager] setScore(), doesn't beat current score, %i.\n", tmp); 587 else if (ret==SCE_NP_COMMUNITY_ERROR_ABORTED) goto error1;//0x8002a109 588 else if (ret<0) goto error2; 589 else 590 { 591 app.DebugPrintf("[LeaderboardManager] setScore(), success. boardId=%i, score=%i\n", boardId, rscore.m_score); 592 } 593 594 // Return. 595 sceNpScoreDestroyTransactionCtx(m_requestId); 596 m_requestId = 0; 597 //m_eStatsState = eStatsState_Idle; 598 return true; 599 600 // Error. 601error2: 602 sceNpScoreDestroyTransactionCtx(m_requestId); 603 m_requestId = 0; 604error1: 605 app.DebugPrintf("[LeaderboardManager] setScore() FAILED, ret=0x%X\n", ret); 606 sceNpScoreDestroyTitleCtx(writeTitleContext); 607 return false; 608} 609 610void OrbisLeaderboardManager::Tick() 611{ 612 ReadView view; 613 614 switch( m_eStatsState ) 615 { 616 case eStatsState_Ready: 617 { 618 assert(m_scores != NULL || m_readCount == 0); 619 620 view.m_numQueries = m_readCount; 621 view.m_queries = m_scores; 622 623 // 4J-JEV: Debugging. 624 //LeaderboardManager::printStats(view); 625 626 eStatsReturn ret = eStatsReturn_NoResults; 627 if (view.m_numQueries > 0) 628 ret = eStatsReturn_Success; 629 630 if (m_readListener != NULL) 631 { 632 app.DebugPrintf("[LeaderboardManager] OnStatsReadComplete(%i, %i, _), m_readCount=%i.\n", ret, m_maxRank, m_readCount); 633 m_readListener->OnStatsReadComplete(ret, m_maxRank, view); 634 } 635 636 m_eStatsState = eStatsState_Idle; 637 638 delete [] m_scores; 639 m_scores = NULL; 640 } 641 break; 642 643 case eStatsState_Failed: 644 { 645 view.m_numQueries = 0; 646 view.m_queries = NULL; 647 648 if ( m_readListener != NULL ) 649 m_readListener->OnStatsReadComplete(eStatsReturn_NetworkError, 0, view); 650 651 m_eStatsState = eStatsState_Idle; 652 } 653 break; 654 655 case eStatsState_Canceled: 656 { 657 m_eStatsState = eStatsState_Idle; 658 } 659 break; 660 661 default: // Getting or Idle. 662 break; 663 } 664} 665 666bool OrbisLeaderboardManager::OpenSession() 667{ 668 if (m_openSessions == 0) 669 { 670 if (m_threadScoreboard == NULL) 671 { 672 m_threadScoreboard = new C4JThread(&scoreboardThreadEntry, this, "4JScoreboard"); 673 m_threadScoreboard->SetProcessor(CPU_CORE_LEADERBOARDS); 674 m_threadScoreboard->SetPriority(THREAD_PRIORITY_BELOW_NORMAL); 675 m_threadScoreboard->Run(); 676 } 677 678 app.DebugPrintf("[LeaderboardManager] OpenSession(): Starting sceNpScore utility.\n"); 679 } 680 else 681 { 682 app.DebugPrintf("[LeaderboardManager] OpenSession(): Another session opened, total=%i\n", m_openSessions+1); 683 } 684 685 m_openSessions++; 686 return true; 687} 688 689void OrbisLeaderboardManager::CloseSession() 690{ 691 m_openSessions--; 692 693 if (m_openSessions == 0) app.DebugPrintf("[LeaderboardManager] CloseSession(): Quitting sceNpScore utility.\n"); 694 else app.DebugPrintf("[LeaderboardManager] CloseSession(): %i sessions still open.\n", m_openSessions); 695} 696 697void OrbisLeaderboardManager::DeleteSession() {} 698 699bool OrbisLeaderboardManager::WriteStats(unsigned int viewCount, ViewIn views) 700{ 701 // Need to cancel read/write operation first. 702 //if (m_eStatsState != eStatsState_Idle) return false; 703 704 // Write relevant parameters. 705 //RegisterScore *regScore = reinterpret_cast<RegisterScore *>(views); 706 707 EnterCriticalSection(&m_csViewsLock); 708 for (int i=0; i<viewCount; i++) 709 { 710 app.DebugPrintf("[LeaderboardManager] WriteStats(), starting. difficulty=%i, statsType=%i, score=%i\n", 711 views[i].m_difficulty, views[i].m_commentData.m_statsType, views[i].m_score); 712 713 m_views.push(views[i]); 714 } 715 LeaveCriticalSection(&m_csViewsLock); 716 717 delete [] views; //*regScore; 718 719 //m_eStatsState = eStatsState_Writing; 720 return true; 721} 722 723// myUID ignored on PS3. 724bool OrbisLeaderboardManager::ReadStats_Friends(LeaderboardReadListener *listener, int difficulty, EStatsType type, PlayerUID myUID, unsigned int startIndex, unsigned int readCount) 725{ 726 // Need to cancel read/write operation first. 727 if (m_eStatsState != eStatsState_Idle) return false; 728 if (!LeaderboardManager::ReadStats_Friends(listener, difficulty, type, myUID, startIndex, readCount)) return false; 729 730 //int ret = sceNpManagerGetNpId(&m_myNpId); 731 //if (ret<0) return false; 732 733 m_eStatsState = eStatsState_Getting; 734 return true; 735} 736 737// myUID ignored on PS3. 738bool OrbisLeaderboardManager::ReadStats_MyScore(LeaderboardReadListener *listener, int difficulty, EStatsType type, PlayerUID myUID, unsigned int readCount) 739{ 740 // Need to cancel read/write operation first. 741 if (m_eStatsState != eStatsState_Idle) return false; 742 if (!LeaderboardManager::ReadStats_MyScore(listener, difficulty, type, myUID, readCount)) return false; 743 744 //int ret = sceNpManagerGetNpId(&m_myNpId); 745 //if (ret<0) return false; 746 747 m_eStatsState = eStatsState_Getting; 748 return true; 749} 750 751// myUID ignored on PS3. 752bool OrbisLeaderboardManager::ReadStats_TopRank(LeaderboardReadListener *listener, int difficulty, EStatsType type, unsigned int startIndex, unsigned int readCount) 753{ 754 // Need to cancel read/write operation first. 755 if (m_eStatsState != eStatsState_Idle) return false; 756 if (!LeaderboardManager::ReadStats_TopRank(listener, difficulty, type, startIndex, readCount)) return false; 757 m_eStatsState = eStatsState_Getting; 758 return true; 759} 760 761void OrbisLeaderboardManager::FlushStats() {} 762 763void OrbisLeaderboardManager::CancelOperation() 764{ 765 m_readListener = NULL; 766 m_eStatsState = eStatsState_Canceled; 767 768 if (m_requestId != 0) 769 { 770 int ret = sceNpScoreAbortTransaction(m_requestId); 771 772 if (ret < 0) 773 { 774 app.DebugPrintf("[LeaderboardManager] CancelOperation(): Problem encountered aborting current operation, 0x%X.\n", ret); 775 } 776 else 777 { 778 app.DebugPrintf("[LeaderboardManager] CancelOperation(): Operation aborted successfully.\n"); 779 } 780 } 781 else 782 { 783 app.DebugPrintf("[LeaderboardManager] CancelOperation(): No current operation.\n"); 784 } 785} 786 787bool OrbisLeaderboardManager::isIdle() 788{ 789 return m_eStatsState == eStatsState_Idle; 790} 791 792int OrbisLeaderboardManager::getBoardId(int difficulty, EStatsType statsType) 793{ 794 switch (statsType) 795 { 796 case eStatsType_Travelling: 797 if (0 <= difficulty && difficulty < 4) return 1 + difficulty; // [1,2,3,4] 798 else return -1; 799 800 case eStatsType_Mining: 801 if (0 <= difficulty && difficulty < 4) return 5 + difficulty; // [5,6,7,8] 802 else return -1; 803 804 case eStatsType_Farming: 805 if (0 <= difficulty && difficulty < 4) return 9 + difficulty; // [9,10,11,12] 806 else return -1; 807 808 case eStatsType_Kills: 809 if (1 <= difficulty && difficulty < 4) return 13 + difficulty - 1; // [13,14,15,16] 810 else return -1; 811 812 default: return -1; 813 } 814} 815 816// 4J-JEV: Filter out all friends who don't have scores. 817/* 818SceNpScoreRankData *OrbisLeaderboardManager::filterJustScorers(unsigned int &num, SceNpScorePlayerRankData *friendsData) 819{ 820int num2 = 0; 821for (int i=0; i<num; i++) if (friendsData[i].hasData) num2++; 822num = num2; num2 = 0; 823SceNpScoreRankData *out = new SceNpScoreRankData[num]; 824for (int i=0; i<num; i++) if (friendsData[i].hasData) out[num2++] = friendsData[i].rankData; 825return out; 826} */ 827 828// 4J-JEV: Unused, here if we want to switch LeaderboardManager::ViewOut to 'SceNpScorePlayerRankData'. 829SceNpScorePlayerRankData *OrbisLeaderboardManager::addPadding(unsigned int num, SceNpScoreRankData *rankData) 830{ 831 SceNpScorePlayerRankData *out = new SceNpScorePlayerRankData[num]; 832 for (int i=0; i<num; i++) 833 { 834 out[i].hasData = true; 835 out[i].rankData = rankData[i]; 836 } 837 delete [] rankData; 838 return out; 839} 840 841// 4J-JEV: Filter and create output object. 842void OrbisLeaderboardManager::convertToOutput(unsigned int &num, ReadScore *out, SceNpScorePlayerRankData *rankData, SceNpScoreComment *comm) 843{ 844 int j=0; 845 for (int i=0; i<num; i++) 846 { 847 if (rankData[i].hasData) 848 { 849 initReadScoreStruct( out[j], rankData[i].rankData ); 850 fillReadScoreStruct( out[j], comm[i] ); 851 852 j++; 853 } 854 } 855 856 num = j; 857} 858 859void OrbisLeaderboardManager::toBinary(void *out, SceNpScoreComment *in) 860{ 861 string decoded = base64_decode( string((char*)in) ); 862 memcpy(out, decoded.c_str(), RECORD_SIZE); 863} 864 865void OrbisLeaderboardManager::fromBinary(SceNpScoreComment **out, void *in) 866{ 867 *out = (SceNpScoreComment *) new unsigned char[SCE_NP_SCORE_COMMENT_MAXLEN + 1]; 868 string encoded = base64_encode((unsigned char const *) in, RECORD_SIZE); 869 memcpy(out, encoded.c_str(), SCE_NP_SCORE_COMMENT_MAXLEN); 870} 871 872void OrbisLeaderboardManager::toBase32(SceNpScoreComment *out, void *in) 873{ 874 ZeroMemory(out,sizeof(SceNpScoreComment)); 875 PBYTE bytes = (PBYTE) in; 876 char *chars = out->utf8Comment; 877 878 for (int i = 0; i < SCE_NP_SCORE_COMMENT_MAXLEN; i++) 879 { 880 int sByte = (i*5) / 8; 881 int eByte = (5+(i*5)) / 8; 882 int dIndex = (i*5) % 8; 883 884 unsigned char fivebits = 0; 885 886 fivebits = *(bytes+sByte) << dIndex; 887 888 if (eByte != sByte) 889 fivebits = fivebits | *(bytes+eByte) >> (8-dIndex); 890 891 fivebits = (fivebits>>3) & 0x1F; 892 893 if (fivebits < 10) // 0 - 9 894 chars[i] = '0' + fivebits; 895 else if (fivebits < 32) // A - V 896 chars[i] = 'A' + (fivebits-10); 897 else 898 assert(false); 899 } 900 901 toSymbols(out->utf8Comment); 902} 903 904void OrbisLeaderboardManager::fromBase32(void *out, SceNpScoreComment *in) 905{ 906 PBYTE bytes = (PBYTE) out; 907 ZeroMemory(bytes, RECORD_SIZE); 908 909 fromSymbols(in->utf8Comment); 910 911 char ch[2] = { 0, 0 }; 912 for (int i = 0; i < SCE_NP_SCORE_COMMENT_MAXLEN; i++) 913 { 914 ch[0] = in->utf8Comment[i]; 915 unsigned char fivebits = strtol(ch, NULL, 32) << 3; 916 917 int sByte = (i*5) / 8; 918 int eByte = (5+(i*5)) / 8; 919 int dIndex = (i*5) % 8; 920 921 *(bytes + sByte) = *(bytes+sByte) | (fivebits >> dIndex); 922 923 if (eByte != sByte) 924 *(bytes + eByte) = fivebits << (8-dIndex); 925 } 926} 927 928char symbBase32[32] = { 929 ' ', '!','\"', '#', '$', '%', '&','\'', '(', ')', 930 '*', '+', '`', '-', '.', '/', ':', ';', '<', '=', 931 '>', '?', '[','\\', ']', '^', '_', '{', '|', '}', 932 '~', '@' 933}; 934 935char charBase32[32] = { 936 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 937 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 938 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 939 'U', 'V' 940}; 941 942void OrbisLeaderboardManager::toSymbols(char *str) 943{ 944 for (int i = 0; i < 63; i++) 945 { 946 for (int j=0; j < 32; j++) 947 { 948 if (str[i]==charBase32[j]) 949 str[i] =symbBase32[j]; 950 } 951 } 952} 953 954void OrbisLeaderboardManager::fromSymbols(char *str) 955{ 956 for (int i = 0; i < 63; i++) 957 { 958 for (int j=0; j < 32; j++) 959 { 960 if (str[i]==symbBase32[j]) 961 str[i] =charBase32[j]; 962 } 963 } 964} 965 966bool OrbisLeaderboardManager::test_string(string testing) 967{ 968#ifndef _CONTENT_PACKAGE 969 static SceNpScoreComment comment; 970 ZeroMemory(&comment, sizeof(SceNpScoreComment)); 971 memcpy(&comment, testing.c_str(), SCE_NP_SCORE_COMMENT_MAXLEN); 972 973 int ctx = sceNpScoreCreateTransactionCtx(m_titleContext); 974 if (ctx<0) return false; 975 976 int ret = sceNpScoreCensorComment(ctx, (const char *) &comment, NULL); 977 978 if (ret == SCE_NP_COMMUNITY_SERVER_ERROR_CENSORED) 979 { 980 app.DebugPrintf("\n[TEST_STRING]: REJECTED "); 981 } 982 else if (ret < 0) 983 { 984 sceNpScoreDestroyTransactionCtx(ctx); 985 return false; 986 } 987 else 988 { 989 app.DebugPrintf("\n[TEST_STRING]: permitted "); 990 } 991 992 app.DebugPrintf("'%s'\n", comment.utf8Comment); 993 sceNpScoreDestroyTransactionCtx(ctx); 994 return true; 995#else 996 return true; 997#endif 998} 999 1000void OrbisLeaderboardManager::initReadScoreStruct(ReadScore &out, SceNpScoreRankData &rankData) 1001{ 1002 ZeroMemory(&out, sizeof(ReadScore)); 1003 1004 // Init rank and onlineID 1005 out.m_uid.setOnlineID( rankData.npId.handle, true ); 1006 out.m_rank = rankData.rank; 1007 1008 // Convert to wstring and copy name. 1009 wstring wstrName = convStringToWstring( string(rankData.npId.handle.data) ).c_str(); 1010 //memcpy(&out.m_name, wstrName.c_str(), XUSER_NAME_SIZE); 1011 out.m_name=wstrName; 1012} 1013 1014void OrbisLeaderboardManager::fillReadScoreStruct(ReadScore &out, SceNpScoreComment &comment) 1015{ 1016 StatsData statsData; 1017 fromBase32( (void *) &statsData, &comment ); 1018 1019 switch (statsData.m_statsType) 1020 { 1021 case eStatsType_Farming: 1022 out.m_statsSize = 6; 1023 out.m_statsData[0] = statsData.m_farming.m_eggs; 1024 out.m_statsData[1] = statsData.m_farming.m_wheat; 1025 out.m_statsData[2] = statsData.m_farming.m_mushroom; 1026 out.m_statsData[3] = statsData.m_farming.m_sugarcane; 1027 out.m_statsData[4] = statsData.m_farming.m_milk; 1028 out.m_statsData[5] = statsData.m_farming.m_pumpkin; 1029 break; 1030 case eStatsType_Mining: 1031 out.m_statsSize = 7; 1032 out.m_statsData[0] = statsData.m_mining.m_dirt; 1033 out.m_statsData[1] = statsData.m_mining.m_cobblestone; 1034 out.m_statsData[2] = statsData.m_mining.m_sand; 1035 out.m_statsData[3] = statsData.m_mining.m_stone; 1036 out.m_statsData[4] = statsData.m_mining.m_gravel; 1037 out.m_statsData[5] = statsData.m_mining.m_clay; 1038 out.m_statsData[6] = statsData.m_mining.m_obsidian; 1039 break; 1040 case eStatsType_Kills: 1041 out.m_statsSize = 7; 1042 out.m_statsData[0] = statsData.m_kills.m_zombie; 1043 out.m_statsData[1] = statsData.m_kills.m_skeleton; 1044 out.m_statsData[2] = statsData.m_kills.m_creeper; 1045 out.m_statsData[3] = statsData.m_kills.m_spider; 1046 out.m_statsData[4] = statsData.m_kills.m_spiderJockey; 1047 out.m_statsData[5] = statsData.m_kills.m_zombiePigman; 1048 out.m_statsData[6] = statsData.m_kills.m_slime; 1049 break; 1050 case eStatsType_Travelling: 1051 out.m_statsSize = 4; 1052 out.m_statsData[0] = statsData.m_travelling.m_walked; 1053 out.m_statsData[1] = statsData.m_travelling.m_fallen; 1054 out.m_statsData[2] = statsData.m_travelling.m_minecart; 1055 out.m_statsData[3] = statsData.m_travelling.m_boat; 1056 break; 1057 } 1058} 1059 1060bool OrbisLeaderboardManager::SortByRank(const ReadScore &lhs, const ReadScore &rhs) 1061{ 1062 return lhs.m_rank < rhs.m_rank; 1063} 1064 1065// Notify plus feature use 1066/*void OrbisLeaderboardManager::NotifyAsyncPlusFeature() 1067{ 1068 SceNpNotifyPlusFeatureParameter param = SceNpNotifyPlusFeatureParameter(); 1069 param.userId = ProfileManager.getUserID(ProfileManager.GetPrimaryPad()); 1070 param.size = sizeof(SceNpNotifyPlusFeatureParameter); 1071 param.features = SCE_NP_PLUS_FEATURE_ASYNC_MULTIPLAY; 1072 ZeroMemory(param.padding, sizeof(char) * 4); 1073 ZeroMemory(param.reserved, sizeof(uint8_t) * 32); 1074 1075 int err = sceNpNotifyPlusFeature(&param); 1076 if (err != SCE_OK) 1077 { 1078 app.DebugPrintf("OrbisLeaderboardManager::NotifyAsyncPlusFeature: sceNpNotifyPlusFeature failed (0x%x)\n", err); 1079 assert(0); 1080 } 1081}*/