1
0

Add player statistics to API (#5193)

* Fixed issue #5166

Co-authored-by: 12xx12 <44411062+12xx12@users.noreply.github.com>
Co-authored-by: Tiger Wang <ziwei.tiger@outlook.com>
This commit is contained in:
nshah25 2021-05-03 16:07:09 -04:00 committed by GitHub
parent 626f8b2350
commit 8be1dd54bb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
56 changed files with 1408 additions and 1002 deletions

View File

@ -79,6 +79,7 @@ function(enable_bindings_generation)
Mobs/MonsterTypes.h Mobs/MonsterTypes.h
OSSupport/File.h OSSupport/File.h
Protocol/MojangAPI.h Protocol/MojangAPI.h
Registries/Statistics.h
Root.h Root.h
Scoreboard.h Scoreboard.h
Server.h Server.h

View File

@ -10245,36 +10245,6 @@ a_Player:OpenWindow(Window);
}, },
Notes = "Returns the full color code to be used for this player's messages (based on their rank). Prefix player messages with this code.", Notes = "Returns the full color code to be used for this player's messages (based on their rank). Prefix player messages with this code.",
}, },
GetDraggingItem =
{
Returns =
{
{
Type = "cItem",
},
},
Notes = "Returns the item the player is dragging in a UI window."
},
GetPrefix =
{
Returns =
{
{
Type = "string",
},
},
Notes = "Returns the prefix to player names for messages (based on their rank), may contain @ format codes.",
},
GetSuffix =
{
Returns =
{
{
Type = "string",
},
},
Notes = "Returns the suffix to player names for messages (based on their rank), may contain @ format codes.",
},
GetCurrentXp = GetCurrentXp =
{ {
Returns = Returns =
@ -10295,6 +10265,16 @@ a_Player:OpenWindow(Window);
}, },
Notes = "Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string.", Notes = "Returns the custom name of this player. If the player hasn't a custom name, it will return an empty string.",
}, },
GetDraggingItem =
{
Returns =
{
{
Type = "cItem",
},
},
Notes = "Returns the item the player is dragging in a UI window."
},
GetEffectiveGameMode = GetEffectiveGameMode =
{ {
Returns = Returns =
@ -10489,6 +10469,16 @@ a_Player:OpenWindow(Window);
}, },
Notes = "Returns the name that is used in the playerlist.", Notes = "Returns the name that is used in the playerlist.",
}, },
GetPrefix =
{
Returns =
{
{
Type = "string",
},
},
Notes = "Returns the prefix to player names for messages (based on their rank), may contain @ format codes.",
},
GetRestrictions = GetRestrictions =
{ {
Returns = Returns =
@ -10519,6 +10509,26 @@ a_Player:OpenWindow(Window);
}, },
Notes = "Returns the player's current set of skin part flags. This is a bitwise OR of various {{Globals#eSkinPart|eSkinPart}} constants. Note that HasSkinPart may be easier to use in most situations.", Notes = "Returns the player's current set of skin part flags. This is a bitwise OR of various {{Globals#eSkinPart|eSkinPart}} constants. Note that HasSkinPart may be easier to use in most situations.",
}, },
GetStatistics =
{
Returns =
{
{
Type = "StatisticsManager",
},
},
Notes = "Returns the player's statistics manager."
},
GetSuffix =
{
Returns =
{
{
Type = "string",
},
},
Notes = "Returns the suffix to player names for messages (based on their rank), may contain @ format codes.",
},
GetTeam = GetTeam =
{ {
Returns = Returns =
@ -13219,7 +13229,41 @@ end
Include = { "wt.*" }, Include = { "wt.*" },
} }
}, -- ConstantGroups }, -- ConstantGroups
}, -- cWindow },
StatisticsManager =
{
Desc = [[
This class provides a store for various types of player statistics. The store will be read and sent to the client when the Statistics button is pressed.
]],
Variables =
{
Custom =
{
Type = "Map of {{CustomStatistic}} to number",
Notes = "Gets or sets the value of a custom statistic.",
},
},
AdditionalInfo =
{
{
Header = "Example usage",
Contents = [[
Each store is a table, keyed by the statistic that the entry tracks, with value typically representing the number of times the event happened:
<pre class="prettyprint lang-lua">
function ModifyPlayerFurnaceInteractions(Player)
local Statistics = Player:GetStatistics()
if (Statistics.Custom[CustomStatistic.WalkOneCm] > 10) then
Statistics.Custom[CustomStatistic.InteractWithFurnace] = 1337
end
-- Next time the player presses Statistics they will see the updated value for furnace interactions.
end
</pre>
]],
},
},
},
BannerPattern = BannerPattern =
{ {
@ -13700,6 +13744,319 @@ end
}, },
} }
}, },
CustomStatistic =
{
Desc = [[
An enumeration of statistics of the custom type to be used with the {{StatisticsManager#Custom|Custom}} statistics store.
]],
Constants =
{
AnimalsBred =
{
Notes = "",
},
AviateOneCm =
{
Notes = "",
},
BellRing =
{
Notes = "",
},
BoatOneCm =
{
Notes = "",
},
CleanArmor =
{
Notes = "",
},
CleanBanner =
{
Notes = "",
},
CleanShulkerBox =
{
Notes = "",
},
ClimbOneCm =
{
Notes = "",
},
CrouchOneCm =
{
Notes = "",
},
DamageAbsorbed =
{
Notes = "",
},
DamageBlockedByShield =
{
Notes = "",
},
DamageDealt =
{
Notes = "",
},
DamageDealtAbsorbed =
{
Notes = "",
},
DamageDealtResisted =
{
Notes = "",
},
DamageResisted =
{
Notes = "",
},
DamageTaken =
{
Notes = "",
},
Deaths =
{
Notes = "",
},
Drop =
{
Notes = "",
},
EatCakeSlice =
{
Notes = "",
},
EnchantItem =
{
Notes = "",
},
FallOneCm =
{
Notes = "",
},
FillCauldron =
{
Notes = "",
},
FishCaught =
{
Notes = "",
},
FlyOneCm =
{
Notes = "",
},
HorseOneCm =
{
Notes = "",
},
InspectDispenser =
{
Notes = "",
},
InspectDropper =
{
Notes = "",
},
InspectHopper =
{
Notes = "",
},
InteractWithAnvil =
{
Notes = "",
},
InteractWithBeacon =
{
Notes = "",
},
InteractWithBlastFurnace =
{
Notes = "",
},
InteractWithBrewingstand =
{
Notes = "",
},
InteractWithCampfire =
{
Notes = "",
},
InteractWithCartographyTable =
{
Notes = "",
},
InteractWithCraftingTable =
{
Notes = "",
},
InteractWithFurnace =
{
Notes = "",
},
InteractWithGrindstone =
{
Notes = "",
},
InteractWithLectern =
{
Notes = "",
},
InteractWithLoom =
{
Notes = "",
},
InteractWithSmithingTable =
{
Notes = "",
},
InteractWithSmoker =
{
Notes = "",
},
InteractWithStonecutter =
{
Notes = "",
},
JunkFished =
{
Notes = "",
},
Jump =
{
Notes = "",
},
LeaveGame =
{
Notes = "",
},
MinecartOneCm =
{
Notes = "",
},
MobKills =
{
Notes = "",
},
OpenBarrel =
{
Notes = "",
},
OpenChest =
{
Notes = "",
},
OpenEnderchest =
{
Notes = "",
},
OpenShulkerBox =
{
Notes = "",
},
PigOneCm =
{
Notes = "",
},
PlayNoteblock =
{
Notes = "",
},
PlayOneMinute =
{
Notes = "",
},
PlayRecord =
{
Notes = "",
},
PlayerKills =
{
Notes = "",
},
PotFlower =
{
Notes = "",
},
RaidTrigger =
{
Notes = "",
},
RaidWin =
{
Notes = "",
},
SleepInBed =
{
Notes = "",
},
SneakTime =
{
Notes = "",
},
SprintOneCm =
{
Notes = "",
},
StriderOneCm =
{
Notes = "",
},
SwimOneCm =
{
Notes = "",
},
TalkedToVillager =
{
Notes = "",
},
TargetHit =
{
Notes = "",
},
TimeSinceDeath =
{
Notes = "",
},
TimeSinceRest =
{
Notes = "",
},
TradedWithVillager =
{
Notes = "",
},
TreasureFished =
{
Notes = "",
},
TriggerTrappedChest =
{
Notes = "",
},
TuneNoteblock =
{
Notes = "",
},
UseCauldron =
{
Notes = "",
},
WalkOnWaterOneCm =
{
Notes = "",
},
WalkOneCm =
{
Notes = "",
},
WalkUnderWaterOneCm =
{
Notes = "",
},
},
},
Globals = Globals =
{ {
Desc = [[ Desc = [[

View File

@ -52,7 +52,6 @@ end
--- Returns the API currently detected from the global environment --- Returns the API currently detected from the global environment
local function CreateAPITables() local function CreateAPITables()
--[[ --[[
@ -121,14 +120,15 @@ local function CreateAPITables()
end end
-- Member variables: -- Member variables:
local GetField = a_ClassObj[".get"];
local SetField = a_ClassObj[".set"] or {}; local SetField = a_ClassObj[".set"] or {};
if ((a_ClassObj[".get"] ~= nil) and (type(a_ClassObj[".get"]) == "table")) then if ((GetField ~= nil) and (type(GetField) == "table")) then
for k in pairs(a_ClassObj[".get"]) do for k, v in pairs(GetField) do
if (SetField[k] == nil) then if ((SetField[k] == nil) and ((type(v) ~= "table") or (v["__newindex"] == nil))) then
-- It is a read-only variable, add it as a constant: -- It is a read-only variable or array, add it as a constant:
table.insert(res.Constants, {Name = k, Value = ""}); table.insert(res.Constants, {Name = k, Value = ""});
else else
-- It is a read-write variable, add it as a variable: -- It is a read-write variable or array, add it as a variable:
table.insert(res.Variables, { Name = k }); table.insert(res.Variables, { Name = k });
end end
end end

View File

@ -123,6 +123,8 @@ $cfile "../BlockEntities/MobHeadEntity.h"
$cfile "../BlockEntities/MobSpawnerEntity.h" $cfile "../BlockEntities/MobSpawnerEntity.h"
$cfile "../BlockEntities/FlowerPotEntity.h" $cfile "../BlockEntities/FlowerPotEntity.h"
// Registries:
$cfile "../Registries/Statistics.h"

View File

@ -1378,6 +1378,21 @@ bool cLuaState::GetStackValue(int a_StackPos, ContiguousByteBuffer & a_Data)
bool cLuaState::GetStackValue(int a_StackPos, CustomStatistic & a_Value)
{
if (lua_isnumber(m_LuaState, a_StackPos))
{
a_Value = static_cast<CustomStatistic>(static_cast<std::underlying_type_t<CustomStatistic>>(lua_tonumber(m_LuaState, a_StackPos)));
return true;
}
return true;
}
bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal) bool cLuaState::GetStackValue(int a_StackPos, double & a_ReturnedVal)
{ {
if (lua_isnumber(m_LuaState, a_StackPos)) if (lua_isnumber(m_LuaState, a_StackPos))

View File

@ -37,6 +37,7 @@ extern "C"
#include "../Defines.h" #include "../Defines.h"
#include "../FunctionRef.h" #include "../FunctionRef.h"
#include "../Registries/Statistics.h"
#include "PluginManager.h" #include "PluginManager.h"
#include "LuaState_Typedefs.inc" #include "LuaState_Typedefs.inc"
@ -657,6 +658,7 @@ public:
bool GetStackValue(int a_StackPos, cTrackedRefPtr & a_Ref); bool GetStackValue(int a_StackPos, cTrackedRefPtr & a_Ref);
bool GetStackValue(int a_StackPos, cTrackedRefSharedPtr & a_Ref); bool GetStackValue(int a_StackPos, cTrackedRefSharedPtr & a_Ref);
bool GetStackValue(int a_StackPos, ContiguousByteBuffer & a_Data); bool GetStackValue(int a_StackPos, ContiguousByteBuffer & a_Data);
bool GetStackValue(int a_StackPos, CustomStatistic & a_Value);
bool GetStackValue(int a_StackPos, double & a_Value); bool GetStackValue(int a_StackPos, double & a_Value);
bool GetStackValue(int a_StackPos, eBlockFace & a_Value); bool GetStackValue(int a_StackPos, eBlockFace & a_Value);
bool GetStackValue(int a_StackPos, eWeather & a_Value); bool GetStackValue(int a_StackPos, eWeather & a_Value);

View File

@ -4348,6 +4348,69 @@ static int tolua_cEntity_GetSpeed(lua_State * tolua_S)
static int tolua_get_StatisticsManager_Custom(lua_State * tolua_S)
{
// Check the params:
cLuaState L(tolua_S);
if (!L.CheckParamNumber(2))
{
return 0;
}
// Get the params:
lua_pushstring(tolua_S, ".self");
lua_rawget(tolua_S, 1);
StatisticsManager * Self = static_cast<StatisticsManager *>(lua_touserdata(tolua_S, -1));
CustomStatistic Statistic;
if (!L.GetStackValue(2, Statistic))
{
return L.ApiParamError("Expected a valid custom statistic ID");
}
// Push result if statistic exists:
if (const auto Result = Self->Custom.find(Statistic); Result != Self->Custom.end())
{
L.Push(Result->second);
return 1;
}
return 0;
}
static int tolua_set_StatisticsManager_Custom(lua_State * tolua_S)
{
// Check the params:
cLuaState L(tolua_S);
if (!L.CheckParamNumber(2))
{
return 0;
}
// Get the params:
lua_pushstring(tolua_S, ".self");
lua_rawget(tolua_S, 1);
StatisticsManager * Self = static_cast<StatisticsManager *>(lua_touserdata(tolua_S, -1));
CustomStatistic Statistic;
StatisticsManager::StatValue Value;
if (!L.GetStackValues(2, Statistic, Value))
{
return L.ApiParamError("Expected a valid custom statistic ID and value");
}
// Set the value:
Self->Custom[Statistic] = Value;
return 0;
}
void cManualBindings::Bind(lua_State * tolua_S) void cManualBindings::Bind(lua_State * tolua_S)
{ {
tolua_beginmodule(tolua_S, nullptr); tolua_beginmodule(tolua_S, nullptr);
@ -4357,10 +4420,12 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_usertype(tolua_S, "cLineBlockTracer"); tolua_usertype(tolua_S, "cLineBlockTracer");
tolua_usertype(tolua_S, "cStringCompression"); tolua_usertype(tolua_S, "cStringCompression");
tolua_usertype(tolua_S, "cUrlParser"); tolua_usertype(tolua_S, "cUrlParser");
// StatisticsManager was already created by cPlayer::GetStatistics' autogenerated bindings.
tolua_cclass(tolua_S, "cCryptoHash", "cCryptoHash", "", nullptr); tolua_cclass(tolua_S, "cCryptoHash", "cCryptoHash", "", nullptr);
tolua_cclass(tolua_S, "cLineBlockTracer", "cLineBlockTracer", "", nullptr); tolua_cclass(tolua_S, "cLineBlockTracer", "cLineBlockTracer", "", nullptr);
tolua_cclass(tolua_S, "cStringCompression", "cStringCompression", "", nullptr); tolua_cclass(tolua_S, "cStringCompression", "cStringCompression", "", nullptr);
tolua_cclass(tolua_S, "cUrlParser", "cUrlParser", "", nullptr); tolua_cclass(tolua_S, "cUrlParser", "cUrlParser", "", nullptr);
tolua_cclass(tolua_S, "StatisticsManager", "StatisticsManager", "", nullptr);
// Globals: // Globals:
tolua_function(tolua_S, "Clamp", tolua_Clamp); tolua_function(tolua_S, "Clamp", tolua_Clamp);
@ -4592,6 +4657,10 @@ void cManualBindings::Bind(lua_State * tolua_S)
tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, nullptr); tolua_variable(tolua_S, "PostParams", tolua_get_HTTPRequest_PostParams, nullptr);
tolua_endmodule(tolua_S); tolua_endmodule(tolua_S);
tolua_beginmodule(tolua_S, "StatisticsManager");
tolua_array(tolua_S, "Custom", tolua_get_StatisticsManager_Custom, tolua_set_StatisticsManager_Custom);
tolua_endmodule(tolua_S);
BindNetwork(tolua_S); BindNetwork(tolua_S);
BindRankManager(tolua_S); BindRankManager(tolua_S);
BindWorld(tolua_S); BindWorld(tolua_S);

View File

@ -206,7 +206,7 @@ void cBeaconEntity::UpdateBeacon(void)
(std::abs(Distance.z) <= 20) (std::abs(Distance.z) <= 20)
) )
{ {
a_Player.AwardAchievement(Statistic::AchFullBeacon); a_Player.AwardAchievement(CustomStatistic::AchFullBeacon);
} }
return false; return false;
} }
@ -313,7 +313,7 @@ bool cBeaconEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
bool cBeaconEntity::UsedBy(cPlayer * a_Player) bool cBeaconEntity::UsedBy(cPlayer * a_Player)
{ {
a_Player->GetStatManager().AddValue(Statistic::InteractWithBeacon); a_Player->GetStatistics().Custom[CustomStatistic::InteractWithBeacon]++;
cWindow * Window = GetWindow(); cWindow * Window = GetWindow();
if (Window == nullptr) if (Window == nullptr)

View File

@ -145,7 +145,7 @@ bool cBrewingstandEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
bool cBrewingstandEntity::UsedBy(cPlayer * a_Player) bool cBrewingstandEntity::UsedBy(cPlayer * a_Player)
{ {
a_Player->GetStatManager().AddValue(Statistic::InteractWithBrewingstand); a_Player->GetStatistics().Custom[CustomStatistic::InteractWithBrewingstand]++;
cWindow * Window = GetWindow(); cWindow * Window = GetWindow();
if (Window == nullptr) if (Window == nullptr)

View File

@ -204,11 +204,11 @@ bool cChestEntity::UsedBy(cPlayer * a_Player)
if (m_BlockType == E_BLOCK_CHEST) if (m_BlockType == E_BLOCK_CHEST)
{ {
a_Player->GetStatManager().AddValue(Statistic::OpenChest); a_Player->GetStatistics().Custom[CustomStatistic::OpenChest]++;
} }
else // E_BLOCK_TRAPPED_CHEST else // E_BLOCK_TRAPPED_CHEST
{ {
a_Player->GetStatManager().AddValue(Statistic::TriggerTrappedChest); a_Player->GetStatistics().Custom[CustomStatistic::TriggerTrappedChest]++;
} }
auto & PrimaryChest = GetPrimaryChest(); auto & PrimaryChest = GetPrimaryChest();

View File

@ -163,11 +163,11 @@ bool cDropSpenserEntity::UsedBy(cPlayer * a_Player)
{ {
if (m_BlockType == E_BLOCK_DISPENSER) if (m_BlockType == E_BLOCK_DISPENSER)
{ {
a_Player->GetStatManager().AddValue(Statistic::InspectDispenser); a_Player->GetStatistics().Custom[CustomStatistic::InspectDispenser]++;
} }
else // E_BLOCK_DROPPER else // E_BLOCK_DROPPER
{ {
a_Player->GetStatManager().AddValue(Statistic::InspectDropper); a_Player->GetStatistics().Custom[CustomStatistic::InspectDropper]++;
} }
cWindow * Window = GetWindow(); cWindow * Window = GetWindow();

View File

@ -62,7 +62,7 @@ bool cEnderChestEntity::UsedBy(cPlayer * a_Player)
return false; return false;
} }
a_Player->GetStatManager().AddValue(Statistic::OpenEnderchest); a_Player->GetStatistics().Custom[CustomStatistic::OpenEnderchest]++;
// If the window is not created, open it anew: // If the window is not created, open it anew:
cWindow * Window = GetWindow(); cWindow * Window = GetWindow();

View File

@ -50,7 +50,7 @@ bool cFlowerPotEntity::UsedBy(cPlayer * a_Player)
return false; return false;
} }
a_Player->GetStatManager().AddValue(Statistic::PotFlower); a_Player->GetStatistics().Custom[CustomStatistic::PotFlower]++;
cItem SelectedItem = a_Player->GetInventory().GetEquippedItem(); cItem SelectedItem = a_Player->GetInventory().GetEquippedItem();
if (IsFlower(SelectedItem.m_ItemType, SelectedItem.m_ItemDamage)) if (IsFlower(SelectedItem.m_ItemType, SelectedItem.m_ItemDamage))

View File

@ -127,7 +127,7 @@ bool cFurnaceEntity::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
bool cFurnaceEntity::UsedBy(cPlayer * a_Player) bool cFurnaceEntity::UsedBy(cPlayer * a_Player)
{ {
a_Player->GetStatManager().AddValue(Statistic::InteractWithFurnace); a_Player->GetStatistics().Custom[CustomStatistic::InteractWithFurnace]++;
cWindow * Window = GetWindow(); cWindow * Window = GetWindow();
if (Window == nullptr) if (Window == nullptr)

View File

@ -113,7 +113,7 @@ void cHopperEntity::SendTo(cClientHandle & a_Client)
bool cHopperEntity::UsedBy(cPlayer * a_Player) bool cHopperEntity::UsedBy(cPlayer * a_Player)
{ {
a_Player->GetStatManager().AddValue(Statistic::InspectHopper); a_Player->GetStatistics().Custom[CustomStatistic::InspectHopper]++;
// If the window is not created, open it anew: // If the window is not created, open it anew:
cWindow * Window = GetWindow(); cWindow * Window = GetWindow();

View File

@ -65,7 +65,8 @@ bool cJukeboxEntity::UsedBy(cPlayer * a_Player)
const cItem & HeldItem = a_Player->GetEquippedItem(); const cItem & HeldItem = a_Player->GetEquippedItem();
if (PlayRecord(HeldItem.m_ItemType)) if (PlayRecord(HeldItem.m_ItemType))
{ {
a_Player->GetStatManager().AddValue(Statistic::PlayRecord); a_Player->GetStatistics().Custom[CustomStatistic::PlayRecord]++;
if (!a_Player->IsGameModeCreative()) if (!a_Player->IsGameModeCreative())
{ {
a_Player->GetInventory().RemoveOneEquippedItem(); a_Player->GetInventory().RemoveOneEquippedItem();

View File

@ -34,7 +34,7 @@ void cNoteEntity::CopyFrom(const cBlockEntity & a_Src)
bool cNoteEntity::UsedBy(cPlayer * a_Player) bool cNoteEntity::UsedBy(cPlayer * a_Player)
{ {
a_Player->GetStatManager().AddValue(Statistic::TuneNoteblock); a_Player->GetStatistics().Custom[CustomStatistic::TuneNoteblock]++;
IncrementNote(); IncrementNote();
MakeSound(); MakeSound();
return true; return true;

View File

@ -134,7 +134,7 @@ bool cBlockBedHandler::OnUse(
// Occupy the bed, where 0x4 = occupied bit: // Occupy the bed, where 0x4 = occupied bit:
a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta | 0x04); a_ChunkInterface.SetBlockMeta(a_BlockPos, Meta | 0x04);
a_Player.GetStatManager().AddValue(Statistic::SleepInBed); a_Player.GetStatistics().Custom[CustomStatistic::SleepInBed]++;
// When sleeping, the player's bounding box moves to approximately where his head is. // When sleeping, the player's bounding box moves to approximately where his head is.
// Set the player's position to somewhere close to the edge of the pillow block: // Set the player's position to somewhere close to the edge of the pillow block:

View File

@ -33,7 +33,7 @@ private:
return false; return false;
} }
a_Player.GetStatManager().AddValue(Statistic::EatCakeSlice); a_Player.GetStatistics().Custom[CustomStatistic::EatCakeSlice]++;
if (Meta >= 5) if (Meta >= 5)
{ {
a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos, &a_Player); a_ChunkInterface.DigBlock(a_WorldInterface, a_BlockPos, &a_Player);

View File

@ -65,7 +65,7 @@ private:
{ {
a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_BUCKET)); a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_BUCKET));
} }
a_Player.GetStatManager().AddValue(Statistic::FillCauldron); a_Player.GetStatistics().Custom[CustomStatistic::FillCauldron]++;
} }
break; break;
} }
@ -79,7 +79,7 @@ private:
{ {
a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_POTION)); a_Player.ReplaceOneEquippedItemTossRest(cItem(E_ITEM_POTION));
} }
a_Player.GetStatManager().AddValue(Statistic::UseCauldron); a_Player.GetStatistics().Custom[CustomStatistic::UseCauldron]++;
} }
break; break;
} }

View File

@ -29,7 +29,7 @@ private:
const Vector3i a_CursorPos const Vector3i a_CursorPos
) const override ) const override
{ {
a_Player.GetStatManager().AddValue(Statistic::InteractWithCraftingTable); a_Player.GetStatistics().Custom[CustomStatistic::InteractWithCraftingTable]++;
cWindow * Window = new cCraftingWindow(); cWindow * Window = new cCraftingWindow();
a_Player.OpenWindow(*Window); a_Player.OpenWindow(*Window);

View File

@ -369,7 +369,7 @@ void cClientHandle::FinishAuthenticate(const AString & a_Name, const cUUID & a_U
cRoot::Get()->SendPlayerLists(m_Player); // Add everyone else to ourself cRoot::Get()->SendPlayerLists(m_Player); // Add everyone else to ourself
// Send statistics: // Send statistics:
SendStatistics(m_Player->GetStatManager()); SendStatistics(m_Player->GetStatistics());
// Delay the first ping until the client "settles down" // Delay the first ping until the client "settles down"
// This should fix #889, "BadCast exception, cannot convert bit to fm" error in client // This should fix #889, "BadCast exception, cannot convert bit to fm" error in client
@ -2970,7 +2970,7 @@ void cClientHandle::SendSpawnMob(const cMonster & a_Mob)
void cClientHandle::SendStatistics(const cStatManager & a_Manager) void cClientHandle::SendStatistics(const StatisticsManager & a_Manager)
{ {
m_Protocol->SendStatistics(a_Manager); m_Protocol->SendStatistics(a_Manager);
} }

View File

@ -35,9 +35,11 @@ class cProtocol;
class cWindow; class cWindow;
class cFallingBlock; class cFallingBlock;
class cCompositeChat; class cCompositeChat;
class cStatManager;
class cMap; class cMap;
class cClientHandle; class cClientHandle;
struct StatisticsManager;
typedef std::shared_ptr<cClientHandle> cClientHandlePtr; typedef std::shared_ptr<cClientHandle> cClientHandlePtr;
@ -211,7 +213,7 @@ public: // tolua_export
void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data); void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data);
void SendSpawnEntity (const cEntity & a_Entity); void SendSpawnEntity (const cEntity & a_Entity);
void SendSpawnMob (const cMonster & a_Mob); void SendSpawnMob (const cMonster & a_Mob);
void SendStatistics (const cStatManager & a_Manager); void SendStatistics (const StatisticsManager & a_Manager);
void SendTabCompletionResults (const AStringVector & a_Results); void SendTabCompletionResults (const AStringVector & a_Results);
void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ); void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ);
void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks); // tolua_export void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks); // tolua_export

View File

@ -528,7 +528,7 @@ bool cEntity::DoTakeDamage(TakeDamageInfo & a_TDI)
} }
} }
Player->GetStatManager().AddValue(Statistic::DamageDealt, FloorC<cStatManager::StatValue>(a_TDI.FinalDamage * 10 + 0.5)); Player->GetStatistics().Custom[CustomStatistic::DamageDealt] += FloorC<StatisticsManager::StatValue>(a_TDI.FinalDamage * 10 + 0.5);
} }
m_Health -= a_TDI.FinalDamage; m_Health -= a_TDI.FinalDamage;

View File

@ -242,10 +242,10 @@ bool cPickup::CollectedBy(cPlayer & a_Dest)
// Check achievements // Check achievements
switch (m_Item.m_ItemType) switch (m_Item.m_ItemType)
{ {
case E_BLOCK_LOG: a_Dest.AwardAchievement(Statistic::AchMineWood); break; case E_BLOCK_LOG: a_Dest.AwardAchievement(CustomStatistic::AchMineWood); break;
case E_ITEM_LEATHER: a_Dest.AwardAchievement(Statistic::AchKillCow); break; case E_ITEM_LEATHER: a_Dest.AwardAchievement(CustomStatistic::AchKillCow); break;
case E_ITEM_DIAMOND: a_Dest.AwardAchievement(Statistic::AchDiamonds); break; case E_ITEM_DIAMOND: a_Dest.AwardAchievement(CustomStatistic::AchDiamonds); break;
case E_ITEM_BLAZE_ROD: a_Dest.AwardAchievement(Statistic::AchBlazeRod); break; case E_ITEM_BLAZE_ROD: a_Dest.AwardAchievement(CustomStatistic::AchBlazeRod); break;
default: break; default: break;
} }

View File

@ -167,7 +167,7 @@ cPlayer::~cPlayer(void)
LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), static_cast<void *>(this), GetUniqueID()); LOGD("Deleting cPlayer \"%s\" at %p, ID %d", GetName().c_str(), static_cast<void *>(this), GetUniqueID());
// "Times ragequit": // "Times ragequit":
m_Stats.AddValue(Statistic::LeaveGame); m_Stats.Custom[CustomStatistic::LeaveGame]++;
SaveToDisk(); SaveToDisk();
@ -482,7 +482,7 @@ void cPlayer::TossItems(const cItems & a_Items)
return; return;
} }
m_Stats.AddValue(Statistic::Drop, static_cast<cStatManager::StatValue>(a_Items.Size())); m_Stats.Custom[CustomStatistic::Drop] += static_cast<StatisticsManager::StatValue>(a_Items.Size());
const auto Speed = (GetLookVector() + Vector3d(0, 0.2, 0)) * 6; // A dash of height and a dollop of speed const auto Speed = (GetLookVector() + Vector3d(0, 0.2, 0)) * 6; // A dash of height and a dollop of speed
const auto Position = GetEyePosition() - Vector3d(0, 0.2, 0); // Correct for eye-height weirdness const auto Position = GetEyePosition() - Vector3d(0, 0.2, 0); // Correct for eye-height weirdness
@ -859,7 +859,7 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
{ {
Pickups.Add(cItem(E_ITEM_RED_APPLE)); Pickups.Add(cItem(E_ITEM_RED_APPLE));
} }
m_Stats.AddValue(Statistic::Drop, static_cast<cStatManager::StatValue>(Pickups.Size())); m_Stats.Custom[CustomStatistic::Drop] += static_cast<StatisticsManager::StatValue>(Pickups.Size());
m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10); m_World->SpawnItemPickups(Pickups, GetPosX(), GetPosY(), GetPosZ(), 10);
SaveToDisk(); // Save it, yeah the world is a tough place ! SaveToDisk(); // Save it, yeah the world is a tough place !
@ -923,8 +923,8 @@ void cPlayer::KilledBy(TakeDamageInfo & a_TDI)
} }
} }
m_Stats.AddValue(Statistic::Deaths); m_Stats.Custom[CustomStatistic::Deaths]++;
m_Stats.SetValue(Statistic::TimeSinceDeath, 0); m_Stats.Custom[CustomStatistic::TimeSinceDeath] = 0;
m_World->GetScoreBoard().AddPlayerScore(GetName(), cObjective::otDeathCount, 1); m_World->GetScoreBoard().AddPlayerScore(GetName(), cObjective::otDeathCount, 1);
} }
@ -939,7 +939,7 @@ void cPlayer::Killed(cEntity * a_Victim)
if (a_Victim->IsPlayer()) if (a_Victim->IsPlayer())
{ {
m_Stats.AddValue(Statistic::PlayerKills); m_Stats.Custom[CustomStatistic::PlayerKills]++;
ScoreBoard.AddPlayerScore(GetName(), cObjective::otPlayerKillCount, 1); ScoreBoard.AddPlayerScore(GetName(), cObjective::otPlayerKillCount, 1);
} }
@ -947,10 +947,10 @@ void cPlayer::Killed(cEntity * a_Victim)
{ {
if (static_cast<cMonster *>(a_Victim)->GetMobFamily() == cMonster::mfHostile) if (static_cast<cMonster *>(a_Victim)->GetMobFamily() == cMonster::mfHostile)
{ {
AwardAchievement(Statistic::AchKillEnemy); AwardAchievement(CustomStatistic::AchKillEnemy);
} }
m_Stats.AddValue(Statistic::MobKills); m_Stats.Custom[CustomStatistic::MobKills]++;
} }
ScoreBoard.AddPlayerScore(GetName(), cObjective::otTotalKillCount, 1); ScoreBoard.AddPlayerScore(GetName(), cObjective::otTotalKillCount, 1);
@ -1373,7 +1373,7 @@ void cPlayer::UpdateCapabilities()
void cPlayer::AwardAchievement(const Statistic a_Ach) void cPlayer::AwardAchievement(const CustomStatistic a_Ach)
{ {
// Check if the prerequisites are met: // Check if the prerequisites are met:
if (!m_Stats.SatisfiesPrerequisite(a_Ach)) if (!m_Stats.SatisfiesPrerequisite(a_Ach))
@ -1382,7 +1382,7 @@ void cPlayer::AwardAchievement(const Statistic a_Ach)
} }
// Increment the statistic and check if we already have it: // Increment the statistic and check if we already have it:
if (m_Stats.AddValue(a_Ach) != 1) if (m_Stats.Custom[a_Ach]++ != 1)
{ {
return; return;
} }
@ -2262,12 +2262,12 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
return; return;
} }
const auto Value = FloorC<cStatManager::StatValue>(a_DeltaPos.Length() * 100 + 0.5); const auto Value = FloorC<StatisticsManager::StatValue>(a_DeltaPos.Length() * 100 + 0.5);
if (m_AttachedTo == nullptr) if (m_AttachedTo == nullptr)
{ {
if (IsFlying()) if (IsFlying())
{ {
m_Stats.AddValue(Statistic::FlyOneCm, Value); m_Stats.Custom[CustomStatistic::FlyOneCm] += Value;
// May be flying and doing any of the following: // May be flying and doing any of the following:
} }
@ -2275,18 +2275,18 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
{ {
if (a_DeltaPos.y > 0.0) // Going up if (a_DeltaPos.y > 0.0) // Going up
{ {
m_Stats.AddValue(Statistic::ClimbOneCm, FloorC<cStatManager::StatValue>(a_DeltaPos.y * 100 + 0.5)); m_Stats.Custom[CustomStatistic::ClimbOneCm] += FloorC<StatisticsManager::StatValue>(a_DeltaPos.y * 100 + 0.5);
} }
} }
else if (IsInWater()) else if (IsInWater())
{ {
if (m_IsHeadInWater) if (m_IsHeadInWater)
{ {
m_Stats.AddValue(Statistic::WalkUnderWaterOneCm, Value); m_Stats.Custom[CustomStatistic::WalkUnderWaterOneCm] += Value;
} }
else else
{ {
m_Stats.AddValue(Statistic::WalkOnWaterOneCm, Value); m_Stats.Custom[CustomStatistic::WalkOnWaterOneCm] += Value;
} }
AddFoodExhaustion(0.00015 * static_cast<double>(Value)); AddFoodExhaustion(0.00015 * static_cast<double>(Value));
} }
@ -2294,17 +2294,17 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
{ {
if (IsCrouched()) if (IsCrouched())
{ {
m_Stats.AddValue(Statistic::CrouchOneCm, Value); m_Stats.Custom[CustomStatistic::CrouchOneCm] += Value;
AddFoodExhaustion(0.0001 * static_cast<double>(Value)); AddFoodExhaustion(0.0001 * static_cast<double>(Value));
} }
if (IsSprinting()) if (IsSprinting())
{ {
m_Stats.AddValue(Statistic::SprintOneCm, Value); m_Stats.Custom[CustomStatistic::SprintOneCm] += Value;
AddFoodExhaustion(0.001 * static_cast<double>(Value)); AddFoodExhaustion(0.001 * static_cast<double>(Value));
} }
else else
{ {
m_Stats.AddValue(Statistic::WalkOneCm, Value); m_Stats.Custom[CustomStatistic::WalkOneCm] += Value;
AddFoodExhaustion(0.0001 * static_cast<double>(Value)); AddFoodExhaustion(0.0001 * static_cast<double>(Value));
} }
} }
@ -2313,13 +2313,13 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
// If a jump just started, process food exhaustion: // If a jump just started, process food exhaustion:
if ((a_DeltaPos.y > 0.0) && a_PreviousIsOnGround) if ((a_DeltaPos.y > 0.0) && a_PreviousIsOnGround)
{ {
m_Stats.AddValue(Statistic::Jump, 1); m_Stats.Custom[CustomStatistic::Jump]++;
AddFoodExhaustion((IsSprinting() ? 0.008 : 0.002) * static_cast<double>(Value)); AddFoodExhaustion((IsSprinting() ? 0.008 : 0.002) * static_cast<double>(Value));
} }
else if (a_DeltaPos.y < 0.0) else if (a_DeltaPos.y < 0.0)
{ {
// Increment statistic // Increment statistic
m_Stats.AddValue(Statistic::FallOneCm, static_cast<cStatManager::StatValue>(std::abs(a_DeltaPos.y) * 100 + 0.5)); m_Stats.Custom[CustomStatistic::FallOneCm] += static_cast<StatisticsManager::StatValue>(-a_DeltaPos.y * 100 + 0.5);
} }
// TODO: good opportunity to detect illegal flight (check for falling tho) // TODO: good opportunity to detect illegal flight (check for falling tho)
} }
@ -2328,15 +2328,15 @@ void cPlayer::UpdateMovementStats(const Vector3d & a_DeltaPos, bool a_PreviousIs
{ {
switch (m_AttachedTo->GetEntityType()) switch (m_AttachedTo->GetEntityType())
{ {
case cEntity::etMinecart: m_Stats.AddValue(Statistic::MinecartOneCm, Value); break; case cEntity::etMinecart: m_Stats.Custom[CustomStatistic::MinecartOneCm] += Value; break;
case cEntity::etBoat: m_Stats.AddValue(Statistic::BoatOneCm, Value); break; case cEntity::etBoat: m_Stats.Custom[CustomStatistic::BoatOneCm] += Value; break;
case cEntity::etMonster: case cEntity::etMonster:
{ {
cMonster * Monster = static_cast<cMonster *>(m_AttachedTo); cMonster * Monster = static_cast<cMonster *>(m_AttachedTo);
switch (Monster->GetMobType()) switch (Monster->GetMobType())
{ {
case mtPig: m_Stats.AddValue(Statistic::PigOneCm, Value); break; case mtPig: m_Stats.Custom[CustomStatistic::PigOneCm] += Value; break;
case mtHorse: m_Stats.AddValue(Statistic::HorseOneCm, Value); break; case mtHorse: m_Stats.Custom[CustomStatistic::HorseOneCm] += Value; break;
default: break; default: break;
} }
break; break;
@ -3004,7 +3004,7 @@ bool cPlayer::DoTakeDamage(TakeDamageInfo & a_TDI)
NotifyNearbyWolves(static_cast<cPawn*>(a_TDI.Attacker), true); NotifyNearbyWolves(static_cast<cPawn*>(a_TDI.Attacker), true);
} }
} }
m_Stats.AddValue(Statistic::DamageTaken, FloorC<cStatManager::StatValue>(a_TDI.FinalDamage * 10 + 0.5)); m_Stats.Custom[CustomStatistic::DamageTaken] += FloorC<StatisticsManager::StatValue>(a_TDI.FinalDamage * 10 + 0.5);
return true; return true;
} }
return false; return false;
@ -3154,11 +3154,11 @@ void cPlayer::OnRemoveFromWorld(cWorld & a_World)
// Award relevant achievements: // Award relevant achievements:
if (DestinationDimension == dimEnd) if (DestinationDimension == dimEnd)
{ {
AwardAchievement(Statistic::AchTheEnd); AwardAchievement(CustomStatistic::AchTheEnd);
} }
else if (DestinationDimension == dimNether) else if (DestinationDimension == dimNether)
{ {
AwardAchievement(Statistic::AchPortal); AwardAchievement(CustomStatistic::AchPortal);
} }
// Set capabilities based on new world: // Set capabilities based on new world:
@ -3218,12 +3218,16 @@ void cPlayer::Tick(std::chrono::milliseconds a_Dt, cChunk & a_Chunk)
return; return;
} }
m_Stats.AddValue(Statistic::PlayOneMinute);
m_Stats.AddValue(Statistic::TimeSinceDeath);
if (IsCrouched())
{ {
m_Stats.AddValue(Statistic::SneakTime); const auto TicksElapsed = static_cast<StatisticsManager::StatValue>(std::chrono::duration_cast<cTickTime>(a_Dt).count());
m_Stats.Custom[CustomStatistic::PlayOneMinute] += TicksElapsed;
m_Stats.Custom[CustomStatistic::TimeSinceDeath] += TicksElapsed;
if (IsCrouched())
{
m_Stats.Custom[CustomStatistic::SneakTime] += TicksElapsed;
}
} }
// Handle the player detach, when the player is in spectator mode // Handle the player detach, when the player is in spectator mode

View File

@ -230,6 +230,9 @@ public:
AString GetIP(void) const; // tolua_export AString GetIP(void) const; // tolua_export
/** Return the associated statistic and achievement manager. */
StatisticsManager & GetStatistics() { return m_Stats; }
/** Returns the associated team, nullptr if none */ /** Returns the associated team, nullptr if none */
cTeam * GetTeam(void) { return m_Team; } // tolua_export cTeam * GetTeam(void) { return m_Team; } // tolua_export
@ -244,13 +247,10 @@ public:
/** Forces the player to query the scoreboard for his team */ /** Forces the player to query the scoreboard for his team */
cTeam * UpdateTeam(void); cTeam * UpdateTeam(void);
/** Return the associated statistic and achievement manager. */
cStatManager & GetStatManager() { return m_Stats; }
/** Awards the player an achievement. /** Awards the player an achievement.
If all prerequisites are met, this method will award the achievement and will broadcast a chat message. If all prerequisites are met, this method will award the achievement and will broadcast a chat message.
If the achievement has been already awarded to the player, this method will just increment the stat counter. */ If the achievement has been already awarded to the player, this method will just increment the stat counter. */
void AwardAchievement(Statistic a_Ach); void AwardAchievement(CustomStatistic a_Ach);
/** Forces the player to move in the given direction. /** Forces the player to move in the given direction.
@deprecated Use SetSpeed instead. */ @deprecated Use SetSpeed instead. */
@ -735,7 +735,7 @@ private:
cTeam * m_Team; cTeam * m_Team;
cStatManager m_Stats; StatisticsManager m_Stats;
/** How long till the player's inventory will be saved /** How long till the player's inventory will be saved
Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */ Default save interval is #defined in PLAYER_INVENTORY_SAVE_INTERVAL */

View File

@ -210,7 +210,7 @@ public:
} }
} }
a_Player.GetStatManager().AddValue(Statistic::TreasureFished, 1); a_Player.GetStatistics().Custom[CustomStatistic::TreasureFished]++;
} }
else if (ItemCategory < JunkChances[LotSLevel]) else if (ItemCategory < JunkChances[LotSLevel])
{ {
@ -262,7 +262,7 @@ public:
Drops.Add(cItem(E_BLOCK_TRIPWIRE_HOOK)); Drops.Add(cItem(E_BLOCK_TRIPWIRE_HOOK));
} }
a_Player.GetStatManager().AddValue(Statistic::JunkFished, 1); a_Player.GetStatistics().Custom[CustomStatistic::JunkFished]++;
} }
else else
{ {
@ -284,7 +284,7 @@ public:
Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_FISH)); Drops.Add(cItem(E_ITEM_RAW_FISH, 1, E_META_RAW_FISH_FISH));
} }
a_Player.GetStatManager().AddValue(Statistic::FishCaught, 1); a_Player.GetStatistics().Custom[CustomStatistic::FishCaught]++;
} }
// Check with plugins if this loot is acceptable: // Check with plugins if this loot is acceptable:

View File

@ -285,7 +285,7 @@ public:
double Dist = (a_Player.GetPosition() - Pos).Length(); double Dist = (a_Player.GetPosition() - Pos).Length();
if (Dist < 50.0) if (Dist < 50.0)
{ {
a_Player.AwardAchievement(Statistic::AchSpawnWither); a_Player.AwardAchievement(CustomStatistic::AchSpawnWither);
} }
return false; return false;
} }

View File

@ -1361,10 +1361,10 @@ void cMonster::LoveTick(void)
m_World->DoWithPlayerByUUID(m_Feeder, [&] (cPlayer & a_Player) m_World->DoWithPlayerByUUID(m_Feeder, [&] (cPlayer & a_Player)
{ {
a_Player.GetStatManager().AddValue(Statistic::AnimalsBred); a_Player.GetStatistics().Custom[CustomStatistic::AnimalsBred]++;
if (GetMobType() == eMonsterType::mtCow) if (GetMobType() == eMonsterType::mtCow)
{ {
a_Player.AwardAchievement(Statistic::AchBreedCow); a_Player.AwardAchievement(CustomStatistic::AchBreedCow);
} }
return true; return true;
}); });

View File

@ -84,7 +84,7 @@ void cWither::KilledBy(TakeDamageInfo & a_TDI)
if (Dist < 50.0) if (Dist < 50.0)
{ {
// If player is close, award achievement // If player is close, award achievement
a_Player.AwardAchievement(Statistic::AchKillWither); a_Player.AwardAchievement(CustomStatistic::AchKillWither);
} }
return false; return false;
} }

View File

@ -7859,62 +7859,62 @@ namespace Palette_1_13
} }
} }
UInt32 From(const Statistic ID) UInt32 From(const CustomStatistic ID)
{ {
switch (ID) switch (ID)
{ {
case Statistic::AnimalsBred: return 25; case CustomStatistic::AnimalsBred: return 25;
case Statistic::AviateOneCm: return 17; case CustomStatistic::AviateOneCm: return 17;
case Statistic::BoatOneCm: return 14; case CustomStatistic::BoatOneCm: return 14;
case Statistic::CleanArmor: return 33; case CustomStatistic::CleanArmor: return 33;
case Statistic::CleanBanner: return 34; case CustomStatistic::CleanBanner: return 34;
case Statistic::ClimbOneCm: return 10; case CustomStatistic::ClimbOneCm: return 10;
case Statistic::CrouchOneCm: return 6; case CustomStatistic::CrouchOneCm: return 6;
case Statistic::DamageDealt: return 21; case CustomStatistic::DamageDealt: return 21;
case Statistic::DamageTaken: return 22; case CustomStatistic::DamageTaken: return 22;
case Statistic::Deaths: return 23; case CustomStatistic::Deaths: return 23;
case Statistic::Drop: return 20; case CustomStatistic::Drop: return 20;
case Statistic::EatCakeSlice: return 30; case CustomStatistic::EatCakeSlice: return 30;
case Statistic::EnchantItem: return 45; case CustomStatistic::EnchantItem: return 45;
case Statistic::FallOneCm: return 9; case CustomStatistic::FallOneCm: return 9;
case Statistic::FillCauldron: return 31; case CustomStatistic::FillCauldron: return 31;
case Statistic::FishCaught: return 27; case CustomStatistic::FishCaught: return 27;
case Statistic::FlyOneCm: return 11; case CustomStatistic::FlyOneCm: return 11;
case Statistic::HorseOneCm: return 16; case CustomStatistic::HorseOneCm: return 16;
case Statistic::InspectDispenser: return 39; case CustomStatistic::InspectDispenser: return 39;
case Statistic::InspectDropper: return 37; case CustomStatistic::InspectDropper: return 37;
case Statistic::InspectHopper: return 38; case CustomStatistic::InspectHopper: return 38;
case Statistic::InteractWithBeacon: return 36; case CustomStatistic::InteractWithBeacon: return 36;
case Statistic::InteractWithBrewingstand: return 35; case CustomStatistic::InteractWithBrewingstand: return 35;
case Statistic::InteractWithCraftingTable: return 48; case CustomStatistic::InteractWithCraftingTable: return 48;
case Statistic::InteractWithFurnace: return 47; case CustomStatistic::InteractWithFurnace: return 47;
case Statistic::Jump: return 19; case CustomStatistic::Jump: return 19;
case Statistic::LeaveGame: return 0; case CustomStatistic::LeaveGame: return 0;
case Statistic::MinecartOneCm: return 13; case CustomStatistic::MinecartOneCm: return 13;
case Statistic::MobKills: return 24; case CustomStatistic::MobKills: return 24;
case Statistic::OpenChest: return 49; case CustomStatistic::OpenChest: return 49;
case Statistic::OpenEnderchest: return 44; case CustomStatistic::OpenEnderchest: return 44;
case Statistic::OpenShulkerBox: return 51; case CustomStatistic::OpenShulkerBox: return 51;
case Statistic::PigOneCm: return 15; case CustomStatistic::PigOneCm: return 15;
case Statistic::PlayerKills: return 26; case CustomStatistic::PlayerKills: return 26;
case Statistic::PlayNoteblock: return 40; case CustomStatistic::PlayNoteblock: return 40;
case Statistic::PlayOneMinute: return 1; case CustomStatistic::PlayOneMinute: return 1;
case Statistic::PlayRecord: return 46; case CustomStatistic::PlayRecord: return 46;
case Statistic::PotFlower: return 42; case CustomStatistic::PotFlower: return 42;
case Statistic::SleepInBed: return 50; case CustomStatistic::SleepInBed: return 50;
case Statistic::SneakTime: return 4; case CustomStatistic::SneakTime: return 4;
case Statistic::SprintOneCm: return 7; case CustomStatistic::SprintOneCm: return 7;
case Statistic::SwimOneCm: return 8; case CustomStatistic::SwimOneCm: return 8;
case Statistic::TalkedToVillager: return 28; case CustomStatistic::TalkedToVillager: return 28;
case Statistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceDeath: return 2;
case Statistic::TimeSinceRest: return 3; case CustomStatistic::TimeSinceRest: return 3;
case Statistic::TradedWithVillager: return 29; case CustomStatistic::TradedWithVillager: return 29;
case Statistic::TriggerTrappedChest: return 43; case CustomStatistic::TriggerTrappedChest: return 43;
case Statistic::TuneNoteblock: return 41; case CustomStatistic::TuneNoteblock: return 41;
case Statistic::UseCauldron: return 32; case CustomStatistic::UseCauldron: return 32;
case Statistic::WalkOneCm: return 5; case CustomStatistic::WalkOneCm: return 5;
case Statistic::WalkOnWaterOneCm: return 18; case CustomStatistic::WalkOnWaterOneCm: return 18;
case Statistic::WalkUnderWaterOneCm: return 12; case CustomStatistic::WalkUnderWaterOneCm: return 12;
default: return UInt32(-1); default: return UInt32(-1);
} }
} }

View File

@ -8,6 +8,6 @@ namespace Palette_1_13
{ {
UInt32 From(BlockState Block); UInt32 From(BlockState Block);
UInt32 From(Item ID); UInt32 From(Item ID);
UInt32 From(Statistic ID); UInt32 From(CustomStatistic ID);
Item ToItem(UInt32 ID); Item ToItem(UInt32 ID);
} }

View File

@ -7870,68 +7870,68 @@ namespace Palette_1_13_1
} }
} }
UInt32 From(const Statistic ID) UInt32 From(const CustomStatistic ID)
{ {
switch (ID) switch (ID)
{ {
case Statistic::AnimalsBred: return 30; case CustomStatistic::AnimalsBred: return 30;
case Statistic::AviateOneCm: return 17; case CustomStatistic::AviateOneCm: return 17;
case Statistic::BoatOneCm: return 14; case CustomStatistic::BoatOneCm: return 14;
case Statistic::CleanArmor: return 38; case CustomStatistic::CleanArmor: return 38;
case Statistic::CleanBanner: return 39; case CustomStatistic::CleanBanner: return 39;
case Statistic::CleanShulkerBox: return 40; case CustomStatistic::CleanShulkerBox: return 40;
case Statistic::ClimbOneCm: return 10; case CustomStatistic::ClimbOneCm: return 10;
case Statistic::CrouchOneCm: return 6; case CustomStatistic::CrouchOneCm: return 6;
case Statistic::DamageAbsorbed: return 26; case CustomStatistic::DamageAbsorbed: return 26;
case Statistic::DamageBlockedByShield: return 25; case CustomStatistic::DamageBlockedByShield: return 25;
case Statistic::DamageDealt: return 21; case CustomStatistic::DamageDealt: return 21;
case Statistic::DamageDealtAbsorbed: return 22; case CustomStatistic::DamageDealtAbsorbed: return 22;
case Statistic::DamageDealtResisted: return 23; case CustomStatistic::DamageDealtResisted: return 23;
case Statistic::DamageResisted: return 27; case CustomStatistic::DamageResisted: return 27;
case Statistic::DamageTaken: return 24; case CustomStatistic::DamageTaken: return 24;
case Statistic::Deaths: return 28; case CustomStatistic::Deaths: return 28;
case Statistic::Drop: return 20; case CustomStatistic::Drop: return 20;
case Statistic::EatCakeSlice: return 35; case CustomStatistic::EatCakeSlice: return 35;
case Statistic::EnchantItem: return 51; case CustomStatistic::EnchantItem: return 51;
case Statistic::FallOneCm: return 9; case CustomStatistic::FallOneCm: return 9;
case Statistic::FillCauldron: return 36; case CustomStatistic::FillCauldron: return 36;
case Statistic::FishCaught: return 32; case CustomStatistic::FishCaught: return 32;
case Statistic::FlyOneCm: return 11; case CustomStatistic::FlyOneCm: return 11;
case Statistic::HorseOneCm: return 16; case CustomStatistic::HorseOneCm: return 16;
case Statistic::InspectDispenser: return 45; case CustomStatistic::InspectDispenser: return 45;
case Statistic::InspectDropper: return 43; case CustomStatistic::InspectDropper: return 43;
case Statistic::InspectHopper: return 44; case CustomStatistic::InspectHopper: return 44;
case Statistic::InteractWithBeacon: return 42; case CustomStatistic::InteractWithBeacon: return 42;
case Statistic::InteractWithBrewingstand: return 41; case CustomStatistic::InteractWithBrewingstand: return 41;
case Statistic::InteractWithCraftingTable: return 54; case CustomStatistic::InteractWithCraftingTable: return 54;
case Statistic::InteractWithFurnace: return 53; case CustomStatistic::InteractWithFurnace: return 53;
case Statistic::Jump: return 19; case CustomStatistic::Jump: return 19;
case Statistic::LeaveGame: return 0; case CustomStatistic::LeaveGame: return 0;
case Statistic::MinecartOneCm: return 13; case CustomStatistic::MinecartOneCm: return 13;
case Statistic::MobKills: return 29; case CustomStatistic::MobKills: return 29;
case Statistic::OpenChest: return 55; case CustomStatistic::OpenChest: return 55;
case Statistic::OpenEnderchest: return 50; case CustomStatistic::OpenEnderchest: return 50;
case Statistic::OpenShulkerBox: return 57; case CustomStatistic::OpenShulkerBox: return 57;
case Statistic::PigOneCm: return 15; case CustomStatistic::PigOneCm: return 15;
case Statistic::PlayerKills: return 31; case CustomStatistic::PlayerKills: return 31;
case Statistic::PlayNoteblock: return 46; case CustomStatistic::PlayNoteblock: return 46;
case Statistic::PlayOneMinute: return 1; case CustomStatistic::PlayOneMinute: return 1;
case Statistic::PlayRecord: return 52; case CustomStatistic::PlayRecord: return 52;
case Statistic::PotFlower: return 48; case CustomStatistic::PotFlower: return 48;
case Statistic::SleepInBed: return 56; case CustomStatistic::SleepInBed: return 56;
case Statistic::SneakTime: return 4; case CustomStatistic::SneakTime: return 4;
case Statistic::SprintOneCm: return 7; case CustomStatistic::SprintOneCm: return 7;
case Statistic::SwimOneCm: return 8; case CustomStatistic::SwimOneCm: return 8;
case Statistic::TalkedToVillager: return 33; case CustomStatistic::TalkedToVillager: return 33;
case Statistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceDeath: return 2;
case Statistic::TimeSinceRest: return 3; case CustomStatistic::TimeSinceRest: return 3;
case Statistic::TradedWithVillager: return 34; case CustomStatistic::TradedWithVillager: return 34;
case Statistic::TriggerTrappedChest: return 49; case CustomStatistic::TriggerTrappedChest: return 49;
case Statistic::TuneNoteblock: return 47; case CustomStatistic::TuneNoteblock: return 47;
case Statistic::UseCauldron: return 37; case CustomStatistic::UseCauldron: return 37;
case Statistic::WalkOneCm: return 5; case CustomStatistic::WalkOneCm: return 5;
case Statistic::WalkOnWaterOneCm: return 18; case CustomStatistic::WalkOnWaterOneCm: return 18;
case Statistic::WalkUnderWaterOneCm: return 12; case CustomStatistic::WalkUnderWaterOneCm: return 12;
default: return UInt32(-1); default: return UInt32(-1);
} }
} }

View File

@ -8,6 +8,6 @@ namespace Palette_1_13_1
{ {
UInt32 From(BlockState Block); UInt32 From(BlockState Block);
UInt32 From(Item ID); UInt32 From(Item ID);
UInt32 From(Statistic ID); UInt32 From(CustomStatistic ID);
Item ToItem(UInt32 ID); Item ToItem(UInt32 ID);
} }

View File

@ -9505,79 +9505,79 @@ namespace Palette_1_14
} }
} }
UInt32 From(const Statistic ID) UInt32 From(const CustomStatistic ID)
{ {
switch (ID) switch (ID)
{ {
case Statistic::AnimalsBred: return 30; case CustomStatistic::AnimalsBred: return 30;
case Statistic::AviateOneCm: return 17; case CustomStatistic::AviateOneCm: return 17;
case Statistic::BellRing: return 66; case CustomStatistic::BellRing: return 66;
case Statistic::BoatOneCm: return 14; case CustomStatistic::BoatOneCm: return 14;
case Statistic::CleanArmor: return 38; case CustomStatistic::CleanArmor: return 38;
case Statistic::CleanBanner: return 39; case CustomStatistic::CleanBanner: return 39;
case Statistic::CleanShulkerBox: return 40; case CustomStatistic::CleanShulkerBox: return 40;
case Statistic::ClimbOneCm: return 10; case CustomStatistic::ClimbOneCm: return 10;
case Statistic::CrouchOneCm: return 6; case CustomStatistic::CrouchOneCm: return 6;
case Statistic::DamageAbsorbed: return 26; case CustomStatistic::DamageAbsorbed: return 26;
case Statistic::DamageBlockedByShield: return 25; case CustomStatistic::DamageBlockedByShield: return 25;
case Statistic::DamageDealt: return 21; case CustomStatistic::DamageDealt: return 21;
case Statistic::DamageDealtAbsorbed: return 22; case CustomStatistic::DamageDealtAbsorbed: return 22;
case Statistic::DamageDealtResisted: return 23; case CustomStatistic::DamageDealtResisted: return 23;
case Statistic::DamageResisted: return 27; case CustomStatistic::DamageResisted: return 27;
case Statistic::DamageTaken: return 24; case CustomStatistic::DamageTaken: return 24;
case Statistic::Deaths: return 28; case CustomStatistic::Deaths: return 28;
case Statistic::Drop: return 20; case CustomStatistic::Drop: return 20;
case Statistic::EatCakeSlice: return 35; case CustomStatistic::EatCakeSlice: return 35;
case Statistic::EnchantItem: return 51; case CustomStatistic::EnchantItem: return 51;
case Statistic::FallOneCm: return 9; case CustomStatistic::FallOneCm: return 9;
case Statistic::FillCauldron: return 36; case CustomStatistic::FillCauldron: return 36;
case Statistic::FishCaught: return 32; case CustomStatistic::FishCaught: return 32;
case Statistic::FlyOneCm: return 11; case CustomStatistic::FlyOneCm: return 11;
case Statistic::HorseOneCm: return 16; case CustomStatistic::HorseOneCm: return 16;
case Statistic::InspectDispenser: return 45; case CustomStatistic::InspectDispenser: return 45;
case Statistic::InspectDropper: return 43; case CustomStatistic::InspectDropper: return 43;
case Statistic::InspectHopper: return 44; case CustomStatistic::InspectHopper: return 44;
case Statistic::InteractWithBeacon: return 42; case CustomStatistic::InteractWithBeacon: return 42;
case Statistic::InteractWithBlastFurnace: return 59; case CustomStatistic::InteractWithBlastFurnace: return 59;
case Statistic::InteractWithBrewingstand: return 41; case CustomStatistic::InteractWithBrewingstand: return 41;
case Statistic::InteractWithCampfire: return 62; case CustomStatistic::InteractWithCampfire: return 62;
case Statistic::InteractWithCartographyTable: return 63; case CustomStatistic::InteractWithCartographyTable: return 63;
case Statistic::InteractWithCraftingTable: return 54; case CustomStatistic::InteractWithCraftingTable: return 54;
case Statistic::InteractWithFurnace: return 53; case CustomStatistic::InteractWithFurnace: return 53;
case Statistic::InteractWithLectern: return 61; case CustomStatistic::InteractWithLectern: return 61;
case Statistic::InteractWithLoom: return 64; case CustomStatistic::InteractWithLoom: return 64;
case Statistic::InteractWithSmoker: return 60; case CustomStatistic::InteractWithSmoker: return 60;
case Statistic::InteractWithStonecutter: return 65; case CustomStatistic::InteractWithStonecutter: return 65;
case Statistic::Jump: return 19; case CustomStatistic::Jump: return 19;
case Statistic::LeaveGame: return 0; case CustomStatistic::LeaveGame: return 0;
case Statistic::MinecartOneCm: return 13; case CustomStatistic::MinecartOneCm: return 13;
case Statistic::MobKills: return 29; case CustomStatistic::MobKills: return 29;
case Statistic::OpenBarrel: return 58; case CustomStatistic::OpenBarrel: return 58;
case Statistic::OpenChest: return 55; case CustomStatistic::OpenChest: return 55;
case Statistic::OpenEnderchest: return 50; case CustomStatistic::OpenEnderchest: return 50;
case Statistic::OpenShulkerBox: return 57; case CustomStatistic::OpenShulkerBox: return 57;
case Statistic::PigOneCm: return 15; case CustomStatistic::PigOneCm: return 15;
case Statistic::PlayerKills: return 31; case CustomStatistic::PlayerKills: return 31;
case Statistic::PlayNoteblock: return 46; case CustomStatistic::PlayNoteblock: return 46;
case Statistic::PlayOneMinute: return 1; case CustomStatistic::PlayOneMinute: return 1;
case Statistic::PlayRecord: return 52; case CustomStatistic::PlayRecord: return 52;
case Statistic::PotFlower: return 48; case CustomStatistic::PotFlower: return 48;
case Statistic::RaidTrigger: return 67; case CustomStatistic::RaidTrigger: return 67;
case Statistic::RaidWin: return 68; case CustomStatistic::RaidWin: return 68;
case Statistic::SleepInBed: return 56; case CustomStatistic::SleepInBed: return 56;
case Statistic::SneakTime: return 4; case CustomStatistic::SneakTime: return 4;
case Statistic::SprintOneCm: return 7; case CustomStatistic::SprintOneCm: return 7;
case Statistic::SwimOneCm: return 18; case CustomStatistic::SwimOneCm: return 18;
case Statistic::TalkedToVillager: return 33; case CustomStatistic::TalkedToVillager: return 33;
case Statistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceDeath: return 2;
case Statistic::TimeSinceRest: return 3; case CustomStatistic::TimeSinceRest: return 3;
case Statistic::TradedWithVillager: return 34; case CustomStatistic::TradedWithVillager: return 34;
case Statistic::TriggerTrappedChest: return 49; case CustomStatistic::TriggerTrappedChest: return 49;
case Statistic::TuneNoteblock: return 47; case CustomStatistic::TuneNoteblock: return 47;
case Statistic::UseCauldron: return 37; case CustomStatistic::UseCauldron: return 37;
case Statistic::WalkOneCm: return 5; case CustomStatistic::WalkOneCm: return 5;
case Statistic::WalkOnWaterOneCm: return 8; case CustomStatistic::WalkOnWaterOneCm: return 8;
case Statistic::WalkUnderWaterOneCm: return 12; case CustomStatistic::WalkUnderWaterOneCm: return 12;
default: return static_cast<UInt32>(-1); default: return static_cast<UInt32>(-1);
} }
} }

View File

@ -8,6 +8,6 @@ namespace Palette_1_14
{ {
UInt32 From(BlockState Block); UInt32 From(BlockState Block);
UInt32 From(Item ID); UInt32 From(Item ID);
UInt32 From(Statistic ID); UInt32 From(CustomStatistic ID);
Item ToItem(UInt32 ID); Item ToItem(UInt32 ID);
} }

View File

@ -9578,81 +9578,81 @@ namespace Palette_1_15
} }
} }
UInt32 From(const Statistic ID) UInt32 From(const CustomStatistic ID)
{ {
switch (ID) switch (ID)
{ {
case Statistic::AnimalsBred: return 30; case CustomStatistic::AnimalsBred: return 30;
case Statistic::AviateOneCm: return 17; case CustomStatistic::AviateOneCm: return 17;
case Statistic::BellRing: return 66; case CustomStatistic::BellRing: return 66;
case Statistic::BoatOneCm: return 14; case CustomStatistic::BoatOneCm: return 14;
case Statistic::CleanArmor: return 38; case CustomStatistic::CleanArmor: return 38;
case Statistic::CleanBanner: return 39; case CustomStatistic::CleanBanner: return 39;
case Statistic::CleanShulkerBox: return 40; case CustomStatistic::CleanShulkerBox: return 40;
case Statistic::ClimbOneCm: return 10; case CustomStatistic::ClimbOneCm: return 10;
case Statistic::CrouchOneCm: return 6; case CustomStatistic::CrouchOneCm: return 6;
case Statistic::DamageAbsorbed: return 26; case CustomStatistic::DamageAbsorbed: return 26;
case Statistic::DamageBlockedByShield: return 25; case CustomStatistic::DamageBlockedByShield: return 25;
case Statistic::DamageDealt: return 21; case CustomStatistic::DamageDealt: return 21;
case Statistic::DamageDealtAbsorbed: return 22; case CustomStatistic::DamageDealtAbsorbed: return 22;
case Statistic::DamageDealtResisted: return 23; case CustomStatistic::DamageDealtResisted: return 23;
case Statistic::DamageResisted: return 27; case CustomStatistic::DamageResisted: return 27;
case Statistic::DamageTaken: return 24; case CustomStatistic::DamageTaken: return 24;
case Statistic::Deaths: return 28; case CustomStatistic::Deaths: return 28;
case Statistic::Drop: return 20; case CustomStatistic::Drop: return 20;
case Statistic::EatCakeSlice: return 35; case CustomStatistic::EatCakeSlice: return 35;
case Statistic::EnchantItem: return 51; case CustomStatistic::EnchantItem: return 51;
case Statistic::FallOneCm: return 9; case CustomStatistic::FallOneCm: return 9;
case Statistic::FillCauldron: return 36; case CustomStatistic::FillCauldron: return 36;
case Statistic::FishCaught: return 32; case CustomStatistic::FishCaught: return 32;
case Statistic::FlyOneCm: return 11; case CustomStatistic::FlyOneCm: return 11;
case Statistic::HorseOneCm: return 16; case CustomStatistic::HorseOneCm: return 16;
case Statistic::InspectDispenser: return 45; case CustomStatistic::InspectDispenser: return 45;
case Statistic::InspectDropper: return 43; case CustomStatistic::InspectDropper: return 43;
case Statistic::InspectHopper: return 44; case CustomStatistic::InspectHopper: return 44;
case Statistic::InteractWithAnvil: return 69; case CustomStatistic::InteractWithAnvil: return 69;
case Statistic::InteractWithBeacon: return 42; case CustomStatistic::InteractWithBeacon: return 42;
case Statistic::InteractWithBlastFurnace: return 59; case CustomStatistic::InteractWithBlastFurnace: return 59;
case Statistic::InteractWithBrewingstand: return 41; case CustomStatistic::InteractWithBrewingstand: return 41;
case Statistic::InteractWithCampfire: return 62; case CustomStatistic::InteractWithCampfire: return 62;
case Statistic::InteractWithCartographyTable: return 63; case CustomStatistic::InteractWithCartographyTable: return 63;
case Statistic::InteractWithCraftingTable: return 54; case CustomStatistic::InteractWithCraftingTable: return 54;
case Statistic::InteractWithFurnace: return 53; case CustomStatistic::InteractWithFurnace: return 53;
case Statistic::InteractWithGrindstone: return 70; case CustomStatistic::InteractWithGrindstone: return 70;
case Statistic::InteractWithLectern: return 61; case CustomStatistic::InteractWithLectern: return 61;
case Statistic::InteractWithLoom: return 64; case CustomStatistic::InteractWithLoom: return 64;
case Statistic::InteractWithSmoker: return 60; case CustomStatistic::InteractWithSmoker: return 60;
case Statistic::InteractWithStonecutter: return 65; case CustomStatistic::InteractWithStonecutter: return 65;
case Statistic::Jump: return 19; case CustomStatistic::Jump: return 19;
case Statistic::LeaveGame: return -0; case CustomStatistic::LeaveGame: return -0;
case Statistic::MinecartOneCm: return 13; case CustomStatistic::MinecartOneCm: return 13;
case Statistic::MobKills: return 29; case CustomStatistic::MobKills: return 29;
case Statistic::OpenBarrel: return 58; case CustomStatistic::OpenBarrel: return 58;
case Statistic::OpenChest: return 55; case CustomStatistic::OpenChest: return 55;
case Statistic::OpenEnderchest: return 50; case CustomStatistic::OpenEnderchest: return 50;
case Statistic::OpenShulkerBox: return 57; case CustomStatistic::OpenShulkerBox: return 57;
case Statistic::PigOneCm: return 15; case CustomStatistic::PigOneCm: return 15;
case Statistic::PlayNoteblock: return 46; case CustomStatistic::PlayNoteblock: return 46;
case Statistic::PlayOneMinute: return 1; case CustomStatistic::PlayOneMinute: return 1;
case Statistic::PlayRecord: return 52; case CustomStatistic::PlayRecord: return 52;
case Statistic::PlayerKills: return 31; case CustomStatistic::PlayerKills: return 31;
case Statistic::PotFlower: return 48; case CustomStatistic::PotFlower: return 48;
case Statistic::RaidTrigger: return 67; case CustomStatistic::RaidTrigger: return 67;
case Statistic::RaidWin: return 68; case CustomStatistic::RaidWin: return 68;
case Statistic::SleepInBed: return 56; case CustomStatistic::SleepInBed: return 56;
case Statistic::SneakTime: return 4; case CustomStatistic::SneakTime: return 4;
case Statistic::SprintOneCm: return 7; case CustomStatistic::SprintOneCm: return 7;
case Statistic::SwimOneCm: return 18; case CustomStatistic::SwimOneCm: return 18;
case Statistic::TalkedToVillager: return 33; case CustomStatistic::TalkedToVillager: return 33;
case Statistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceDeath: return 2;
case Statistic::TimeSinceRest: return 3; case CustomStatistic::TimeSinceRest: return 3;
case Statistic::TradedWithVillager: return 34; case CustomStatistic::TradedWithVillager: return 34;
case Statistic::TriggerTrappedChest: return 49; case CustomStatistic::TriggerTrappedChest: return 49;
case Statistic::TuneNoteblock: return 47; case CustomStatistic::TuneNoteblock: return 47;
case Statistic::UseCauldron: return 37; case CustomStatistic::UseCauldron: return 37;
case Statistic::WalkOnWaterOneCm: return 8; case CustomStatistic::WalkOnWaterOneCm: return 8;
case Statistic::WalkOneCm: return 5; case CustomStatistic::WalkOneCm: return 5;
case Statistic::WalkUnderWaterOneCm: return 12; case CustomStatistic::WalkUnderWaterOneCm: return 12;
default: return UInt32(-1); default: return UInt32(-1);
} }
} }

View File

@ -8,6 +8,6 @@ namespace Palette_1_15
{ {
UInt32 From(BlockState Block); UInt32 From(BlockState Block);
UInt32 From(Item ID); UInt32 From(Item ID);
UInt32 From(Statistic ID); UInt32 From(CustomStatistic ID);
Item ToItem(UInt32 ID); Item ToItem(UInt32 ID);
} }

View File

@ -12762,84 +12762,84 @@ namespace Palette_1_16
UNREACHABLE("Invalid item"); UNREACHABLE("Invalid item");
} }
UInt32 From(const Statistic ID) UInt32 From(const CustomStatistic ID)
{ {
switch (ID) switch (ID)
{ {
case Statistic::AnimalsBred: return 31; case CustomStatistic::AnimalsBred: return 31;
case Statistic::AviateOneCm: return 17; case CustomStatistic::AviateOneCm: return 17;
case Statistic::BellRing: return 67; case CustomStatistic::BellRing: return 67;
case Statistic::BoatOneCm: return 14; case CustomStatistic::BoatOneCm: return 14;
case Statistic::CleanArmor: return 39; case CustomStatistic::CleanArmor: return 39;
case Statistic::CleanBanner: return 40; case CustomStatistic::CleanBanner: return 40;
case Statistic::CleanShulkerBox: return 41; case CustomStatistic::CleanShulkerBox: return 41;
case Statistic::ClimbOneCm: return 10; case CustomStatistic::ClimbOneCm: return 10;
case Statistic::CrouchOneCm: return 6; case CustomStatistic::CrouchOneCm: return 6;
case Statistic::DamageAbsorbed: return 27; case CustomStatistic::DamageAbsorbed: return 27;
case Statistic::DamageBlockedByShield: return 26; case CustomStatistic::DamageBlockedByShield: return 26;
case Statistic::DamageDealt: return 22; case CustomStatistic::DamageDealt: return 22;
case Statistic::DamageDealtAbsorbed: return 23; case CustomStatistic::DamageDealtAbsorbed: return 23;
case Statistic::DamageDealtResisted: return 24; case CustomStatistic::DamageDealtResisted: return 24;
case Statistic::DamageResisted: return 28; case CustomStatistic::DamageResisted: return 28;
case Statistic::DamageTaken: return 25; case CustomStatistic::DamageTaken: return 25;
case Statistic::Deaths: return 29; case CustomStatistic::Deaths: return 29;
case Statistic::Drop: return 21; case CustomStatistic::Drop: return 21;
case Statistic::EatCakeSlice: return 36; case CustomStatistic::EatCakeSlice: return 36;
case Statistic::EnchantItem: return 52; case CustomStatistic::EnchantItem: return 52;
case Statistic::FallOneCm: return 9; case CustomStatistic::FallOneCm: return 9;
case Statistic::FillCauldron: return 37; case CustomStatistic::FillCauldron: return 37;
case Statistic::FishCaught: return 33; case CustomStatistic::FishCaught: return 33;
case Statistic::FlyOneCm: return 11; case CustomStatistic::FlyOneCm: return 11;
case Statistic::HorseOneCm: return 16; case CustomStatistic::HorseOneCm: return 16;
case Statistic::InspectDispenser: return 46; case CustomStatistic::InspectDispenser: return 46;
case Statistic::InspectDropper: return 44; case CustomStatistic::InspectDropper: return 44;
case Statistic::InspectHopper: return 45; case CustomStatistic::InspectHopper: return 45;
case Statistic::InteractWithAnvil: return 70; case CustomStatistic::InteractWithAnvil: return 70;
case Statistic::InteractWithBeacon: return 43; case CustomStatistic::InteractWithBeacon: return 43;
case Statistic::InteractWithBlastFurnace: return 60; case CustomStatistic::InteractWithBlastFurnace: return 60;
case Statistic::InteractWithBrewingstand: return 42; case CustomStatistic::InteractWithBrewingstand: return 42;
case Statistic::InteractWithCampfire: return 63; case CustomStatistic::InteractWithCampfire: return 63;
case Statistic::InteractWithCartographyTable: return 64; case CustomStatistic::InteractWithCartographyTable: return 64;
case Statistic::InteractWithCraftingTable: return 55; case CustomStatistic::InteractWithCraftingTable: return 55;
case Statistic::InteractWithFurnace: return 54; case CustomStatistic::InteractWithFurnace: return 54;
case Statistic::InteractWithGrindstone: return 71; case CustomStatistic::InteractWithGrindstone: return 71;
case Statistic::InteractWithLectern: return 62; case CustomStatistic::InteractWithLectern: return 62;
case Statistic::InteractWithLoom: return 65; case CustomStatistic::InteractWithLoom: return 65;
case Statistic::InteractWithSmithingTable: return 73; case CustomStatistic::InteractWithSmithingTable: return 73;
case Statistic::InteractWithSmoker: return 61; case CustomStatistic::InteractWithSmoker: return 61;
case Statistic::InteractWithStonecutter: return 66; case CustomStatistic::InteractWithStonecutter: return 66;
case Statistic::Jump: return 20; case CustomStatistic::Jump: return 20;
case Statistic::LeaveGame: return -0; case CustomStatistic::LeaveGame: return -0;
case Statistic::MinecartOneCm: return 13; case CustomStatistic::MinecartOneCm: return 13;
case Statistic::MobKills: return 30; case CustomStatistic::MobKills: return 30;
case Statistic::OpenBarrel: return 59; case CustomStatistic::OpenBarrel: return 59;
case Statistic::OpenChest: return 56; case CustomStatistic::OpenChest: return 56;
case Statistic::OpenEnderchest: return 51; case CustomStatistic::OpenEnderchest: return 51;
case Statistic::OpenShulkerBox: return 58; case CustomStatistic::OpenShulkerBox: return 58;
case Statistic::PigOneCm: return 15; case CustomStatistic::PigOneCm: return 15;
case Statistic::PlayNoteblock: return 47; case CustomStatistic::PlayNoteblock: return 47;
case Statistic::PlayOneMinute: return 1; case CustomStatistic::PlayOneMinute: return 1;
case Statistic::PlayRecord: return 53; case CustomStatistic::PlayRecord: return 53;
case Statistic::PlayerKills: return 32; case CustomStatistic::PlayerKills: return 32;
case Statistic::PotFlower: return 49; case CustomStatistic::PotFlower: return 49;
case Statistic::RaidTrigger: return 68; case CustomStatistic::RaidTrigger: return 68;
case Statistic::RaidWin: return 69; case CustomStatistic::RaidWin: return 69;
case Statistic::SleepInBed: return 57; case CustomStatistic::SleepInBed: return 57;
case Statistic::SneakTime: return 4; case CustomStatistic::SneakTime: return 4;
case Statistic::SprintOneCm: return 7; case CustomStatistic::SprintOneCm: return 7;
case Statistic::StriderOneCm: return 19; case CustomStatistic::StriderOneCm: return 19;
case Statistic::SwimOneCm: return 18; case CustomStatistic::SwimOneCm: return 18;
case Statistic::TalkedToVillager: return 34; case CustomStatistic::TalkedToVillager: return 34;
case Statistic::TargetHit: return 72; case CustomStatistic::TargetHit: return 72;
case Statistic::TimeSinceDeath: return 2; case CustomStatistic::TimeSinceDeath: return 2;
case Statistic::TimeSinceRest: return 3; case CustomStatistic::TimeSinceRest: return 3;
case Statistic::TradedWithVillager: return 35; case CustomStatistic::TradedWithVillager: return 35;
case Statistic::TriggerTrappedChest: return 50; case CustomStatistic::TriggerTrappedChest: return 50;
case Statistic::TuneNoteblock: return 48; case CustomStatistic::TuneNoteblock: return 48;
case Statistic::UseCauldron: return 38; case CustomStatistic::UseCauldron: return 38;
case Statistic::WalkOnWaterOneCm: return 8; case CustomStatistic::WalkOnWaterOneCm: return 8;
case Statistic::WalkOneCm: return 5; case CustomStatistic::WalkOneCm: return 5;
case Statistic::WalkUnderWaterOneCm: return 12; case CustomStatistic::WalkUnderWaterOneCm: return 12;
default: return UInt32(-1); default: return UInt32(-1);
} }
} }

View File

@ -8,6 +8,6 @@ namespace Palette_1_16
{ {
UInt32 From(BlockState Block); UInt32 From(BlockState Block);
UInt32 From(Item ID); UInt32 From(Item ID);
UInt32 From(Statistic ID); UInt32 From(CustomStatistic ID);
Item ToItem(UInt32 ID); Item ToItem(UInt32 ID);
} }

View File

@ -29,9 +29,10 @@ class cPainting;
class cWorld; class cWorld;
class cMonster; class cMonster;
class cCompositeChat; class cCompositeChat;
class cStatManager;
class cPacketizer; class cPacketizer;
struct StatisticsManager;
@ -422,7 +423,7 @@ public:
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0; virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) = 0;
virtual void SendSpawnEntity (const cEntity & a_Entity) = 0; virtual void SendSpawnEntity (const cEntity & a_Entity) = 0;
virtual void SendSpawnMob (const cMonster & a_Mob) = 0; virtual void SendSpawnMob (const cMonster & a_Mob) = 0;
virtual void SendStatistics (const cStatManager & a_Manager) = 0; virtual void SendStatistics (const StatisticsManager & a_Manager) = 0;
virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0; virtual void SendTabCompletionResults (const AStringVector & a_Results) = 0;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) = 0;
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0; virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) = 0;

View File

@ -142,24 +142,22 @@ void cProtocol_1_13::SendScoreboardObjective(const AString & a_Name, const AStri
void cProtocol_1_13::SendStatistics(const cStatManager & a_Manager) void cProtocol_1_13::SendStatistics(const StatisticsManager & a_Manager)
{ {
ASSERT(m_State == 3); // In game mode? ASSERT(m_State == 3); // In game mode?
UInt32 Size = 0; UInt32 Size = 0;
a_Manager.ForEachStatisticType([this, &Size](const auto & Store)
{
for (const auto & Item : Store)
{
// Client balks at out-of-range values so there is no good default value
// We're forced to not send the statistics this protocol version doesn't support
if (GetProtocolStatisticType(Item.first) != static_cast<UInt32>(-1)) for (const auto & [Statistic, Value] : a_Manager.Custom)
{ {
Size++; // Client balks at out-of-range values so there is no good default value.
} // We're forced to not send the statistics this protocol version doesn't support.
if (GetProtocolStatisticType(Statistic) != static_cast<UInt32>(-1))
{
Size++;
} }
}); }
// No need to check Size != 0 // No need to check Size != 0
// Assume that the vast majority of the time there's at least one statistic to send // Assume that the vast majority of the time there's at least one statistic to send
@ -167,22 +165,19 @@ void cProtocol_1_13::SendStatistics(const cStatManager & a_Manager)
cPacketizer Pkt(*this, pktStatistics); cPacketizer Pkt(*this, pktStatistics);
Pkt.WriteVarInt32(Size); Pkt.WriteVarInt32(Size);
a_Manager.ForEachStatisticType([this, &Pkt](const cStatManager::CustomStore & Store) for (const auto & [Statistic, Value] : a_Manager.Custom)
{ {
for (const auto & Item : Store) const auto ID = GetProtocolStatisticType(Statistic);
if (ID == static_cast<UInt32>(-1))
{ {
const auto ID = GetProtocolStatisticType(Item.first); // Unsupported, don't send:
if (ID == static_cast<UInt32>(-1)) continue;
{
// Unsupported, don't send:
continue;
}
Pkt.WriteVarInt32(8); // "Custom" category
Pkt.WriteVarInt32(ID);
Pkt.WriteVarInt32(static_cast<UInt32>(Item.second));
} }
});
Pkt.WriteVarInt32(8); // "Custom" category.
Pkt.WriteVarInt32(ID);
Pkt.WriteVarInt32(static_cast<UInt32>(Value));
}
} }
@ -588,7 +583,7 @@ UInt32 cProtocol_1_13::GetProtocolMobType(eMonsterType a_MobType) const
UInt32 cProtocol_1_13::GetProtocolStatisticType(Statistic a_Statistic) const UInt32 cProtocol_1_13::GetProtocolStatisticType(const CustomStatistic a_Statistic) const
{ {
return Palette_1_13::From(a_Statistic); return Palette_1_13::From(a_Statistic);
} }
@ -1480,7 +1475,7 @@ UInt32 cProtocol_1_13_1::GetProtocolItemType(short a_ItemID, short a_ItemDamage)
UInt32 cProtocol_1_13_1::GetProtocolStatisticType(Statistic a_Statistic) const UInt32 cProtocol_1_13_1::GetProtocolStatisticType(const CustomStatistic a_Statistic) const
{ {
return Palette_1_13_1::From(a_Statistic); return Palette_1_13_1::From(a_Statistic);
} }

View File

@ -42,7 +42,7 @@ protected:
virtual void SendPaintingSpawn (const cPainting & a_Painting) override; virtual void SendPaintingSpawn (const cPainting & a_Painting) override;
virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override; virtual void SendParticleEffect (const AString & a_ParticleName, Vector3f a_Src, Vector3f a_Offset, float a_ParticleData, int a_ParticleAmount, std::array<int, 2> a_Data) override;
virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override; virtual void SendScoreboardObjective (const AString & a_Name, const AString & a_DisplayName, Byte a_Mode) override;
virtual void SendStatistics (const cStatManager & a_Manager) override; virtual void SendStatistics (const StatisticsManager & a_Manager) override;
virtual void SendTabCompletionResults (const AStringVector & a_Results) override; virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override; virtual void SendUpdateBlockEntity (cBlockEntity & a_BlockEntity) override;
virtual UInt8 GetEntityMetadataID(EntityMetadata a_Metadata) const; virtual UInt8 GetEntityMetadataID(EntityMetadata a_Metadata) const;
@ -53,7 +53,7 @@ protected:
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const; virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const;
virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override; virtual UInt32 GetProtocolMobType(eMonsterType a_MobType) const override;
virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) const; virtual UInt32 GetProtocolStatisticType(CustomStatistic a_Statistic) const;
virtual Version GetProtocolVersion() const override; virtual Version GetProtocolVersion() const override;
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;
@ -88,7 +88,7 @@ protected:
virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) const override; virtual std::pair<short, short> GetItemFromProtocolID(UInt32 a_ProtocolID) const override;
virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override; virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override;
virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override; virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override;
virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) const override; virtual UInt32 GetProtocolStatisticType(CustomStatistic a_Statistic) const override;
virtual Version GetProtocolVersion() const override; virtual Version GetProtocolVersion() const override;
}; };

View File

@ -238,7 +238,7 @@ UInt32 cProtocol_1_14::GetProtocolItemType(short a_ItemID, short a_ItemDamage) c
UInt32 cProtocol_1_14::GetProtocolStatisticType(Statistic a_Statistic) const UInt32 cProtocol_1_14::GetProtocolStatisticType(const CustomStatistic a_Statistic) const
{ {
return Palette_1_14::From(a_Statistic); return Palette_1_14::From(a_Statistic);
} }

View File

@ -45,7 +45,7 @@ protected:
virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override; virtual UInt32 GetProtocolBlockType(BLOCKTYPE a_BlockType, NIBBLETYPE a_Meta) const override;
virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override; virtual signed char GetProtocolEntityStatus(EntityAnimation a_Animation) const override;
virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override; virtual UInt32 GetProtocolItemType(short a_ItemID, short a_ItemDamage) const override;
virtual UInt32 GetProtocolStatisticType(Statistic a_Statistic) const override; virtual UInt32 GetProtocolStatisticType(CustomStatistic a_Statistic) const override;
virtual Version GetProtocolVersion() const override; virtual Version GetProtocolVersion() const override;
virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override; virtual bool HandlePacket(cByteBuffer & a_ByteBuffer, UInt32 a_PacketType) override;

View File

@ -1458,30 +1458,21 @@ void cProtocol_1_8_0::SendSpawnMob(const cMonster & a_Mob)
void cProtocol_1_8_0::SendStatistics(const cStatManager & a_Manager) void cProtocol_1_8_0::SendStatistics(const StatisticsManager & a_Manager)
{ {
ASSERT(m_State == 3); // In game mode? ASSERT(m_State == 3); // In game mode?
UInt32 Size = 0;
a_Manager.ForEachStatisticType([&Size](const auto & Store)
{
Size += static_cast<UInt32>(Store.size());
});
// No need to check Size != 0
// Assume that the vast majority of the time there's at least one statistic to send
cPacketizer Pkt(*this, pktStatistics); cPacketizer Pkt(*this, pktStatistics);
Pkt.WriteVarInt32(Size);
a_Manager.ForEachStatisticType([&Pkt](const cStatManager::CustomStore & Store) // No need to check Size != 0.
// Assume that the vast majority of the time there's at least one statistic to send:
Pkt.WriteVarInt32(static_cast<UInt32>(a_Manager.Custom.size()));
for (const auto & [Statistic, Value] : a_Manager.Custom)
{ {
for (const auto & Item : Store) Pkt.WriteString(GetProtocolStatisticName(Statistic));
{ Pkt.WriteVarInt32(static_cast<UInt32>(Value));
Pkt.WriteString(GetProtocolStatisticName(Item.first)); }
Pkt.WriteVarInt32(static_cast<UInt32>(Item.second));
}
});
} }
@ -2401,15 +2392,13 @@ void cProtocol_1_8_0::HandlePacketClientStatus(cByteBuffer & a_ByteBuffer)
case 1: case 1:
{ {
// Request stats // Request stats
const cStatManager & Manager = m_Client->GetPlayer()->GetStatManager(); SendStatistics(m_Client->GetPlayer()->GetStatistics());
SendStatistics(Manager);
break; break;
} }
case 2: case 2:
{ {
// Open Inventory achievement // Open Inventory achievement
m_Client->GetPlayer()->AwardAchievement(Statistic::AchOpenInventory); m_Client->GetPlayer()->AwardAchievement(CustomStatistic::AchOpenInventory);
break; break;
} }
} }
@ -4042,99 +4031,99 @@ int cProtocol_1_8_0::GetProtocolParticleID(const AString & a_ParticleName)
const char * cProtocol_1_8_0::GetProtocolStatisticName(Statistic a_Statistic) const char * cProtocol_1_8_0::GetProtocolStatisticName(const CustomStatistic a_Statistic)
{ {
switch (a_Statistic) switch (a_Statistic)
{ {
// V1.8 Achievements // V1.8 Achievements
case Statistic::AchOpenInventory: return "achievement.openInventory"; case CustomStatistic::AchOpenInventory: return "achievement.openInventory";
case Statistic::AchMineWood: return "achievement.mineWood"; case CustomStatistic::AchMineWood: return "achievement.mineWood";
case Statistic::AchBuildWorkBench: return "achievement.buildWorkBench"; case CustomStatistic::AchBuildWorkBench: return "achievement.buildWorkBench";
case Statistic::AchBuildPickaxe: return "achievement.buildPickaxe"; case CustomStatistic::AchBuildPickaxe: return "achievement.buildPickaxe";
case Statistic::AchBuildFurnace: return "achievement.buildFurnace"; case CustomStatistic::AchBuildFurnace: return "achievement.buildFurnace";
case Statistic::AchAcquireIron: return "achievement.acquireIron"; case CustomStatistic::AchAcquireIron: return "achievement.acquireIron";
case Statistic::AchBuildHoe: return "achievement.buildHoe"; case CustomStatistic::AchBuildHoe: return "achievement.buildHoe";
case Statistic::AchMakeBread: return "achievement.makeBread"; case CustomStatistic::AchMakeBread: return "achievement.makeBread";
case Statistic::AchBakeCake: return "achievement.bakeCake"; case CustomStatistic::AchBakeCake: return "achievement.bakeCake";
case Statistic::AchBuildBetterPickaxe: return "achievement.buildBetterPickaxe"; case CustomStatistic::AchBuildBetterPickaxe: return "achievement.buildBetterPickaxe";
case Statistic::AchCookFish: return "achievement.cookFish"; case CustomStatistic::AchCookFish: return "achievement.cookFish";
case Statistic::AchOnARail: return "achievement.onARail"; case CustomStatistic::AchOnARail: return "achievement.onARail";
case Statistic::AchBuildSword: return "achievement.buildSword"; case CustomStatistic::AchBuildSword: return "achievement.buildSword";
case Statistic::AchKillEnemy: return "achievement.killEnemy"; case CustomStatistic::AchKillEnemy: return "achievement.killEnemy";
case Statistic::AchKillCow: return "achievement.killCow"; case CustomStatistic::AchKillCow: return "achievement.killCow";
case Statistic::AchFlyPig: return "achievement.flyPig"; case CustomStatistic::AchFlyPig: return "achievement.flyPig";
case Statistic::AchSnipeSkeleton: return "achievement.snipeSkeleton"; case CustomStatistic::AchSnipeSkeleton: return "achievement.snipeSkeleton";
case Statistic::AchDiamonds: return "achievement.diamonds"; case CustomStatistic::AchDiamonds: return "achievement.diamonds";
case Statistic::AchPortal: return "achievement.portal"; case CustomStatistic::AchPortal: return "achievement.portal";
case Statistic::AchGhast: return "achievement.ghast"; case CustomStatistic::AchGhast: return "achievement.ghast";
case Statistic::AchBlazeRod: return "achievement.blazeRod"; case CustomStatistic::AchBlazeRod: return "achievement.blazeRod";
case Statistic::AchPotion: return "achievement.potion"; case CustomStatistic::AchPotion: return "achievement.potion";
case Statistic::AchTheEnd: return "achievement.theEnd"; case CustomStatistic::AchTheEnd: return "achievement.theEnd";
case Statistic::AchTheEnd2: return "achievement.theEnd2"; case CustomStatistic::AchTheEnd2: return "achievement.theEnd2";
case Statistic::AchEnchantments: return "achievement.enchantments"; case CustomStatistic::AchEnchantments: return "achievement.enchantments";
case Statistic::AchOverkill: return "achievement.overkill"; case CustomStatistic::AchOverkill: return "achievement.overkill";
case Statistic::AchBookcase: return "achievement.bookcase"; case CustomStatistic::AchBookcase: return "achievement.bookcase";
case Statistic::AchExploreAllBiomes: return "achievement.exploreAllBiomes"; case CustomStatistic::AchExploreAllBiomes: return "achievement.exploreAllBiomes";
case Statistic::AchSpawnWither: return "achievement.spawnWither"; case CustomStatistic::AchSpawnWither: return "achievement.spawnWither";
case Statistic::AchKillWither: return "achievement.killWither"; case CustomStatistic::AchKillWither: return "achievement.killWither";
case Statistic::AchFullBeacon: return "achievement.fullBeacon"; case CustomStatistic::AchFullBeacon: return "achievement.fullBeacon";
case Statistic::AchBreedCow: return "achievement.breedCow"; case CustomStatistic::AchBreedCow: return "achievement.breedCow";
case Statistic::AchDiamondsToYou: return "achievement.diamondsToYou"; case CustomStatistic::AchDiamondsToYou: return "achievement.diamondsToYou";
// V1.8 stats // V1.8 stats
case Statistic::AnimalsBred: return "stat.animalsBred"; case CustomStatistic::AnimalsBred: return "stat.animalsBred";
case Statistic::BoatOneCm: return "stat.boatOneCm"; case CustomStatistic::BoatOneCm: return "stat.boatOneCm";
case Statistic::ClimbOneCm: return "stat.climbOneCm"; case CustomStatistic::ClimbOneCm: return "stat.climbOneCm";
case Statistic::CrouchOneCm: return "stat.crouchOneCm"; case CustomStatistic::CrouchOneCm: return "stat.crouchOneCm";
case Statistic::DamageDealt: return "stat.damageDealt"; case CustomStatistic::DamageDealt: return "stat.damageDealt";
case Statistic::DamageTaken: return "stat.damageTaken"; case CustomStatistic::DamageTaken: return "stat.damageTaken";
case Statistic::Deaths: return "stat.deaths"; case CustomStatistic::Deaths: return "stat.deaths";
case Statistic::Drop: return "stat.drop"; case CustomStatistic::Drop: return "stat.drop";
case Statistic::FallOneCm: return "stat.fallOneCm"; case CustomStatistic::FallOneCm: return "stat.fallOneCm";
case Statistic::FishCaught: return "stat.fishCaught"; case CustomStatistic::FishCaught: return "stat.fishCaught";
case Statistic::FlyOneCm: return "stat.flyOneCm"; case CustomStatistic::FlyOneCm: return "stat.flyOneCm";
case Statistic::HorseOneCm: return "stat.horseOneCm"; case CustomStatistic::HorseOneCm: return "stat.horseOneCm";
case Statistic::Jump: return "stat.jump"; case CustomStatistic::Jump: return "stat.jump";
case Statistic::LeaveGame: return "stat.leaveGame"; case CustomStatistic::LeaveGame: return "stat.leaveGame";
case Statistic::MinecartOneCm: return "stat.minecartOneCm"; case CustomStatistic::MinecartOneCm: return "stat.minecartOneCm";
case Statistic::MobKills: return "stat.mobKills"; case CustomStatistic::MobKills: return "stat.mobKills";
case Statistic::PigOneCm: return "stat.pigOneCm"; case CustomStatistic::PigOneCm: return "stat.pigOneCm";
case Statistic::PlayerKills: return "stat.playerKills"; case CustomStatistic::PlayerKills: return "stat.playerKills";
case Statistic::PlayOneMinute: return "stat.playOneMinute"; case CustomStatistic::PlayOneMinute: return "stat.playOneMinute";
case Statistic::SprintOneCm: return "stat.sprintOneCm"; case CustomStatistic::SprintOneCm: return "stat.sprintOneCm";
case Statistic::SwimOneCm: return "stat.swimOneCm"; case CustomStatistic::SwimOneCm: return "stat.swimOneCm";
case Statistic::TalkedToVillager: return "stat.talkedToVillager"; case CustomStatistic::TalkedToVillager: return "stat.talkedToVillager";
case Statistic::TimeSinceDeath: return "stat.timeSinceDeath"; case CustomStatistic::TimeSinceDeath: return "stat.timeSinceDeath";
case Statistic::TradedWithVillager: return "stat.tradedWithVillager"; case CustomStatistic::TradedWithVillager: return "stat.tradedWithVillager";
case Statistic::WalkOneCm: return "stat.walkOneCm"; case CustomStatistic::WalkOneCm: return "stat.walkOneCm";
case Statistic::WalkUnderWaterOneCm: return "stat.diveOneCm"; case CustomStatistic::WalkUnderWaterOneCm: return "stat.diveOneCm";
// V1.8.2 stats // V1.8.2 stats
case Statistic::CleanArmor: return "stat.armorCleaned"; case CustomStatistic::CleanArmor: return "stat.armorCleaned";
case Statistic::CleanBanner: return "stat.bannerCleaned"; case CustomStatistic::CleanBanner: return "stat.bannerCleaned";
case Statistic::EatCakeSlice: return "stat.cakeSlicesEaten"; case CustomStatistic::EatCakeSlice: return "stat.cakeSlicesEaten";
case Statistic::EnchantItem: return "stat.itemEnchanted"; case CustomStatistic::EnchantItem: return "stat.itemEnchanted";
case Statistic::FillCauldron: return "stat.cauldronFilled"; case CustomStatistic::FillCauldron: return "stat.cauldronFilled";
case Statistic::InspectDispenser: return "stat.dispenserInspected"; case CustomStatistic::InspectDispenser: return "stat.dispenserInspected";
case Statistic::InspectDropper: return "stat.dropperInspected"; case CustomStatistic::InspectDropper: return "stat.dropperInspected";
case Statistic::InspectHopper: return "stat.hopperInspected"; case CustomStatistic::InspectHopper: return "stat.hopperInspected";
case Statistic::InteractWithBeacon: return "stat.beaconInteraction"; case CustomStatistic::InteractWithBeacon: return "stat.beaconInteraction";
case Statistic::InteractWithBrewingstand: return "stat.brewingstandInteraction"; case CustomStatistic::InteractWithBrewingstand: return "stat.brewingstandInteraction";
case Statistic::InteractWithCraftingTable: return "stat.craftingTableInteraction"; case CustomStatistic::InteractWithCraftingTable: return "stat.craftingTableInteraction";
case Statistic::InteractWithFurnace: return "stat.furnaceInteraction"; case CustomStatistic::InteractWithFurnace: return "stat.furnaceInteraction";
case Statistic::OpenChest: return "stat.chestOpened"; case CustomStatistic::OpenChest: return "stat.chestOpened";
case Statistic::OpenEnderchest: return "stat.enderchestOpened"; case CustomStatistic::OpenEnderchest: return "stat.enderchestOpened";
case Statistic::PlayNoteblock: return "stat.noteblockPlayed"; case CustomStatistic::PlayNoteblock: return "stat.noteblockPlayed";
case Statistic::PlayRecord: return "stat.recordPlayed"; case CustomStatistic::PlayRecord: return "stat.recordPlayed";
case Statistic::PotFlower: return "stat.flowerPotted"; case CustomStatistic::PotFlower: return "stat.flowerPotted";
case Statistic::TriggerTrappedChest: return "stat.trappedChestTriggered"; case CustomStatistic::TriggerTrappedChest: return "stat.trappedChestTriggered";
case Statistic::TuneNoteblock: return "stat.noteblockTuned"; case CustomStatistic::TuneNoteblock: return "stat.noteblockTuned";
case Statistic::UseCauldron: return "stat.cauldronUsed"; case CustomStatistic::UseCauldron: return "stat.cauldronUsed";
// V1.9 stats // V1.9 stats
case Statistic::AviateOneCm: return "stat.aviateOneCm"; case CustomStatistic::AviateOneCm: return "stat.aviateOneCm";
case Statistic::SleepInBed: return "stat.sleepInBed"; case CustomStatistic::SleepInBed: return "stat.sleepInBed";
case Statistic::SneakTime: return "stat.sneakTime"; case CustomStatistic::SneakTime: return "stat.sneakTime";
default: return ""; default: return "";
} }
} }

View File

@ -113,7 +113,7 @@ public:
virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override; virtual void SendSoundParticleEffect (const EffectID a_EffectID, int a_SrcX, int a_SrcY, int a_SrcZ, int a_Data) override;
virtual void SendSpawnEntity (const cEntity & a_Entity) override; virtual void SendSpawnEntity (const cEntity & a_Entity) override;
virtual void SendSpawnMob (const cMonster & a_Mob) override; virtual void SendSpawnMob (const cMonster & a_Mob) override;
virtual void SendStatistics (const cStatManager & a_Manager) override; virtual void SendStatistics (const StatisticsManager & a_Manager) override;
virtual void SendTabCompletionResults (const AStringVector & a_Results) override; virtual void SendTabCompletionResults (const AStringVector & a_Results) override;
virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override; virtual void SendThunderbolt (int a_BlockX, int a_BlockY, int a_BlockZ) override;
virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override; virtual void SendTitleTimes (int a_FadeInTicks, int a_DisplayTicks, int a_FadeOutTicks) override;
@ -267,7 +267,7 @@ private:
/** Converts a statistic to a protocol-specific string. /** Converts a statistic to a protocol-specific string.
Protocols <= 1.12 use strings, hence this is a static as the string-mapping was append-only for the versions that used it. Protocols <= 1.12 use strings, hence this is a static as the string-mapping was append-only for the versions that used it.
Returns an empty string, handled correctly by the client, for newer, unsupported statistics. */ Returns an empty string, handled correctly by the client, for newer, unsupported statistics. */
static const char * GetProtocolStatisticName(Statistic a_Statistic); static const char * GetProtocolStatisticName(CustomStatistic a_Statistic);
/** Handle a complete packet stored in the given buffer. */ /** Handle a complete packet stored in the given buffer. */
void HandlePacket(cByteBuffer & a_Buffer); void HandlePacket(cByteBuffer & a_Buffer);

View File

@ -1,7 +1,10 @@
#pragma once #pragma once
enum class Statistic // tolua_begin
enum class CustomStatistic
{ {
// tolua_end
/* Achievements */ /* Achievements */
AchOpenInventory, /* Taking Inventory */ AchOpenInventory, /* Taking Inventory */
AchMineWood, /* Getting Wood */ AchMineWood, /* Getting Wood */
@ -37,6 +40,8 @@ enum class Statistic
AchBreedCow, /* Repopulation */ AchBreedCow, /* Repopulation */
AchDiamondsToYou, /* Diamonds to you! */ AchDiamondsToYou, /* Diamonds to you! */
// tolua_begin
/* Statistics */ /* Statistics */
AnimalsBred, AnimalsBred,
AviateOneCm, AviateOneCm,
@ -117,3 +122,4 @@ enum class Statistic
JunkFished, JunkFished,
TreasureFished, TreasureFished,
}; };
// tolua_end

View File

@ -9,61 +9,43 @@
void cStatManager::SetValue(const Statistic a_Stat, const StatValue a_Value) bool StatisticsManager::SatisfiesPrerequisite(const CustomStatistic a_Stat) const
{
m_CustomStatistics[a_Stat] = a_Value;
}
cStatManager::StatValue cStatManager::AddValue(const Statistic a_Stat, const StatValue a_Delta)
{
return m_CustomStatistics[a_Stat] += a_Delta;
}
bool cStatManager::SatisfiesPrerequisite(const Statistic a_Stat)
{ {
switch (a_Stat) switch (a_Stat)
{ {
case Statistic::AchMineWood: return IsStatisticPresent(Statistic::AchOpenInventory); case CustomStatistic::AchMineWood: return IsStatisticPresent(CustomStatistic::AchOpenInventory);
case Statistic::AchBuildWorkBench: return IsStatisticPresent(Statistic::AchMineWood); case CustomStatistic::AchBuildWorkBench: return IsStatisticPresent(CustomStatistic::AchMineWood);
case Statistic::AchBuildHoe: return IsStatisticPresent(Statistic::AchBuildWorkBench); case CustomStatistic::AchBuildHoe: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench);
case Statistic::AchBakeCake: return IsStatisticPresent(Statistic::AchBuildHoe); case CustomStatistic::AchBakeCake: return IsStatisticPresent(CustomStatistic::AchBuildHoe);
case Statistic::AchMakeBread: return IsStatisticPresent(Statistic::AchBuildHoe); case CustomStatistic::AchMakeBread: return IsStatisticPresent(CustomStatistic::AchBuildHoe);
case Statistic::AchBuildSword: return IsStatisticPresent(Statistic::AchBuildWorkBench); case CustomStatistic::AchBuildSword: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench);
case Statistic::AchKillCow: return IsStatisticPresent(Statistic::AchBuildSword); case CustomStatistic::AchKillCow: return IsStatisticPresent(CustomStatistic::AchBuildSword);
case Statistic::AchFlyPig: return IsStatisticPresent(Statistic::AchKillCow); case CustomStatistic::AchFlyPig: return IsStatisticPresent(CustomStatistic::AchKillCow);
case Statistic::AchBreedCow: return IsStatisticPresent(Statistic::AchKillCow); case CustomStatistic::AchBreedCow: return IsStatisticPresent(CustomStatistic::AchKillCow);
case Statistic::AchKillEnemy: return IsStatisticPresent(Statistic::AchBuildSword); case CustomStatistic::AchKillEnemy: return IsStatisticPresent(CustomStatistic::AchBuildSword);
case Statistic::AchSnipeSkeleton: return IsStatisticPresent(Statistic::AchKillEnemy); case CustomStatistic::AchSnipeSkeleton: return IsStatisticPresent(CustomStatistic::AchKillEnemy);
case Statistic::AchBuildPickaxe: return IsStatisticPresent(Statistic::AchBuildWorkBench); case CustomStatistic::AchBuildPickaxe: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench);
case Statistic::AchBuildBetterPickaxe: return IsStatisticPresent(Statistic::AchBuildPickaxe); case CustomStatistic::AchBuildBetterPickaxe: return IsStatisticPresent(CustomStatistic::AchBuildPickaxe);
case Statistic::AchBuildFurnace: return IsStatisticPresent(Statistic::AchBuildWorkBench); case CustomStatistic::AchBuildFurnace: return IsStatisticPresent(CustomStatistic::AchBuildWorkBench);
case Statistic::AchCookFish: return IsStatisticPresent(Statistic::AchBuildFurnace); case CustomStatistic::AchCookFish: return IsStatisticPresent(CustomStatistic::AchBuildFurnace);
case Statistic::AchAcquireIron: return IsStatisticPresent(Statistic::AchBuildFurnace); case CustomStatistic::AchAcquireIron: return IsStatisticPresent(CustomStatistic::AchBuildFurnace);
case Statistic::AchOnARail: return IsStatisticPresent(Statistic::AchAcquireIron); case CustomStatistic::AchOnARail: return IsStatisticPresent(CustomStatistic::AchAcquireIron);
case Statistic::AchDiamonds: return IsStatisticPresent(Statistic::AchAcquireIron); case CustomStatistic::AchDiamonds: return IsStatisticPresent(CustomStatistic::AchAcquireIron);
case Statistic::AchPortal: return IsStatisticPresent(Statistic::AchDiamonds); case CustomStatistic::AchPortal: return IsStatisticPresent(CustomStatistic::AchDiamonds);
case Statistic::AchGhast: return IsStatisticPresent(Statistic::AchPortal); case CustomStatistic::AchGhast: return IsStatisticPresent(CustomStatistic::AchPortal);
case Statistic::AchBlazeRod: return IsStatisticPresent(Statistic::AchPortal); case CustomStatistic::AchBlazeRod: return IsStatisticPresent(CustomStatistic::AchPortal);
case Statistic::AchPotion: return IsStatisticPresent(Statistic::AchBlazeRod); case CustomStatistic::AchPotion: return IsStatisticPresent(CustomStatistic::AchBlazeRod);
case Statistic::AchTheEnd: return IsStatisticPresent(Statistic::AchBlazeRod); case CustomStatistic::AchTheEnd: return IsStatisticPresent(CustomStatistic::AchBlazeRod);
case Statistic::AchTheEnd2: return IsStatisticPresent(Statistic::AchTheEnd); case CustomStatistic::AchTheEnd2: return IsStatisticPresent(CustomStatistic::AchTheEnd);
case Statistic::AchEnchantments: return IsStatisticPresent(Statistic::AchDiamonds); case CustomStatistic::AchEnchantments: return IsStatisticPresent(CustomStatistic::AchDiamonds);
case Statistic::AchOverkill: return IsStatisticPresent(Statistic::AchEnchantments); case CustomStatistic::AchOverkill: return IsStatisticPresent(CustomStatistic::AchEnchantments);
case Statistic::AchBookcase: return IsStatisticPresent(Statistic::AchEnchantments); case CustomStatistic::AchBookcase: return IsStatisticPresent(CustomStatistic::AchEnchantments);
case Statistic::AchExploreAllBiomes: return IsStatisticPresent(Statistic::AchTheEnd); case CustomStatistic::AchExploreAllBiomes: return IsStatisticPresent(CustomStatistic::AchTheEnd);
case Statistic::AchSpawnWither: return IsStatisticPresent(Statistic::AchTheEnd2); case CustomStatistic::AchSpawnWither: return IsStatisticPresent(CustomStatistic::AchTheEnd2);
case Statistic::AchKillWither: return IsStatisticPresent(Statistic::AchSpawnWither); case CustomStatistic::AchKillWither: return IsStatisticPresent(CustomStatistic::AchSpawnWither);
case Statistic::AchFullBeacon: return IsStatisticPresent(Statistic::AchKillWither); case CustomStatistic::AchFullBeacon: return IsStatisticPresent(CustomStatistic::AchKillWither);
case Statistic::AchDiamondsToYou: return IsStatisticPresent(Statistic::AchDiamonds); case CustomStatistic::AchDiamondsToYou: return IsStatisticPresent(CustomStatistic::AchDiamonds);
default: return true; default: UNREACHABLE("Unsupported achievement type");
} }
} }
@ -71,10 +53,10 @@ bool cStatManager::SatisfiesPrerequisite(const Statistic a_Stat)
bool cStatManager::IsStatisticPresent(const Statistic a_Stat) const bool StatisticsManager::IsStatisticPresent(const CustomStatistic a_Stat) const
{ {
const auto Result = m_CustomStatistics.find(a_Stat); const auto Result = Custom.find(a_Stat);
if (Result != m_CustomStatistics.end()) if (Result != Custom.end())
{ {
return Result->second > 0; return Result->second > 0;
} }

View File

@ -25,35 +25,19 @@ exported from the server https://wiki.vg/Data_Generators
/** Class that manages the statistics and achievements of a single player. */ /** Class that manages the statistics and achievements of a single player. */
class cStatManager struct StatisticsManager
{ {
public:
typedef unsigned StatValue; typedef unsigned StatValue;
typedef std::unordered_map<Statistic, StatValue> CustomStore;
/** Set the value of the specified statistic. */ // TODO: Block tallies, entities killed, all the others
void SetValue(Statistic a_Stat, StatValue a_Value);
/** Increments the specified statistic. Returns the new value. */ std::unordered_map<CustomStatistic, StatValue> Custom;
StatValue AddValue(Statistic a_Stat, StatValue a_Delta = 1);
/** Returns whether the prerequisite for awarding an achievement are satisfied. */ /** Returns whether the prerequisite for awarding an achievement are satisfied. */
bool SatisfiesPrerequisite(Statistic a_Stat); bool SatisfiesPrerequisite(CustomStatistic a_Stat) const;
/** Invokes the given callbacks for each category of tracked statistics. */
template <class CustomCallback>
void ForEachStatisticType(CustomCallback a_Custom) const
{
a_Custom(m_CustomStatistics);
}
private: private:
/** Returns if a statistic is both present and has nonzero value. */ /** Returns if a statistic is both present and has nonzero value. */
bool IsStatisticPresent(Statistic a_Stat) const; bool IsStatisticPresent(CustomStatistic a_Stat) const;
// TODO: Block tallies, entities killed, all the others
CustomStore m_CustomStatistics;
}; };

View File

@ -766,16 +766,16 @@ void cSlotAreaCrafting::HandleCraftItem(const cItem & a_Result, cPlayer & a_Play
{ {
switch (a_Result.m_ItemType) switch (a_Result.m_ItemType)
{ {
case E_BLOCK_WORKBENCH: a_Player.AwardAchievement(Statistic::AchBuildWorkBench); break; case E_BLOCK_WORKBENCH: a_Player.AwardAchievement(CustomStatistic::AchBuildWorkBench); break;
case E_BLOCK_FURNACE: a_Player.AwardAchievement(Statistic::AchBuildFurnace); break; case E_BLOCK_FURNACE: a_Player.AwardAchievement(CustomStatistic::AchBuildFurnace); break;
case E_BLOCK_CAKE: a_Player.AwardAchievement(Statistic::AchBakeCake); break; case E_BLOCK_CAKE: a_Player.AwardAchievement(CustomStatistic::AchBakeCake); break;
case E_BLOCK_ENCHANTMENT_TABLE: a_Player.AwardAchievement(Statistic::AchEnchantments); break; case E_BLOCK_ENCHANTMENT_TABLE: a_Player.AwardAchievement(CustomStatistic::AchEnchantments); break;
case E_BLOCK_BOOKCASE: a_Player.AwardAchievement(Statistic::AchBookcase); break; case E_BLOCK_BOOKCASE: a_Player.AwardAchievement(CustomStatistic::AchBookcase); break;
case E_ITEM_WOODEN_PICKAXE: a_Player.AwardAchievement(Statistic::AchBuildPickaxe); break; case E_ITEM_WOODEN_PICKAXE: a_Player.AwardAchievement(CustomStatistic::AchBuildPickaxe); break;
case E_ITEM_WOODEN_SWORD: a_Player.AwardAchievement(Statistic::AchBuildSword); break; case E_ITEM_WOODEN_SWORD: a_Player.AwardAchievement(CustomStatistic::AchBuildSword); break;
case E_ITEM_STONE_PICKAXE: a_Player.AwardAchievement(Statistic::AchBuildBetterPickaxe); break; case E_ITEM_STONE_PICKAXE: a_Player.AwardAchievement(CustomStatistic::AchBuildBetterPickaxe); break;
case E_ITEM_WOODEN_HOE: a_Player.AwardAchievement(Statistic::AchBuildHoe); break; case E_ITEM_WOODEN_HOE: a_Player.AwardAchievement(CustomStatistic::AchBuildHoe); break;
case E_ITEM_BREAD: a_Player.AwardAchievement(Statistic::AchMakeBread); break; case E_ITEM_BREAD: a_Player.AwardAchievement(CustomStatistic::AchMakeBread); break;
default: break; default: break;
} }
} }
@ -2105,8 +2105,8 @@ void cSlotAreaFurnace::HandleSmeltItem(const cItem & a_Result, cPlayer & a_Playe
/** TODO 2014-05-12 xdot: Figure out when to call this method. */ /** TODO 2014-05-12 xdot: Figure out when to call this method. */
switch (a_Result.m_ItemType) switch (a_Result.m_ItemType)
{ {
case E_ITEM_IRON: a_Player.AwardAchievement(Statistic::AchAcquireIron); break; case E_ITEM_IRON: a_Player.AwardAchievement(CustomStatistic::AchAcquireIron); break;
case E_ITEM_COOKED_FISH: a_Player.AwardAchievement(Statistic::AchCookFish); break; case E_ITEM_COOKED_FISH: a_Player.AwardAchievement(CustomStatistic::AchCookFish); break;
default: break; default: break;
} }
} }
@ -2255,7 +2255,7 @@ void cSlotAreaBrewingstand::HandleBrewedItem(cPlayer & a_Player, const cItem & a
// Award an achievement if the item is not a water bottle (is a real brewed potion) // Award an achievement if the item is not a water bottle (is a real brewed potion)
if (a_ClickedItem.m_ItemDamage > 0) if (a_ClickedItem.m_ItemDamage > 0)
{ {
a_Player.AwardAchievement(Statistic::AchPotion); a_Player.AwardAchievement(CustomStatistic::AchPotion);
} }
} }

View File

@ -15,123 +15,123 @@ unsigned NamespaceSerializer::DataVersion()
std::string_view NamespaceSerializer::From(const Statistic a_ID) std::string_view NamespaceSerializer::From(const CustomStatistic a_ID)
{ {
switch (a_ID) switch (a_ID)
{ {
case Statistic::AnimalsBred: return "animals_bred"; case CustomStatistic::AnimalsBred: return "animals_bred";
case Statistic::AviateOneCm: return "aviate_one_cm"; case CustomStatistic::AviateOneCm: return "aviate_one_cm";
case Statistic::BellRing: return "bell_ring"; case CustomStatistic::BellRing: return "bell_ring";
case Statistic::BoatOneCm: return "boat_one_cm"; case CustomStatistic::BoatOneCm: return "boat_one_cm";
case Statistic::CleanArmor: return "clean_armor"; case CustomStatistic::CleanArmor: return "clean_armor";
case Statistic::CleanBanner: return "clean_banner"; case CustomStatistic::CleanBanner: return "clean_banner";
case Statistic::CleanShulkerBox: return "clean_shulker_box"; case CustomStatistic::CleanShulkerBox: return "clean_shulker_box";
case Statistic::ClimbOneCm: return "climb_one_cm"; case CustomStatistic::ClimbOneCm: return "climb_one_cm";
case Statistic::CrouchOneCm: return "crouch_one_cm"; case CustomStatistic::CrouchOneCm: return "crouch_one_cm";
case Statistic::DamageAbsorbed: return "damage_absorbed"; case CustomStatistic::DamageAbsorbed: return "damage_absorbed";
case Statistic::DamageBlockedByShield: return "damage_blocked_by_shield"; case CustomStatistic::DamageBlockedByShield: return "damage_blocked_by_shield";
case Statistic::DamageDealt: return "damage_dealt"; case CustomStatistic::DamageDealt: return "damage_dealt";
case Statistic::DamageDealtAbsorbed: return "damage_dealt_absorbed"; case CustomStatistic::DamageDealtAbsorbed: return "damage_dealt_absorbed";
case Statistic::DamageDealtResisted: return "damage_dealt_resisted"; case CustomStatistic::DamageDealtResisted: return "damage_dealt_resisted";
case Statistic::DamageResisted: return "damage_resisted"; case CustomStatistic::DamageResisted: return "damage_resisted";
case Statistic::DamageTaken: return "damage_taken"; case CustomStatistic::DamageTaken: return "damage_taken";
case Statistic::Deaths: return "deaths"; case CustomStatistic::Deaths: return "deaths";
case Statistic::Drop: return "drop"; case CustomStatistic::Drop: return "drop";
case Statistic::EatCakeSlice: return "eat_cake_slice"; case CustomStatistic::EatCakeSlice: return "eat_cake_slice";
case Statistic::EnchantItem: return "enchant_item"; case CustomStatistic::EnchantItem: return "enchant_item";
case Statistic::FallOneCm: return "fall_one_cm"; case CustomStatistic::FallOneCm: return "fall_one_cm";
case Statistic::FillCauldron: return "fill_cauldron"; case CustomStatistic::FillCauldron: return "fill_cauldron";
case Statistic::FishCaught: return "fish_caught"; case CustomStatistic::FishCaught: return "fish_caught";
case Statistic::FlyOneCm: return "fly_one_cm"; case CustomStatistic::FlyOneCm: return "fly_one_cm";
case Statistic::HorseOneCm: return "horse_one_cm"; case CustomStatistic::HorseOneCm: return "horse_one_cm";
case Statistic::InspectDispenser: return "inspect_dispenser"; case CustomStatistic::InspectDispenser: return "inspect_dispenser";
case Statistic::InspectDropper: return "inspect_dropper"; case CustomStatistic::InspectDropper: return "inspect_dropper";
case Statistic::InspectHopper: return "inspect_hopper"; case CustomStatistic::InspectHopper: return "inspect_hopper";
case Statistic::InteractWithAnvil: return "interact_with_anvil"; case CustomStatistic::InteractWithAnvil: return "interact_with_anvil";
case Statistic::InteractWithBeacon: return "interact_with_beacon"; case CustomStatistic::InteractWithBeacon: return "interact_with_beacon";
case Statistic::InteractWithBlastFurnace: return "interact_with_blast_furnace"; case CustomStatistic::InteractWithBlastFurnace: return "interact_with_blast_furnace";
case Statistic::InteractWithBrewingstand: return "interact_with_brewingstand"; case CustomStatistic::InteractWithBrewingstand: return "interact_with_brewingstand";
case Statistic::InteractWithCampfire: return "interact_with_campfire"; case CustomStatistic::InteractWithCampfire: return "interact_with_campfire";
case Statistic::InteractWithCartographyTable: return "interact_with_cartography_table"; case CustomStatistic::InteractWithCartographyTable: return "interact_with_cartography_table";
case Statistic::InteractWithCraftingTable: return "interact_with_crafting_table"; case CustomStatistic::InteractWithCraftingTable: return "interact_with_crafting_table";
case Statistic::InteractWithFurnace: return "interact_with_furnace"; case CustomStatistic::InteractWithFurnace: return "interact_with_furnace";
case Statistic::InteractWithGrindstone: return "interact_with_grindstone"; case CustomStatistic::InteractWithGrindstone: return "interact_with_grindstone";
case Statistic::InteractWithLectern: return "interact_with_lectern"; case CustomStatistic::InteractWithLectern: return "interact_with_lectern";
case Statistic::InteractWithLoom: return "interact_with_loom"; case CustomStatistic::InteractWithLoom: return "interact_with_loom";
case Statistic::InteractWithSmithingTable: return "interact_with_smithing_table"; case CustomStatistic::InteractWithSmithingTable: return "interact_with_smithing_table";
case Statistic::InteractWithSmoker: return "interact_with_smoker"; case CustomStatistic::InteractWithSmoker: return "interact_with_smoker";
case Statistic::InteractWithStonecutter: return "interact_with_stonecutter"; case CustomStatistic::InteractWithStonecutter: return "interact_with_stonecutter";
case Statistic::Jump: return "jump"; case CustomStatistic::Jump: return "jump";
case Statistic::LeaveGame: return "leave_game"; case CustomStatistic::LeaveGame: return "leave_game";
case Statistic::MinecartOneCm: return "minecart_one_cm"; case CustomStatistic::MinecartOneCm: return "minecart_one_cm";
case Statistic::MobKills: return "mob_kills"; case CustomStatistic::MobKills: return "mob_kills";
case Statistic::OpenBarrel: return "open_barrel"; case CustomStatistic::OpenBarrel: return "open_barrel";
case Statistic::OpenChest: return "open_chest"; case CustomStatistic::OpenChest: return "open_chest";
case Statistic::OpenEnderchest: return "open_enderchest"; case CustomStatistic::OpenEnderchest: return "open_enderchest";
case Statistic::OpenShulkerBox: return "open_shulker_box"; case CustomStatistic::OpenShulkerBox: return "open_shulker_box";
case Statistic::PigOneCm: return "pig_one_cm"; case CustomStatistic::PigOneCm: return "pig_one_cm";
case Statistic::PlayNoteblock: return "play_noteblock"; case CustomStatistic::PlayNoteblock: return "play_noteblock";
case Statistic::PlayOneMinute: return "play_one_minute"; case CustomStatistic::PlayOneMinute: return "play_one_minute";
case Statistic::PlayRecord: return "play_record"; case CustomStatistic::PlayRecord: return "play_record";
case Statistic::PlayerKills: return "player_kills"; case CustomStatistic::PlayerKills: return "player_kills";
case Statistic::PotFlower: return "pot_flower"; case CustomStatistic::PotFlower: return "pot_flower";
case Statistic::RaidTrigger: return "raid_trigger"; case CustomStatistic::RaidTrigger: return "raid_trigger";
case Statistic::RaidWin: return "raid_win"; case CustomStatistic::RaidWin: return "raid_win";
case Statistic::SleepInBed: return "sleep_in_bed"; case CustomStatistic::SleepInBed: return "sleep_in_bed";
case Statistic::SneakTime: return "sneak_time"; case CustomStatistic::SneakTime: return "sneak_time";
case Statistic::SprintOneCm: return "sprint_one_cm"; case CustomStatistic::SprintOneCm: return "sprint_one_cm";
case Statistic::StriderOneCm: return "strider_one_cm"; case CustomStatistic::StriderOneCm: return "strider_one_cm";
case Statistic::SwimOneCm: return "swim_one_cm"; case CustomStatistic::SwimOneCm: return "swim_one_cm";
case Statistic::TalkedToVillager: return "talked_to_villager"; case CustomStatistic::TalkedToVillager: return "talked_to_villager";
case Statistic::TargetHit: return "target_hit"; case CustomStatistic::TargetHit: return "target_hit";
case Statistic::TimeSinceDeath: return "time_since_death"; case CustomStatistic::TimeSinceDeath: return "time_since_death";
case Statistic::TimeSinceRest: return "time_since_rest"; case CustomStatistic::TimeSinceRest: return "time_since_rest";
case Statistic::TradedWithVillager: return "traded_with_villager"; case CustomStatistic::TradedWithVillager: return "traded_with_villager";
case Statistic::TriggerTrappedChest: return "trigger_trapped_chest"; case CustomStatistic::TriggerTrappedChest: return "trigger_trapped_chest";
case Statistic::TuneNoteblock: return "tune_noteblock"; case CustomStatistic::TuneNoteblock: return "tune_noteblock";
case Statistic::UseCauldron: return "use_cauldron"; case CustomStatistic::UseCauldron: return "use_cauldron";
case Statistic::WalkOnWaterOneCm: return "walk_on_water_one_cm"; case CustomStatistic::WalkOnWaterOneCm: return "walk_on_water_one_cm";
case Statistic::WalkOneCm: return "walk_one_cm"; case CustomStatistic::WalkOneCm: return "walk_one_cm";
case Statistic::WalkUnderWaterOneCm: return "walk_under_water_one_cm"; case CustomStatistic::WalkUnderWaterOneCm: return "walk_under_water_one_cm";
// Old ones just for compatibility // Old ones just for compatibility
case Statistic::JunkFished: return "junk_fished"; case CustomStatistic::JunkFished: return "junk_fished";
case Statistic::TreasureFished: return "treasure_fished"; case CustomStatistic::TreasureFished: return "treasure_fished";
// The old advancements // The old advancements
case Statistic::AchOpenInventory: return "cuberite:achievement.openInventory"; case CustomStatistic::AchOpenInventory: return "cuberite:achievement.openInventory";
case Statistic::AchMineWood: return "cuberite:achievement.mineWood"; case CustomStatistic::AchMineWood: return "cuberite:achievement.mineWood";
case Statistic::AchBuildWorkBench: return "cuberite:achievement.buildWorkBench"; case CustomStatistic::AchBuildWorkBench: return "cuberite:achievement.buildWorkBench";
case Statistic::AchBuildPickaxe: return "cuberite:achievement.buildPickaxe"; case CustomStatistic::AchBuildPickaxe: return "cuberite:achievement.buildPickaxe";
case Statistic::AchBuildFurnace: return "cuberite:achievement.buildFurnace"; case CustomStatistic::AchBuildFurnace: return "cuberite:achievement.buildFurnace";
case Statistic::AchAcquireIron: return "cuberite:achievement.acquireIron"; case CustomStatistic::AchAcquireIron: return "cuberite:achievement.acquireIron";
case Statistic::AchBuildHoe: return "cuberite:achievement.buildHoe"; case CustomStatistic::AchBuildHoe: return "cuberite:achievement.buildHoe";
case Statistic::AchMakeBread: return "cuberite:achievement.makeBread"; case CustomStatistic::AchMakeBread: return "cuberite:achievement.makeBread";
case Statistic::AchBakeCake: return "cuberite:achievement.bakeCake"; case CustomStatistic::AchBakeCake: return "cuberite:achievement.bakeCake";
case Statistic::AchBuildBetterPickaxe: return "cuberite:achievement.buildBetterPickaxe"; case CustomStatistic::AchBuildBetterPickaxe: return "cuberite:achievement.buildBetterPickaxe";
case Statistic::AchCookFish: return "cuberite:achievement.cookFish"; case CustomStatistic::AchCookFish: return "cuberite:achievement.cookFish";
case Statistic::AchOnARail: return "cuberite:achievement.onARail"; case CustomStatistic::AchOnARail: return "cuberite:achievement.onARail";
case Statistic::AchBuildSword: return "cuberite:achievement.buildSword"; case CustomStatistic::AchBuildSword: return "cuberite:achievement.buildSword";
case Statistic::AchKillEnemy: return "cuberite:achievement.killEnemy"; case CustomStatistic::AchKillEnemy: return "cuberite:achievement.killEnemy";
case Statistic::AchKillCow: return "cuberite:achievement.killCow"; case CustomStatistic::AchKillCow: return "cuberite:achievement.killCow";
case Statistic::AchFlyPig: return "cuberite:achievement.flyPig"; case CustomStatistic::AchFlyPig: return "cuberite:achievement.flyPig";
case Statistic::AchSnipeSkeleton: return "cuberite:achievement.snipeSkeleton"; case CustomStatistic::AchSnipeSkeleton: return "cuberite:achievement.snipeSkeleton";
case Statistic::AchDiamonds: return "cuberite:achievement.diamonds"; case CustomStatistic::AchDiamonds: return "cuberite:achievement.diamonds";
case Statistic::AchPortal: return "cuberite:achievement.portal"; case CustomStatistic::AchPortal: return "cuberite:achievement.portal";
case Statistic::AchGhast: return "cuberite:achievement.ghast"; case CustomStatistic::AchGhast: return "cuberite:achievement.ghast";
case Statistic::AchBlazeRod: return "cuberite:achievement.blazeRod"; case CustomStatistic::AchBlazeRod: return "cuberite:achievement.blazeRod";
case Statistic::AchPotion: return "cuberite:achievement.potion"; case CustomStatistic::AchPotion: return "cuberite:achievement.potion";
case Statistic::AchTheEnd: return "cuberite:achievement.theEnd"; case CustomStatistic::AchTheEnd: return "cuberite:achievement.theEnd";
case Statistic::AchTheEnd2: return "cuberite:achievement.theEnd2"; case CustomStatistic::AchTheEnd2: return "cuberite:achievement.theEnd2";
case Statistic::AchEnchantments: return "cuberite:achievement.enchantments"; case CustomStatistic::AchEnchantments: return "cuberite:achievement.enchantments";
case Statistic::AchOverkill: return "cuberite:achievement.overkill"; case CustomStatistic::AchOverkill: return "cuberite:achievement.overkill";
case Statistic::AchBookcase: return "cuberite:achievement.bookcase"; case CustomStatistic::AchBookcase: return "cuberite:achievement.bookcase";
case Statistic::AchExploreAllBiomes: return "cuberite:achievement.exploreAllBiomes"; case CustomStatistic::AchExploreAllBiomes: return "cuberite:achievement.exploreAllBiomes";
case Statistic::AchSpawnWither: return "cuberite:achievement.spawnWither"; case CustomStatistic::AchSpawnWither: return "cuberite:achievement.spawnWither";
case Statistic::AchKillWither: return "cuberite:achievement.killWither"; case CustomStatistic::AchKillWither: return "cuberite:achievement.killWither";
case Statistic::AchFullBeacon: return "cuberite:achievement.fullBeacon"; case CustomStatistic::AchFullBeacon: return "cuberite:achievement.fullBeacon";
case Statistic::AchBreedCow: return "cuberite:achievement.breedCow"; case CustomStatistic::AchBreedCow: return "cuberite:achievement.breedCow";
case Statistic::AchDiamondsToYou: return "cuberite:achievement.diamondsToYou"; case CustomStatistic::AchDiamondsToYou: return "cuberite:achievement.diamondsToYou";
} }
UNREACHABLE("Tried to save unhandled statistic"); UNREACHABLE("Tried to save unhandled statistic");
} }
@ -274,123 +274,123 @@ std::string_view NamespaceSerializer::From(const BannerPattern a_Pattern)
Statistic NamespaceSerializer::ToCustomStatistic(const std::string_view ID) CustomStatistic NamespaceSerializer::ToCustomStatistic(const std::string_view ID)
{ {
static const std::unordered_map<std::string_view, Statistic> CustomStatistics static const std::unordered_map<std::string_view, CustomStatistic> CustomStatistics
{ {
{ "animals_bred", Statistic::AnimalsBred }, { "animals_bred", CustomStatistic::AnimalsBred },
{ "aviate_one_cm", Statistic::AviateOneCm }, { "aviate_one_cm", CustomStatistic::AviateOneCm },
{ "bell_ring", Statistic::BellRing }, { "bell_ring", CustomStatistic::BellRing },
{ "boat_one_cm", Statistic::BoatOneCm }, { "boat_one_cm", CustomStatistic::BoatOneCm },
{ "clean_armor", Statistic::CleanArmor }, { "clean_armor", CustomStatistic::CleanArmor },
{ "clean_banner", Statistic::CleanBanner }, { "clean_banner", CustomStatistic::CleanBanner },
{ "clean_shulker_box", Statistic::CleanShulkerBox }, { "clean_shulker_box", CustomStatistic::CleanShulkerBox },
{ "climb_one_cm", Statistic::ClimbOneCm }, { "climb_one_cm", CustomStatistic::ClimbOneCm },
{ "crouch_one_cm", Statistic::CrouchOneCm }, { "crouch_one_cm", CustomStatistic::CrouchOneCm },
{ "damage_absorbed", Statistic::DamageAbsorbed }, { "damage_absorbed", CustomStatistic::DamageAbsorbed },
{ "damage_blocked_by_shield", Statistic::DamageBlockedByShield }, { "damage_blocked_by_shield", CustomStatistic::DamageBlockedByShield },
{ "damage_dealt", Statistic::DamageDealt }, { "damage_dealt", CustomStatistic::DamageDealt },
{ "damage_dealt_absorbed", Statistic::DamageDealtAbsorbed }, { "damage_dealt_absorbed", CustomStatistic::DamageDealtAbsorbed },
{ "damage_dealt_resisted", Statistic::DamageDealtResisted }, { "damage_dealt_resisted", CustomStatistic::DamageDealtResisted },
{ "damage_resisted", Statistic::DamageResisted }, { "damage_resisted", CustomStatistic::DamageResisted },
{ "damage_taken", Statistic::DamageTaken }, { "damage_taken", CustomStatistic::DamageTaken },
{ "deaths", Statistic::Deaths }, { "deaths", CustomStatistic::Deaths },
{ "drop", Statistic::Drop }, { "drop", CustomStatistic::Drop },
{ "eat_cake_slice", Statistic::EatCakeSlice }, { "eat_cake_slice", CustomStatistic::EatCakeSlice },
{ "enchant_item", Statistic::EnchantItem }, { "enchant_item", CustomStatistic::EnchantItem },
{ "fall_one_cm", Statistic::FallOneCm }, { "fall_one_cm", CustomStatistic::FallOneCm },
{ "fill_cauldron", Statistic::FillCauldron }, { "fill_cauldron", CustomStatistic::FillCauldron },
{ "fish_caught", Statistic::FishCaught }, { "fish_caught", CustomStatistic::FishCaught },
{ "fly_one_cm", Statistic::FlyOneCm }, { "fly_one_cm", CustomStatistic::FlyOneCm },
{ "horse_one_cm", Statistic::HorseOneCm }, { "horse_one_cm", CustomStatistic::HorseOneCm },
{ "inspect_dispenser", Statistic::InspectDispenser }, { "inspect_dispenser", CustomStatistic::InspectDispenser },
{ "inspect_dropper", Statistic::InspectDropper }, { "inspect_dropper", CustomStatistic::InspectDropper },
{ "inspect_hopper", Statistic::InspectHopper }, { "inspect_hopper", CustomStatistic::InspectHopper },
{ "interact_with_anvil", Statistic::InteractWithAnvil }, { "interact_with_anvil", CustomStatistic::InteractWithAnvil },
{ "interact_with_beacon", Statistic::InteractWithBeacon }, { "interact_with_beacon", CustomStatistic::InteractWithBeacon },
{ "interact_with_blast_furnace", Statistic::InteractWithBlastFurnace }, { "interact_with_blast_furnace", CustomStatistic::InteractWithBlastFurnace },
{ "interact_with_brewingstand", Statistic::InteractWithBrewingstand }, { "interact_with_brewingstand", CustomStatistic::InteractWithBrewingstand },
{ "interact_with_campfire", Statistic::InteractWithCampfire }, { "interact_with_campfire", CustomStatistic::InteractWithCampfire },
{ "interact_with_cartography_table", Statistic::InteractWithCartographyTable }, { "interact_with_cartography_table", CustomStatistic::InteractWithCartographyTable },
{ "interact_with_crafting_table", Statistic::InteractWithCraftingTable }, { "interact_with_crafting_table", CustomStatistic::InteractWithCraftingTable },
{ "interact_with_furnace", Statistic::InteractWithFurnace }, { "interact_with_furnace", CustomStatistic::InteractWithFurnace },
{ "interact_with_grindstone", Statistic::InteractWithGrindstone }, { "interact_with_grindstone", CustomStatistic::InteractWithGrindstone },
{ "interact_with_lectern", Statistic::InteractWithLectern }, { "interact_with_lectern", CustomStatistic::InteractWithLectern },
{ "interact_with_loom", Statistic::InteractWithLoom }, { "interact_with_loom", CustomStatistic::InteractWithLoom },
{ "interact_with_smithing_table", Statistic::InteractWithSmithingTable }, { "interact_with_smithing_table", CustomStatistic::InteractWithSmithingTable },
{ "interact_with_smoker", Statistic::InteractWithSmoker }, { "interact_with_smoker", CustomStatistic::InteractWithSmoker },
{ "interact_with_stonecutter", Statistic::InteractWithStonecutter }, { "interact_with_stonecutter", CustomStatistic::InteractWithStonecutter },
{ "jump", Statistic::Jump }, { "jump", CustomStatistic::Jump },
{ "leave_game", Statistic::LeaveGame }, { "leave_game", CustomStatistic::LeaveGame },
{ "minecart_one_cm", Statistic::MinecartOneCm }, { "minecart_one_cm", CustomStatistic::MinecartOneCm },
{ "mob_kills", Statistic::MobKills }, { "mob_kills", CustomStatistic::MobKills },
{ "open_barrel", Statistic::OpenBarrel }, { "open_barrel", CustomStatistic::OpenBarrel },
{ "open_chest", Statistic::OpenChest }, { "open_chest", CustomStatistic::OpenChest },
{ "open_enderchest", Statistic::OpenEnderchest }, { "open_enderchest", CustomStatistic::OpenEnderchest },
{ "open_shulker_box", Statistic::OpenShulkerBox }, { "open_shulker_box", CustomStatistic::OpenShulkerBox },
{ "pig_one_cm", Statistic::PigOneCm }, { "pig_one_cm", CustomStatistic::PigOneCm },
{ "play_noteblock", Statistic::PlayNoteblock }, { "play_noteblock", CustomStatistic::PlayNoteblock },
{ "play_one_minute", Statistic::PlayOneMinute }, { "play_one_minute", CustomStatistic::PlayOneMinute },
{ "play_record", Statistic::PlayRecord }, { "play_record", CustomStatistic::PlayRecord },
{ "player_kills", Statistic::PlayerKills }, { "player_kills", CustomStatistic::PlayerKills },
{ "pot_flower", Statistic::PotFlower }, { "pot_flower", CustomStatistic::PotFlower },
{ "raid_trigger", Statistic::RaidTrigger }, { "raid_trigger", CustomStatistic::RaidTrigger },
{ "raid_win", Statistic::RaidWin }, { "raid_win", CustomStatistic::RaidWin },
{ "sleep_in_bed", Statistic::SleepInBed }, { "sleep_in_bed", CustomStatistic::SleepInBed },
{ "sneak_time", Statistic::SneakTime }, { "sneak_time", CustomStatistic::SneakTime },
{ "sprint_one_cm", Statistic::SprintOneCm }, { "sprint_one_cm", CustomStatistic::SprintOneCm },
{ "strider_one_cm", Statistic::StriderOneCm }, { "strider_one_cm", CustomStatistic::StriderOneCm },
{ "swim_one_cm", Statistic::SwimOneCm }, { "swim_one_cm", CustomStatistic::SwimOneCm },
{ "talked_to_villager", Statistic::TalkedToVillager }, { "talked_to_villager", CustomStatistic::TalkedToVillager },
{ "target_hit", Statistic::TargetHit }, { "target_hit", CustomStatistic::TargetHit },
{ "time_since_death", Statistic::TimeSinceDeath }, { "time_since_death", CustomStatistic::TimeSinceDeath },
{ "time_since_rest", Statistic::TimeSinceRest }, { "time_since_rest", CustomStatistic::TimeSinceRest },
{ "traded_with_villager", Statistic::TradedWithVillager }, { "traded_with_villager", CustomStatistic::TradedWithVillager },
{ "trigger_trapped_chest", Statistic::TriggerTrappedChest }, { "trigger_trapped_chest", CustomStatistic::TriggerTrappedChest },
{ "tune_noteblock", Statistic::TuneNoteblock }, { "tune_noteblock", CustomStatistic::TuneNoteblock },
{ "use_cauldron", Statistic::UseCauldron }, { "use_cauldron", CustomStatistic::UseCauldron },
{ "walk_on_water_one_cm", Statistic::WalkOnWaterOneCm }, { "walk_on_water_one_cm", CustomStatistic::WalkOnWaterOneCm },
{ "walk_one_cm", Statistic::WalkOneCm }, { "walk_one_cm", CustomStatistic::WalkOneCm },
{ "walk_under_water_one_cm", Statistic::WalkUnderWaterOneCm }, { "walk_under_water_one_cm", CustomStatistic::WalkUnderWaterOneCm },
// Old ones just for compatibility // Old ones just for compatibility
{ "junk_fished", Statistic::JunkFished }, { "junk_fished", CustomStatistic::JunkFished },
{ "treasure_fished", Statistic::TreasureFished }, { "treasure_fished", CustomStatistic::TreasureFished },
// The old advancements // The old advancements
{ "cuberite:achievement.openInventory", Statistic::AchOpenInventory }, { "cuberite:achievement.openInventory", CustomStatistic::AchOpenInventory },
{ "cuberite:achievement.mineWood", Statistic::AchMineWood }, { "cuberite:achievement.mineWood", CustomStatistic::AchMineWood },
{ "cuberite:achievement.buildWorkBench", Statistic::AchBuildWorkBench }, { "cuberite:achievement.buildWorkBench", CustomStatistic::AchBuildWorkBench },
{ "cuberite:achievement.buildPickaxe", Statistic::AchBuildPickaxe }, { "cuberite:achievement.buildPickaxe", CustomStatistic::AchBuildPickaxe },
{ "cuberite:achievement.buildFurnace", Statistic::AchBuildFurnace }, { "cuberite:achievement.buildFurnace", CustomStatistic::AchBuildFurnace },
{ "cuberite:achievement.acquireIron", Statistic::AchAcquireIron }, { "cuberite:achievement.acquireIron", CustomStatistic::AchAcquireIron },
{ "cuberite:achievement.buildHoe", Statistic::AchBuildHoe }, { "cuberite:achievement.buildHoe", CustomStatistic::AchBuildHoe },
{ "cuberite:achievement.makeBread", Statistic::AchMakeBread }, { "cuberite:achievement.makeBread", CustomStatistic::AchMakeBread },
{ "cuberite:achievement.bakeCake", Statistic::AchBakeCake }, { "cuberite:achievement.bakeCake", CustomStatistic::AchBakeCake },
{ "cuberite:achievement.buildBetterPickaxe", Statistic::AchBuildBetterPickaxe }, { "cuberite:achievement.buildBetterPickaxe", CustomStatistic::AchBuildBetterPickaxe },
{ "cuberite:achievement.cookFish", Statistic::AchCookFish }, { "cuberite:achievement.cookFish", CustomStatistic::AchCookFish },
{ "cuberite:achievement.onARail", Statistic::AchOnARail }, { "cuberite:achievement.onARail", CustomStatistic::AchOnARail },
{ "cuberite:achievement.buildSword", Statistic::AchBuildSword }, { "cuberite:achievement.buildSword", CustomStatistic::AchBuildSword },
{ "cuberite:achievement.killEnemy", Statistic::AchKillEnemy }, { "cuberite:achievement.killEnemy", CustomStatistic::AchKillEnemy },
{ "cuberite:achievement.killCow", Statistic::AchKillCow }, { "cuberite:achievement.killCow", CustomStatistic::AchKillCow },
{ "cuberite:achievement.flyPig", Statistic::AchFlyPig }, { "cuberite:achievement.flyPig", CustomStatistic::AchFlyPig },
{ "cuberite:achievement.snipeSkeleton", Statistic::AchSnipeSkeleton }, { "cuberite:achievement.snipeSkeleton", CustomStatistic::AchSnipeSkeleton },
{ "cuberite:achievement.diamonds", Statistic::AchDiamonds }, { "cuberite:achievement.diamonds", CustomStatistic::AchDiamonds },
{ "cuberite:achievement.portal", Statistic::AchPortal }, { "cuberite:achievement.portal", CustomStatistic::AchPortal },
{ "cuberite:achievement.ghast", Statistic::AchGhast }, { "cuberite:achievement.ghast", CustomStatistic::AchGhast },
{ "cuberite:achievement.blazeRod", Statistic::AchBlazeRod }, { "cuberite:achievement.blazeRod", CustomStatistic::AchBlazeRod },
{ "cuberite:achievement.potion", Statistic::AchPotion }, { "cuberite:achievement.potion", CustomStatistic::AchPotion },
{ "cuberite:achievement.theEnd", Statistic::AchTheEnd }, { "cuberite:achievement.theEnd", CustomStatistic::AchTheEnd },
{ "cuberite:achievement.theEnd2", Statistic::AchTheEnd2 }, { "cuberite:achievement.theEnd2", CustomStatistic::AchTheEnd2 },
{ "cuberite:achievement.enchantments", Statistic::AchEnchantments }, { "cuberite:achievement.enchantments", CustomStatistic::AchEnchantments },
{ "cuberite:achievement.overkill", Statistic::AchOverkill }, { "cuberite:achievement.overkill", CustomStatistic::AchOverkill },
{ "cuberite:achievement.bookcase", Statistic::AchBookcase }, { "cuberite:achievement.bookcase", CustomStatistic::AchBookcase },
{ "cuberite:achievement.exploreAllBiomes", Statistic::AchExploreAllBiomes }, { "cuberite:achievement.exploreAllBiomes", CustomStatistic::AchExploreAllBiomes },
{ "cuberite:achievement.spawnWither", Statistic::AchSpawnWither }, { "cuberite:achievement.spawnWither", CustomStatistic::AchSpawnWither },
{ "cuberite:achievement.killWither", Statistic::AchKillWither }, { "cuberite:achievement.killWither", CustomStatistic::AchKillWither },
{ "cuberite:achievement.fullBeacon", Statistic::AchFullBeacon }, { "cuberite:achievement.fullBeacon", CustomStatistic::AchFullBeacon },
{ "cuberite:achievement.breedCow", Statistic::AchBreedCow }, { "cuberite:achievement.breedCow", CustomStatistic::AchBreedCow },
{ "cuberite:achievement.diamondsToYou", Statistic::AchDiamondsToYou} { "cuberite:achievement.diamondsToYou", CustomStatistic::AchDiamondsToYou}
}; };
return CustomStatistics.at(ID); return CustomStatistics.at(ID);

View File

@ -15,11 +15,11 @@ namespace NamespaceSerializer
unsigned DataVersion(); unsigned DataVersion();
std::string_view From(Statistic a_ID); std::string_view From(CustomStatistic a_ID);
std::string_view From(eMonsterType a_ID); std::string_view From(eMonsterType a_ID);
std::string_view From(BannerPattern a_ID); std::string_view From(BannerPattern a_ID);
Statistic ToCustomStatistic(std::string_view a_ID); CustomStatistic ToCustomStatistic(std::string_view a_ID);
eMonsterType ToMonsterType(std::string_view a_ID); eMonsterType ToMonsterType(std::string_view a_ID);
std::pair<Namespace, std::string_view> SplitNamespacedID(std::string_view ID); std::pair<Namespace, std::string_view> SplitNamespacedID(std::string_view ID);

View File

@ -33,115 +33,112 @@ namespace StatSerializer
static void SaveStatToJSON(const cStatManager & Manager, Json::Value & a_Out) static void SaveStatToJSON(const StatisticsManager & Manager, Json::Value & a_Out)
{ {
Manager.ForEachStatisticType([&a_Out](const cStatManager::CustomStore & Store) if (Manager.Custom.empty())
{ {
if (Store.empty()) // Avoid saving "custom": null to disk:
{ return;
// Avoid saving "custom": null to disk: }
return;
}
auto & Custom = a_Out["custom"]; auto & Custom = a_Out["custom"];
for (const auto & Item : Store) for (const auto & [Statistic, Value] : Manager.Custom)
{ {
Custom[NamespaceSerializer::From(Item.first).data()] = Item.second; Custom[NamespaceSerializer::From(Statistic).data()] = Value;
} }
});
} }
static void LoadLegacyFromJSON(cStatManager & Manager, const Json::Value & In) static void LoadLegacyFromJSON(StatisticsManager & Manager, const Json::Value & In)
{ {
// Upgrade mapping from pre-1.13 names. TODO: remove on 2020-09-18 // Upgrade mapping from pre-1.13 names. TODO: remove on 2020-09-18
static const std::unordered_map<std::string_view, Statistic> LegacyMapping static const std::unordered_map<std::string_view, CustomStatistic> LegacyMapping
{ {
{ "achievement.openInventory", Statistic::AchOpenInventory }, { "achievement.openInventory", CustomStatistic::AchOpenInventory },
{ "achievement.mineWood", Statistic::AchMineWood }, { "achievement.mineWood", CustomStatistic::AchMineWood },
{ "achievement.buildWorkBench", Statistic::AchBuildWorkBench }, { "achievement.buildWorkBench", CustomStatistic::AchBuildWorkBench },
{ "achievement.buildPickaxe", Statistic::AchBuildPickaxe }, { "achievement.buildPickaxe", CustomStatistic::AchBuildPickaxe },
{ "achievement.buildFurnace", Statistic::AchBuildFurnace }, { "achievement.buildFurnace", CustomStatistic::AchBuildFurnace },
{ "achievement.acquireIron", Statistic::AchAcquireIron }, { "achievement.acquireIron", CustomStatistic::AchAcquireIron },
{ "achievement.buildHoe", Statistic::AchBuildHoe }, { "achievement.buildHoe", CustomStatistic::AchBuildHoe },
{ "achievement.makeBread", Statistic::AchMakeBread }, { "achievement.makeBread", CustomStatistic::AchMakeBread },
{ "achievement.bakeCake", Statistic::AchBakeCake }, { "achievement.bakeCake", CustomStatistic::AchBakeCake },
{ "achievement.buildBetterPickaxe", Statistic::AchBuildBetterPickaxe }, { "achievement.buildBetterPickaxe", CustomStatistic::AchBuildBetterPickaxe },
{ "achievement.cookFish", Statistic::AchCookFish }, { "achievement.cookFish", CustomStatistic::AchCookFish },
{ "achievement.onARail", Statistic::AchOnARail }, { "achievement.onARail", CustomStatistic::AchOnARail },
{ "achievement.buildSword", Statistic::AchBuildSword }, { "achievement.buildSword", CustomStatistic::AchBuildSword },
{ "achievement.killEnemy", Statistic::AchKillEnemy }, { "achievement.killEnemy", CustomStatistic::AchKillEnemy },
{ "achievement.killCow", Statistic::AchKillCow }, { "achievement.killCow", CustomStatistic::AchKillCow },
{ "achievement.flyPig", Statistic::AchFlyPig }, { "achievement.flyPig", CustomStatistic::AchFlyPig },
{ "achievement.snipeSkeleton", Statistic::AchSnipeSkeleton }, { "achievement.snipeSkeleton", CustomStatistic::AchSnipeSkeleton },
{ "achievement.diamonds", Statistic::AchDiamonds }, { "achievement.diamonds", CustomStatistic::AchDiamonds },
{ "achievement.portal", Statistic::AchPortal }, { "achievement.portal", CustomStatistic::AchPortal },
{ "achievement.ghast", Statistic::AchGhast }, { "achievement.ghast", CustomStatistic::AchGhast },
{ "achievement.blazeRod", Statistic::AchBlazeRod }, { "achievement.blazeRod", CustomStatistic::AchBlazeRod },
{ "achievement.potion", Statistic::AchPotion }, { "achievement.potion", CustomStatistic::AchPotion },
{ "achievement.theEnd", Statistic::AchTheEnd }, { "achievement.theEnd", CustomStatistic::AchTheEnd },
{ "achievement.theEnd2", Statistic::AchTheEnd2 }, { "achievement.theEnd2", CustomStatistic::AchTheEnd2 },
{ "achievement.enchantments", Statistic::AchEnchantments }, { "achievement.enchantments", CustomStatistic::AchEnchantments },
{ "achievement.overkill", Statistic::AchOverkill }, { "achievement.overkill", CustomStatistic::AchOverkill },
{ "achievement.bookcase", Statistic::AchBookcase }, { "achievement.bookcase", CustomStatistic::AchBookcase },
{ "achievement.exploreAllBiomes", Statistic::AchExploreAllBiomes }, { "achievement.exploreAllBiomes", CustomStatistic::AchExploreAllBiomes },
{ "achievement.spawnWither", Statistic::AchSpawnWither }, { "achievement.spawnWither", CustomStatistic::AchSpawnWither },
{ "achievement.killWither", Statistic::AchKillWither }, { "achievement.killWither", CustomStatistic::AchKillWither },
{ "achievement.fullBeacon", Statistic::AchFullBeacon }, { "achievement.fullBeacon", CustomStatistic::AchFullBeacon },
{ "achievement.breedCow", Statistic::AchBreedCow }, { "achievement.breedCow", CustomStatistic::AchBreedCow },
{ "achievement.diamondsToYou", Statistic::AchDiamondsToYou }, { "achievement.diamondsToYou", CustomStatistic::AchDiamondsToYou },
{ "stat.animalsBred", Statistic::AnimalsBred }, { "stat.animalsBred", CustomStatistic::AnimalsBred },
{ "stat.boatOneCm", Statistic::BoatOneCm }, { "stat.boatOneCm", CustomStatistic::BoatOneCm },
{ "stat.climbOneCm", Statistic::ClimbOneCm }, { "stat.climbOneCm", CustomStatistic::ClimbOneCm },
{ "stat.crouchOneCm", Statistic::CrouchOneCm }, { "stat.crouchOneCm", CustomStatistic::CrouchOneCm },
{ "stat.damageDealt", Statistic::DamageDealt }, { "stat.damageDealt", CustomStatistic::DamageDealt },
{ "stat.damageTaken", Statistic::DamageTaken }, { "stat.damageTaken", CustomStatistic::DamageTaken },
{ "stat.deaths", Statistic::Deaths }, { "stat.deaths", CustomStatistic::Deaths },
{ "stat.drop", Statistic::Drop }, { "stat.drop", CustomStatistic::Drop },
{ "stat.fallOneCm", Statistic::FallOneCm }, { "stat.fallOneCm", CustomStatistic::FallOneCm },
{ "stat.fishCaught", Statistic::FishCaught }, { "stat.fishCaught", CustomStatistic::FishCaught },
{ "stat.flyOneCm", Statistic::FlyOneCm }, { "stat.flyOneCm", CustomStatistic::FlyOneCm },
{ "stat.horseOneCm", Statistic::HorseOneCm }, { "stat.horseOneCm", CustomStatistic::HorseOneCm },
{ "stat.jump", Statistic::Jump }, { "stat.jump", CustomStatistic::Jump },
{ "stat.leaveGame", Statistic::LeaveGame }, { "stat.leaveGame", CustomStatistic::LeaveGame },
{ "stat.minecartOneCm", Statistic::MinecartOneCm }, { "stat.minecartOneCm", CustomStatistic::MinecartOneCm },
{ "stat.mobKills", Statistic::MobKills }, { "stat.mobKills", CustomStatistic::MobKills },
{ "stat.pigOneCm", Statistic::PigOneCm }, { "stat.pigOneCm", CustomStatistic::PigOneCm },
{ "stat.playerKills", Statistic::PlayerKills }, { "stat.playerKills", CustomStatistic::PlayerKills },
{ "stat.playOneMinute", Statistic::PlayOneMinute }, { "stat.playOneMinute", CustomStatistic::PlayOneMinute },
{ "stat.sprintOneCm", Statistic::SprintOneCm }, { "stat.sprintOneCm", CustomStatistic::SprintOneCm },
{ "stat.swimOneCm", Statistic::SwimOneCm }, { "stat.swimOneCm", CustomStatistic::SwimOneCm },
{ "stat.talkedToVillager", Statistic::TalkedToVillager }, { "stat.talkedToVillager", CustomStatistic::TalkedToVillager },
{ "stat.timeSinceDeath", Statistic::TimeSinceDeath }, { "stat.timeSinceDeath", CustomStatistic::TimeSinceDeath },
{ "stat.tradedWithVillager", Statistic::TradedWithVillager }, { "stat.tradedWithVillager", CustomStatistic::TradedWithVillager },
{ "stat.walkOneCm", Statistic::WalkOneCm }, { "stat.walkOneCm", CustomStatistic::WalkOneCm },
{ "stat.diveOneCm", Statistic::WalkUnderWaterOneCm }, { "stat.diveOneCm", CustomStatistic::WalkUnderWaterOneCm },
{ "stat.armorCleaned", Statistic::CleanArmor }, { "stat.armorCleaned", CustomStatistic::CleanArmor },
{ "stat.bannerCleaned", Statistic::CleanBanner }, { "stat.bannerCleaned", CustomStatistic::CleanBanner },
{ "stat.cakeSlicesEaten", Statistic::EatCakeSlice }, { "stat.cakeSlicesEaten", CustomStatistic::EatCakeSlice },
{ "stat.itemEnchanted", Statistic::EnchantItem }, { "stat.itemEnchanted", CustomStatistic::EnchantItem },
{ "stat.cauldronFilled", Statistic::FillCauldron }, { "stat.cauldronFilled", CustomStatistic::FillCauldron },
{ "stat.dispenserInspected", Statistic::InspectDispenser }, { "stat.dispenserInspected", CustomStatistic::InspectDispenser },
{ "stat.dropperInspected", Statistic::InspectDropper }, { "stat.dropperInspected", CustomStatistic::InspectDropper },
{ "stat.hopperInspected", Statistic::InspectHopper }, { "stat.hopperInspected", CustomStatistic::InspectHopper },
{ "stat.beaconInteraction", Statistic::InteractWithBeacon }, { "stat.beaconInteraction", CustomStatistic::InteractWithBeacon },
{ "stat.brewingstandInteraction", Statistic::InteractWithBrewingstand }, { "stat.brewingstandInteraction", CustomStatistic::InteractWithBrewingstand },
{ "stat.craftingTableInteraction", Statistic::InteractWithCraftingTable }, { "stat.craftingTableInteraction", CustomStatistic::InteractWithCraftingTable },
{ "stat.furnaceInteraction", Statistic::InteractWithFurnace }, { "stat.furnaceInteraction", CustomStatistic::InteractWithFurnace },
{ "stat.chestOpened", Statistic::OpenChest }, { "stat.chestOpened", CustomStatistic::OpenChest },
{ "stat.enderchestOpened", Statistic::OpenEnderchest }, { "stat.enderchestOpened", CustomStatistic::OpenEnderchest },
{ "stat.noteblockPlayed", Statistic::PlayNoteblock }, { "stat.noteblockPlayed", CustomStatistic::PlayNoteblock },
{ "stat.recordPlayed", Statistic::PlayRecord }, { "stat.recordPlayed", CustomStatistic::PlayRecord },
{ "stat.flowerPotted", Statistic::PotFlower }, { "stat.flowerPotted", CustomStatistic::PotFlower },
{ "stat.trappedChestTriggered", Statistic::TriggerTrappedChest }, { "stat.trappedChestTriggered", CustomStatistic::TriggerTrappedChest },
{ "stat.noteblockTuned", Statistic::TuneNoteblock }, { "stat.noteblockTuned", CustomStatistic::TuneNoteblock },
{ "stat.cauldronUsed", Statistic::UseCauldron }, { "stat.cauldronUsed", CustomStatistic::UseCauldron },
{ "stat.aviateOneCm", Statistic::AviateOneCm }, { "stat.aviateOneCm", CustomStatistic::AviateOneCm },
{ "stat.sleepInBed", Statistic::SleepInBed }, { "stat.sleepInBed", CustomStatistic::SleepInBed },
{ "stat.sneakTime", Statistic::SneakTime } { "stat.sneakTime", CustomStatistic::SneakTime }
}; };
for (auto Entry = In.begin(); Entry != In.end(); ++Entry) for (auto Entry = In.begin(); Entry != In.end(); ++Entry)
@ -151,7 +148,7 @@ namespace StatSerializer
if ((FindResult != LegacyMapping.end()) && Entry->isInt()) if ((FindResult != LegacyMapping.end()) && Entry->isInt())
{ {
Manager.SetValue(FindResult->second, Entry->asUInt()); Manager.Custom[FindResult->second] = Entry->asUInt();
} }
} }
} }
@ -160,7 +157,7 @@ namespace StatSerializer
static void LoadCustomStatFromJSON(cStatManager & Manager, const Json::Value & a_In) static void LoadCustomStatFromJSON(StatisticsManager & Manager, const Json::Value & a_In)
{ {
for (auto it = a_In.begin(); it != a_In.end(); ++it) for (auto it = a_In.begin(); it != a_In.end(); ++it)
{ {
@ -175,7 +172,7 @@ namespace StatSerializer
const auto & StatName = StatInfo.second; const auto & StatName = StatInfo.second;
try try
{ {
Manager.SetValue(NamespaceSerializer::ToCustomStatistic(StatName), it->asUInt()); Manager.Custom[NamespaceSerializer::ToCustomStatistic(StatName)] = it->asUInt();
} }
catch (const std::out_of_range &) catch (const std::out_of_range &)
{ {
@ -192,7 +189,7 @@ namespace StatSerializer
void Load(cStatManager & Manager, const std::string & WorldPath, std::string && FileName) void Load(StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName)
{ {
Json::Value Root; Json::Value Root;
InputFileStream(MakeStatisticsDirectory(WorldPath, std::move(FileName))) >> Root; InputFileStream(MakeStatisticsDirectory(WorldPath, std::move(FileName))) >> Root;
@ -205,7 +202,7 @@ namespace StatSerializer
void Save(const cStatManager & Manager, const std::string & WorldPath, std::string && FileName) void Save(const StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName)
{ {
Json::Value Root; Json::Value Root;

View File

@ -13,8 +13,7 @@
// fwd: struct StatisticsManager;
class cStatManager;
namespace Json { class Value; } namespace Json { class Value; }
@ -24,8 +23,8 @@ namespace Json { class Value; }
namespace StatSerializer namespace StatSerializer
{ {
/* Try to load the player statistics. */ /* Try to load the player statistics. */
void Load(cStatManager & Manager, const std::string & WorldPath, std::string && FileName); void Load(StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName);
/* Try to save the player statistics. */ /* Try to save the player statistics. */
void Save(const cStatManager & Manager, const std::string & WorldPath, std::string && FileName); void Save(const StatisticsManager & Manager, const std::string & WorldPath, std::string && FileName);
} }