the game where you go into mines and start crafting! but for consoles (forked directly from smartcmd's github)
at main 1221 lines 32 kB view raw
1#include "stdafx.h" 2 3#include "ItemStat.h" 4 5#include "Achievement.h" 6#include "Achievements.h" 7 8#include "DamageSource.h" 9#include "Player.h" 10#include "ItemInstance.h" 11#include "Tile.h" 12#include "Item.h" 13#include "Level.h" 14 15#include "..\Minecraft.Client\Minecraft.h" 16#include "LevelData.h" 17#include "LevelSettings.h" 18 19#include "..\Minecraft.Client\LocalPlayer.h" 20#include "..\Minecraft.Client\MultiPlayerLocalPlayer.h" 21 22#include "EntityIO.h" 23 24#include "..\Minecraft.Client\Durango\ServiceConfig\Events-XBLA.8-149E11AEEvents.h" 25 26#include "DurangoStats.h" 27 28 /////////////////// 29 // Ds Item Event // 30 /////////////////// 31 32string DsItemEvent::nameMethods[] = { 33 "NONE", "itemPickedUp", "itemCrafted", 34 "itemTakenFromChest", "itemTakenFromEnderchest", 35 "itemBought", "itemSmithed", "blockMined", "blockPlaced", "MAX" 36}; 37 38DsItemEvent::DsItemEvent(int id, const wstring &name) : Stat(id,name) {} 39 40bool DsItemEvent::onLeaderboard(ELeaderboardId leaderboard, eAcquisitionMethod methodId, Param *param) 41{ 42 switch (methodId) 43 { 44 case eAcquisitionMethod_Pickedup: 45 switch (param->itemId) 46 { 47 case Item::egg_Id: 48 case Tile::mushroom_brown_Id: 49 case Tile::mushroom_red_Id: 50 return leaderboard == eLeaderboardId_FARMING; 51 } 52 break; 53 54 case eAcquisitionMethod_Mined: 55 switch (param->itemId) 56 { 57 case Tile::dirt_Id: 58 case Tile::stoneBrick_Id: 59 case Tile::sand_Id: 60 case Tile::stone_Id: 61 case Tile::gravel_Id: 62 case Tile::clay_Id: 63 case Tile::obsidian_Id: 64 return leaderboard == eLeaderboardId_MINING; 65 66 case Tile::wheat_Id: 67 case Tile::pumpkin_Id: 68 case Tile::reeds_Id: 69 return leaderboard == eLeaderboardId_FARMING; 70 } 71 break; 72 } 73 74 return false; 75} 76 77 78// 4J-JEV, for tiles/items we want to record stats together. 79int DsItemEvent::mergeIds(int itemId) 80{ 81 switch (itemId) 82 { 83 default: 84 return itemId; 85 86 case Tile::mushroom_brown_Id: 87 case Tile::mushroom_red_Id: 88 return Tile::mushroom_brown_Id; 89 90 case Tile::dirt_Id: 91 case Tile::grass_Id: 92 case Tile::farmland_Id: 93 return Tile::dirt_Id; 94 95 case Tile::redstoneLight_Id: 96 case Tile::redstoneLight_lit_Id: 97 return Tile::redstoneLight_Id; 98 99 case Tile::redStoneOre_Id: 100 case Tile::redStoneOre_lit_Id: 101 return Tile::redStoneOre_Id; 102 } 103} 104 105void DsItemEvent::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 106{ 107 if (paramBlob.length == sizeof(Param)) 108 { 109 Param *param = (Param *) paramBlob.data; 110 111 // Combine block ids. 112 param->itemId = mergeIds( param->itemId ); 113 114 // Send farming leaderboard updates. 115 if ( (param->methodId == eAcquisitionMethod_Pickedup && onLeaderboard(eLeaderboardId_FARMING, eAcquisitionMethod_Pickedup, param)) 116 || (param->methodId == eAcquisitionMethod_Mined && onLeaderboard(eLeaderboardId_FARMING, eAcquisitionMethod_Mined, param)) ) 117 { 118 EventWriteLeaderboardTotals( 119 DurangoStats::getUserId(player), //UserId 120 DurangoStats::getPlayerSession(), // PlayerSessionId 121 player->level->difficulty, // Difficulty, 122 eLeaderboardId_FARMING, // ScoreboardId 123 param->itemCount); 124 125 app.DebugPrintf("<%ls>\tscoreboardFarming(%i:%i:%i)\n", DurangoStats::getUserId(player), 126 player->level->difficulty, eLeaderboardId_FARMING, param->itemCount); 127 } 128 129 // Send mining leaderboard updates. 130 if ( param->methodId == eAcquisitionMethod_Mined && onLeaderboard(eLeaderboardId_MINING, eAcquisitionMethod_Mined, param) ) 131 { 132 EventWriteLeaderboardTotals( 133 DurangoStats::getUserId(player), //UserId 134 DurangoStats::getPlayerSession(), // PlayerSessionId 135 player->level->difficulty, // Difficulty, 136 eLeaderboardId_MINING, // ScoreboardId 137 param->itemCount); 138 app.DebugPrintf("<%ls>\tscoreboardMining(%i:%i:%i)\n", DurangoStats::getUserId(player), 139 player->level->difficulty, eLeaderboardId_MINING, param->itemCount); 140 } 141 142 // Debug printout. 143 string method = nameMethods[(int)param->methodId]; 144 app.DebugPrintf("<%ls>\t%s(%i:%i:%i)\n", DurangoStats::getUserId(player), 145 method.c_str(), param->itemId, param->itemAux, param->itemCount); 146 147 // Split on acquisition method, then send relevant events. 148 if (param->methodId == eAcquisitionMethod_Placed) 149 { 150 EventWriteBlockPlaced( 151 DurangoStats::getUserId(player), 152 DurangoStats::getPlayerSession(), 153 player->level->difficulty, 154 param->itemId, 155 param->itemAux, 156 param->itemCount 157 ); 158 } 159 else if (param->methodId == eAcquisitionMethod_Mined) 160 { 161 EventWriteBlockBroken( 162 DurangoStats::getUserId(player), 163 DurangoStats::getPlayerSession(), 164 player->level->difficulty, 165 param->itemId, 166 param->itemAux, 167 param->itemCount 168 ); 169 } 170 else 171 { 172 EventWriteMcItemAcquired( 173 DurangoStats::getUserId(player), 174 0, // TODO 175 DurangoStats::getPlayerSession(), 176 0, 177 0, 178 player->level->difficulty, 179 param->itemId, 180 param->methodId, 181 0, 0, 0, // (x,y,z) 182 param->itemAux, 183 param->itemCount 184 ); 185 } 186 } 187} 188 189/* 4J-JEV: note that mined events will only fire with 'Instant_Mine' on if you are carrying an appropriate 190 * tool for the block that you are mining. 191 */ 192byteArray DsItemEvent::createParamBlob(eAcquisitionMethod eMethod, int itemId, int itemAux, int itemCount) 193{ 194 byteArray output; 195 Param param = { eMethod, itemId, itemAux, itemCount }; 196 output.data = (byte *) new Param(param); 197 output.length = sizeof(Param); 198 return output; 199} 200 201 202 /////////////////// 203 // Ds Mob Killed // 204 /////////////////// 205 206DsMobKilled::DsMobKilled(int id, const wstring &name) : Stat(id,name) {} 207 208void DsMobKilled::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 209{ 210 if (paramBlob.length == sizeof(Param)) 211 { 212 Param *param = (Param *) paramBlob.data; 213 214 if (param->mobType < 0) return; 215 216 if (EventWriteMobKilled(DurangoStats::getUserId(player), 217 0, 218 DurangoStats::getPlayerSession(), 219 DurangoStats::getMultiplayerCorrelationId(), 220 0, 221 player->level->difficulty, 222 DurangoStats::getPlayerSession(), // ROUND ID 223 0, 224 param->weaponId, 225 param->mobType, 226 param->isRanged?1:0, 227 0, 0, 0, // (x,y,z), 228 0, 229 param->distance, 230 param->mobType) 231 == 0) 232 { 233 app.DebugPrintf("<%ls>\t%s(%i:%i:%i:%i)\n", DurangoStats::getUserId(player), 234 (param->isRanged?"mobShotWithEntity":"mobKilledInMelee"), 235 param->mobType, param->weaponId, param->distance, param->damage); 236 } 237 238 switch(EntityIO::getClass(param->mobType)) 239 { 240 case eTYPE_MONSTER: 241 if(param->mobType != SPIDER_JOCKEY_ID) break; 242 // Fallthrough is spider jockey 243 case eTYPE_ZOMBIE: 244 case eTYPE_SKELETON: 245 case eTYPE_CREEPER: 246 case eTYPE_SPIDER: 247 case eTYPE_PIGZOMBIE: 248 case eTYPE_SLIME: 249 250 if (EventWriteLeaderboardTotals( 251 DurangoStats::getUserId(player), //UserId 252 DurangoStats::getPlayerSession(), // PlayerSessionId 253 player->level->difficulty, // Difficulty, 254 eLeaderboardId_KILLING, // ScoreboardId 255 1) // Count 256 == 0) 257 { 258 app.DebugPrintf("<%ls>\tscoreboardKills(%i:%i:1)\n", DurangoStats::getUserId(player), 259 player->level->difficulty, eLeaderboardId_KILLING); 260 } 261 } 262 } 263} 264 265byteArray DsMobKilled::createParamBlob(shared_ptr<Player> player, shared_ptr<Mob> mob, DamageSource *dmgSrc) 266{ 267 // 4J-JEV: Get the id we use for Durango Server Stats. 268 int mob_networking_id; 269 eINSTANCEOF mobEType = mob->GetType(); 270 if ( (mobEType == eTYPE_SPIDER) && (mob->rider.lock() != NULL) && (mob->rider.lock()->GetType() == eTYPE_SKELETON) && mob->rider.lock()->isAlive() ) 271 { 272 mob_networking_id = SPIDER_JOCKEY_ID; // Spider jockey only a concept for leaderboards. 273 } 274 else if ( (mobEType == eTYPE_SKELETON) && (mob->riding != NULL) && (mob->riding->GetType() == eTYPE_SPIDER) && mob->riding->isAlive() ) 275 { 276 mob_networking_id = SPIDER_JOCKEY_ID; // Spider jockey only a concept for leaderboards. 277 } 278 else 279 { 280 mob_networking_id = EntityIO::eTypeToIoid(mobEType); 281 } 282 283 // Kill made with projectile, arrow/ghast/fireball/snowball. 284 // NB: Snowball kills would make an awesome achievement. ("Not a snowball's chance...") 285 if ( dmgSrc->isProjectile() ) 286 { 287 byteArray output; 288 Param param = { 289 DsMobKilled::RANGED, 290 mob_networking_id, 291 EntityIO::eTypeToIoid(dmgSrc->getDirectEntity()->GetType()), 292 mob->distanceTo(player->x, player->y, player->z), 293 0/*not needed*/ 294 }; 295 output.data = (byte*) new Param(param); 296 output.length = sizeof(Param); 297 return output; 298 } 299 300 // Kill made in melee, use itemInHand as weapon. 301 shared_ptr<ItemInstance> item = player->getCarriedItem(); 302 byteArray output; 303 Param param = { 304 DsMobKilled::MELEE, 305 mob_networking_id, 306 (item != NULL ? item->getItem()->id : 0), 307 mob->distanceTo(player->x, player->y, player->z), 308 0/*not needed*/ 309 }; 310 output.data = (byte*) new Param(param); 311 output.length = sizeof(Param); 312 return output; 313} 314 315 316 ///////////////////// 317 // Ds Mob Interact // 318 ///////////////////// 319 320string DsMobInteract::nameInteract[] = { 321 "unknownMobInteraction", "mobBred", "mobTamed", "mobCured", "mobCrafted", "mobSheared" 322}; 323 324DsMobInteract::DsMobInteract(int id, const wstring &name) : Stat(id,name) {} 325 326void DsMobInteract::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 327{ 328 if (paramBlob.length == sizeof(Param)) 329 { 330 Param *param = (Param *) paramBlob.data; 331 332 if (param->mobId < 0) return; 333 334 app.DebugPrintf("<%ls>\t%s(%i)\n", DurangoStats::getUserId(player), 335 nameInteract[param->interactionType].c_str(), param->mobId); 336 337 EventWriteMobInteract( 338 DurangoStats::getUserId(player), 339 DurangoStats::getPlayerSession(), 340 param->mobId, 341 param->interactionType ); 342 } 343} 344 345byteArray DsMobInteract::createParamBlob(eInteract interactionId, int entityId) 346{ 347 byteArray output; 348 Param param = { interactionId, EntityIO::eTypeToIoid((eINSTANCEOF)entityId) }; 349 output.data = (byte*) new Param(param); 350 output.length = sizeof(Param); 351 return output; 352} 353 354 355 /////////////// 356 // Ds Travel // 357 /////////////// 358 359string DsTravel::nameMethods[eMethod_MAX] = 360 { 361 "Walk", "Swim", "Fall", "Climb", "Cart", "Boat", "Pig", "Time" 362 }; 363 364unsigned int DsTravel::CACHE_SIZES[eMethod_MAX] = 365 { 366 40, // WALK - Meters? 367 20, // SWIM - Meters? 368 0, // FALL - Meters? - Fall event naturally only sends on land, no caching necessary. 369 10, // CLIMB - Meters? 370 70, // CART - Meters? 371 70, // BOAT - Meters? 372 10, // PIG - Meters? 373 20*60*5, // TIME - GameTicks (20*60*5 ~ 5 mins) 374 }; 375 376DsTravel::DsTravel(int id, const wstring &name) : Stat(id,name) 377{ 378 ZeroMemory(&param_cache, sizeof(unsigned int)*eMethod_MAX*MAX_LOCAL_PLAYERS); 379} 380 381void DsTravel::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 382{ 383 if (paramBlob.length == sizeof(Param)) 384 { 385 Param *param = (Param*) paramBlob.data; 386 387 int newDistance = cache(player->GetXboxPad(), *param); 388 389 if ( newDistance > 0 ) write(player, param->method, newDistance); 390 } 391} 392 393byteArray DsTravel::createParamBlob(eMethod method, int distance) 394{ 395 byteArray output; 396 Param param = { method, distance }; 397 output.data = (byte*) new Param(param); 398 output.length = sizeof(Param); 399 return output; 400} 401 402int DsTravel::cache(int iPad, Param &param) 403{ 404 if ( (eMethod_walk <= param.method) && (param.method < eMethod_MAX) ) 405 { 406 param_cache[iPad][param.method] += param.distance; 407 408 if (param_cache[iPad][param.method] > CACHE_SIZES[param.method]) 409 { 410 int out = param_cache[iPad][param.method]; 411 param_cache[iPad][param.method] = 0; 412 return out; 413 } 414 } 415 416 return 0; 417} 418 419void DsTravel::flush(shared_ptr<LocalPlayer> player) 420{ 421 int iPad = player->GetXboxPad(); 422 for (int i = 0; i < eMethod_MAX; i++) 423 { 424 if (param_cache[iPad][i] > 0) 425 { 426 write( player, (eMethod) i, param_cache[iPad][i] ); 427 param_cache[iPad][i] = 0; 428 } 429 } 430} 431 432void DsTravel::write(shared_ptr<LocalPlayer> player, eMethod method, int distance) 433{ 434 if (player == nullptr) return; 435 436 app.DebugPrintf("<%ls>\t%s(%i)\n", DurangoStats::getUserId(player), nameMethods[method].c_str(), distance); 437 438 if (method == DsTravel::eMethod_time) 439 { 440 EventWriteIncTimePlayed( 441 DurangoStats::getUserId(player), 442 DurangoStats::getPlayerSession(), 443 player->level->difficulty, 444 distance 445 ); 446 } 447 else if ( (eMethod_walk <= method) && (method < eMethod_MAX) ) 448 { 449 EventWriteIncDistanceTravelled( 450 DurangoStats::getUserId(player), 451 DurangoStats::getPlayerSession(), 452 player->level->difficulty, 453 distance, 454 method 455 ); 456 457 switch(method) 458 { 459 case eMethod_walk: 460 case eMethod_fall: 461 case eMethod_minecart: 462 case eMethod_boat: 463 EventWriteLeaderboardTotals( 464 DurangoStats::getUserId(player), //UserId 465 DurangoStats::getPlayerSession(), // PlayerSessionId 466 player->level->difficulty, // Difficulty, 467 eLeaderboardId_TRAVELLING, // ScoreboardId 468 distance); 469 break; 470 } 471 } 472} 473 474 ////////////////// 475 // Ds Item Used // 476 ////////////////// 477 478DsItemUsed::DsItemUsed(int id, const wstring &name) : Stat(id,name) {} 479 480void DsItemUsed::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 481{ 482 if (paramBlob.length == sizeof(Param)) 483 { 484 Param *param = (Param*) paramBlob.data; 485 app.DebugPrintf("<%ls>\titemUsed(%i,%i,%i)\n", DurangoStats::getUserId(player), 486 param->itemId, 487 param->aux, 488 param->count 489 ); 490 491 EventWriteMcItemUsed( 492 DurangoStats::getUserId(player), 493 0, // SectionId, 494 DurangoStats::getPlayerSession(), 495 0, // MultiplayerCorrelationId, 496 0, // Gameplay Mode, 497 player->level->difficulty, 498 param->itemId, 499 0, 0, 0, // (x,y,z) 500 param->aux, 501 param->count, 502 param->hunger 503 ); 504 } 505} 506 507byteArray DsItemUsed::createParamBlob(int itemId, int aux, int count, int health, int hunger) 508{ 509 byteArray output; 510 Param param = { itemId, aux, count, health, hunger }; 511 output.data = (byte*) new Param(param); 512 output.length = sizeof(Param); 513 return output; 514} 515 516 517 //////////////////// 518 // Ds Achievement // 519 //////////////////// 520 521DsAchievement::DsAchievement(int id, const wstring &name) : Stat(id,name) {} 522 523void DsAchievement::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 524{ 525 if (paramBlob.length == sizeof(SmallParam)) 526 { 527 SmallParam *paramS = (SmallParam*) paramBlob.data; 528 assert( DurangoStats::binaryAchievement(paramS->award) ); 529 app.DebugPrintf("<%ls>\tAchievement(%i)\n", DurangoStats::getUserId(player), paramS->award); 530 531 bool canAward = true; 532 if(paramS->award == eAward_stayinFrosty) 533 { 534 canAward = !player->m_bHasAwardedStayinFrosty; 535 player->m_bHasAwardedStayinFrosty = true; 536 } 537 538 if(canAward) 539 { 540 EventWriteAchievementGet( 541 DurangoStats::getUserId(player), 542 DurangoStats::getPlayerSession(), 543 paramS->award 544 ); 545 } 546 } 547 else if (paramBlob.length == sizeof(LargeParam)) 548 { 549 LargeParam *paramL = (LargeParam*) paramBlob.data; 550 assert( DurangoStats::enhancedAchievement(paramL->award) ); 551 552 switch(paramL->award) 553 { 554 case eAward_musicToMyEars: 555 app.DebugPrintf("<%ls>\tmusicToMyEars(%i)\n", DurangoStats::getUserId(player), paramL->count); 556 EventWritePlayedMusicDisc( 557 DurangoStats::getUserId(player), 558 DurangoStats::getPlayerSession(), 559 paramL->count 560 ); 561 break; 562 563 case eAward_chestfulOfCobblestone: 564 app.DebugPrintf("<%ls>\tchestfulOfCobblestone(%i)\n", DurangoStats::getUserId(player), paramL->count); 565 EventWriteChestfulOfCobblestone( 566 DurangoStats::getUserId(player), 567 DurangoStats::getPlayerSession(), 568 paramL->count 569 ); 570 break; 571 572 case eAward_overkill: 573 app.DebugPrintf("<%ls>\toverkill(%i)\n", DurangoStats::getUserId(player), paramL->count); 574 EventWriteOverkill( 575 DurangoStats::getUserId(player), 576 DurangoStats::getPlayerSession(), 577 paramL->count 578 ); 579 break; 580 581 case eAward_OnARail: 582 app.DebugPrintf("<%ls>\nonARail(%i)\n", DurangoStats::getUserId(player), paramL->count); 583 EventWriteOnARail( 584 DurangoStats::getUserId(player), 585 DurangoStats::getPlayerSession(), 586 paramL->count 587 ); 588 break; 589 } 590 } 591 else assert(false); // Unsuitable paramBlob length. 592} 593 594byteArray DsAchievement::createSmallParamBlob(eAward award) 595{ 596 byteArray output; 597 SmallParam param = { award }; 598 output.data = (byte*) new SmallParam(param); 599 output.length = sizeof(SmallParam); 600 return output; 601} 602 603byteArray DsAchievement::createLargeParamBlob(eAward award, int count) 604{ 605 byteArray output; 606 LargeParam param = { award, count }; 607 output.data = (byte*) new LargeParam(param); 608 output.length = sizeof(LargeParam); 609 return output; 610} 611 612 613 ////////////////////////// 614 // Ds Changed Dimension // 615 ////////////////////////// 616 617DsChangedDimension::DsChangedDimension(int id, const wstring &name) : Stat(id,name) {} 618 619void DsChangedDimension::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 620{ 621 if (paramBlob.length == sizeof(Param)) 622 { 623 Param *param = (Param*) paramBlob.data; 624 app.DebugPrintf("<%ls>\tchangedDimension(%i:%i)\n", DurangoStats::getUserId(player), 625 param->fromDimId, param->toDimId); 626 627 // No longer used. 628 } 629} 630 631byteArray DsChangedDimension::createParamBlob(int fromDimId, int toDimId) 632{ 633 byteArray output; 634 Param param = { fromDimId, toDimId }; 635 output.data = (byte*) new Param(param); 636 output.length = sizeof(Param); 637 return output; 638} 639 640 641 ////////////////////// 642 // Ds Entered Biome // 643 ////////////////////// 644 645DsEnteredBiome::DsEnteredBiome(int id, const wstring &name) : Stat(id,name) {} 646 647void DsEnteredBiome::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) 648{ 649 if (paramBlob.length == sizeof(Param)) 650 { 651 Param *param = (Param*) paramBlob.data; 652 app.DebugPrintf("<%ls>\tenteredBiome(%i)\n", DurangoStats::getUserId(player), param->biomeId); 653 654 EventWriteEnteredNewBiome( 655 DurangoStats::getUserId(player), 656 DurangoStats::getPlayerSession(), 657 param->biomeId 658 ); 659 } 660} 661 662byteArray DsEnteredBiome::createParamBlob(int biomeId) 663{ 664 byteArray output; 665 Param param = { biomeId }; 666 output.data = (byte*) new Param(param); 667 output.length = sizeof(Param); 668 return output; 669} 670 671 //////////////////////// 672 // DURANGO STATISTICS // 673 //////////////////////// 674 675DurangoStats::DurangoStats() 676{ 677 // Hopefully only using the first parameter 678 itemsAcquired = new DsItemEvent( itemsAcquired_Id, L"itemsAcquired" ); 679 itemsAcquired->postConstruct(); 680 681 itemUsed = new DsItemUsed( itemUsed_Id, L"itemUsed" ); 682 itemUsed->postConstruct(); 683 684 travel = new DsTravel( travel_Id, L"travel" ); 685 travel->setAwardLocallyOnly()->postConstruct(); 686 687 mobKilled = new DsMobKilled( mobKilled_Id, L"mobKilled" ); 688 mobKilled->postConstruct(); 689 690 mobInteract = new DsMobInteract( mobInteract_Id, L"mobInteract" ); 691 mobInteract->postConstruct(); 692 693 changedDimension = new DsChangedDimension( changedDimension_Id, L"changedDimension" ); 694 changedDimension->postConstruct(); 695 696 enteredBiome = new DsEnteredBiome( enteredBiome_Id, L"enteredBiome" ); 697 enteredBiome->postConstruct(); 698 699 achievement = new DsAchievement( binAchievement_Id, L"achievement" ); 700 achievement->postConstruct(); 701 702 achievementLocal = new DsAchievement( binAchievementLocal_Id, L"achievementLocal" ); 703 achievementLocal->setAwardLocallyOnly(); 704 achievementLocal->postConstruct(); 705 706 EventRegisterXBLA_149E11AE(); 707} 708 709DurangoStats::~DurangoStats() 710{ 711 EventUnregisterXBLA_149E11AE(); 712} 713 714Stat *DurangoStats::get_stat(int i) 715{ 716 switch (i) 717 { 718 case itemsAcquired_Id: return (Stat*) itemsAcquired; 719 case itemUsed_Id: return (Stat*) itemUsed; 720 case travel_Id: return (Stat*) travel; 721 case mobKilled_Id: return (Stat*) mobKilled; 722 case mobInteract_Id: return (Stat*) mobInteract; 723 case changedDimension_Id: return (Stat*) changedDimension; 724 case enteredBiome_Id: return (Stat*) enteredBiome; 725 case binAchievement_Id: return (Stat*) achievement; 726 case binAchievementLocal_Id: return (Stat*) achievementLocal; 727 728 // Unrecognised stat id 729 default: assert(false); break; 730 } 731 732 return NULL; 733} 734 735Stat* DurangoStats::get_walkOneM() 736{ 737 return travel; 738} 739 740Stat* DurangoStats::get_swimOneM() 741{ 742 return travel; 743} 744 745Stat* DurangoStats::get_fallOneM() 746{ 747 return travel; 748} 749 750Stat* DurangoStats::get_climbOneM() 751{ 752 return travel; 753} 754 755Stat* DurangoStats::get_minecartOneM() 756{ 757 return travel; 758} 759 760Stat* DurangoStats::get_boatOneM() 761{ 762 return travel; 763} 764 765Stat* DurangoStats::get_pigOneM() 766{ 767 return travel; 768} 769 770Stat *DurangoStats::get_cowsMilked() 771{ 772 return get_itemsCrafted(Item::bucket_milk_Id); 773} 774 775Stat* DurangoStats::get_killMob() 776{ 777 return mobKilled; 778} 779 780Stat* DurangoStats::get_breedEntity(eINSTANCEOF entityId) 781{ 782 return mobInteract; 783} 784 785Stat* DurangoStats::get_tamedEntity(eINSTANCEOF entityId) 786{ 787 return mobInteract; 788} 789 790Stat* DurangoStats::get_curedEntity(eINSTANCEOF entityId) 791{ 792 return mobInteract; 793} 794 795Stat* DurangoStats::get_craftedEntity(eINSTANCEOF entityId) 796{ 797 return mobInteract; 798} 799 800Stat* DurangoStats::get_shearedEntity(eINSTANCEOF entityId) 801{ 802 return mobInteract; 803} 804 805Stat* DurangoStats::get_timePlayed() 806{ 807 return travel; 808} 809 810Stat* DurangoStats::get_blocksPlaced(int blockId) 811{ 812 return (Stat*) itemsAcquired; 813} 814 815Stat* DurangoStats::get_blocksMined(int blockId) 816{ 817 return (Stat*) itemsAcquired; 818} 819 820Stat* DurangoStats::get_itemsCollected(int itemId, int itemAux) 821{ 822 return (Stat*) itemsAcquired; 823} 824 825Stat* DurangoStats::get_itemsCrafted(int itemId) 826{ 827 switch (itemId) 828 { 829 // 4J-JEV: These items can be crafted trivially to and from their block equivalents, 830 // 'Acquire Hardware' also relies on 'Count_Crafted(IronIngot) == Count_Forged(IronIngot)" on the Stats server. 831 case Item::ironIngot_Id: 832 case Item::goldIngot_Id: 833 case Item::diamond_Id: 834 case Item::redStone_Id: 835 case Item::emerald_Id: 836 return NULL; 837 838 case Item::dye_powder_Id: 839 default: 840 return (Stat*) itemsAcquired; 841 } 842 843} 844 845Stat* DurangoStats::get_itemsSmelted(int itemId) 846{ 847 // 4J-JEV: Context needed for itemCrafted for iron/gold being smelted. 848 return (Stat*) itemsAcquired; 849} 850 851Stat* DurangoStats::get_itemsUsed(int itemId) 852{ 853 return (Stat*) itemUsed; 854} 855 856Stat *DurangoStats::get_itemsBought(int itemId) 857{ 858 return (Stat*) itemsAcquired; 859} 860 861Stat* DurangoStats::get_changedDimension(int from, int to) 862{ 863 return (Stat*) changedDimension; 864} 865 866Stat* DurangoStats::get_enteredBiome(int biomeId) 867{ 868 return (Stat*) enteredBiome; 869} 870 871Stat* DurangoStats::get_achievement(eAward achievementId) 872{ 873 // Special case for 'binary' achievements. 874 if ( binaryAchievement(achievementId) 875 || enhancedAchievement(achievementId) ) 876 { 877 switch (achievementId) 878 { 879 case eAward_chestfulOfCobblestone: 880 case eAward_TakingInventory: 881 return achievementLocal; 882 883 default: 884 return achievement; 885 } 886 } 887 else if (achievementId == eAward_zombieDoctor) 888 { 889 return get_curedEntity(eTYPE_ZOMBIE); 890 } 891 892 // Other achievements awarded through more detailed generic events. 893 return NULL; 894} 895 896byteArray DurangoStats::getParam_walkOneM(int distance) 897{ 898 return DsTravel::createParamBlob(DsTravel::eMethod_walk, distance); 899} 900 901byteArray DurangoStats::getParam_swimOneM(int distance) 902{ 903 return DsTravel::createParamBlob(DsTravel::eMethod_swim,distance); 904} 905 906byteArray DurangoStats::getParam_fallOneM(int distance) 907{ 908 return DsTravel::createParamBlob(DsTravel::eMethod_fall,distance); 909} 910 911byteArray DurangoStats::getParam_climbOneM(int distance) 912{ 913 return DsTravel::createParamBlob(DsTravel::eMethod_climb,distance); 914} 915 916byteArray DurangoStats::getParam_minecartOneM(int distance) 917{ 918 return DsTravel::createParamBlob(DsTravel::eMethod_minecart,distance); 919} 920 921byteArray DurangoStats::getParam_boatOneM(int distance) 922{ 923 return DsTravel::createParamBlob(DsTravel::eMethod_boat,distance); 924} 925 926byteArray DurangoStats::getParam_pigOneM(int distance) 927{ 928 return DsTravel::createParamBlob(DsTravel::eMethod_pig,distance); 929} 930 931byteArray DurangoStats::getParam_cowsMilked() 932{ 933 return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Crafted, Item::bucket_milk_Id, 0, 1); 934} 935 936byteArray DurangoStats::getParam_blocksPlaced(int blockId, int data, int count) 937{ 938 return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Placed, blockId, data, count); 939} 940 941byteArray DurangoStats::getParam_blocksMined(int blockId, int data, int count) 942{ 943 return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Mined, blockId, data, count); 944} 945 946byteArray DurangoStats::getParam_itemsCollected(int id, int aux, int count) 947{ 948 return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Pickedup, id, aux, count); 949} 950 951byteArray DurangoStats::getParam_itemsCrafted(int id, int aux, int count) 952{ 953 return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Crafted, id, aux, count); 954} 955 956byteArray DurangoStats::getParam_itemsUsed(shared_ptr<Player> player, shared_ptr<ItemInstance> itm) 957{ 958 return DsItemUsed::createParamBlob( 959 itm->getItem()->id, itm->getAuxValue(), itm->GetCount(), 960 player->getHealth(), player->getFoodData()->getFoodLevel() 961 ); 962} 963 964byteArray DurangoStats::getParam_itemsBought(int id, int aux, int count) 965{ 966 return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Bought, id, aux, count); 967} 968 969byteArray DurangoStats::getParam_mobKill(shared_ptr<Player> player, shared_ptr<Mob> mob, DamageSource *dmgSrc) 970{ 971 return DsMobKilled::createParamBlob(player,mob,dmgSrc); 972} 973 974byteArray DurangoStats::getParam_breedEntity(eINSTANCEOF entityId) 975{ 976 return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Breed, entityId); 977} 978 979byteArray DurangoStats::getParam_tamedEntity(eINSTANCEOF entityId) 980{ 981 return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Tamed, entityId); 982} 983 984byteArray DurangoStats::getParam_curedEntity(eINSTANCEOF entityId) 985{ 986 return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Cured, entityId); 987} 988 989byteArray DurangoStats::getParam_craftedEntity(eINSTANCEOF entityId) 990{ 991 return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Crafted, entityId); 992} 993 994byteArray DurangoStats::getParam_shearedEntity(eINSTANCEOF entityId) 995{ 996 return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Sheared, entityId); 997} 998 999byteArray DurangoStats::getParam_time(int timediff) 1000{ 1001 return DsTravel::createParamBlob(DsTravel::eMethod_time, timediff); 1002} 1003 1004byteArray DurangoStats::getParam_changedDimension(int from, int to) 1005{ 1006 return DsChangedDimension::createParamBlob(from,to); 1007} 1008 1009byteArray DurangoStats::getParam_enteredBiome(int biomeId) 1010{ 1011 return DsEnteredBiome::createParamBlob(biomeId); 1012} 1013 1014byteArray DurangoStats::getParam_achievement(eAward id) 1015{ 1016 if (binaryAchievement(id)) 1017 { 1018 return DsAchievement::createSmallParamBlob(id); 1019 } 1020 else if (enhancedAchievement(id)) 1021 { 1022 assert(false); // Should be calling the appropriate getParam function. 1023 } 1024 else if (id == eAward_zombieDoctor) 1025 { 1026 return getParam_curedEntity(eTYPE_ZOMBIE); 1027 } 1028 1029 // If its not a binary achievement, 1030 // don't bother constructing the param blob. 1031 return getParam_noArgs(); 1032} 1033 1034byteArray DurangoStats::getParam_onARail(int dist) 1035{ 1036 return DsAchievement::createLargeParamBlob(eAward_OnARail, dist); 1037} 1038 1039byteArray DurangoStats::getParam_chestfulOfCobblestone(int count) 1040{ 1041 return DsAchievement::createLargeParamBlob(eAward_chestfulOfCobblestone, count); 1042} 1043 1044byteArray DurangoStats::getParam_overkill(int dmg) 1045{ 1046 return DsAchievement::createLargeParamBlob(eAward_overkill, dmg); 1047} 1048 1049byteArray DurangoStats::getParam_musicToMyEars(int recordId) 1050{ 1051 return DsAchievement::createLargeParamBlob(eAward_musicToMyEars, recordId); 1052} 1053 1054bool DurangoStats::binaryAchievement(eAward achievementId) 1055{ 1056 switch (achievementId) 1057 { 1058 case eAward_InToTheNether: 1059 case eAward_theEnd: 1060 case eAward_WhenPigsFly: 1061 case eAward_diamondsToYou: 1062 case eAward_stayinFrosty: 1063 case eAward_renewableEnergy: 1064 case eAward_ironMan: 1065 case eAward_winGame: 1066 case /*maybe*/ eAward_TakingInventory: 1067 return true; 1068 default: 1069 return false; 1070 } 1071} 1072 1073/** 4J-JEV, 1074 Basically achievements with an inconsequential extra parameter 1075 that I thought best not to / prefered not to / couldn't be bothered to make class handlers for. 1076 (Motivation: it would be nice for players to see how close they were/are to achieving these things). 1077*/ 1078bool DurangoStats::enhancedAchievement(eAward achievementId) 1079{ 1080 switch (achievementId) 1081 { 1082 //case eAward_TakingInventory: 1083 case eAward_musicToMyEars: 1084 case eAward_chestfulOfCobblestone: 1085 case eAward_overkill: 1086 case eAward_OnARail: 1087 return true; 1088 default: 1089 return false; 1090 } 1091} 1092 1093 1094void DurangoStats::generatePlayerSession() 1095{ 1096 DurangoStats *dsInstance = (DurangoStats *) GenericStats::getInstance(); 1097 CoCreateGuid( &dsInstance->playerSessionId ); 1098} 1099 1100LPCGUID DurangoStats::getPlayerSession() 1101{ 1102 DurangoStats *dsInstance = (DurangoStats *) GenericStats::getInstance(); 1103 LPCGUID lpcguid = &dsInstance->playerSessionId; 1104 return lpcguid; 1105} 1106 1107void DurangoStats::setMultiplayerCorrelationId(Platform::String^ mcpId) 1108{ 1109 ((DurangoStats*)GenericStats::getInstance())->multiplayerCorrelationId = mcpId; 1110} 1111 1112LPCWSTR DurangoStats::getMultiplayerCorrelationId() 1113{ 1114 return ((DurangoStats*)GenericStats::getInstance())->multiplayerCorrelationId->Data(); 1115} 1116 1117LPCWSTR DurangoStats::getUserId(shared_ptr<LocalPlayer> player) 1118{ 1119 return getUserId(player->GetXboxPad()); 1120} 1121 1122LPCWSTR DurangoStats::getUserId(int iPad) 1123{ 1124 static wstring cache = L""; 1125 PlayerUID uid = INVALID_XUID; 1126 ProfileManager.GetXUID(iPad, &uid, true); 1127 cache = uid.toString(); 1128 return cache.c_str(); 1129} 1130 1131void DurangoStats::playerSessionStart(PlayerUID uid, shared_ptr<Player> plr) 1132{ 1133 if (plr != NULL && plr->level != NULL && plr->level->getLevelData() != NULL) 1134 { 1135 //wprintf(uid.toString().c_str()); 1136 1137 //EventWritePlayerSessionStart( 1138 app.DebugPrintf(">>>\tPlayerSessionStart(%ls,%s,%ls,%i,%i)\n", 1139 uid.toString(), 1140 DurangoStats::getPlayerSession(), 1141 DurangoStats::getMultiplayerCorrelationId(), 1142 plr->level->getLevelData()->getGameType()->isSurvival(), 1143 plr->level->difficulty 1144 ); 1145 1146 EventWritePlayerSessionStart( 1147 uid.toString().c_str(), 1148 DurangoStats::getPlayerSession(), 1149 DurangoStats::getMultiplayerCorrelationId(), 1150 plr->level->getLevelData()->getGameType()->isSurvival(), 1151 plr->level->difficulty 1152 ); 1153 } 1154} 1155 1156void DurangoStats::playerSessionStart(int iPad) 1157{ 1158 PlayerUID puid; shared_ptr<Player> plr; 1159 ProfileManager.GetXUID(iPad, &puid, true); 1160 plr = Minecraft::GetInstance()->localplayers[iPad]; 1161 playerSessionStart(puid,plr); 1162} 1163 1164void DurangoStats::playerSessionPause(int iPad) 1165{ 1166 shared_ptr<MultiplayerLocalPlayer> plr = Minecraft::GetInstance()->localplayers[iPad]; 1167 if (plr != NULL && plr->level != NULL && plr->level->getLevelData() != NULL) 1168 { 1169 PlayerUID puid; 1170 ProfileManager.GetXUID(iPad, &puid, true); 1171 1172 //EventWritePlayerSessionPause( 1173 app.DebugPrintf(">>>\tPlayerSessionPause(%ls,%s,%ls)\n", 1174 puid.toString().c_str(), 1175 DurangoStats::getPlayerSession(), 1176 DurangoStats::getMultiplayerCorrelationId() 1177 ); 1178 1179 EventWritePlayerSessionPause( 1180 puid.toString().c_str(), 1181 DurangoStats::getPlayerSession(), 1182 DurangoStats::getMultiplayerCorrelationId() 1183 ); 1184 } 1185} 1186 1187void DurangoStats::playerSessionResume(int iPad) 1188{ 1189 shared_ptr<MultiplayerLocalPlayer> plr = Minecraft::GetInstance()->localplayers[iPad]; 1190 if (plr != NULL && plr->level != NULL && plr->level->getLevelData() != NULL) 1191 { 1192 PlayerUID puid; 1193 ProfileManager.GetXUID(iPad, &puid, true); 1194 1195 //EventWritePlayerSessionResume( 1196 app.DebugPrintf(">>>\tPlayerSessionResume(%ls,%s,%ls,%i,%i)\n", 1197 puid.toString().c_str(), 1198 DurangoStats::getPlayerSession(), 1199 DurangoStats::getMultiplayerCorrelationId(), 1200 plr->level->getLevelData()->getGameType()->isSurvival(), 1201 plr->level->difficulty 1202 ); 1203 1204 EventWritePlayerSessionResume( 1205 puid.toString().c_str(), 1206 DurangoStats::getPlayerSession(), 1207 DurangoStats::getMultiplayerCorrelationId(), 1208 plr->level->getLevelData()->getGameType()->isSurvival(), 1209 plr->level->difficulty 1210 ); 1211 } 1212} 1213 1214void DurangoStats::playerSessionEnd(int iPad) 1215{ 1216 shared_ptr<MultiplayerLocalPlayer> plr = Minecraft::GetInstance()->localplayers[iPad]; 1217 if (plr != NULL) 1218 { 1219 DurangoStats::getInstance()->travel->flush(plr); 1220 } 1221}