AzerothCore 3.3.5a
OpenSource WoW Emulator
Loading...
Searching...
No Matches
ServerMailMgr Class Reference

#include "ServerMailMgr.h"

Public Member Functions

void LoadMailServerTemplates ()
 Loads all server mail templates from the database into memory.
 
void LoadMailServerTemplatesItems ()
 Loads all items associated with server mail templates.
 
void LoadMailServerTemplatesConditions ()
 Loads all conditions associated with server mail templates.
 
ServerMailConditionType GetServerMailConditionType (std::string_view conditionTypeStr) const
 Convert DB value of conditionType to ServerMailConditionType.
 
bool ConditionTypeUsesConditionState (ServerMailConditionType type) const
 Check if ConditionType should use ConditionState.
 
void SendServerMail (Player *player, uint32 id, uint32 senderEntry, uint32 money, std::vector< ServerMailItems > const &items, std::vector< ServerMailCondition > const &conditions, std::string const &subject, std::string const &body) const
 Sends a server mail to a player if the template is active and the player is eligible.
 
ServerMailContainer const & GetAllServerMailStore () const
 Retrieves the entire server mail store.
 

Static Public Member Functions

static ServerMailMgrinstance ()
 

Private Member Functions

 ServerMailMgr ()=default
 
 ~ServerMailMgr ()=default
 

Private Attributes

ServerMailContainer _serverMailStore
 

Detailed Description

Constructor & Destructor Documentation

◆ ServerMailMgr()

ServerMailMgr::ServerMailMgr ( )
privatedefault

◆ ~ServerMailMgr()

ServerMailMgr::~ServerMailMgr ( )
privatedefault

Member Function Documentation

◆ ConditionTypeUsesConditionState()

bool ServerMailMgr::ConditionTypeUsesConditionState ( ServerMailConditionType  type) const

Check if ConditionType should use ConditionState.

Returns
True if the ConditionType is allowed to use ConditionState, otherwise False.
335{
336 switch (type)
337 {
340 return true;
341 default:
342 return false;
343 }
344}
@ Quest
Requires the player to have completed a specific quest.
@ Reputation
Requires the player to have earned reputation with a specific faction.

References Quest, and Reputation.

Referenced by LoadMailServerTemplatesConditions().

◆ GetAllServerMailStore()

ServerMailContainer const & ServerMailMgr::GetAllServerMailStore ( ) const
inline

Retrieves the entire server mail store.

This function returns a constant reference to the internal _serverMailStore container, which holds all server mail data.

Returns
A constant reference to the ServerMailContainer containing all stored server mail.
227{ return _serverMailStore; }
ServerMailContainer _serverMailStore
Definition ServerMailMgr.h:230

References _serverMailStore.

◆ GetServerMailConditionType()

ServerMailConditionType ServerMailMgr::GetServerMailConditionType ( std::string_view  conditionTypeStr) const

Convert DB value of conditionType to ServerMailConditionType.

Lookup the corresponding SeverMailConditionType enum for the provided string by DB. If the string is not found we return internal default value ServerMailConditionType::Invalid

Parameters
conditionTypeStrstring value from DB of conditionType
Returns
ServerMailConditionType The corresponding value (see ServerMailConditionType) or default to ServerMailConditionType::Invalid
326{
327 for (auto const& pair : ServerMailConditionTypePairs)
328 if (pair.first == conditionTypeStr)
329 return pair.second;
330
332}
@ Invalid
Internal use, not used in DB.
constexpr std::pair< std::string_view, ServerMailConditionType > ServerMailConditionTypePairs[]
Assign string condition to corresponding ServerMailConditionType enum value.
Definition ServerMailMgr.h:62

References Invalid, and ServerMailConditionTypePairs.

Referenced by LoadMailServerTemplatesConditions().

◆ instance()

ServerMailMgr * ServerMailMgr::instance ( )
static
33{
35 return &instance;
36}
Definition ServerMailMgr.h:149
static ServerMailMgr * instance()
Definition ServerMailMgr.cpp:32

References instance().

Referenced by instance().

◆ LoadMailServerTemplates()

void ServerMailMgr::LoadMailServerTemplates ( )

Loads all server mail templates from the database into memory.

Queries the mail_server_template table and loads all rows into memory. This method is intended to be called during server startup.

39{
40 uint32 oldMSTime = getMSTime();
41
42 _serverMailStore.clear(); // for reload case
43
44 // 0 1 2 3 4 5 6
45 QueryResult result = CharacterDatabase.Query("SELECT `id`, `senderEntry`, `moneyA`, `moneyH`, `subject`, `body`, `active` FROM `mail_server_template`");
46 if (!result)
47 {
48 LOG_INFO("server.loading", ">> Loaded 0 server mail rewards. DB table `mail_server_template` is empty.");
49 LOG_INFO("server.loading", " ");
50 return;
51 }
52
53 _serverMailStore.reserve(result->GetRowCount());
54
55 do
56 {
57 Field* fields = result->Fetch();
58
59 uint32 id = fields[0].Get<uint32>();
60
61 ServerMail& servMail = _serverMailStore[id];
62 servMail.id = id;
63 servMail.senderEntry = fields[1].Get<uint32>();
64 servMail.moneyA = fields[2].Get<uint32>();
65 servMail.moneyH = fields[3].Get<uint32>();
66 servMail.subject = fields[4].Get<std::string>();
67 servMail.body = fields[5].Get<std::string>();
68 servMail.active = fields[6].Get<uint8>();
69
70 // Skip non-activated entries
71 if (!servMail.active)
72 continue;
73
74 if (servMail.moneyA > MAX_MONEY_AMOUNT || servMail.moneyH > MAX_MONEY_AMOUNT)
75 {
76 LOG_ERROR("sql.sql", "Table `mail_server_template` has moneyA {} or moneyH {} larger than MAX_MONEY_AMOUNT {} for id {}, skipped.", servMail.moneyA, servMail.moneyH, MAX_MONEY_AMOUNT, servMail.id);
77 continue;
78 }
79
80 if (servMail.senderEntry && !sObjectMgr->GetCreatureTemplate(servMail.senderEntry))
81 {
82 LOG_ERROR("sql.sql", "Table `mail_server_template` has invalid senderEntry {} (no matching creature_template) for id {}, falling back to default sender.", servMail.senderEntry, servMail.id);
83 servMail.senderEntry = 0;
84 }
85 } while (result->NextRow());
86
89
90 LOG_INFO("server.loading", ">> Loaded {} Mail Server definitions in {} ms", _serverMailStore.size(), GetMSTimeDiffToNow(oldMSTime));
91 LOG_INFO("server.loading", " ");
92}
std::shared_ptr< ResultSet > QueryResult
Definition DatabaseEnvFwd.h:27
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition DatabaseEnv.cpp:21
std::uint8_t uint8
Definition Define.h:109
std::uint32_t uint32
Definition Define.h:107
#define LOG_INFO(filterType__,...)
Definition Log.h:153
#define LOG_ERROR(filterType__,...)
Definition Log.h:145
#define sObjectMgr
Definition ObjectMgr.h:1732
#define MAX_MONEY_AMOUNT
Definition Player.h:923
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition Timer.h:131
uint32 getMSTime()
Definition Timer.h:103
Class used to access individual fields of database query result.
Definition Field.h:98
std::enable_if_t< std::is_arithmetic_v< T >, T > Get() const
Definition Field.h:112
void LoadMailServerTemplatesItems()
Loads all items associated with server mail templates.
Definition ServerMailMgr.cpp:94
void LoadMailServerTemplatesConditions()
Loads all conditions associated with server mail templates.
Definition ServerMailMgr.cpp:163
Represents a server mail template, including rewards, conditions, and metadata.
Definition ServerMailMgr.h:128
uint32 id
Definition ServerMailMgr.h:130

References _serverMailStore, CharacterDatabase, Field::Get(), getMSTime(), GetMSTimeDiffToNow(), ServerMail::id, LoadMailServerTemplatesConditions(), LoadMailServerTemplatesItems(), LOG_ERROR, LOG_INFO, MAX_MONEY_AMOUNT, and sObjectMgr.

◆ LoadMailServerTemplatesConditions()

void ServerMailMgr::LoadMailServerTemplatesConditions ( )

Loads all conditions associated with server mail templates.

Queries the mail_server_template_conditions table and loads all conditions into memory, linking them to their corresponding templates by template ID. This method is intended to be called during server startup.

164{
165 // 0 1 2 3
166 QueryResult result = CharacterDatabase.Query("SELECT `templateID`, `conditionType`, `conditionValue`, `conditionState` FROM `mail_server_template_conditions`");
167 if (!result)
168 {
169 LOG_WARN("server.loading", ">> Loaded 0 server mail conditions. DB table `mail_server_template_conditions` is empty.");
170 return;
171 }
172
173 do
174 {
175 Field* fields = result->Fetch();
176
177 uint32 templateID = fields[0].Get<uint32>();
178 std::string_view conditionTypeStr = fields[1].Get<std::string_view>();
179 uint32 conditionValue = fields[2].Get<uint32>();
180 uint32 conditionState = fields[3].Get<uint32>();
181
182 if (_serverMailStore.find(templateID) == _serverMailStore.end())
183 {
184 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has an invalid templateID {}, skipped.", templateID);
185 continue;
186 }
187
188 // Get conditiontype from ServerMailConditionTypePairs
189 ServerMailConditionType conditionType;
190 conditionType = GetServerMailConditionType(conditionTypeStr);
191 if (conditionType == ServerMailConditionType::Invalid) [[unlikely]]
192 {
193 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has unknown conditionType '{}', skipped.", conditionTypeStr);
194 continue;
195 }
196
197 if (conditionState && !ConditionTypeUsesConditionState(conditionType))
198 LOG_WARN("sql.sql", "Table `mail_server_template_conditions` has conditionState value ({}) for conditionType ({}) which does not use conditionState.", conditionState, conditionTypeStr);
199
200 switch (conditionType)
201 {
203 if (conditionValue > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
204 {
205 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Level' with invalid conditionValue ({}), max level is ({}) for templateID {}, skipped.", conditionValue, sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL), templateID);
206 continue;
207 }
208 break;
210 {
211 Quest const* qInfo = sObjectMgr->GetQuestTemplate(conditionValue);
212 if (!qInfo)
213 {
214 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Quest' with invalid quest in conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
215 continue;
216 }
217 if (conditionState < QUEST_STATUS_NONE || conditionState >= MAX_QUEST_STATUS ||
218 /*2 and 4 not defined and should not be used*/ conditionState == 2 || conditionState == 4)
219 {
220 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Quest' with invalid conditionState ({}) for templateID {}, skipped.", conditionState, templateID);
221 continue;
222 }
223 break;
224 }
226 {
227 AchievementEntry const* achievement = sAchievementStore.LookupEntry(conditionValue);
228 if (!achievement)
229 {
230 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Achievement' with invalid achievement in conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
231 continue;
232 }
233 break;
234 }
236 {
237 FactionEntry const* faction = sFactionStore.LookupEntry(conditionValue);
238 if (!faction)
239 {
240 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Reputation' with invalid faction in conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
241 continue;
242 }
243 if (conditionState < REP_HATED || conditionState > REP_EXALTED)
244 {
245 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Reputation' with invalid conditionState ({}) for templateID {}, skipped.", conditionState, templateID);
246 continue;
247 }
248 break;
249 }
251 if (conditionValue < TEAM_ALLIANCE || conditionValue > TEAM_HORDE)
252 {
253 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Faction' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
254 continue;
255 }
256 break;
258 if (conditionValue & ~sRaceMgr->GetPlayableRaceMask())
259 {
260 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Race' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
261 continue;
262 }
263 break;
265 if (conditionValue & ~CLASSMASK_ALL_PLAYABLE)
266 {
267 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Class' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
268 continue;
269 }
270 break;
272 if ((conditionValue & ~ACCOUNT_FLAGS_ALL) != 0)
273 {
274 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'AccountFlags' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
275 continue;
276 }
277 break;
278 default:
279 break;
280 }
281
282 ServerMailCondition condition;
283 condition.type = conditionType;
284 condition.value = conditionValue;
285 condition.state = conditionState;
286 _serverMailStore[templateID].conditions.push_back(condition);
287
288 } while (result->NextRow());
289}
constexpr uint32 ACCOUNT_FLAGS_ALL
Definition Common.h:103
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
DBCStorage< AchievementEntry > sAchievementStore(Achievementfmt)
#define LOG_WARN(filterType__,...)
Definition Log.h:149
@ MAX_QUEST_STATUS
Definition QuestDef.h:107
#define sRaceMgr
Definition RaceMgr.h:52
ServerMailConditionType
Represents the type of conditions that can be applied to server mail.
Definition ServerMailMgr.h:46
@ AccountFlags
Requires the player to have a specific AccountFlag (bit)
@ Faction
Requires the player to be a part of a specific faction. Horde/Alliance.
@ Race
Requires the player to be a specific race.
@ Class
Requires the player to be a specific class.
@ Level
Requires the player to be at least a specific level.
@ Achievement
Requires the player to have earned a specific achievement.
@ REP_EXALTED
Definition SharedDefines.h:164
#define CLASSMASK_ALL_PLAYABLE
Definition SharedDefines.h:142
@ TEAM_HORDE
Definition SharedDefines.h:749
@ CONFIG_MAX_PLAYER_LEVEL
Definition WorldConfig.h:193
Definition QuestDef.h:210
bool ConditionTypeUsesConditionState(ServerMailConditionType type) const
Check if ConditionType should use ConditionState.
Definition ServerMailMgr.cpp:334
ServerMailConditionType GetServerMailConditionType(std::string_view conditionTypeStr) const
Convert DB value of conditionType to ServerMailConditionType.
Definition ServerMailMgr.cpp:325
#define sWorld
Definition World.h:317
Definition DBCStructure.h:40
Definition DBCStructure.h:907
Represents a condition that must be met for a player to receive a server mail.
Definition ServerMailMgr.h:88
uint32 state
Definition ServerMailMgr.h:93
ServerMailConditionType type
Definition ServerMailMgr.h:91
uint32 value
Definition ServerMailMgr.h:92

References _serverMailStore, ACCOUNT_FLAGS_ALL, AccountFlags, Achievement, CharacterDatabase, Class, CLASSMASK_ALL_PLAYABLE, ConditionTypeUsesConditionState(), CONFIG_MAX_PLAYER_LEVEL, Faction, Field::Get(), GetServerMailConditionType(), Invalid, Level, LOG_ERROR, LOG_WARN, MAX_QUEST_STATUS, Quest, Race, REP_EXALTED, Reputation, sAchievementStore, sFactionStore, sObjectMgr, sRaceMgr, ServerMailCondition::state, sWorld, TEAM_HORDE, ServerMailCondition::type, and ServerMailCondition::value.

Referenced by LoadMailServerTemplates().

◆ LoadMailServerTemplatesItems()

void ServerMailMgr::LoadMailServerTemplatesItems ( )

Loads all items associated with server mail templates.

Queries the mail_server_template_items table and loads all items into memory, linking them to their corresponding templates by template ID. This method is intended to be called during server startup.

95{
96 // 0 1 2 3
97 QueryResult result = CharacterDatabase.Query("SELECT `templateID`, `faction`, `item`, `itemCount` FROM `mail_server_template_items`");
98 if (!result)
99 {
100 LOG_WARN("server.loading", ">> Loaded 0 server mail items. DB table `mail_server_template_items` is empty.");
101 return;
102 }
103
104 do
105 {
106 Field* fields = result->Fetch();
107
108 uint32 templateID = fields[0].Get<uint32>();
109 std::string_view faction = fields[1].Get<std::string_view>();
110 uint32 item = fields[2].Get<uint32>();
111 uint32 itemCount = fields[3].Get<uint32>();
112
113 if (_serverMailStore.find(templateID) == _serverMailStore.end())
114 {
115 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has an invalid templateID {}, skipped.", templateID);
116 continue;
117 }
118
119 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item);
120 if (!itemTemplate)
121 {
122 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has an invalid item {} for templateID {}, skipped.", item, templateID);
123 continue;
124 }
125
126 if (!itemCount)
127 {
128 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount 0 for item {}, skipped.", item);
129 continue;
130 }
131
132 uint32 stackable = itemTemplate->Stackable;
133 if (itemCount > stackable)
134 {
135 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount {} exceeding item_template.Stackable {} for item {}, skipped.", itemCount, stackable, item);
136 continue;
137 }
138
139 uint32 maxCount = itemTemplate->MaxCount;
140 if (maxCount && itemCount > maxCount)
141 {
142 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount {} exceeding item_template.MaxCount {} for item {}, skipped", itemCount, maxCount, item);
143 continue;
144 }
145
146 ServerMailItems mailItem;
147 mailItem.item = item;
148 mailItem.itemCount = itemCount;
149
150 if (faction == "Alliance")
151 _serverMailStore[templateID].itemsA.push_back(mailItem);
152 else if (faction == "Horde")
153 _serverMailStore[templateID].itemsH.push_back(mailItem);
154 else [[unlikely]]
155 {
156 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has invalid faction value '{}' for templateID {}, skipped.", faction, templateID);
157 continue;
158 }
159
160 } while (result->NextRow());
161}
Definition ItemTemplate.h:619
int32 MaxCount
Definition ItemTemplate.h:644
int32 Stackable
Definition ItemTemplate.h:645
Represents an item reward associated with a server mail template.
Definition ServerMailMgr.h:114
uint32 itemCount
Definition ServerMailMgr.h:117
uint32 item
Definition ServerMailMgr.h:116

References _serverMailStore, CharacterDatabase, Field::Get(), ServerMailItems::item, ServerMailItems::itemCount, LOG_ERROR, LOG_WARN, ItemTemplate::MaxCount, sObjectMgr, and ItemTemplate::Stackable.

Referenced by LoadMailServerTemplates().

◆ SendServerMail()

void ServerMailMgr::SendServerMail ( Player player,
uint32  id,
uint32  senderEntry,
uint32  money,
std::vector< ServerMailItems > const &  items,
std::vector< ServerMailCondition > const &  conditions,
std::string const &  subject,
std::string const &  body 
) const

Sends a server mail to a player if the template is active and the player is eligible.

This method handles the creation of the mail, adding money and items, and saving the mail to the database. It also records that the player received the mail to prevent duplicate delivery.

Parameters
playerThe recipient player.
idThe template ID.
senderEntryEntry from creature_template. 0 for default "Customer Support" sender.
moneyMoney reward.
itemsList of items to include in the mail.
conditionsList of the conditions for the mail.
subjectMail subject.
bodyMail body.
activeWhether the mail template is active.
295{
296 for (ServerMailCondition const& condition : conditions)
297 if (!condition.CheckCondition(player))
298 return;
299
300 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
301
302 MailSender sender = senderEntry
304 : MailSender(MAIL_NORMAL, player->GetGUID().GetCounter(), MAIL_STATIONERY_GM);
305 MailDraft draft(subject, body);
306
307 draft.AddMoney(money);
308 // Loop through all items and attach them to the mail
309 for (auto const& mailItem : items)
310 if (Item* newItem = Item::CreateItem(mailItem.item, mailItem.itemCount))
311 {
312 newItem->SaveToDB(trans);
313 draft.AddItem(newItem);
314 }
315
316 draft.SendMailTo(trans, MailReceiver(player), sender);
317 CharacterDatabase.CommitTransaction(trans);
318
320 stmt->SetData(0, player->GetGUID().GetCounter());
321 stmt->SetData(1, id);
322 CharacterDatabase.Execute(stmt);
323}
@ CHAR_REP_MAIL_SERVER_CHARACTER
Definition CharacterDatabase.h:85
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
Definition DatabaseEnvFwd.h:69
@ MAIL_STATIONERY_GM
Definition Mail.h:59
@ MAIL_STATIONERY_DEFAULT
Definition Mail.h:58
@ MAIL_CREATURE
Definition Mail.h:39
@ MAIL_NORMAL
Definition Mail.h:37
Definition Item.h:220
Definition Mail.h:119
Definition Mail.h:105
Definition Mail.h:83
LowType GetCounter() const
Definition ObjectGuid.h:145
static ObjectGuid GetGUID(Object const *o)
Definition Object.h:114
Acore::Types::is_default< T > SetData(const uint8 index, T value)
Definition PreparedStatement.h:77
Definition PreparedStatement.h:157

References MailDraft::AddItem(), MailDraft::AddMoney(), CHAR_REP_MAIL_SERVER_CHARACTER, CharacterDatabase, Item::CreateItem(), ObjectGuid::GetCounter(), Object::GetGUID(), MAIL_CREATURE, MAIL_NORMAL, MAIL_STATIONERY_DEFAULT, MAIL_STATIONERY_GM, MailDraft::SendMailTo(), and PreparedStatementBase::SetData().

Member Data Documentation

◆ _serverMailStore


The documentation for this class was generated from the following files: