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.
316{
317 switch (type)
318 {
321 return true;
322 default:
323 return false;
324 }
325}
@ 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.
223{ return _serverMailStore; }
ServerMailContainer _serverMailStore
Definition ServerMailMgr.h:226

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
307{
308 for (auto const& pair : ServerMailConditionTypePairs)
309 if (pair.first == conditionTypeStr)
310 return pair.second;
311
313}
@ 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:61

References Invalid, and ServerMailConditionTypePairs.

Referenced by LoadMailServerTemplatesConditions().

◆ instance()

ServerMailMgr * ServerMailMgr::instance ( )
static
30{
32 return &instance;
33}
Definition ServerMailMgr.h:146
static ServerMailMgr * instance()
Definition ServerMailMgr.cpp:29

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.

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

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.

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

References _serverMailStore, 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.

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

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.
278{
279 for (ServerMailCondition const& condition : conditions)
280 if (!condition.CheckCondition(player))
281 return;
282
283 CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
284
286 MailDraft draft(subject, body);
287
288 draft.AddMoney(money);
289 // Loop through all items and attach them to the mail
290 for (auto const& mailItem : items)
291 if (Item* newItem = Item::CreateItem(mailItem.item, mailItem.itemCount))
292 {
293 newItem->SaveToDB(trans);
294 draft.AddItem(newItem);
295 }
296
297 draft.SendMailTo(trans, MailReceiver(player), sender);
298 CharacterDatabase.CommitTransaction(trans);
299
301 stmt->SetData(0, player->GetGUID().GetCounter());
302 stmt->SetData(1, id);
303 CharacterDatabase.Execute(stmt);
304}
@ 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:112
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: