diff options
Diffstat (limited to 'Minecraft.World/DurangoStats.cpp')
| -rw-r--r-- | Minecraft.World/DurangoStats.cpp | 1221 |
1 files changed, 1221 insertions, 0 deletions
diff --git a/Minecraft.World/DurangoStats.cpp b/Minecraft.World/DurangoStats.cpp new file mode 100644 index 00000000..c9b51c84 --- /dev/null +++ b/Minecraft.World/DurangoStats.cpp @@ -0,0 +1,1221 @@ +#include "stdafx.h" + +#include "ItemStat.h" + +#include "Achievement.h" +#include "Achievements.h" + +#include "DamageSource.h" +#include "Player.h" +#include "ItemInstance.h" +#include "Tile.h" +#include "Item.h" +#include "Level.h" + +#include "..\Minecraft.Client\Minecraft.h" +#include "LevelData.h" +#include "LevelSettings.h" + +#include "..\Minecraft.Client\LocalPlayer.h" +#include "..\Minecraft.Client\MultiPlayerLocalPlayer.h" + +#include "EntityIO.h" + +#include "..\Minecraft.Client\Durango\ServiceConfig\Events-XBLA.8-149E11AEEvents.h" + +#include "DurangoStats.h" + + /////////////////// + // Ds Item Event // + /////////////////// + +string DsItemEvent::nameMethods[] = { + "NONE", "itemPickedUp", "itemCrafted", + "itemTakenFromChest", "itemTakenFromEnderchest", + "itemBought", "itemSmithed", "blockMined", "blockPlaced", "MAX" +}; + +DsItemEvent::DsItemEvent(int id, const wstring &name) : Stat(id,name) {} + +bool DsItemEvent::onLeaderboard(ELeaderboardId leaderboard, eAcquisitionMethod methodId, Param *param) +{ + switch (methodId) + { + case eAcquisitionMethod_Pickedup: + switch (param->itemId) + { + case Item::egg_Id: + case Tile::mushroom1_Id: + case Tile::mushroom2_Id: + return leaderboard == eLeaderboardId_FARMING; + } + break; + + case eAcquisitionMethod_Mined: + switch (param->itemId) + { + case Tile::dirt_Id: + case Tile::stoneBrick_Id: + case Tile::sand_Id: + case Tile::rock_Id: + case Tile::gravel_Id: + case Tile::clay_Id: + case Tile::obsidian_Id: + return leaderboard == eLeaderboardId_MINING; + + case Tile::crops_Id: + case Tile::pumpkin_Id: + case Tile::reeds_Id: + return leaderboard == eLeaderboardId_FARMING; + } + break; + } + + return false; +} + + +// 4J-JEV, for tiles/items we want to record stats together. +int DsItemEvent::mergeIds(int itemId) +{ + switch (itemId) + { + default: + return itemId; + + case Tile::mushroom1_Id: + case Tile::mushroom2_Id: + return Tile::mushroom1_Id; + + case Tile::dirt_Id: + case Tile::grass_Id: + case Tile::farmland_Id: + return Tile::dirt_Id; + + case Tile::redstoneLight_Id: + case Tile::redstoneLight_lit_Id: + return Tile::redstoneLight_Id; + + case Tile::redStoneOre_Id: + case Tile::redStoneOre_lit_Id: + return Tile::redStoneOre_Id; + } +} + +void DsItemEvent::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param *) paramBlob.data; + + // Combine block ids. + param->itemId = mergeIds( param->itemId ); + + // Send farming leaderboard updates. + if ( (param->methodId == eAcquisitionMethod_Pickedup && onLeaderboard(eLeaderboardId_FARMING, eAcquisitionMethod_Pickedup, param)) + || (param->methodId == eAcquisitionMethod_Mined && onLeaderboard(eLeaderboardId_FARMING, eAcquisitionMethod_Mined, param)) ) + { + EventWriteLeaderboardTotals( + DurangoStats::getUserId(player), //UserId + DurangoStats::getPlayerSession(), // PlayerSessionId + player->level->difficulty, // Difficulty, + eLeaderboardId_FARMING, // ScoreboardId + param->itemCount); + + app.DebugPrintf("<%ls>\tscoreboardFarming(%i:%i:%i)\n", DurangoStats::getUserId(player), + player->level->difficulty, eLeaderboardId_FARMING, param->itemCount); + } + + // Send mining leaderboard updates. + if ( param->methodId == eAcquisitionMethod_Mined && onLeaderboard(eLeaderboardId_MINING, eAcquisitionMethod_Mined, param) ) + { + EventWriteLeaderboardTotals( + DurangoStats::getUserId(player), //UserId + DurangoStats::getPlayerSession(), // PlayerSessionId + player->level->difficulty, // Difficulty, + eLeaderboardId_MINING, // ScoreboardId + param->itemCount); + app.DebugPrintf("<%ls>\tscoreboardMining(%i:%i:%i)\n", DurangoStats::getUserId(player), + player->level->difficulty, eLeaderboardId_MINING, param->itemCount); + } + + // Debug printout. + string method = nameMethods[(int)param->methodId]; + app.DebugPrintf("<%ls>\t%s(%i:%i:%i)\n", DurangoStats::getUserId(player), + method.c_str(), param->itemId, param->itemAux, param->itemCount); + + // Split on acquisition method, then send relevant events. + if (param->methodId == eAcquisitionMethod_Placed) + { + EventWriteBlockPlaced( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + player->level->difficulty, + param->itemId, + param->itemAux, + param->itemCount + ); + } + else if (param->methodId == eAcquisitionMethod_Mined) + { + EventWriteBlockBroken( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + player->level->difficulty, + param->itemId, + param->itemAux, + param->itemCount + ); + } + else + { + EventWriteMcItemAcquired( + DurangoStats::getUserId(player), + 0, // TODO + DurangoStats::getPlayerSession(), + 0, + 0, + player->level->difficulty, + param->itemId, + param->methodId, + 0, 0, 0, // (x,y,z) + param->itemAux, + param->itemCount + ); + } + } +} + +/* 4J-JEV: note that mined events will only fire with 'Instant_Mine' on if you are carrying an appropriate + * tool for the block that you are mining. + */ +byteArray DsItemEvent::createParamBlob(eAcquisitionMethod eMethod, int itemId, int itemAux, int itemCount) +{ + byteArray output; + Param param = { eMethod, itemId, itemAux, itemCount }; + output.data = (byte *) new Param(param); + output.length = sizeof(Param); + return output; +} + + + /////////////////// + // Ds Mob Killed // + /////////////////// + +DsMobKilled::DsMobKilled(int id, const wstring &name) : Stat(id,name) {} + +void DsMobKilled::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param *) paramBlob.data; + + if (param->mobType < 0) return; + + if (EventWriteMobKilled(DurangoStats::getUserId(player), + 0, + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId(), + 0, + player->level->difficulty, + DurangoStats::getPlayerSession(), // ROUND ID + 0, + param->weaponId, + param->mobType, + param->isRanged?1:0, + 0, 0, 0, // (x,y,z), + 0, + param->distance, + param->mobType) + == 0) + { + app.DebugPrintf("<%ls>\t%s(%i:%i:%i:%i)\n", DurangoStats::getUserId(player), + (param->isRanged?"mobShotWithEntity":"mobKilledInMelee"), + param->mobType, param->weaponId, param->distance, param->damage); + } + + switch(EntityIO::getClass(param->mobType)) + { + case eTYPE_MONSTER: + if(param->mobType != SPIDER_JOCKEY_ID) break; + // Fallthrough is spider jockey + case eTYPE_ZOMBIE: + case eTYPE_SKELETON: + case eTYPE_CREEPER: + case eTYPE_SPIDER: + case eTYPE_PIGZOMBIE: + case eTYPE_SLIME: + + if (EventWriteLeaderboardTotals( + DurangoStats::getUserId(player), //UserId + DurangoStats::getPlayerSession(), // PlayerSessionId + player->level->difficulty, // Difficulty, + eLeaderboardId_KILLING, // ScoreboardId + 1) // Count + == 0) + { + app.DebugPrintf("<%ls>\tscoreboardKills(%i:%i:1)\n", DurangoStats::getUserId(player), + player->level->difficulty, eLeaderboardId_KILLING); + } + } + } +} + +byteArray DsMobKilled::createParamBlob(shared_ptr<Player> player, shared_ptr<Mob> mob, DamageSource *dmgSrc) +{ + // 4J-JEV: Get the id we use for Durango Server Stats. + int mob_networking_id; + eINSTANCEOF mobEType = mob->GetType(); + if ( (mobEType == eTYPE_SPIDER) && (mob->rider.lock() != NULL) && (mob->rider.lock()->GetType() == eTYPE_SKELETON) ) + { + mob_networking_id = SPIDER_JOCKEY_ID; // Spider jockey only a concept for leaderboards. + } + else if ( (mobEType == eTYPE_SKELETON) && (mob->riding != NULL) && (mob->riding->GetType() == eTYPE_SPIDER) ) + { + mob_networking_id = SPIDER_JOCKEY_ID; // Spider jockey only a concept for leaderboards. + } + else + { + mob_networking_id = EntityIO::eTypeToIoid(mobEType); + } + + // Kill made with projectile, arrow/ghast/fireball/snowball. + // NB: Snowball kills would make an awesome achievement. ("Not a snowball's chance...") + if ( dmgSrc->isProjectile() ) + { + byteArray output; + Param param = { + DsMobKilled::RANGED, + mob_networking_id, + EntityIO::eTypeToIoid(dmgSrc->getDirectEntity()->GetType()), + mob->distanceTo(player->x, player->y, player->z), + 0/*not needed*/ + }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; + } + + // Kill made in melee, use itemInHand as weapon. + shared_ptr<ItemInstance> item = player->getCarriedItem(); + byteArray output; + Param param = { + DsMobKilled::MELEE, + mob_networking_id, + (item != NULL ? item->getItem()->id : 0), + mob->distanceTo(player->x, player->y, player->z), + 0/*not needed*/ + }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; +} + + + ///////////////////// + // Ds Mob Interact // + ///////////////////// + +string DsMobInteract::nameInteract[] = { + "unknownMobInteraction", "mobBred", "mobTamed", "mobCured", "mobCrafted", "mobSheared" +}; + +DsMobInteract::DsMobInteract(int id, const wstring &name) : Stat(id,name) {} + +void DsMobInteract::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param *) paramBlob.data; + + if (param->mobId < 0) return; + + app.DebugPrintf("<%ls>\t%s(%i)\n", DurangoStats::getUserId(player), + nameInteract[param->interactionType].c_str(), param->mobId); + + EventWriteMobInteract( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + param->mobId, + param->interactionType ); + } +} + +byteArray DsMobInteract::createParamBlob(eInteract interactionId, int entityId) +{ + byteArray output; + Param param = { interactionId, EntityIO::eTypeToIoid((eINSTANCEOF)entityId) }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; +} + + + /////////////// + // Ds Travel // + /////////////// + +string DsTravel::nameMethods[eMethod_MAX] = + { + "Walk", "Swim", "Fall", "Climb", "Cart", "Boat", "Pig", "Time" + }; + +unsigned int DsTravel::CACHE_SIZES[eMethod_MAX] = + { + 40, // WALK - Meters? + 20, // SWIM - Meters? + 0, // FALL - Meters? - Fall event naturally only sends on land, no caching necessary. + 10, // CLIMB - Meters? + 70, // CART - Meters? + 70, // BOAT - Meters? + 10, // PIG - Meters? + 20*60*5, // TIME - GameTicks (20*60*5 ~ 5 mins) + }; + +DsTravel::DsTravel(int id, const wstring &name) : Stat(id,name) +{ + ZeroMemory(¶m_cache, sizeof(unsigned int)*eMethod_MAX*MAX_LOCAL_PLAYERS); +} + +void DsTravel::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param*) paramBlob.data; + + int newDistance = cache(player->GetXboxPad(), *param); + + if ( newDistance > 0 ) write(player, param->method, newDistance); + } +} + +byteArray DsTravel::createParamBlob(eMethod method, int distance) +{ + byteArray output; + Param param = { method, distance }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; +} + +int DsTravel::cache(int iPad, Param ¶m) +{ + if ( (eMethod_walk <= param.method) && (param.method < eMethod_MAX) ) + { + param_cache[iPad][param.method] += param.distance; + + if (param_cache[iPad][param.method] > CACHE_SIZES[param.method]) + { + int out = param_cache[iPad][param.method]; + param_cache[iPad][param.method] = 0; + return out; + } + } + + return 0; +} + +void DsTravel::flush(shared_ptr<LocalPlayer> player) +{ + int iPad = player->GetXboxPad(); + for (int i = 0; i < eMethod_MAX; i++) + { + if (param_cache[iPad][i] > 0) + { + write( player, (eMethod) i, param_cache[iPad][i] ); + param_cache[iPad][i] = 0; + } + } +} + +void DsTravel::write(shared_ptr<LocalPlayer> player, eMethod method, int distance) +{ + if (player == nullptr) return; + + app.DebugPrintf("<%ls>\t%s(%i)\n", DurangoStats::getUserId(player), nameMethods[method].c_str(), distance); + + if (method == DsTravel::eMethod_time) + { + EventWriteIncTimePlayed( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + player->level->difficulty, + distance + ); + } + else if ( (eMethod_walk <= method) && (method < eMethod_MAX) ) + { + EventWriteIncDistanceTravelled( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + player->level->difficulty, + distance, + method + ); + + switch(method) + { + case eMethod_walk: + case eMethod_fall: + case eMethod_minecart: + case eMethod_boat: + EventWriteLeaderboardTotals( + DurangoStats::getUserId(player), //UserId + DurangoStats::getPlayerSession(), // PlayerSessionId + player->level->difficulty, // Difficulty, + eLeaderboardId_TRAVELLING, // ScoreboardId + distance); + break; + } + } +} + + ////////////////// + // Ds Item Used // + ////////////////// + +DsItemUsed::DsItemUsed(int id, const wstring &name) : Stat(id,name) {} + +void DsItemUsed::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param*) paramBlob.data; + app.DebugPrintf("<%ls>\titemUsed(%i,%i,%i)\n", DurangoStats::getUserId(player), + param->itemId, + param->aux, + param->count + ); + + EventWriteMcItemUsed( + DurangoStats::getUserId(player), + 0, // SectionId, + DurangoStats::getPlayerSession(), + 0, // MultiplayerCorrelationId, + 0, // Gameplay Mode, + player->level->difficulty, + param->itemId, + 0, 0, 0, // (x,y,z) + param->aux, + param->count, + param->hunger + ); + } +} + +byteArray DsItemUsed::createParamBlob(int itemId, int aux, int count, int health, int hunger) +{ + byteArray output; + Param param = { itemId, aux, count, health, hunger }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; +} + + + //////////////////// + // Ds Achievement // + //////////////////// + +DsAchievement::DsAchievement(int id, const wstring &name) : Stat(id,name) {} + +void DsAchievement::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(SmallParam)) + { + SmallParam *paramS = (SmallParam*) paramBlob.data; + assert( DurangoStats::binaryAchievement(paramS->award) ); + app.DebugPrintf("<%ls>\tAchievement(%i)\n", DurangoStats::getUserId(player), paramS->award); + + bool canAward = true; + if(paramS->award == eAward_stayinFrosty) + { + canAward = !player->m_bHasAwardedStayinFrosty; + player->m_bHasAwardedStayinFrosty = true; + } + + if(canAward) + { + EventWriteAchievementGet( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + paramS->award + ); + } + } + else if (paramBlob.length == sizeof(LargeParam)) + { + LargeParam *paramL = (LargeParam*) paramBlob.data; + assert( DurangoStats::enhancedAchievement(paramL->award) ); + + switch(paramL->award) + { + case eAward_musicToMyEars: + app.DebugPrintf("<%ls>\tmusicToMyEars(%i)\n", DurangoStats::getUserId(player), paramL->count); + EventWritePlayedMusicDisc( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + paramL->count + ); + break; + + case eAward_chestfulOfCobblestone: + app.DebugPrintf("<%ls>\tchestfulOfCobblestone(%i)\n", DurangoStats::getUserId(player), paramL->count); + EventWriteChestfulOfCobblestone( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + paramL->count + ); + break; + + case eAward_overkill: + app.DebugPrintf("<%ls>\toverkill(%i)\n", DurangoStats::getUserId(player), paramL->count); + EventWriteOverkill( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + paramL->count + ); + break; + + case eAward_OnARail: + app.DebugPrintf("<%ls>\nonARail(%i)\n", DurangoStats::getUserId(player), paramL->count); + EventWriteOnARail( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + paramL->count + ); + break; + } + } + else assert(false); // Unsuitable paramBlob length. +} + +byteArray DsAchievement::createSmallParamBlob(eAward award) +{ + byteArray output; + SmallParam param = { award }; + output.data = (byte*) new SmallParam(param); + output.length = sizeof(SmallParam); + return output; +} + +byteArray DsAchievement::createLargeParamBlob(eAward award, int count) +{ + byteArray output; + LargeParam param = { award, count }; + output.data = (byte*) new LargeParam(param); + output.length = sizeof(LargeParam); + return output; +} + + + ////////////////////////// + // Ds Changed Dimension // + ////////////////////////// + +DsChangedDimension::DsChangedDimension(int id, const wstring &name) : Stat(id,name) {} + +void DsChangedDimension::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param*) paramBlob.data; + app.DebugPrintf("<%ls>\tchangedDimension(%i:%i)\n", DurangoStats::getUserId(player), + param->fromDimId, param->toDimId); + + // No longer used. + } +} + +byteArray DsChangedDimension::createParamBlob(int fromDimId, int toDimId) +{ + byteArray output; + Param param = { fromDimId, toDimId }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; +} + + + ////////////////////// + // Ds Entered Biome // + ////////////////////// + +DsEnteredBiome::DsEnteredBiome(int id, const wstring &name) : Stat(id,name) {} + +void DsEnteredBiome::handleParamBlob(shared_ptr<LocalPlayer> player, byteArray paramBlob) +{ + if (paramBlob.length == sizeof(Param)) + { + Param *param = (Param*) paramBlob.data; + app.DebugPrintf("<%ls>\tenteredBiome(%i)\n", DurangoStats::getUserId(player), param->biomeId); + + EventWriteEnteredNewBiome( + DurangoStats::getUserId(player), + DurangoStats::getPlayerSession(), + param->biomeId + ); + } +} + +byteArray DsEnteredBiome::createParamBlob(int biomeId) +{ + byteArray output; + Param param = { biomeId }; + output.data = (byte*) new Param(param); + output.length = sizeof(Param); + return output; +} + + //////////////////////// + // DURANGO STATISTICS // + //////////////////////// + +DurangoStats::DurangoStats() +{ + // Hopefully only using the first parameter + itemsAcquired = new DsItemEvent( itemsAcquired_Id, L"itemsAcquired" ); + itemsAcquired->postConstruct(); + + itemUsed = new DsItemUsed( itemUsed_Id, L"itemUsed" ); + itemUsed->postConstruct(); + + travel = new DsTravel( travel_Id, L"travel" ); + travel->setAwardLocallyOnly()->postConstruct(); + + mobKilled = new DsMobKilled( mobKilled_Id, L"mobKilled" ); + mobKilled->postConstruct(); + + mobInteract = new DsMobInteract( mobInteract_Id, L"mobInteract" ); + mobInteract->postConstruct(); + + changedDimension = new DsChangedDimension( changedDimension_Id, L"changedDimension" ); + changedDimension->postConstruct(); + + enteredBiome = new DsEnteredBiome( enteredBiome_Id, L"enteredBiome" ); + enteredBiome->postConstruct(); + + achievement = new DsAchievement( binAchievement_Id, L"achievement" ); + achievement->postConstruct(); + + achievementLocal = new DsAchievement( binAchievementLocal_Id, L"achievementLocal" ); + achievementLocal->setAwardLocallyOnly(); + achievementLocal->postConstruct(); + + EventRegisterXBLA_149E11AE(); +} + +DurangoStats::~DurangoStats() +{ + EventUnregisterXBLA_149E11AE(); +} + +Stat *DurangoStats::get_stat(int i) +{ + switch (i) + { + case itemsAcquired_Id: return (Stat*) itemsAcquired; + case itemUsed_Id: return (Stat*) itemUsed; + case travel_Id: return (Stat*) travel; + case mobKilled_Id: return (Stat*) mobKilled; + case mobInteract_Id: return (Stat*) mobInteract; + case changedDimension_Id: return (Stat*) changedDimension; + case enteredBiome_Id: return (Stat*) enteredBiome; + case binAchievement_Id: return (Stat*) achievement; + case binAchievementLocal_Id: return (Stat*) achievementLocal; + + // Unrecognised stat id + default: assert(false); break; + } + + return NULL; +} + +Stat* DurangoStats::get_walkOneM() +{ + return travel; +} + +Stat* DurangoStats::get_swimOneM() +{ + return travel; +} + +Stat* DurangoStats::get_fallOneM() +{ + return travel; +} + +Stat* DurangoStats::get_climbOneM() +{ + return travel; +} + +Stat* DurangoStats::get_minecartOneM() +{ + return travel; +} + +Stat* DurangoStats::get_boatOneM() +{ + return travel; +} + +Stat* DurangoStats::get_pigOneM() +{ + return travel; +} + +Stat *DurangoStats::get_cowsMilked() +{ + return get_itemsCrafted(Item::milk_Id); +} + +Stat* DurangoStats::get_killMob() +{ + return mobKilled; +} + +Stat* DurangoStats::get_breedEntity(eINSTANCEOF entityId) +{ + return mobInteract; +} + +Stat* DurangoStats::get_tamedEntity(eINSTANCEOF entityId) +{ + return mobInteract; +} + +Stat* DurangoStats::get_curedEntity(eINSTANCEOF entityId) +{ + return mobInteract; +} + +Stat* DurangoStats::get_craftedEntity(eINSTANCEOF entityId) +{ + return mobInteract; +} + +Stat* DurangoStats::get_shearedEntity(eINSTANCEOF entityId) +{ + return mobInteract; +} + +Stat* DurangoStats::get_timePlayed() +{ + return travel; +} + +Stat* DurangoStats::get_blocksPlaced(int blockId) +{ + return (Stat*) itemsAcquired; +} + +Stat* DurangoStats::get_blocksMined(int blockId) +{ + return (Stat*) itemsAcquired; +} + +Stat* DurangoStats::get_itemsCollected(int itemId, int itemAux) +{ + return (Stat*) itemsAcquired; +} + +Stat* DurangoStats::get_itemsCrafted(int itemId) +{ + switch (itemId) + { + // 4J-JEV: These items can be crafted trivially to and from their block equivalents, + // 'Acquire Hardware' also relies on 'Count_Crafted(IronIngot) == Count_Forged(IronIngot)" on the Stats server. + case Item::ironIngot_Id: + case Item::goldIngot_Id: + case Item::diamond_Id: + case Item::redStone_Id: + case Item::emerald_Id: + return NULL; + + case Item::dye_powder_Id: + default: + return (Stat*) itemsAcquired; + } + +} + +Stat* DurangoStats::get_itemsSmelted(int itemId) +{ + // 4J-JEV: Context needed for itemCrafted for iron/gold being smelted. + return (Stat*) itemsAcquired; +} + +Stat* DurangoStats::get_itemsUsed(int itemId) +{ + return (Stat*) itemUsed; +} + +Stat *DurangoStats::get_itemsBought(int itemId) +{ + return (Stat*) itemsAcquired; +} + +Stat* DurangoStats::get_changedDimension(int from, int to) +{ + return (Stat*) changedDimension; +} + +Stat* DurangoStats::get_enteredBiome(int biomeId) +{ + return (Stat*) enteredBiome; +} + +Stat* DurangoStats::get_achievement(eAward achievementId) +{ + // Special case for 'binary' achievements. + if ( binaryAchievement(achievementId) + || enhancedAchievement(achievementId) ) + { + switch (achievementId) + { + case eAward_chestfulOfCobblestone: + case eAward_TakingInventory: + return achievementLocal; + + default: + return achievement; + } + } + else if (achievementId == eAward_zombieDoctor) + { + return get_curedEntity(eTYPE_ZOMBIE); + } + + // Other achievements awarded through more detailed generic events. + return NULL; +} + +byteArray DurangoStats::getParam_walkOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_walk, distance); +} + +byteArray DurangoStats::getParam_swimOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_swim,distance); +} + +byteArray DurangoStats::getParam_fallOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_fall,distance); +} + +byteArray DurangoStats::getParam_climbOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_climb,distance); +} + +byteArray DurangoStats::getParam_minecartOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_minecart,distance); +} + +byteArray DurangoStats::getParam_boatOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_boat,distance); +} + +byteArray DurangoStats::getParam_pigOneM(int distance) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_pig,distance); +} + +byteArray DurangoStats::getParam_cowsMilked() +{ + return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Crafted, Item::milk_Id, 0, 1); +} + +byteArray DurangoStats::getParam_blocksPlaced(int blockId, int data, int count) +{ + return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Placed, blockId, data, count); +} + +byteArray DurangoStats::getParam_blocksMined(int blockId, int data, int count) +{ + return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Mined, blockId, data, count); +} + +byteArray DurangoStats::getParam_itemsCollected(int id, int aux, int count) +{ + return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Pickedup, id, aux, count); +} + +byteArray DurangoStats::getParam_itemsCrafted(int id, int aux, int count) +{ + return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Crafted, id, aux, count); +} + +byteArray DurangoStats::getParam_itemsUsed(shared_ptr<Player> player, shared_ptr<ItemInstance> itm) +{ + return DsItemUsed::createParamBlob( + itm->getItem()->id, itm->getAuxValue(), itm->GetCount(), + player->getHealth(), player->getFoodData()->getFoodLevel() + ); +} + +byteArray DurangoStats::getParam_itemsBought(int id, int aux, int count) +{ + return DsItemEvent::createParamBlob(DsItemEvent::eAcquisitionMethod_Bought, id, aux, count); +} + +byteArray DurangoStats::getParam_mobKill(shared_ptr<Player> player, shared_ptr<Mob> mob, DamageSource *dmgSrc) +{ + return DsMobKilled::createParamBlob(player,mob,dmgSrc); +} + +byteArray DurangoStats::getParam_breedEntity(eINSTANCEOF entityId) +{ + return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Breed, entityId); +} + +byteArray DurangoStats::getParam_tamedEntity(eINSTANCEOF entityId) +{ + return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Tamed, entityId); +} + +byteArray DurangoStats::getParam_curedEntity(eINSTANCEOF entityId) +{ + return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Cured, entityId); +} + +byteArray DurangoStats::getParam_craftedEntity(eINSTANCEOF entityId) +{ + return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Crafted, entityId); +} + +byteArray DurangoStats::getParam_shearedEntity(eINSTANCEOF entityId) +{ + return DsMobInteract::createParamBlob(DsMobInteract::eInteract_Sheared, entityId); +} + +byteArray DurangoStats::getParam_time(int timediff) +{ + return DsTravel::createParamBlob(DsTravel::eMethod_time, timediff); +} + +byteArray DurangoStats::getParam_changedDimension(int from, int to) +{ + return DsChangedDimension::createParamBlob(from,to); +} + +byteArray DurangoStats::getParam_enteredBiome(int biomeId) +{ + return DsEnteredBiome::createParamBlob(biomeId); +} + +byteArray DurangoStats::getParam_achievement(eAward id) +{ + if (binaryAchievement(id)) + { + return DsAchievement::createSmallParamBlob(id); + } + else if (enhancedAchievement(id)) + { + assert(false); // Should be calling the appropriate getParam function. + } + else if (id == eAward_zombieDoctor) + { + return getParam_curedEntity(eTYPE_ZOMBIE); + } + + // If its not a binary achievement, + // don't bother constructing the param blob. + return getParam_noArgs(); +} + +byteArray DurangoStats::getParam_onARail(int dist) +{ + return DsAchievement::createLargeParamBlob(eAward_OnARail, dist); +} + +byteArray DurangoStats::getParam_chestfulOfCobblestone(int count) +{ + return DsAchievement::createLargeParamBlob(eAward_chestfulOfCobblestone, count); +} + +byteArray DurangoStats::getParam_overkill(int dmg) +{ + return DsAchievement::createLargeParamBlob(eAward_overkill, dmg); +} + +byteArray DurangoStats::getParam_musicToMyEars(int recordId) +{ + return DsAchievement::createLargeParamBlob(eAward_musicToMyEars, recordId); +} + +bool DurangoStats::binaryAchievement(eAward achievementId) +{ + switch (achievementId) + { + case eAward_InToTheNether: + case eAward_theEnd: + case eAward_WhenPigsFly: + case eAward_diamondsToYou: + case eAward_stayinFrosty: + case eAward_renewableEnergy: + case eAward_ironMan: + case eAward_winGame: + case /*maybe*/ eAward_TakingInventory: + return true; + default: + return false; + } +} + +/** 4J-JEV, + Basically achievements with an inconsequential extra parameter + that I thought best not to / prefered not to / couldn't be bothered to make class handlers for. + (Motivation: it would be nice for players to see how close they were/are to achieving these things). +*/ +bool DurangoStats::enhancedAchievement(eAward achievementId) +{ + switch (achievementId) + { + //case eAward_TakingInventory: + case eAward_musicToMyEars: + case eAward_chestfulOfCobblestone: + case eAward_overkill: + case eAward_OnARail: + return true; + default: + return false; + } +} + + +void DurangoStats::generatePlayerSession() +{ + DurangoStats *dsInstance = (DurangoStats *) GenericStats::getInstance(); + CoCreateGuid( &dsInstance->playerSessionId ); +} + +LPCGUID DurangoStats::getPlayerSession() +{ + DurangoStats *dsInstance = (DurangoStats *) GenericStats::getInstance(); + LPCGUID lpcguid = &dsInstance->playerSessionId; + return lpcguid; +} + +void DurangoStats::setMultiplayerCorrelationId(Platform::String^ mcpId) +{ + ((DurangoStats*)GenericStats::getInstance())->multiplayerCorrelationId = mcpId; +} + +LPCWSTR DurangoStats::getMultiplayerCorrelationId() +{ + return ((DurangoStats*)GenericStats::getInstance())->multiplayerCorrelationId->Data(); +} + +LPCWSTR DurangoStats::getUserId(shared_ptr<LocalPlayer> player) +{ + return getUserId(player->GetXboxPad()); +} + +LPCWSTR DurangoStats::getUserId(int iPad) +{ + static wstring cache = L""; + PlayerUID uid = INVALID_XUID; + ProfileManager.GetXUID(iPad, &uid, true); + cache = uid.toString(); + return cache.c_str(); +} + +void DurangoStats::playerSessionStart(PlayerUID uid, shared_ptr<Player> plr) +{ + if (plr != NULL && plr->level != NULL && plr->level->getLevelData() != NULL) + { + //wprintf(uid.toString().c_str()); + + //EventWritePlayerSessionStart( + app.DebugPrintf(">>>\tPlayerSessionStart(%ls,%s,%ls,%i,%i)\n", + uid.toString(), + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId(), + plr->level->getLevelData()->getGameType()->isSurvival(), + plr->level->difficulty + ); + + EventWritePlayerSessionStart( + uid.toString().c_str(), + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId(), + plr->level->getLevelData()->getGameType()->isSurvival(), + plr->level->difficulty + ); + } +} + +void DurangoStats::playerSessionStart(int iPad) +{ + PlayerUID puid; shared_ptr<Player> plr; + ProfileManager.GetXUID(iPad, &puid, true); + plr = Minecraft::GetInstance()->localplayers[iPad]; + playerSessionStart(puid,plr); +} + +void DurangoStats::playerSessionPause(int iPad) +{ + shared_ptr<MultiplayerLocalPlayer> plr = Minecraft::GetInstance()->localplayers[iPad]; + if (plr != NULL && plr->level != NULL && plr->level->getLevelData() != NULL) + { + PlayerUID puid; + ProfileManager.GetXUID(iPad, &puid, true); + + //EventWritePlayerSessionPause( + app.DebugPrintf(">>>\tPlayerSessionPause(%ls,%s,%ls)\n", + puid.toString().c_str(), + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId() + ); + + EventWritePlayerSessionPause( + puid.toString().c_str(), + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId() + ); + } +} + +void DurangoStats::playerSessionResume(int iPad) +{ + shared_ptr<MultiplayerLocalPlayer> plr = Minecraft::GetInstance()->localplayers[iPad]; + if (plr != NULL && plr->level != NULL && plr->level->getLevelData() != NULL) + { + PlayerUID puid; + ProfileManager.GetXUID(iPad, &puid, true); + + //EventWritePlayerSessionResume( + app.DebugPrintf(">>>\tPlayerSessionResume(%ls,%s,%ls,%i,%i)\n", + puid.toString().c_str(), + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId(), + plr->level->getLevelData()->getGameType()->isSurvival(), + plr->level->difficulty + ); + + EventWritePlayerSessionResume( + puid.toString().c_str(), + DurangoStats::getPlayerSession(), + DurangoStats::getMultiplayerCorrelationId(), + plr->level->getLevelData()->getGameType()->isSurvival(), + plr->level->difficulty + ); + } +} + +void DurangoStats::playerSessionEnd(int iPad) +{ + shared_ptr<MultiplayerLocalPlayer> plr = Minecraft::GetInstance()->localplayers[iPad]; + if (plr != NULL) + { + DurangoStats::getInstance()->travel->flush(plr); + } +}
\ No newline at end of file |
