Core/Mail: Load mails at login instead of on demand when queried by packets (logging in always sends one of the packets that cause mail loading anyway)

Port From (https://github.com/TrinityCore/TrinityCore/commit/a9b4f9aca0d0b90e59e0ed26e9bb4cce7d0ceeab)
This commit is contained in:
hondacrx
2022-03-02 09:52:35 -05:00
parent 6e6ee2d694
commit 150b09205b
9 changed files with 95 additions and 126 deletions
@@ -118,8 +118,6 @@ namespace Framework.Database
PrepareStatement(CharStatements.SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_REPUTATION, "SELECT faction, standing, flags FROM character_reputation WHERE guid = ?");
PrepareStatement(CharStatements.SEL_CHARACTER_INVENTORY, "SELECT " + SelectItemInstanceContent + ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC"); PrepareStatement(CharStatements.SEL_CHARACTER_INVENTORY, "SELECT " + SelectItemInstanceContent + ", bag, slot FROM character_inventory ci JOIN item_instance ii ON ci.item = ii.guid LEFT JOIN item_instance_gems ig ON ii.guid = ig.itemGuid LEFT JOIN item_instance_transmog iit ON ii.guid = iit.itemGuid LEFT JOIN item_instance_modifiers im ON ii.guid = im.itemGuid WHERE ci.guid = ? ORDER BY (ii.flags & 0x80000) ASC, bag ASC, slot ASC");
PrepareStatement(CharStatements.SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activeTalentGroup AND a.guid = ? ORDER BY button"); PrepareStatement(CharStatements.SEL_CHARACTER_ACTIONS, "SELECT a.button, a.action, a.type FROM character_action as a, characters as c WHERE a.guid = c.guid AND a.spec = c.activeTalentGroup AND a.guid = ? ORDER BY button");
PrepareStatement(CharStatements.SEL_CHARACTER_MAILCOUNT, "SELECT COUNT(id) FROM mail WHERE receiver = ? AND (checked & 1) = 0 AND deliver_time <= ?");
PrepareStatement(CharStatements.SEL_CHARACTER_MAILDATE, "SELECT MIN(deliver_time) FROM mail WHERE receiver = ? AND (checked & 1) = 0");
PrepareStatement(CharStatements.SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?"); PrepareStatement(CharStatements.SEL_MAIL_COUNT, "SELECT COUNT(*) FROM mail WHERE receiver = ?");
PrepareStatement(CharStatements.SEL_CHARACTER_SOCIALLIST, "SELECT cs.friend, c.account, cs.flags, cs.note FROM character_social cs JOIN characters c ON c.guid = cs.friend WHERE cs.guid = ? AND c.deleteinfos_name IS NULL LIMIT 255"); PrepareStatement(CharStatements.SEL_CHARACTER_SOCIALLIST, "SELECT cs.friend, c.account, cs.flags, cs.note FROM character_social cs JOIN characters c ON c.guid = cs.friend WHERE cs.guid = ? AND c.deleteinfos_name IS NULL LIMIT 255");
PrepareStatement(CharStatements.SEL_CHARACTER_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ, orientation FROM character_homebind WHERE guid = ?"); PrepareStatement(CharStatements.SEL_CHARACTER_HOMEBIND, "SELECT mapId, zoneId, posX, posY, posZ, orientation FROM character_homebind WHERE guid = ?");
@@ -860,8 +858,6 @@ namespace Framework.Database
SEL_CHARACTER_INVENTORY, SEL_CHARACTER_INVENTORY,
SEL_CHARACTER_ACTIONS, SEL_CHARACTER_ACTIONS,
SEL_CHARACTER_ACTIONS_SPEC, SEL_CHARACTER_ACTIONS_SPEC,
SEL_CHARACTER_MAILCOUNT,
SEL_CHARACTER_MAILDATE,
SEL_MAIL_COUNT, SEL_MAIL_COUNT,
SEL_CHARACTER_SOCIALLIST, SEL_CHARACTER_SOCIALLIST,
SEL_CHARACTER_HOMEBIND, SEL_CHARACTER_HOMEBIND,
+1 -1
View File
@@ -680,7 +680,7 @@ namespace Game.Chat
if (target != null) if (target != null)
target_ac_sec = target.GetSecurity(); target_ac_sec = target.GetSecurity();
else if (target_account != 0) else if (target_account != 0)
target_ac_sec = Global.AccountMgr.GetSecurity(target_account); target_ac_sec = Global.AccountMgr.GetSecurity(target_account, (int)Global.WorldMgr.GetRealmId().Index);
else else
return true; // caller must report error for (target == NULL && target_account == 0) return true; // caller must report error for (target == NULL && target_account == 0)
+30 -62
View File
@@ -1180,47 +1180,36 @@ namespace Game.Entities
} }
while (result.NextRow()); while (result.NextRow());
} }
void _LoadMailInit(SQLResult resultUnread, SQLResult resultDelivery)
{
if (!resultUnread.IsEmpty())
unReadMails = (byte)resultUnread.Read<ulong>(0);
if (!resultDelivery.IsEmpty()) public void _LoadMail(SQLResult mailsResult, SQLResult mailItemsResult, SQLResult artifactResult, SQLResult azeriteItemResult, SQLResult azeriteItemMilestonePowersResult, SQLResult azeriteItemUnlockedEssencesResult, SQLResult azeriteEmpoweredItemResult)
m_nextMailDelivereTime = resultDelivery.Read<uint>(0);
}
public void _LoadMail()
{ {
m_mail.Clear(); m_mail.Clear();
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAIL);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult result = DB.Characters.Query(stmt);
Dictionary<uint, Mail> mailById = new(); Dictionary<uint, Mail> mailById = new();
if (!result.IsEmpty()) if (!mailsResult.IsEmpty())
{ {
do do
{ {
Mail m = new(); Mail m = new();
m.messageID = result.Read<uint>(0); m.messageID = mailsResult.Read<uint>(0);
m.messageType = (MailMessageType)result.Read<byte>(1); m.messageType = (MailMessageType)mailsResult.Read<byte>(1);
m.sender = result.Read<uint>(2); m.sender = mailsResult.Read<uint>(2);
m.receiver = result.Read<uint>(3); m.receiver = mailsResult.Read<uint>(3);
m.subject = result.Read<string>(4); m.subject = mailsResult.Read<string>(4);
m.body = result.Read<string>(5); m.body = mailsResult.Read<string>(5);
m.expire_time = result.Read<long>(6); m.expire_time = mailsResult.Read<long>(6);
m.deliver_time = result.Read<long>(7); m.deliver_time = mailsResult.Read<long>(7);
m.money = result.Read<ulong>(8); m.money = mailsResult.Read<ulong>(8);
m.COD = result.Read<ulong>(9); m.COD = mailsResult.Read<ulong>(9);
m.checkMask = (MailCheckMask)result.Read<byte>(10); m.checkMask = (MailCheckMask)mailsResult.Read<byte>(10);
m.stationery = (MailStationery)result.Read<byte>(11); m.stationery = (MailStationery)mailsResult.Read<byte>(11);
m.mailTemplateId = result.Read<ushort>(12); m.mailTemplateId = mailsResult.Read<ushort>(12);
if (m.mailTemplateId != 0 && !CliDB.MailTemplateStorage.ContainsKey(m.mailTemplateId)) if (m.mailTemplateId != 0 && !CliDB.MailTemplateStorage.ContainsKey(m.mailTemplateId))
{ {
Log.outError(LogFilter.Player, "Player:_LoadMail - Mail ({0}) have not existed MailTemplateId ({1}), remove at load", m.messageID, m.mailTemplateId); Log.outError(LogFilter.Player, $"Player:_LoadMail - Mail ({m.messageID}) have not existed MailTemplateId ({m.mailTemplateId}), remove at load");
m.mailTemplateId = 0; m.mailTemplateId = 0;
} }
@@ -1229,47 +1218,23 @@ namespace Game.Entities
m_mail.Add(m); m_mail.Add(m);
mailById[m.messageID] = m; mailById[m.messageID] = m;
} }
while (result.NextRow()); while (mailsResult.NextRow());
} }
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS); if (!mailItemsResult.IsEmpty())
stmt.AddValue(0, GetGUID().GetCounter());
result = DB.Characters.Query(stmt);
if (!result.IsEmpty())
{ {
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_ARTIFACT);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult artifactResult = DB.Characters.Query(stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult azeriteResult = DB.Characters.Query(stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE_MILESTONE_POWER);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult azeriteItemMilestonePowersResult = DB.Characters.Query(stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE_UNLOCKED_ESSENCE);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult azeriteItemUnlockedEssencesResult = DB.Characters.Query(stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE_EMPOWERED);
stmt.AddValue(0, GetGUID().GetCounter());
SQLResult azeriteEmpoweredItemResult = DB.Characters.Query(stmt);
Dictionary<ulong, ItemAdditionalLoadInfo> additionalData = new(); Dictionary<ulong, ItemAdditionalLoadInfo> additionalData = new();
ItemAdditionalLoadInfo.Init(additionalData, artifactResult, azeriteResult, azeriteItemMilestonePowersResult, azeriteItemUnlockedEssencesResult, azeriteEmpoweredItemResult); ItemAdditionalLoadInfo.Init(additionalData, artifactResult, azeriteItemResult, azeriteItemMilestonePowersResult, azeriteItemUnlockedEssencesResult, azeriteEmpoweredItemResult);
do do
{ {
uint mailId = result.Read<uint>(52); uint mailId = mailItemsResult.Read<uint>(52);
_LoadMailedItem(GetGUID(), this, mailId, mailById[mailId], result.GetFields(), additionalData.LookupByKey(result.Read<ulong>(0))); _LoadMailedItem(GetGUID(), this, mailId, mailById[mailId], mailItemsResult.GetFields(), additionalData.LookupByKey(mailItemsResult.Read<ulong>(0)));
} }
while (result.NextRow()); while (mailItemsResult.NextRow());
} }
m_mailsLoaded = true; UpdateNextMailTimeAndUnreads();
} }
static Item _LoadMailedItem(ObjectGuid playerGuid, Player player, uint mailId, Mail mail, SQLFields fields, ItemAdditionalLoadInfo addionalData) static Item _LoadMailedItem(ObjectGuid playerGuid, Player player, uint mailId, Mail mail, SQLFields fields, ItemAdditionalLoadInfo addionalData)
@@ -2199,9 +2164,6 @@ namespace Game.Entities
} }
public void _SaveMail(SQLTransaction trans) public void _SaveMail(SQLTransaction trans)
{ {
if (!m_mailsLoaded)
return;
PreparedStatement stmt; PreparedStatement stmt;
foreach (var m in m_mail) foreach (var m in m_mail)
@@ -3174,7 +3136,13 @@ namespace Game.Entities
_LoadActions(holder.GetResult(PlayerLoginQueryLoad.Actions)); _LoadActions(holder.GetResult(PlayerLoginQueryLoad.Actions));
// unread mails and next delivery time, actual mails not loaded // unread mails and next delivery time, actual mails not loaded
_LoadMailInit(holder.GetResult(PlayerLoginQueryLoad.MailCount), holder.GetResult(PlayerLoginQueryLoad.MailDate)); _LoadMail(holder.GetResult(PlayerLoginQueryLoad.Mails),
holder.GetResult(PlayerLoginQueryLoad.MailItems),
holder.GetResult(PlayerLoginQueryLoad.MailItemsArtifact),
holder.GetResult(PlayerLoginQueryLoad.MailItemsAzerite),
holder.GetResult(PlayerLoginQueryLoad.MailItemsAzeriteMilestonePower),
holder.GetResult(PlayerLoginQueryLoad.MailItemsAzeriteUnlockedEssence),
holder.GetResult(PlayerLoginQueryLoad.MailItemsAzeriteEmpowered));
m_social = Global.SocialMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.SocialList), GetGUID()); m_social = Global.SocialMgr.LoadFromDB(holder.GetResult(PlayerLoginQueryLoad.SocialList), GetGUID());
@@ -127,7 +127,6 @@ namespace Game.Entities
Dictionary<ulong, Item> mMitems = new(); Dictionary<ulong, Item> mMitems = new();
public byte unReadMails; public byte unReadMails;
long m_nextMailDelivereTime; long m_nextMailDelivereTime;
public bool m_mailsLoaded;
public bool m_mailsUpdated; public bool m_mailsUpdated;
//Pets //Pets
-1
View File
@@ -2751,7 +2751,6 @@ namespace Game.Entities
m_nextMailDelivereTime = deliver_time; m_nextMailDelivereTime = deliver_time;
} }
} }
public bool IsMailsLoaded() { return m_mailsLoaded; }
public void AddMItem(Item it) public void AddMItem(Item it)
{ {
mMitems[it.GetGUID().GetCounter()] = it; mMitems[it.GetGUID().GetCounter()] = it;
+5 -11
View File
@@ -9440,11 +9440,15 @@ namespace Game
uint returnedCount = 0; uint returnedCount = 0;
do do
{ {
ulong receiver = result.Read<ulong>(3);
if (serverUp && Global.ObjAccessor.FindConnectedPlayer(ObjectGuid.Create(HighGuid.Player, receiver)))
continue;
Mail m = new(); Mail m = new();
m.messageID = result.Read<uint>(0); m.messageID = result.Read<uint>(0);
m.messageType = (MailMessageType)result.Read<byte>(1); m.messageType = (MailMessageType)result.Read<byte>(1);
m.sender = result.Read<uint>(2); m.sender = result.Read<uint>(2);
m.receiver = result.Read<ulong>(3); m.receiver = receiver;
bool has_items = result.Read<bool>(4); bool has_items = result.Read<bool>(4);
m.expire_time = result.Read<long>(5); m.expire_time = result.Read<long>(5);
m.deliver_time = 0; m.deliver_time = 0;
@@ -9452,16 +9456,6 @@ namespace Game
m.checkMask = (MailCheckMask)result.Read<byte>(7); m.checkMask = (MailCheckMask)result.Read<byte>(7);
m.mailTemplateId = result.Read<ushort>(8); m.mailTemplateId = result.Read<ushort>(8);
Player player = null;
if (serverUp)
player = Global.ObjAccessor.FindPlayer(ObjectGuid.Create(HighGuid.Player, m.receiver));
if (player && player.m_mailsLoaded)
{ // this code will run very improbably (the time is between 4 and 5 am, in game is online a player, who has old mail
// his in mailbox and he has already listed his mails)
continue;
}
// Delete or return mail // Delete or return mail
if (has_items) if (has_items)
{ {
+31 -7
View File
@@ -2693,14 +2693,33 @@ namespace Game
stmt.AddValue(0, lowGuid); stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.Actions, stmt); SetQuery(PlayerLoginQueryLoad.Actions, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_MAILCOUNT); stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAIL);
stmt.AddValue(0, lowGuid); stmt.AddValue(0, lowGuid);
stmt.AddValue(1, GameTime.GetGameTime()); SetQuery(PlayerLoginQueryLoad.Mails, stmt);
SetQuery(PlayerLoginQueryLoad.MailCount, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_MAILDATE); stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS);
stmt.AddValue(0, lowGuid); stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.MailDate, stmt); SetQuery(PlayerLoginQueryLoad.MailItems, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_ARTIFACT);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.MailItemsArtifact, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.MailItemsAzerite, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE_MILESTONE_POWER);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.MailItemsAzeriteMilestonePower, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE_UNLOCKED_ESSENCE);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.MailItemsAzeriteUnlockedEssence, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_MAILITEMS_AZERITE_EMPOWERED);
stmt.AddValue(0, lowGuid);
SetQuery(PlayerLoginQueryLoad.MailItemsAzeriteEmpowered, stmt);
stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_SOCIALLIST); stmt = DB.Characters.GetPreparedStatement(CharStatements.SEL_CHARACTER_SOCIALLIST);
stmt.AddValue(0, lowGuid); stmt.AddValue(0, lowGuid);
@@ -2884,8 +2903,13 @@ namespace Game
AzeriteUnlockedEssences, AzeriteUnlockedEssences,
AzeriteEmpowered, AzeriteEmpowered,
Actions, Actions,
MailCount, Mails,
MailDate, MailItems,
MailItemsArtifact,
MailItemsAzerite,
MailItemsAzeriteMilestonePower,
MailItemsAzeriteUnlockedEssence,
MailItemsAzeriteEmpowered,
SocialList, SocialList,
HomeBind, HomeBind,
SpellCooldowns, SpellCooldowns,
-7
View File
@@ -568,10 +568,6 @@ namespace Game
Player player = GetPlayer(); Player player = GetPlayer();
//load players mails, and mailed items
if (!player.m_mailsLoaded)
player._LoadMail();
var mails = player.GetMails(); var mails = player.GetMails();
MailListResult response = new(); MailListResult response = new();
@@ -658,9 +654,6 @@ namespace Game
{ {
MailQueryNextTimeResult result = new(); MailQueryNextTimeResult result = new();
if (!GetPlayer().m_mailsLoaded)
GetPlayer()._LoadMail();
if (GetPlayer().unReadMails > 0) if (GetPlayer().unReadMails > 0)
{ {
result.NextMailTime = 0.0f; result.NextMailTime = 0.0f;
+28 -32
View File
@@ -159,9 +159,9 @@ namespace Game.Mails
// default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master) // default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master)
else else
if (m_COD != 0) if (m_COD != 0)
expire_delay = 3 * Time.Day; expire_delay = 3 * Time.Day;
else else
expire_delay = (uint)(pSender != null && pSender.IsGameMaster() ? 90 * Time.Day : 30 * Time.Day); expire_delay = (uint)(pSender != null && pSender.IsGameMaster() ? 90 * Time.Day : 30 * Time.Day);
long expire_time = deliver_time + expire_delay; long expire_time = deliver_time + expire_delay;
@@ -198,38 +198,34 @@ namespace Game.Mails
{ {
pReceiver.AddNewMailDeliverTime(deliver_time); pReceiver.AddNewMailDeliverTime(deliver_time);
if (pReceiver.IsMailsLoaded())
Mail m = new();
m.messageID = mailId;
m.mailTemplateId = GetMailTemplateId();
m.subject = GetSubject();
m.body = GetBody();
m.money = GetMoney();
m.COD = GetCOD();
foreach (var item in m_items.Values)
m.AddItem(item.GetGUID().GetCounter(), item.GetEntry());
m.messageType = sender.GetMailMessageType();
m.stationery = sender.GetStationery();
m.sender = sender.GetSenderId();
m.receiver = receiver.GetPlayerGUIDLow();
m.expire_time = expire_time;
m.deliver_time = deliver_time;
m.checkMask = checkMask;
m.state = MailState.Unchanged;
pReceiver.AddMail(m); // to insert new mail to beginning of maillist
if (!m_items.Empty())
{ {
Mail m = new();
m.messageID = mailId;
m.mailTemplateId = GetMailTemplateId();
m.subject = GetSubject();
m.body = GetBody();
m.money = GetMoney();
m.COD = GetCOD();
foreach (var item in m_items.Values) foreach (var item in m_items.Values)
m.AddItem(item.GetGUID().GetCounter(), item.GetEntry()); pReceiver.AddMItem(item);
m.messageType = sender.GetMailMessageType();
m.stationery = sender.GetStationery();
m.sender = sender.GetSenderId();
m.receiver = receiver.GetPlayerGUIDLow();
m.expire_time = expire_time;
m.deliver_time = deliver_time;
m.checkMask = checkMask;
m.state = MailState.Unchanged;
pReceiver.AddMail(m); // to insert new mail to beginning of maillist
if (!m_items.Empty())
{
foreach (var item in m_items.Values)
pReceiver.AddMItem(item);
}
} }
else if (!m_items.Empty())
DeleteIncludedItems(null);
} }
else if (!m_items.Empty()) else if (!m_items.Empty())
DeleteIncludedItems(null); DeleteIncludedItems(null);