test(messages): UpdatePlayerStatistic against live capture packets

Live sent UpdatePlayerStatistic (1481) server to client; the struct
already reads and writes those packets. Documents what the client does
with it. Needs the FromLiveCapture test helper.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-28 23:40:14 -05:00
parent 7621a4fcdc
commit a61a01c4fb
2 changed files with 24 additions and 1 deletions

View File

@@ -100,7 +100,9 @@ namespace GameMessages {
LWOMAPID zoneID{ LWOMAPID_INVALID }; // optional
};
// Client -> server.
// Client -> server here; live sent it server -> client (live captures hold no client -> server copy). The client's CharacterComponent adds updateValue
// to the passport statistic and, for every statistic but MetersTraveled, updates the passport UI. updateID is a
// StatisticID. See docs/CaptureUnknowns.md.
struct UpdatePlayerStatistic : public NetGameMsg {
UpdatePlayerStatistic() : NetGameMsg(MessageType::Game::UPDATE_PLAYER_STATISTIC) {}
void Serialize(RakNet::BitStream& bitStream) const override;

View File

@@ -6,6 +6,7 @@
#include "ObjectMessages.h"
#include "PlayerMessages.h"
#include "QuickBuildMessages.h"
#include "StatisticID.h"
#include "ZoneMessages.h"
#include <array>
@@ -722,3 +723,23 @@ TEST_F(RemainingMessagesTests, LeaderboardMessagesMatchLegacy) {
data.leaderboard = &leaderboard;
ExpectSameAsLegacy([&](const SystemAddress& address) { LegacyGameMessages::SendActivitySummaryLeaderboardData(0x1000000000000001LL, &leaderboard, address); }, data, SendMode::SendToClient);
}
// Packets from 2011/2012 live captures: live sent UpdatePlayerStatistic (1481) server -> client. The client reads
// a u32 statistic and an optional i64 amount that defaults to 1 (0x00d8c870 in 1.10.64).
TEST_F(RemainingMessagesTests, UpdatePlayerStatisticMatchesLiveCapture) {
// CurrencyCollected after a SetCurrency, amount left at the default.
const auto currency = FromLiveCapture<GameMessages::UpdatePlayerStatistic>("5305000c000000005e7dea8e00000010c9050100000000");
EXPECT_EQ(currency.target, 0x100000008eea7d5eLL);
EXPECT_EQ(currency.updateID, static_cast<int32_t>(StatisticID::CurrencyCollected));
EXPECT_EQ(currency.updateValue, 1);
// CurrencyCollected with an amount.
const auto coins = FromLiveCapture<GameMessages::UpdatePlayerStatistic>("5305000c000000005e7dea8e00000010c90501000000fa0080000000000000");
EXPECT_EQ(coins.updateID, static_cast<int32_t>(StatisticID::CurrencyCollected));
EXPECT_EQ(coins.updateValue, 500);
// MetersTraveled, sent periodically while the player moves.
const auto meters = FromLiveCapture<GameMessages::UpdatePlayerStatistic>("5305000c000000005e7dea8e00000010c9050c0000008e8000000000000000");
EXPECT_EQ(meters.updateID, static_cast<int32_t>(StatisticID::MetersTraveled));
EXPECT_EQ(meters.updateValue, 29);
}