diff options
-rw-r--r-- | src/WorldStorage/StatSerializer.cpp | 129 | ||||
-rw-r--r-- | src/WorldStorage/StatSerializer.h | 6 |
2 files changed, 122 insertions, 13 deletions
diff --git a/src/WorldStorage/StatSerializer.cpp b/src/WorldStorage/StatSerializer.cpp index de8a1d277..50767ae94 100644 --- a/src/WorldStorage/StatSerializer.cpp +++ b/src/WorldStorage/StatSerializer.cpp @@ -7,26 +7,114 @@ #include "../Statistics.h" #include "NamespaceSerializer.h" -#include <fstream> #include <json/json.h> -cStatSerializer::cStatSerializer(cStatManager & a_Manager, const AString & a_WorldName, const AString & a_FileName) - : m_Manager(a_Manager) +// Upgrade mapping from pre-1.13 names. TODO: remove on 2020-09-18 +static const std::unordered_map<std::string_view, Statistic> LegacyMapping +{ + { "achievement.openInventory", Statistic::AchOpenInventory }, + { "achievement.mineWood", Statistic::AchMineWood }, + { "achievement.buildWorkBench", Statistic::AchBuildWorkBench }, + { "achievement.buildPickaxe", Statistic::AchBuildPickaxe }, + { "achievement.buildFurnace", Statistic::AchBuildFurnace }, + { "achievement.acquireIron", Statistic::AchAcquireIron }, + { "achievement.buildHoe", Statistic::AchBuildHoe }, + { "achievement.makeBread", Statistic::AchMakeBread }, + { "achievement.bakeCake", Statistic::AchBakeCake }, + { "achievement.buildBetterPickaxe", Statistic::AchBuildBetterPickaxe }, + { "achievement.cookFish", Statistic::AchCookFish }, + { "achievement.onARail", Statistic::AchOnARail }, + { "achievement.buildSword", Statistic::AchBuildSword }, + { "achievement.killEnemy", Statistic::AchKillEnemy }, + { "achievement.killCow", Statistic::AchKillCow }, + { "achievement.flyPig", Statistic::AchFlyPig }, + { "achievement.snipeSkeleton", Statistic::AchSnipeSkeleton }, + { "achievement.diamonds", Statistic::AchDiamonds }, + { "achievement.portal", Statistic::AchPortal }, + { "achievement.ghast", Statistic::AchGhast }, + { "achievement.blazeRod", Statistic::AchBlazeRod }, + { "achievement.potion", Statistic::AchPotion }, + { "achievement.theEnd", Statistic::AchTheEnd }, + { "achievement.theEnd2", Statistic::AchTheEnd2 }, + { "achievement.enchantments", Statistic::AchEnchantments }, + { "achievement.overkill", Statistic::AchOverkill }, + { "achievement.bookcase", Statistic::AchBookcase }, + { "achievement.exploreAllBiomes", Statistic::AchExploreAllBiomes }, + { "achievement.spawnWither", Statistic::AchSpawnWither }, + { "achievement.killWither", Statistic::AchKillWither }, + { "achievement.fullBeacon", Statistic::AchFullBeacon }, + { "achievement.breedCow", Statistic::AchBreedCow }, + { "achievement.diamondsToYou", Statistic::AchDiamondsToYou }, + { "stat.animalsBred", Statistic::AnimalsBred }, + { "stat.boatOneCm", Statistic::BoatOneCm }, + { "stat.climbOneCm", Statistic::ClimbOneCm }, + { "stat.crouchOneCm", Statistic::CrouchOneCm }, + { "stat.damageDealt", Statistic::DamageDealt }, + { "stat.damageTaken", Statistic::DamageTaken }, + { "stat.deaths", Statistic::Deaths }, + { "stat.drop", Statistic::Drop }, + { "stat.fallOneCm", Statistic::FallOneCm }, + { "stat.fishCaught", Statistic::FishCaught }, + { "stat.flyOneCm", Statistic::FlyOneCm }, + { "stat.horseOneCm", Statistic::HorseOneCm }, + { "stat.jump", Statistic::Jump }, + { "stat.leaveGame", Statistic::LeaveGame }, + { "stat.minecartOneCm", Statistic::MinecartOneCm }, + { "stat.mobKills", Statistic::MobKills }, + { "stat.pigOneCm", Statistic::PigOneCm }, + { "stat.playerKills", Statistic::PlayerKills }, + { "stat.playOneMinute", Statistic::PlayOneMinute }, + { "stat.sprintOneCm", Statistic::SprintOneCm }, + { "stat.swimOneCm", Statistic::SwimOneCm }, + { "stat.talkedToVillager", Statistic::TalkedToVillager }, + { "stat.timeSinceDeath", Statistic::TimeSinceDeath }, + { "stat.tradedWithVillager", Statistic::TradedWithVillager }, + { "stat.walkOneCm", Statistic::WalkOneCm }, + { "stat.diveOneCm", Statistic::WalkUnderWaterOneCm }, + { "stat.armorCleaned", Statistic::CleanArmor }, + { "stat.bannerCleaned", Statistic::CleanBanner }, + { "stat.cakeSlicesEaten", Statistic::EatCakeSlice }, + { "stat.itemEnchanted", Statistic::EnchantItem }, + { "stat.cauldronFilled", Statistic::FillCauldron }, + { "stat.dispenserInspected", Statistic::InspectDispenser }, + { "stat.dropperInspected", Statistic::InspectDropper }, + { "stat.hopperInspected", Statistic::InspectHopper }, + { "stat.beaconInteraction", Statistic::InteractWithBeacon }, + { "stat.brewingstandInteraction", Statistic::InteractWithBrewingstand }, + { "stat.craftingTableInteraction", Statistic::InteractWithCraftingTable }, + { "stat.furnaceInteraction", Statistic::InteractWithFurnace }, + { "stat.chestOpened", Statistic::OpenChest }, + { "stat.enderchestOpened", Statistic::OpenEnderchest }, + { "stat.noteblockPlayed", Statistic::PlayNoteblock }, + { "stat.recordPlayed", Statistic::PlayRecord }, + { "stat.flowerPotted", Statistic::PotFlower }, + { "stat.trappedChestTriggered", Statistic::TriggerTrappedChest }, + { "stat.noteblockTuned", Statistic::TuneNoteblock }, + { "stat.cauldronUsed", Statistic::UseCauldron }, + { "stat.aviateOneCm", Statistic::AviateOneCm }, + { "stat.sleepInBed", Statistic::SleepInBed }, + { "stat.sneakTime", Statistic::SneakTime } +}; + + + + + +cStatSerializer::cStatSerializer(cStatManager & Manager, const std::string & WorldPath, std::string FileName) : + m_Manager(Manager), + m_Path(WorldPath + cFile::GetPathSeparator() + "stats") { // Even though stats are shared between worlds, they are (usually) saved // inside the folder of the default world. - AString StatsPath; - Printf(StatsPath, "%s%cstats", a_WorldName.c_str(), cFile::PathSeparator()); - - m_Path = StatsPath + cFile::PathSeparator() + a_FileName + ".json"; - // Ensure that the directory exists. - cFile::CreateFolder(StatsPath); + cFile::CreateFolder(m_Path); + + m_Path += cFile::GetPathSeparator() + std::move(FileName) + ".json"; } @@ -36,8 +124,9 @@ cStatSerializer::cStatSerializer(cStatManager & a_Manager, const AString & a_Wor void cStatSerializer::Load(void) { Json::Value Root; - std::ifstream(m_Path) >> Root; + InputFileStream(m_Path) >> Root; + LoadLegacyFromJSON(Root); LoadCustomStatFromJSON(Root["stats"]["custom"]); } @@ -52,7 +141,7 @@ void cStatSerializer::Save(void) SaveStatToJSON(Root["stats"]); Root["DataVersion"] = NamespaceSerializer::DataVersion(); - std::ofstream(m_Path) << Root; + OutputFileStream(m_Path) << Root; } @@ -81,6 +170,24 @@ void cStatSerializer::SaveStatToJSON(Json::Value & a_Out) +void cStatSerializer::LoadLegacyFromJSON(const Json::Value & In) +{ + for (auto Entry = In.begin(); Entry != In.end(); ++Entry) + { + const auto & Key = Entry.key().asString(); + const auto FindResult = LegacyMapping.find(Key); + + if ((FindResult != LegacyMapping.end()) && Entry->isInt()) + { + m_Manager.SetValue(FindResult->second, Entry->asInt()); + } + } +} + + + + + void cStatSerializer::LoadCustomStatFromJSON(const Json::Value & a_In) { for (auto it = a_In.begin() ; it != a_In.end() ; ++it) diff --git a/src/WorldStorage/StatSerializer.h b/src/WorldStorage/StatSerializer.h index e6a5bd325..efbdbe4e5 100644 --- a/src/WorldStorage/StatSerializer.h +++ b/src/WorldStorage/StatSerializer.h @@ -25,7 +25,7 @@ class cStatSerializer { public: - cStatSerializer(cStatManager & a_Manager, const AString & a_WorldName, const AString & a_FileName); + cStatSerializer(cStatManager & Manager, const std::string & WorldPath, std::string FileName); /* Try to load the player statistics. */ void Load(void); @@ -37,9 +37,11 @@ private: void SaveStatToJSON(Json::Value & a_Out); + void LoadLegacyFromJSON(const Json::Value & In); + void LoadCustomStatFromJSON(const Json::Value & a_In); cStatManager & m_Manager; - AString m_Path; + std::string m_Path; } ; |