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 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.
325{
326 switch (type)
327 {
330 return true;
331 default:
332 return false;
333 }
334}
@ 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.
225{ return _serverMailStore; }
ServerMailContainer _serverMailStore
Definition ServerMailMgr.h:228

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
316{
317 for (auto const& pair : ServerMailConditionTypePairs)
318 if (pair.first == conditionTypeStr)
319 return pair.second;
320
322}
@ 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
32{
34 return &instance;
35}
Definition ServerMailMgr.h:148
static ServerMailMgr * instance()
Definition ServerMailMgr.cpp:31

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.

38{
39 uint32 oldMSTime = getMSTime();
40
41 _serverMailStore.clear(); // for reload case
42
43 // 0 1 2 3 4 5
44 QueryResult result = CharacterDatabase.Query("SELECT `id`, `moneyA`, `moneyH`, `subject`, `body`, `active` FROM `mail_server_template`");
45 if (!result)
46 {
47 LOG_INFO("server.loading", ">> Loaded 0 server mail rewards. DB table `mail_server_template` is empty.");
48 LOG_INFO("server.loading", " ");
49 return;
50 }
51
52 _serverMailStore.reserve(result->GetRowCount());
53
54 do
55 {
56 Field* fields = result->Fetch();
57
58 uint32 id = fields[0].Get<uint32>();
59
60 ServerMail& servMail = _serverMailStore[id];
61 servMail.id = id;
62 servMail.moneyA = fields[1].Get<uint32>();
63 servMail.moneyH = fields[2].Get<uint32>();
64 servMail.subject = fields[3].Get<std::string>();
65 servMail.body = fields[4].Get<std::string>();
66 servMail.active = fields[5].Get<uint8>();
67
68 // Skip non-activated entries
69 if (!servMail.active)
70 continue;
71
72 if (servMail.moneyA > MAX_MONEY_AMOUNT || servMail.moneyH > MAX_MONEY_AMOUNT)
73 {
74 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);
75 continue;
76 }
77 } while (result->NextRow());
78
81
82 LOG_INFO("server.loading", ">> Loaded {} Mail Server definitions in {} ms", _serverMailStore.size(), GetMSTimeDiffToNow(oldMSTime));
83 LOG_INFO("server.loading", " ");
84}
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:166
#define LOG_ERROR(filterType__,...)
Definition Log.h:158
#define MAX_MONEY_AMOUNT
Definition Player.h:937
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:86
void LoadMailServerTemplatesConditions()
Loads all conditions associated with server mail templates.
Definition ServerMailMgr.cpp:155
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, and MAX_MONEY_AMOUNT.

◆ 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.

156{
157 // 0 1 2 3
158 QueryResult result = CharacterDatabase.Query("SELECT `templateID`, `conditionType`, `conditionValue`, `conditionState` FROM `mail_server_template_conditions`");
159 if (!result)
160 {
161 LOG_WARN("server.loading", ">> Loaded 0 server mail conditions. DB table `mail_server_template_conditions` is empty.");
162 return;
163 }
164
165 do
166 {
167 Field* fields = result->Fetch();
168
169 uint32 templateID = fields[0].Get<uint32>();
170 std::string_view conditionTypeStr = fields[1].Get<std::string_view>();
171 uint32 conditionValue = fields[2].Get<uint32>();
172 uint32 conditionState = fields[3].Get<uint32>();
173
174 if (_serverMailStore.find(templateID) == _serverMailStore.end())
175 {
176 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has an invalid templateID {}, skipped.", templateID);
177 continue;
178 }
179
180 // Get conditiontype from ServerMailConditionTypePairs
181 ServerMailConditionType conditionType;
182 conditionType = GetServerMailConditionType(conditionTypeStr);
183 if (conditionType == ServerMailConditionType::Invalid) [[unlikely]]
184 {
185 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has unknown conditionType '{}', skipped.", conditionTypeStr);
186 continue;
187 }
188
189 if (conditionState && !ConditionTypeUsesConditionState(conditionType))
190 LOG_WARN("sql.sql", "Table `mail_server_template_conditions` has conditionState value ({}) for conditionType ({}) which does not use conditionState.", conditionState, conditionTypeStr);
191
192 switch (conditionType)
193 {
195 if (conditionValue > sWorld->getIntConfig(CONFIG_MAX_PLAYER_LEVEL))
196 {
197 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);
198 continue;
199 }
200 break;
202 {
203 Quest const* qInfo = sObjectMgr->GetQuestTemplate(conditionValue);
204 if (!qInfo)
205 {
206 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Quest' with invalid quest in conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
207 continue;
208 }
209 if (conditionState < QUEST_STATUS_NONE || conditionState >= MAX_QUEST_STATUS ||
210 /*2 and 4 not defined and should not be used*/ conditionState == 2 || conditionState == 4)
211 {
212 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Quest' with invalid conditionState ({}) for templateID {}, skipped.", conditionState, templateID);
213 continue;
214 }
215 break;
216 }
218 {
219 AchievementEntry const* achievement = sAchievementStore.LookupEntry(conditionValue);
220 if (!achievement)
221 {
222 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Achievement' with invalid achievement in conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
223 continue;
224 }
225 break;
226 }
228 {
229 FactionEntry const* faction = sFactionStore.LookupEntry(conditionValue);
230 if (!faction)
231 {
232 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Reputation' with invalid faction in conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
233 continue;
234 }
235 if (conditionState < REP_HATED || conditionState > REP_EXALTED)
236 {
237 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Reputation' with invalid conditionState ({}) for templateID {}, skipped.", conditionState, templateID);
238 continue;
239 }
240 break;
241 }
243 if (conditionValue < TEAM_ALLIANCE || conditionValue > TEAM_HORDE)
244 {
245 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Faction' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
246 continue;
247 }
248 break;
250 if (conditionValue & ~RACEMASK_ALL_PLAYABLE)
251 {
252 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Race' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
253 continue;
254 }
255 break;
257 if (conditionValue & ~CLASSMASK_ALL_PLAYABLE)
258 {
259 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'Class' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
260 continue;
261 }
262 break;
264 if ((conditionValue & ~ACCOUNT_FLAGS_ALL) != 0)
265 {
266 LOG_ERROR("sql.sql", "Table `mail_server_template_conditions` has conditionType 'AccountFlags' with invalid conditionValue ({}) for templateID {}, skipped.", conditionValue, templateID);
267 continue;
268 }
269 break;
270 default:
271 break;
272 }
273
274 ServerMailCondition condition;
275 condition.type = conditionType;
276 condition.value = conditionValue;
277 condition.state = conditionState;
278 _serverMailStore[templateID].conditions.push_back(condition);
279
280 } while (result->NextRow());
281}
constexpr uint32 ACCOUNT_FLAGS_ALL
Definition Common.h:103
DBCStorage< FactionEntry > sFactionStore(FactionEntryfmt)
DBCStorage< AchievementEntry > sAchievementStore(Achievementfmt)
#define LOG_WARN(filterType__,...)
Definition Log.h:162
#define sObjectMgr
Definition ObjectMgr.h:1650
@ MAX_QUEST_STATUS
Definition QuestDef.h:107
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:187
#define CLASSMASK_ALL_PLAYABLE
Definition SharedDefines.h:157
@ TEAM_HORDE
Definition SharedDefines.h:761
#define RACEMASK_ALL_PLAYABLE
Definition SharedDefines.h:97
@ CONFIG_MAX_PLAYER_LEVEL
Definition WorldConfig.h:186
Definition QuestDef.h:210
bool ConditionTypeUsesConditionState(ServerMailConditionType type) const
Check if ConditionType should use ConditionState.
Definition ServerMailMgr.cpp:324
ServerMailConditionType GetServerMailConditionType(std::string_view conditionTypeStr) const
Convert DB value of conditionType to ServerMailConditionType.
Definition ServerMailMgr.cpp:315
#define sWorld
Definition World.h:320
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, RACEMASK_ALL_PLAYABLE, REP_EXALTED, Reputation, sAchievementStore, sFactionStore, sObjectMgr, 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.

87{
88 // 0 1 2 3
89 QueryResult result = CharacterDatabase.Query("SELECT `templateID`, `faction`, `item`, `itemCount` FROM `mail_server_template_items`");
90 if (!result)
91 {
92 LOG_WARN("server.loading", ">> Loaded 0 server mail items. DB table `mail_server_template_items` is empty.");
93 return;
94 }
95
96 do
97 {
98 Field* fields = result->Fetch();
99
100 uint32 templateID = fields[0].Get<uint32>();
101 std::string_view faction = fields[1].Get<std::string_view>();
102 uint32 item = fields[2].Get<uint32>();
103 uint32 itemCount = fields[3].Get<uint32>();
104
105 if (_serverMailStore.find(templateID) == _serverMailStore.end())
106 {
107 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has an invalid templateID {}, skipped.", templateID);
108 continue;
109 }
110
111 ItemTemplate const* itemTemplate = sObjectMgr->GetItemTemplate(item);
112 if (!itemTemplate)
113 {
114 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has an invalid item {} for templateID {}, skipped.", item, templateID);
115 continue;
116 }
117
118 if (!itemCount)
119 {
120 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount 0 for item {}, skipped.", item);
121 continue;
122 }
123
124 uint32 stackable = itemTemplate->Stackable;
125 if (itemCount > stackable)
126 {
127 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount {} exceeding item_template.Stackable {} for item {}, skipped.", itemCount, stackable, item);
128 continue;
129 }
130
131 uint32 maxCount = itemTemplate->MaxCount;
132 if (maxCount && itemCount > maxCount)
133 {
134 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has itemCount {} exceeding item_template.MaxCount {} for item {}, skipped", itemCount, maxCount, item);
135 continue;
136 }
137
138 ServerMailItems mailItem;
139 mailItem.item = item;
140 mailItem.itemCount = itemCount;
141
142 if (faction == "Alliance")
143 _serverMailStore[templateID].itemsA.push_back(mailItem);
144 else if (faction == "Horde")
145 _serverMailStore[templateID].itemsH.push_back(mailItem);
146 else [[unlikely]]
147 {
148 LOG_ERROR("sql.sql", "Table `mail_server_template_items` has invalid faction value '{}' for templateID {}, skipped.", faction, templateID);
149 continue;
150 }
151
152 } while (result->NextRow());
153}
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  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.
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.
287{
288 for (ServerMailCondition const& condition : conditions)
289 if (!condition.CheckCondition(player))
290 return;
291
292 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
293
295 MailDraft draft(subject, body);
296
297 draft.AddMoney(money);
298 // Loop through all items and attach them to the mail
299 for (auto const& mailItem : items)
300 if (Item* newItem = Item::CreateItem(mailItem.item, mailItem.itemCount))
301 {
302 newItem->SaveToDB(trans);
303 draft.AddItem(newItem);
304 }
305
306 draft.SendMailTo(trans, MailReceiver(player), sender);
307 CharacterDatabase.CommitTransaction(trans);
308
310 stmt->SetData(0, player->GetGUID().GetCounter());
311 stmt->SetData(1, id);
312 CharacterDatabase.Execute(stmt);
313}
@ CHAR_REP_MAIL_SERVER_CHARACTER
Definition CharacterDatabase.h:85
SQLTransaction< CharacterDatabaseConnection > CharacterDatabaseTransaction
Definition DatabaseEnvFwd.h:69
@ MAIL_STATIONERY_GM
Definition Mail.h:59
@ 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:113
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_NORMAL, MAIL_STATIONERY_GM, MailDraft::SendMailTo(), and PreparedStatementBase::SetData().

Member Data Documentation

◆ _serverMailStore


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