TrinityCore
Loading...
Searching...
No Matches
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 "DBCStores.h"
23#include "Log.h"
24#include "Player.h"
25#include "World.h"
26#include "WorldSession.h"
27
29{
30 for (auto itr = _channels.begin(); itr != _channels.end(); ++itr)
31 delete itr->second;
32
33 for (auto itr = _customChannels.begin(); itr != _customChannels.end(); ++itr)
34 delete itr->second;
35}
36
37/*static*/ void ChannelMgr::LoadFromDB()
38{
39 if (!sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS))
40 {
41 TC_LOG_INFO("server.loading", ">> Loaded 0 custom chat channels. Custom channel saving is disabled.");
42 return;
43 }
44
45 uint32 oldMSTime = getMSTime();
47 {
49 stmt->setUInt32(0, days * DAY);
50 CharacterDatabase.Execute(stmt);
51 }
52
53 QueryResult result = CharacterDatabase.Query("SELECT name, team, announce, ownership, password, bannedList FROM channels");
54 if (!result)
55 {
56 TC_LOG_INFO("server.loading", ">> Loaded 0 custom chat channels. DB table `channels` is empty.");
57 return;
58 }
59
60 std::vector<std::pair<std::string, uint32>> toDelete;
61 uint32 count = 0;
62 do
63 {
64 Field* fields = result->Fetch();
65 std::string dbName = fields[0].GetString();
66 uint32 team = fields[1].GetUInt32();
67 bool dbAnnounce = fields[2].GetBool();
68 bool dbOwnership = fields[3].GetBool();
69 std::string dbPass = fields[4].GetString();
70 std::string dbBanned = fields[5].GetString();
71
72 std::wstring channelName;
73 if (!Utf8toWStr(dbName, channelName))
74 {
75 TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '{}' from database - invalid utf8 sequence? Deleted.", dbName);
76 toDelete.emplace_back(std::move(dbName), team);
77 continue;
78 }
79
80 ChannelMgr* mgr = ForTeam(team);
81 if (!mgr)
82 {
83 TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '{}' from database - invalid team {}. Deleted.", dbName, team);
84 toDelete.emplace_back(std::move(dbName), team);
85 continue;
86 }
87
88 auto [itr, isNew] = mgr->_customChannels.try_emplace(std::move(channelName));
89 if (!isNew)
90 {
91 // with CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL both teams share the same manager, so channels with the same name from each team collide
92 TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '{}' (team {}) from database - a channel with the same name is already loaded. Skipped.", dbName, team);
93 continue;
94 }
95
96 Channel* channel = itr->second = new Channel(dbName, team, dbBanned);
97 channel->SetAnnounce(dbAnnounce);
98 channel->SetOwnership(dbOwnership);
99 channel->SetPassword(dbPass);
100
101 ++count;
102 } while (result->NextRow());
103
104 for (auto const& [dbName, team] : toDelete)
105 {
107 stmt->setString(0, dbName);
108 stmt->setUInt32(1, team);
109 CharacterDatabase.Execute(stmt);
110 }
111
112 TC_LOG_INFO("server.loading", ">> Loaded {} custom chat channels in {} ms", count, GetMSTimeDiffToNow(oldMSTime));
113}
114
116{
117 static ChannelMgr allianceChannelMgr(ALLIANCE);
118 static ChannelMgr hordeChannelMgr(HORDE);
119
121 return &allianceChannelMgr; // cross-faction
122
123 if (team == ALLIANCE)
124 return &allianceChannelMgr;
125
126 if (team == HORDE)
127 return &hordeChannelMgr;
128
129 return nullptr;
130}
131
132Channel* ChannelMgr::GetChannelForPlayerByNamePart(std::string const& namePart, Player* playerSearcher)
133{
134 std::wstring channelNamePart;
135 if (!Utf8toWStr(namePart, channelNamePart))
136 return nullptr;
137
138 wstrToLower(channelNamePart);
139 for (Channel* channel : playerSearcher->GetJoinedChannels())
140 {
141 std::string chanName = channel->GetName(playerSearcher->GetSession()->GetSessionDbcLocale());
142
143 std::wstring channelNameW;
144 if (!Utf8toWStr(chanName, channelNameW))
145 continue;
146
147 wstrToLower(channelNameW);
148 if (!channelNameW.compare(0, channelNamePart.size(), channelNamePart))
149 return channel;
150 }
151
152 return nullptr;
153}
154
156{
157 for (auto pair : _customChannels)
158 pair.second->UpdateChannelInDB();
159}
160
162{
163 ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId);
164 uint32 zoneId = zoneEntry ? zoneEntry->ID : 0;
166 zoneId = 0;
167
168 std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId);
169
170 auto itr = _channels.find(key);
171 if (itr != _channels.end())
172 return itr->second;
173
174 Channel* newChannel = new Channel(channelId, _team, zoneEntry);
175 _channels[key] = newChannel;
176 return newChannel;
177}
178
180{
181 std::wstring channelName;
182 if (!Utf8toWStr(name, channelName))
183 return nullptr;
184
185 wstrToLower(channelName);
186
187 Channel*& c = _customChannels[channelName];
188 if (c)
189 return nullptr;
190
191 Channel* newChannel = new Channel(name, _team);
192 newChannel->SetDirty();
193
194 c = newChannel;
195 return newChannel;
196}
197
198Channel* ChannelMgr::GetCustomChannel(std::string const& name) const
199{
200 std::wstring channelName;
201 if (!Utf8toWStr(name, channelName))
202 return nullptr;
203
204 wstrToLower(channelName);
205 auto itr = _customChannels.find(channelName);
206 if (itr != _customChannels.end())
207 return itr->second;
208
209 return nullptr;
210}
211
212Channel* ChannelMgr::GetChannel(uint32 channelId, std::string const& name, Player* player, bool pkt /*= true*/, AreaTableEntry const* zoneEntry /*= nullptr*/) const
213{
214 Channel* ret = nullptr;
215 bool send = false;
216
217 if (channelId) // builtin
218 {
219 ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId);
220 uint32 zoneId = zoneEntry ? zoneEntry->ID : 0;
222 zoneId = 0;
223
224 std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId);
225
226 auto itr = _channels.find(key);
227 if (itr != _channels.end())
228 ret = itr->second;
229 else
230 send = true;
231 }
232 else // custom
233 {
234 std::wstring channelName;
235 if (!Utf8toWStr(name, channelName))
236 return nullptr;
237
238 wstrToLower(channelName);
239 auto itr = _customChannels.find(channelName);
240 if (itr != _customChannels.end())
241 ret = itr->second;
242 else
243 send = true;
244 }
245
246 if (send && pkt)
247 {
248 std::string channelName = name;
249 Channel::GetChannelName(channelName, channelId, player->GetSession()->GetSessionDbcLocale(), zoneEntry);
250
251 SendNotOnChannelNotify(player, channelName);
252 }
253
254 return ret;
255}
256
257void ChannelMgr::LeftChannel(uint32 channelId, AreaTableEntry const* zoneEntry)
258{
259 ChatChannelsEntry const* channelEntry = sChatChannelsStore.AssertEntry(channelId);
260 uint32 zoneId = zoneEntry ? zoneEntry->ID : 0;
262 zoneId = 0;
263
264 std::pair<uint32, uint32> key = std::make_pair(channelId, zoneId);
265
266 auto itr = _channels.find(key);
267 if (itr == _channels.end())
268 return;
269
270 Channel* channel = itr->second;
271 if (!channel->GetNumPlayers())
272 {
273 _channels.erase(itr);
274 delete channel;
275 }
276}
277
278void ChannelMgr::SendNotOnChannelNotify(Player const* player, std::string const& name)
279{
282 notify._Channel = name;
283 player->SendDirectMessage(notify.Write());
284}
@ CHANNEL_DBC_FLAG_CITY_ONLY
Definition Channel.h:98
@ CHANNEL_DBC_FLAG_GLOBAL
Definition Channel.h:96
@ CHAT_NOT_MEMBER_NOTICE
Definition Channel.h:40
@ CHAR_DEL_CHANNEL
@ CHAR_DEL_OLD_CHANNELS
@ DAY
Definition Common.h:31
DBCStorage< ChatChannelsEntry > sChatChannelsStore(ChatChannelsEntryfmt)
std::shared_ptr< ResultSet > QueryResult
DatabaseWorkerPool< CharacterDatabaseConnection > CharacterDatabase
Accessor to the character database.
uint32_t uint32
Definition Define.h:133
#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)
Channel * GetCustomChannel(std::string const &name) const
static void LoadFromDB()
void LeftChannel(uint32 channelId, AreaTableEntry const *zoneEntry)
CustomChannelContainer _customChannels
Definition ChannelMgr.h:52
Channel * GetChannel(uint32 channelId, std::string const &name, Player *player, bool pkt=true, AreaTableEntry const *zoneEntry=nullptr) const
static ChannelMgr * ForTeam(uint32 team)
Channel * GetSystemChannel(uint32 channelId, AreaTableEntry const *zoneEntry=nullptr)
uint32 const _team
Definition ChannelMgr.h:54
void SaveToDB()
static Channel * GetChannelForPlayerByNamePart(std::string const &namePart, Player *playerSearcher)
BuiltinChannelContainer _channels
Definition ChannelMgr.h:53
static void SendNotOnChannelNotify(Player const *player, std::string const &name)
void SetDirty()
Definition Channel.h:186
void SetPassword(std::string const &password)
Definition Channel.h:189
static void GetChannelName(std::string &channelName, uint32 channelId, LocaleConstant locale, AreaTableEntry const *zoneEntry)
Definition Channel.cpp:88
void SetAnnounce(bool announce)
Definition Channel.h:183
void SetOwnership(bool ownership)
Definition Channel.h:231
uint32 GetNumPlayers() const
Definition Channel.h:192
Class used to access individual fields of database query result.
Definition Field.h:92
std::string GetString() const
Definition Field.cpp:125
bool GetBool() const
Definition Field.h:100
uint32 GetUInt32() const
Definition Field.cpp:61
void SendDirectMessage(WorldPacket const *data) const
Definition Player.cpp:6163
WorldSession * GetSession() const
Definition Player.h:1705
JoinedChannelsList const & GetJoinedChannels() const
Definition Player.h:1774
void setUInt32(uint8 index, uint32 value)
void setString(uint8 index, std::string const &value)
std::string _Channel
Channel Name.
WorldPacket const * Write() override
LocaleConstant GetSessionDbcLocale() const
#define sWorld
Definition World.h:901
@ CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION
Definition World.h:353
@ CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL
Definition World.h:97
@ CONFIG_PRESERVE_CUSTOM_CHANNELS
Definition World.h:149