TrinityCore
ChannelMgr.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "ChannelMgr.h"
19#include "Channel.h"
20#include "ChannelPackets.h"
21#include "DatabaseEnv.h"
22#include "DB2Stores.h"
23#include "Log.h"
24#include "Player.h"
25#include "Realm.h"
26#include "World.h"
27#include "WorldSession.h"
28
30
32{
33 for (auto itr = _channels.begin(); itr != _channels.end(); ++itr)
34 delete itr->second;
35
36 for (auto itr = _customChannels.begin(); itr != _customChannels.end(); ++itr)
37 delete itr->second;
38}
39
40/*static*/ void ChannelMgr::LoadFromDB()
41{
42 SpecialLinkedArea = sAreaTableStore.AssertEntry(3459);
44
45 if (!sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS))
46 {
47 TC_LOG_INFO("server.loading", ">> Loaded 0 custom chat channels. Custom channel saving is disabled.");
48 return;
49 }
50
51 uint32 oldMSTime = getMSTime();
53 {
55 stmt->setUInt32(0, days * DAY);
56 CharacterDatabase.Execute(stmt);
57 }
58
59 QueryResult result = CharacterDatabase.Query("SELECT name, team, announce, ownership, password, bannedList FROM channels");
60 if (!result)
61 {
62 TC_LOG_INFO("server.loading", ">> Loaded 0 custom chat channels. DB table `channels` is empty.");
63 return;
64 }
65
66 std::vector<std::pair<std::string, uint32>> toDelete;
67 uint32 count = 0;
68 do
69 {
70 Field* fields = result->Fetch();
71 std::string dbName = fields[0].GetString();
72 uint32 team = fields[1].GetUInt32();
73 bool dbAnnounce = fields[2].GetBool();
74 bool dbOwnership = fields[3].GetBool();
75 std::string dbPass = fields[4].GetString();
76 std::string dbBanned = fields[5].GetString();
77
78 std::wstring channelName;
79 if (!Utf8toWStr(dbName, channelName))
80 {
81 TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '{}' from database - invalid utf8 sequence? Deleted.", dbName);
82 toDelete.push_back({ dbName, team });
83 continue;
84 }
85
86 ChannelMgr* mgr = ForTeam(team);
87 if (!mgr)
88 {
89 TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '{}' from database - invalid team {}. Deleted.", dbName, team);
90 toDelete.push_back({ dbName, team });
91 continue;
92 }
93
94 Channel* channel = new Channel(mgr->CreateCustomChannelGuid(), dbName, team, dbBanned);
95 channel->SetAnnounce(dbAnnounce);
96 channel->SetOwnership(dbOwnership);
97 channel->SetPassword(dbPass);
98 mgr->_customChannels.emplace(channelName, channel);
99
100 ++count;
101 } while (result->NextRow());
102
103 for (std::pair<std::string, uint32> const& pair : toDelete)
104 {
106 stmt->setString(0, pair.first);
107 stmt->setUInt32(1, pair.second);
108 CharacterDatabase.Execute(stmt);
109 }
110
111 TC_LOG_INFO("server.loading", ">> Loaded {} custom chat channels in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
112}
113
115{
116 static ChannelMgr allianceChannelMgr(ALLIANCE);
117 static ChannelMgr hordeChannelMgr(HORDE);
118
120 return &allianceChannelMgr; // cross-faction
121
122 if (team == ALLIANCE)
123 return &allianceChannelMgr;
124
125 if (team == HORDE)
126 return &hordeChannelMgr;
127
128 return nullptr;
129}
130
131Channel* ChannelMgr::GetChannelForPlayerByNamePart(std::string const& namePart, Player* playerSearcher)
132{
133 std::wstring channelNamePart;
134 if (!Utf8toWStr(namePart, channelNamePart))
135 return nullptr;
136
137 wstrToLower(channelNamePart);
138 for (Channel* channel : playerSearcher->GetJoinedChannels())
139 {
140 std::string chanName = channel->GetName(playerSearcher->GetSession()->GetSessionDbcLocale());
141
142 std::wstring channelNameW;
143 if (!Utf8toWStr(chanName, channelNameW))
144 continue;
145
146 wstrToLower(channelNameW);
147 if (!channelNameW.compare(0, channelNamePart.size(), channelNamePart))
148 return channel;
149 }
150
151 return nullptr;
152}
153
155{
156 for (auto pair : _customChannels)
157 pair.second->UpdateChannelInDB();
158}
159
161{
162 for (Channel* channel : playerSearcher->GetJoinedChannels())
163 if (channel->GetGUID() == channelGuid)
164 return channel;
165
166 return nullptr;
167}
168
169Channel* ChannelMgr::GetSystemChannel(uint32 channelId, AreaTableEntry const* zoneEntry /* = nullptr */)
170{
171 ObjectGuid channelGuid = CreateBuiltinChannelGuid(channelId, zoneEntry);
172 auto itr = _channels.find(channelGuid);
173 if (itr != _channels.end())
174 return itr->second;
175
176 Channel* newChannel = new Channel(channelGuid, channelId, _team, zoneEntry);
177 _channels[channelGuid] = newChannel;
178 return newChannel;
179}
180
182{
183 std::wstring channelName;
184 if (!Utf8toWStr(name, channelName))
185 return nullptr;
186
187 wstrToLower(channelName);
188
189 Channel*& c = _customChannels[channelName];
190 if (c)
191 return nullptr;
192
193 Channel* newChannel = new Channel(CreateCustomChannelGuid(), name, _team);
194 newChannel->SetDirty();
195
196 c = newChannel;
197 return newChannel;
198}
199
200Channel* ChannelMgr::GetCustomChannel(std::string const& name) const
201{
202 std::wstring channelName;
203 if (!Utf8toWStr(name, channelName))
204 return nullptr;
205
206 wstrToLower(channelName);
207 auto itr = _customChannels.find(channelName);
208 if (itr != _customChannels.end())
209 return itr->second;
210
211 return nullptr;
212}
213
214Channel* ChannelMgr::GetChannel(uint32 channelId, std::string const& name, Player* player, bool notify /*= true*/, AreaTableEntry const* zoneEntry /*= nullptr*/) const
215{
216 Channel* result = nullptr;
217 if (channelId) // builtin
218 {
219 auto itr = _channels.find(CreateBuiltinChannelGuid(channelId, zoneEntry));
220 if (itr != _channels.end())
221 result = itr->second;
222 }
223 else // custom
224 {
225 std::wstring channelName;
226 if (!Utf8toWStr(name, channelName))
227 return nullptr;
228
229 wstrToLower(channelName);
230
231 auto itr = _customChannels.find(channelName);
232 if (itr != _customChannels.end())
233 result = itr->second;
234 }
235
236 if (!result && notify)
237 {
238 std::string channelName = name;
239 Channel::GetChannelName(channelName, channelId, player->GetSession()->GetSessionDbcLocale(), zoneEntry);
240
241 SendNotOnChannelNotify(player, channelName);
242 }
243
244 return result;
245}
246
247void ChannelMgr::LeftChannel(uint32 channelId, AreaTableEntry const* zoneEntry)
248{
249 auto itr = _channels.find(CreateBuiltinChannelGuid(channelId, zoneEntry));
250 if (itr == _channels.end())
251 return;
252
253 Channel* channel = itr->second;
254 if (!channel->GetNumPlayers())
255 {
256 _channels.erase(itr);
257 delete channel;
258 }
259}
260
261void ChannelMgr::SendNotOnChannelNotify(Player const* player, std::string const& name)
262{
265 notify._Channel = name;
266 player->SendDirectMessage(notify.Write());
267}
268
270{
271 return ObjectGuid::Create<HighGuid::ChatChannel>(false, false, 0, _team == ALLIANCE ? 3 : 5, _guidGenerator.Generate());
272}
273
274ObjectGuid ChannelMgr::CreateBuiltinChannelGuid(uint32 channelId, AreaTableEntry const* zoneEntry /*= nullptr*/) const
275{
276 ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId);
277 uint32 zoneId = 0;
278 if (zoneEntry && channelEntry->GetFlags().HasFlag(ChatChannelFlags::ZoneBased) && !channelEntry->GetFlags().HasFlag(ChatChannelFlags::LinkedChannel))
279 zoneId = zoneEntry->ID;
280
281 if (channelEntry->GetFlags().HasFlag(ChatChannelFlags::GlobalForTournament))
282 if (Cfg_CategoriesEntry const* category = sCfgCategoriesStore.LookupEntry(realm.Timezone))
283 if (category->GetFlags().HasFlag(CfgCategoriesFlags::Tournament))
284 zoneId = 0;
285
286 return ObjectGuid::Create<HighGuid::ChatChannel>(true, channelEntry->GetFlags().HasFlag(ChatChannelFlags::LinkedChannel), zoneId, _team == ALLIANCE ? 3 : 5, channelId);
287}
@ CHAT_NOT_MEMBER_NOTICE
Definition: Channel.h:48
@ CHAR_DEL_CHANNEL
@ CHAR_DEL_OLD_CHANNELS
@ DAY
Definition: Common.h:31
DB2Storage< Cfg_CategoriesEntry > sCfgCategoriesStore("Cfg_Categories.db2", &CfgCategoriesLoadInfo::Instance)
DB2Storage< ChatChannelsEntry > sChatChannelsStore("ChatChannels.db2", &ChatChannelsLoadInfo::Instance)
DB2Storage< AreaTableEntry > sAreaTableStore("AreaTable.db2", &AreaTableLoadInfo::Instance)
@ LinkedChatSpecialArea
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
Definition: DatabaseEnv.cpp:21
uint32_t uint32
Definition: Define.h:142
#define ASSERT
Definition: Errors.h:68
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
#define TC_LOG_INFO(filterType__,...)
Definition: Log.h:159
@ ALLIANCE
@ HORDE
uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
Definition: Timer.h:57
uint32 getMSTime()
Definition: Timer.h:33
void wstrToLower(std::wstring &str)
Definition: Util.cpp:480
bool Utf8toWStr(char const *utf8str, size_t csize, wchar_t *wstr, size_t &wsize)
Definition: Util.cpp:383
Channel * CreateCustomChannel(std::string const &name)
Definition: ChannelMgr.cpp:181
ObjectGuid CreateBuiltinChannelGuid(uint32 channelId, AreaTableEntry const *zoneEntry=nullptr) const
Definition: ChannelMgr.cpp:274
Channel * GetCustomChannel(std::string const &name) const
Definition: ChannelMgr.cpp:200
static void LoadFromDB()
Definition: ChannelMgr.cpp:40
void LeftChannel(uint32 channelId, AreaTableEntry const *zoneEntry)
Definition: ChannelMgr.cpp:247
CustomChannelContainer _customChannels
Definition: ChannelMgr.h:58
static AreaTableEntry const * SpecialLinkedArea
Definition: ChannelMgr.h:48
static ChannelMgr * ForTeam(uint32 team)
Definition: ChannelMgr.cpp:114
Channel * GetSystemChannel(uint32 channelId, AreaTableEntry const *zoneEntry=nullptr)
Definition: ChannelMgr.cpp:169
ObjectGuidGenerator _guidGenerator
Definition: ChannelMgr.h:61
Channel * GetChannel(uint32 channelId, std::string const &name, Player *player, bool notify=true, AreaTableEntry const *zoneEntry=nullptr) const
Definition: ChannelMgr.cpp:214
uint32 const _team
Definition: ChannelMgr.h:60
ObjectGuid CreateCustomChannelGuid()
Definition: ChannelMgr.cpp:269
void SaveToDB()
Definition: ChannelMgr.cpp:154
static Channel * GetChannelForPlayerByNamePart(std::string const &namePart, Player *playerSearcher)
Definition: ChannelMgr.cpp:131
static Channel * GetChannelForPlayerByGuid(ObjectGuid channelGuid, Player *playerSearcher)
Definition: ChannelMgr.cpp:160
BuiltinChannelContainer _channels
Definition: ChannelMgr.h:59
static void SendNotOnChannelNotify(Player const *player, std::string const &name)
Definition: ChannelMgr.cpp:261
void SetDirty()
Definition: Channel.h:177
void SetPassword(std::string const &password)
Definition: Channel.h:180
static void GetChannelName(std::string &channelName, uint32 channelId, LocaleConstant locale, AreaTableEntry const *zoneEntry)
Definition: Channel.cpp:97
void SetAnnounce(bool announce)
Definition: Channel.h:174
void SetOwnership(bool ownership)
Definition: Channel.h:221
uint32 GetNumPlayers() const
Definition: Channel.h:183
Class used to access individual fields of database query result.
Definition: Field.h:90
std::string GetString() const
Definition: Field.cpp:118
bool GetBool() const
Definition: Field.h:98
uint32 GetUInt32() const
Definition: Field.cpp:62
ObjectGuid::LowType Generate()
Definition: ObjectGuid.cpp:788
void SendDirectMessage(WorldPacket const *data) const
Definition: Player.cpp:6324
WorldSession * GetSession() const
Definition: Player.h:2101
JoinedChannelsList const & GetJoinedChannels() const
Definition: Player.h:2191
void setUInt32(const uint8 index, const uint32 value)
void setString(const uint8 index, const std::string &value)
std::string _Channel
Channel Name.
WorldPacket const * Write() override
LocaleConstant GetSessionDbcLocale() const
#define sWorld
Definition: World.h:931
Realm realm
Definition: World.cpp:3966
@ CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION
Definition: World.h:378
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL
Definition: World.h:110
@ CONFIG_PRESERVE_CUSTOM_CHANNELS
Definition: World.h:161
EnumFlag< AreaFlags > GetFlags() const
Definition: DB2Structure.h:153
EnumFlag< ChatChannelFlags > GetFlags() const
Definition: DB2Structure.h:621
uint8 Timezone
Definition: Realm.h:90