diff --git a/dGame/dUtilities/Mail.cpp b/dGame/dUtilities/Mail.cpp index e7630ed6c..6254954c1 100644 --- a/dGame/dUtilities/Mail.cpp +++ b/dGame/dUtilities/Mail.cpp @@ -443,6 +443,14 @@ void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, LWOOBJ response.Send(sysAddr); } +void Mail::NotifyUnreadMailOnLoad(const uint32_t unreadCount, const SystemAddress& sysAddr) { + if (unreadCount == 0) return; + NotificationResponse response; + response.status = eNotificationResponse::NewMail; + response.mailCount = unreadCount; + response.Send(sysAddr); +} + bool Mail::NotifyNewMailHere(LWOOBJID receiver) { // Mail stores the character ID; the player's object ID also carries the character bit GeneralUtils::SetBit(receiver, eObjectBits::CHARACTER); diff --git a/dGame/dUtilities/Mail.h b/dGame/dUtilities/Mail.h index 3fdc8084c..aaab9b4a9 100644 --- a/dGame/dUtilities/Mail.h +++ b/dGame/dUtilities/Mail.h @@ -210,6 +210,10 @@ namespace Mail { void HandleMail(RakNet::BitStream& inStream, const SystemAddress& sysAddr, Entity* player); + // Part of a player's load: live told the client about unread mail right after the respawn checkpoint, without + // being asked (NotificationResponse NewMail with the count), and sent nothing when there was none. + void NotifyUnreadMailOnLoad(uint32_t unreadCount, const SystemAddress& sysAddr); + // Tells the receiver about their unread mail if they are a player in this world. Returns false if they are not. bool NotifyNewMailHere(LWOOBJID receiver); diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 9dd673c96..2a4529c0a 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1136,10 +1136,7 @@ void LoadPlayer(const SystemAddress& sysAddr) { invalidTransferList.bCustomerFeedbackOnInvalidMapTransfer = false; invalidTransferList.SendToClient(sysAddr); GameMessages::SendDoneLoading(player->GetObjectID(), respawnPoint, spawnPosition, spawnRotation, sysAddr); - - //Send the player it's mail count: - //update: this might not be needed so im going to try disabling this here. - //Mail::HandleNotificationRequest(sysAddr, player->GetObjectID()); + Mail::NotifyUnreadMailOnLoad(Database::Get()->GetUnreadMailCount(c->GetID()), sysAddr); //Notify chat that a player has loaded: auto* character = player->GetCharacter(); diff --git a/tests/dGameTests/dGameMessagesTests/LoadSequenceTests.cpp b/tests/dGameTests/dGameMessagesTests/LoadSequenceTests.cpp index fb88cf906..ac96042c1 100644 --- a/tests/dGameTests/dGameMessagesTests/LoadSequenceTests.cpp +++ b/tests/dGameTests/dGameMessagesTests/LoadSequenceTests.cpp @@ -1,6 +1,7 @@ #include "GameDependencies.h" #include "GameMessageTestUtils.h" +#include "Mail.h" #include "MovementMessages.h" #include "ZoneMessages.h" @@ -63,3 +64,17 @@ TEST_F(LoadSequenceTests, SavedCheckpointIsSentUnrotated) { EXPECT_EQ(checkpoints[0].pos, saved); EXPECT_EQ(checkpoints[0].rot, QuatUtils::IDENTITY); } + +// Unread mail is announced during the load without the client asking; nothing is sent without unread mail. +// Live's packet (56 bytes) also fills the three fields DLU leaves 0 with object IDs the client does not use here. +TEST_F(LoadSequenceTests, UnreadMailIsAnnouncedOnLoad) { + auto sent = Capture([&] { Mail::NotifyUnreadMailOnLoad(0, ClientAddress()); }); + EXPECT_TRUE(sent.empty()); + + sent = Capture([&] { Mail::NotifyUnreadMailOnLoad(1, ClientAddress()); }); + ASSERT_EQ(sent.size(), 1u); + EXPECT_EQ(sent[0].sysAddr, ClientAddress()); + EXPECT_PACKET_EQ(FromHex( + "53 05 00 31 00 00 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 " + "00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00"), FromCapture(sent[0])); +}