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