mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2026-11-15 00:07:13 +00:00
fix(character): the character data packet sends txfring=true, as live
LWOInventoryComponent_Client::LoadConfigData (0x00cde200) reads txfring from the character data; without it the client runs its inventory-full tips (msgPlayerReady 0x00bde5e0) on every world load. Of 226 captured live character data packets, 222 had the key, all true; the server never wrote it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -250,6 +250,7 @@ namespace ClientPackets {
|
||||
ldfData.Insert<int32_t>(u"chatmode", chatMode);
|
||||
ldfData.Insert<int64_t>(u"reputation", reputation);
|
||||
ldfData.Insert<int32_t>(u"propertycloneid", propertyCloneID);
|
||||
if (txfring) ldfData.Insert<bool>(u"txfring", true);
|
||||
|
||||
data.Write<uint32_t>(ldfData.values.size());
|
||||
for (const auto& toSerialize : ldfData | std::views::values) toSerialize->WriteToPacket(data);
|
||||
@@ -307,6 +308,7 @@ namespace ClientPackets {
|
||||
if (decompressedSize != static_cast<int32_t>(uncompressedSize)) return false;
|
||||
|
||||
RakNet::BitStream data(uncompressed.data(), uncompressed.size(), false);
|
||||
txfring = false; // the client's value without the key
|
||||
uint32_t count{};
|
||||
VALIDATE_READ(data.Read(count));
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
@@ -343,6 +345,12 @@ namespace ClientPackets {
|
||||
if (key == u"xmlData") xmlData = value;
|
||||
break;
|
||||
}
|
||||
case LDF_TYPE_BOOLEAN: {
|
||||
uint8_t value{};
|
||||
VALIDATE_READ(data.Read(value));
|
||||
if (key == u"txfring") txfring = value != 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false; // CreateCharacter never uses other types
|
||||
}
|
||||
|
||||
@@ -185,6 +185,10 @@ namespace ClientPackets {
|
||||
int32_t chatMode{}; // DLU sends the GM level
|
||||
int64_t reputation{};
|
||||
int32_t propertyCloneID{};
|
||||
// LWOInventoryComponent_Client::LoadConfigData (0x00cde200) reads it; live sent true in every character data
|
||||
// packet, and with it false the client shows inventory-full tips on every world load. Not written when false
|
||||
// (the client's default).
|
||||
bool txfring = true;
|
||||
|
||||
CreateCharacter() : LUBitStream(ServiceType::CLIENT, MessageType::Client::CREATE_CHARACTER) {}
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
|
||||
@@ -639,6 +639,7 @@ json ToJson(const ClientPackets::CreateCharacter& m) {
|
||||
j["chatMode"] = ToJson(m.chatMode);
|
||||
j["reputation"] = ToJson(m.reputation);
|
||||
j["propertyCloneID"] = ToJson(m.propertyCloneID);
|
||||
j["txfring"] = ToJson(m.txfring);
|
||||
return j;
|
||||
}
|
||||
json ToJson(const ClientPackets::ChatModerationString& m) {
|
||||
|
||||
@@ -309,6 +309,7 @@ TEST_F(WorldPacketsTests, CreateCharacterMatchesLegacy) {
|
||||
packet.chatMode = static_cast<int32_t>(gm);
|
||||
packet.reputation = reputation;
|
||||
packet.propertyCloneID = cloneID;
|
||||
packet.txfring = false; // the legacy sender never wrote it
|
||||
ExpectSameSend([&](const SystemAddress& a) { LegacyWorldPackets::SendCreateCharacter(a, reputation, objectID, xml, name, gm, cloneID); }, packet);
|
||||
|
||||
const auto copy = RoundTrip(packet);
|
||||
@@ -329,6 +330,16 @@ TEST_F(WorldPacketsTests, CreateCharacterMatchesLegacy) {
|
||||
ExpectTruncatedFails(packet);
|
||||
}
|
||||
|
||||
// Live sent txfring=true in every character data packet (222 of the 222 that had the key, of 226)
|
||||
TEST_F(WorldPacketsTests, CreateCharacterSendsTxfring) {
|
||||
ClientPackets::CreateCharacter packet;
|
||||
EXPECT_TRUE(packet.txfring);
|
||||
EXPECT_TRUE(RoundTrip(packet).txfring);
|
||||
|
||||
packet.txfring = false;
|
||||
EXPECT_FALSE(RoundTrip(packet).txfring);
|
||||
}
|
||||
|
||||
TEST_F(WorldPacketsTests, CharacterListMatchesLegacy) {
|
||||
FakeCharacter first;
|
||||
FakeCharacter second;
|
||||
|
||||
Reference in New Issue
Block a user