aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2019-08-01 23:41:45 +0200
committerShauren <shauren.trinity@gmail.com>2021-12-17 23:22:13 +0100
commit8839fa3fe24e72e4506e94389663b82ab2292649 (patch)
tree08a1a3408e0432679874ec1ab9243429884894ef /src
parent8c3eb07889f72955879c8a0e0881b51befb60067 (diff)
Core/Chat: Custom channel preservation rewrite. Channel data is now loaded at startup, and written to the DB periodically, instead of both things happening in real time.
(cherry picked from commit fedf1f557b2aa1cbb0f4bc722b24afb59cc30855)
Diffstat (limited to 'src')
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.cpp6
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h3
-rw-r--r--src/server/game/Chat/Channels/Channel.cpp76
-rw-r--r--src/server/game/Chat/Channels/Channel.h18
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.cpp113
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.h4
-rw-r--r--src/server/game/World/World.cpp23
-rw-r--r--src/server/game/World/World.h2
-rw-r--r--src/server/worldserver/worldserver.conf.dist7
9 files changed, 161 insertions, 91 deletions
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp
index 4bc1dc7b802..ff1c1b3e7e6 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.cpp
+++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp
@@ -326,11 +326,11 @@ void CharacterDatabaseConnection::DoPrepareStatements()
" ON DUPLICATE KEY UPDATE LogGuid = VALUES (LogGuid), EventType = VALUES (EventType), PlayerGuid = VALUES (PlayerGuid), Flags = VALUES (Flags), Value = VALUES (Value), Timestamp = VALUES (Timestamp)", CONNECTION_ASYNC);
// Chat channel handling
- PrepareStatement(CHAR_SEL_CHANNEL, "SELECT name, announce, ownership, password, bannedList FROM channels WHERE name = ? AND team = ?", CONNECTION_SYNCH);
- PrepareStatement(CHAR_INS_CHANNEL, "INSERT INTO channels(name, team, lastUsed) VALUES (?, ?, UNIX_TIMESTAMP())", CONNECTION_ASYNC);
- PrepareStatement(CHAR_UPD_CHANNEL, "UPDATE channels SET announce = ?, ownership = ?, password = ?, bannedList = ?, lastUsed = UNIX_TIMESTAMP() WHERE name = ? AND team = ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_UPD_CHANNEL, "INSERT INTO channels (name, team, announce, ownership, password, bannedList, lastUsed) VALUES (?, ?, ?, ?, ?, ?, UNIX_TIMESTAMP()) "
+ "ON DUPLICATE KEY UPDATE announce=VALUES(announce), ownership=VALUES(ownership), password=VALUES(password), bannedList=VALUES(bannedList), lastUsed=VALUES(lastUsed)", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHANNEL_USAGE, "UPDATE channels SET lastUsed = UNIX_TIMESTAMP() WHERE name = ? AND team = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_UPD_CHANNEL_OWNERSHIP, "UPDATE channels SET ownership = ? WHERE name LIKE ?", CONNECTION_ASYNC);
+ PrepareStatement(CHAR_DEL_CHANNEL, "DELETE FROM channels WHERE name = ? AND team = ?", CONNECTION_ASYNC);
PrepareStatement(CHAR_DEL_OLD_CHANNELS, "DELETE FROM channels WHERE ownership = 1 AND lastUsed + ? < UNIX_TIMESTAMP()", CONNECTION_ASYNC);
// Equipmentsets
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index 1de37e1a2ca..7460f5d8e28 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -257,11 +257,10 @@ enum CharacterDatabaseStatements : uint32
CHAR_SEL_GUILD_ACHIEVEMENT_CRITERIA,
CHAR_INS_GUILD_NEWS,
- CHAR_SEL_CHANNEL,
- CHAR_INS_CHANNEL,
CHAR_UPD_CHANNEL,
CHAR_UPD_CHANNEL_USAGE,
CHAR_UPD_CHANNEL_OWNERSHIP,
+ CHAR_DEL_CHANNEL,
CHAR_DEL_OLD_CHANNELS,
CHAR_UPD_EQUIP_SET,
diff --git a/src/server/game/Chat/Channels/Channel.cpp b/src/server/game/Chat/Channels/Channel.cpp
index 7d29cf7014d..022d4546a09 100644
--- a/src/server/game/Chat/Channels/Channel.cpp
+++ b/src/server/game/Chat/Channels/Channel.cpp
@@ -22,6 +22,7 @@
#include "ChatPackets.h"
#include "DB2Stores.h"
#include "DatabaseEnv.h"
+#include "GameTime.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "Language.h"
@@ -35,9 +36,10 @@
#include <sstream>
Channel::Channel(ObjectGuid const& guid, uint32 channelId, uint32 team /*= 0*/, AreaTableEntry const* zoneEntry /*= nullptr*/) :
+ _isDirty(false),
+ _nextActivityUpdateTime(0),
_announceEnabled(false), // no join/leave announces
_ownershipEnabled(false), // no ownership handout
- _persistentChannel(false),
_isOwnerInvisible(false),
_channelFlags(CHANNEL_FLAG_GENERAL), // for all built-in channels
_channelId(channelId),
@@ -59,9 +61,10 @@ Channel::Channel(ObjectGuid const& guid, uint32 channelId, uint32 team /*= 0*/,
}
Channel::Channel(ObjectGuid const& guid, std::string const& name, uint32 team /*= 0*/, std::string const& banList) :
+ _isDirty(false),
+ _nextActivityUpdateTime(0),
_announceEnabled(true),
_ownershipEnabled(true),
- _persistentChannel(sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS)),
_isOwnerInvisible(false),
_channelFlags(CHANNEL_FLAG_CUSTOM),
_channelId(0),
@@ -110,45 +113,39 @@ std::string Channel::GetName(LocaleConstant locale /*= DEFAULT_LOCALE*/) const
return result;
}
-void Channel::UpdateChannelInDB() const
+void Channel::UpdateChannelInDB()
{
- if (_persistentChannel)
+ time_t const now = GameTime::GetGameTime();
+ if (_isDirty)
{
std::ostringstream banlist;
for (ObjectGuid const& guid : _bannedStore)
banlist << guid.ToHexString() << ' ';
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL);
- stmt->setBool(0, _announceEnabled);
- stmt->setBool(1, _ownershipEnabled);
- stmt->setString(2, _channelPassword);
- stmt->setString(3, banlist.str());
- stmt->setString(4, _channelName);
- stmt->setUInt32(5, _channelTeam);
+ stmt->setString(0, _channelName);
+ stmt->setUInt32(1, _channelTeam);
+ stmt->setBool(2, _announceEnabled);
+ stmt->setBool(3, _ownershipEnabled);
+ stmt->setString(4, _channelPassword);
+ stmt->setString(5, banlist.str());
CharacterDatabase.Execute(stmt);
-
- TC_LOG_DEBUG("chat.system", "Channel (%s) updated in database", _channelName.c_str());
}
-}
-
-void Channel::UpdateChannelUseageInDB() const
-{
- CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL_USAGE);
- stmt->setString(0, _channelName);
- stmt->setUInt32(1, _channelTeam);
- CharacterDatabase.Execute(stmt);
-}
-
-void Channel::CleanOldChannelsInDB()
-{
- if (sWorld->getIntConfig(CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION) > 0)
+ else if (_nextActivityUpdateTime <= now)
{
- CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CHANNELS);
- stmt->setInt64(0, sWorld->getIntConfig(CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION) * DAY);
- CharacterDatabase.Execute(stmt);
-
- TC_LOG_DEBUG("chat.system", "Cleaned out unused custom chat channels.");
+ if (!_playersStore.empty())
+ {
+ CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHANNEL_USAGE);
+ stmt->setString(0, _channelName);
+ stmt->setUInt32(1, _channelTeam);
+ CharacterDatabase.Execute(stmt);
+ }
}
+ else
+ return;
+
+ _isDirty = false;
+ _nextActivityUpdateTime = now + urand(1 * MINUTE, 6 * MINUTE) * std::max(1u, sWorld->getIntConfig(CONFIG_PRESERVE_CUSTOM_CHANNEL_INTERVAL));
}
void Channel::JoinChannel(Player* player, std::string const& pass)
@@ -203,6 +200,8 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
}
bool newChannel = _playersStore.empty();
+ if (newChannel)
+ _nextActivityUpdateTime = 0; // force activity update on next channel tick
PlayerInfo& playerInfo = _playersStore[guid];
playerInfo.SetInvisible(!player->isGMVisible());
@@ -235,10 +234,6 @@ void Channel::JoinChannel(Player* player, std::string const& pass)
// Custom channel handling
if (!IsConstant())
{
- // Update last_used timestamp in db
- if (!_playersStore.empty())
- UpdateChannelUseageInDB();
-
// If the channel has no owner yet and ownership is allowed, set the new owner.
// or if the owner was a GM with .gm visible off
// don't do this if the new player is, too, an invis GM, unless the channel was empty
@@ -306,9 +301,6 @@ void Channel::LeaveChannel(Player* player, bool send, bool suspend)
if (!IsConstant())
{
- // Update last_used timestamp in db
- UpdateChannelUseageInDB();
-
// If the channel owner left and there are still playersStore inside, pick a new owner
// do not pick invisible gm owner unless there are only invisible gms in that channel (rare)
if (changeowner && _ownershipEnabled && !_playersStore.empty())
@@ -379,7 +371,7 @@ void Channel::KickOrBan(Player const* player, std::string const& badname, bool b
if (ban && !IsBanned(victim))
{
_bannedStore.insert(victim);
- UpdateChannelInDB();
+ _isDirty = true;
if (!player->GetSession()->HasPermission(rbac::RBAC_PERM_SILENTLY_JOIN_CHANNEL))
{
@@ -443,7 +435,7 @@ void Channel::UnBan(Player const* player, std::string const& badname)
ChannelNameBuilder<PlayerUnbannedAppend> builder(this, appender);
SendToAll(builder);
- UpdateChannelInDB();
+ _isDirty = true;
}
void Channel::Password(Player const* player, std::string const& pass)
@@ -473,7 +465,7 @@ void Channel::Password(Player const* player, std::string const& pass)
ChannelNameBuilder<PasswordChangedAppend> builder(this, appender);
SendToAll(builder);
- UpdateChannelInDB();
+ _isDirty = true;
}
void Channel::SetMode(Player const* player, std::string const& p2n, bool mod, bool set)
@@ -675,7 +667,7 @@ void Channel::Announce(Player const* player)
SendToAll(builder);
}
- UpdateChannelInDB();
+ _isDirty = true;
}
void Channel::Say(ObjectGuid const& guid, std::string const& what, uint32 lang) const
@@ -869,7 +861,7 @@ void Channel::SetOwner(ObjectGuid const& guid, bool exclaim)
SendToAll(ownerBuilder);
}
- UpdateChannelInDB();
+ _isDirty = true;
}
}
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 30802964a9d..efff8d0fca8 100644
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -20,6 +20,7 @@
#include "Common.h"
#include "ObjectGuid.h"
+#include <ctime>
#include <map>
#include <unordered_set>
@@ -187,6 +188,10 @@ class TC_GAME_API Channel
bool IsAnnounce() const { return _announceEnabled; }
void SetAnnounce(bool announce) { _announceEnabled = announce; }
+ // will be saved to DB on next channel save interval
+ void SetDirty() { _isDirty = true; }
+ void UpdateChannelInDB();
+
void SetPassword(std::string const& password) { _channelPassword = password; }
bool CheckPassword(std::string const& password) const { return _channelPassword.empty() || (_channelPassword == password); }
@@ -229,7 +234,6 @@ class TC_GAME_API Channel
void JoinNotify(Player const* player);
void LeaveNotify(Player const* player);
void SetOwnership(bool ownership) { _ownershipEnabled = ownership; }
- static void CleanOldChannelsInDB();
private:
template <class Builder>
@@ -244,11 +248,9 @@ class TC_GAME_API Channel
template <class Builder>
void SendToAllWithAddon(Builder& builder, std::string const& addonPrefix, ObjectGuid const& guid = ObjectGuid::Empty, ObjectGuid const& accountGuid = ObjectGuid::Empty) const;
- bool IsOn(ObjectGuid const& who) const { return _playersStore.count(who) != 0; }
- bool IsBanned(ObjectGuid const& guid) const { return _bannedStore.count(guid) != 0; }
-
- void UpdateChannelInDB() const;
- void UpdateChannelUseageInDB() const;
+ bool IsOn(ObjectGuid who) const { return _playersStore.find(who) != _playersStore.end(); }
+ bool IsBanned(ObjectGuid guid) const { return _bannedStore.find(guid) != _bannedStore.end(); }
+
uint8 GetPlayerFlags(ObjectGuid const& guid) const
{
@@ -262,9 +264,11 @@ class TC_GAME_API Channel
typedef std::map<ObjectGuid, PlayerInfo> PlayerContainer;
typedef GuidUnorderedSet BannedContainer;
+ bool _isDirty; // whether the channel needs to be saved to DB
+ time_t _nextActivityUpdateTime;
+
bool _announceEnabled; //< Whether we should broadcast a packet whenever a player joins/exits the channel
bool _ownershipEnabled; //< Whether the channel has to maintain an owner
- bool _persistentChannel; //< Whether the channel is saved to DB
bool _isOwnerInvisible; //< Whether the channel is owned by invisible GM, ownership should change to first player that joins channel
uint8 _channelFlags;
diff --git a/src/server/game/Chat/Channels/ChannelMgr.cpp b/src/server/game/Chat/Channels/ChannelMgr.cpp
index e218038800a..af86bf83a9f 100644
--- a/src/server/game/Chat/Channels/ChannelMgr.cpp
+++ b/src/server/game/Chat/Channels/ChannelMgr.cpp
@@ -35,7 +35,78 @@ ChannelMgr::~ChannelMgr()
delete itr->second;
}
-ChannelMgr* ChannelMgr::ForTeam(uint32 team)
+/*static*/ void ChannelMgr::LoadFromDB()
+{
+ if (!sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS))
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 custom chat channels. Custom channel saving is disabled.");
+ return;
+ }
+
+ uint32 oldMSTime = getMSTime();
+ if (uint32 days = sWorld->getIntConfig(CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION))
+ {
+ CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CHANNELS);
+ stmt->setUInt32(0, days * DAY);
+ CharacterDatabase.Execute(stmt);
+ }
+
+ QueryResult result = CharacterDatabase.Query("SELECT name, team, announce, ownership, password, bannedList FROM channels");
+ if (!result)
+ {
+ TC_LOG_INFO("server.loading", ">> Loaded 0 custom chat channels. DB table `channels` is empty.");
+ return;
+ }
+
+ std::vector<std::pair<std::string, uint32>> toDelete;
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+ std::string dbName = fields[0].GetString(); // may be different - channel names are case insensitive
+ uint32 team = fields[1].GetUInt32();
+ bool dbAnnounce = fields[2].GetBool();
+ bool dbOwnership = fields[3].GetBool();
+ std::string dbPass = fields[4].GetString();
+ std::string dbBanned = fields[5].GetString();
+
+ std::wstring channelName;
+ if (!Utf8toWStr(dbName, channelName))
+ {
+ TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '%s' from database - invalid utf8 sequence? Deleted.", dbName.c_str());
+ toDelete.push_back({ dbName, team });
+ continue;
+ }
+
+ ChannelMgr* mgr = ForTeam(team);
+ if (!mgr)
+ {
+ TC_LOG_ERROR("server.loading", "Failed to load custom chat channel '%s' from database - invalid team %u. Deleted.", dbName.c_str());
+ toDelete.push_back({ dbName, team });
+ continue;
+ }
+
+ Channel* channel = new Channel(mgr->CreateCustomChannelGuid(), dbName, team, dbBanned);
+ channel->SetAnnounce(dbAnnounce);
+ channel->SetOwnership(dbOwnership);
+ channel->SetPassword(dbPass);
+ mgr->_customChannels.emplace(channelName, channel);
+
+ ++count;
+ } while (result->NextRow());
+
+ for (std::pair<std::string, uint32> const& pair : toDelete)
+ {
+ CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHANNEL);
+ stmt->setString(0, pair.first);
+ stmt->setUInt32(1, pair.second);
+ CharacterDatabase.Execute(stmt);
+ }
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u custom chat channels in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
+}
+
+/*static*/ ChannelMgr* ChannelMgr::ForTeam(uint32 team)
{
static ChannelMgr allianceChannelMgr(ALLIANCE);
static ChannelMgr hordeChannelMgr(HORDE);
@@ -75,6 +146,12 @@ Channel* ChannelMgr::GetChannelForPlayerByNamePart(std::string const& namePart,
return nullptr;
}
+void ChannelMgr::SaveToDB()
+{
+ for (auto pair : _customChannels)
+ pair.second->UpdateChannelInDB();
+}
+
Channel* ChannelMgr::GetChannelForPlayerByGuid(ObjectGuid channelGuid, Player* playerSearcher)
{
for (Channel* channel : playerSearcher->GetJoinedChannels())
@@ -109,21 +186,13 @@ Channel* ChannelMgr::CreateCustomChannel(std::string const& name)
return nullptr;
Channel* newChannel = new Channel(CreateCustomChannelGuid(), name, _team);
-
- if (sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS))
- {
- CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHANNEL);
- stmt->setString(0, name);
- stmt->setUInt32(1, _team);
- CharacterDatabase.Execute(stmt);
- TC_LOG_DEBUG("chat.system", "Channel(%s) saved in database", name.c_str());
- }
+ newChannel->SetDirty();
c = newChannel;
return newChannel;
}
-Channel* ChannelMgr::GetCustomChannel(std::string const& name)
+Channel* ChannelMgr::GetCustomChannel(std::string const& name) const
{
std::wstring channelName;
if (!Utf8toWStr(name, channelName))
@@ -133,28 +202,6 @@ Channel* ChannelMgr::GetCustomChannel(std::string const& name)
auto itr = _customChannels.find(channelName);
if (itr != _customChannels.end())
return itr->second;
- else if (sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS))
- {
- CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHANNEL);
- stmt->setString(0, name);
- stmt->setUInt32(1, _team);
- if (PreparedQueryResult result = CharacterDatabase.Query(stmt))
- {
- Field* fields = result->Fetch();
- std::string dbName = fields[0].GetString(); // may be different - channel names are case insensitive
- bool dbAnnounce = fields[1].GetBool();
- bool dbOwnership = fields[2].GetBool();
- std::string dbPass = fields[3].GetString();
- std::string dbBanned = fields[4].GetString();
-
- Channel* channel = new Channel(CreateCustomChannelGuid(), dbName, _team, dbBanned);
- channel->SetAnnounce(dbAnnounce);
- channel->SetOwnership(dbOwnership);
- channel->SetPassword(dbPass);
- _customChannels.emplace(channelName, channel);
- return channel;
- }
- }
return nullptr;
}
diff --git a/src/server/game/Chat/Channels/ChannelMgr.h b/src/server/game/Chat/Channels/ChannelMgr.h
index ed2f986c940..325969d5dae 100644
--- a/src/server/game/Chat/Channels/ChannelMgr.h
+++ b/src/server/game/Chat/Channels/ChannelMgr.h
@@ -36,13 +36,15 @@ class TC_GAME_API ChannelMgr
~ChannelMgr();
public:
+ static void LoadFromDB();
static ChannelMgr* ForTeam(uint32 team);
static Channel* GetChannelForPlayerByNamePart(std::string const& namePart, Player* playerSearcher);
static Channel* GetChannelForPlayerByGuid(ObjectGuid channelGuid, Player* playerSearcher);
+ void SaveToDB();
Channel* GetSystemChannel(uint32 channelId, AreaTableEntry const* zoneEntry = nullptr);
Channel* CreateCustomChannel(std::string const& name);
- Channel* GetCustomChannel(std::string const& name);
+ Channel* GetCustomChannel(std::string const& name) const;
Channel* GetChannel(uint32 channelId, std::string const& name, Player* player, bool notify = true, AreaTableEntry const* zoneEntry = nullptr) const;
void LeftChannel(std::string const& name);
void LeftChannel(uint32 channelId, AreaTableEntry const* zoneEntry);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index be04aef3b90..1eee1879ebc 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -33,7 +33,7 @@
#include "BattlePetMgr.h"
#include "BlackMarketMgr.h"
#include "CalendarMgr.h"
-#include "Channel.h"
+#include "ChannelMgr.h"
#include "CharacterCache.h"
#include "CharacterDatabaseCleaner.h"
#include "CharacterTemplateDataStore.h"
@@ -763,6 +763,7 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_MAIL_LEVEL_REQ] = sConfigMgr->GetIntDefault("LevelReq.Mail", 1);
m_bool_configs[CONFIG_PRESERVE_CUSTOM_CHANNELS] = sConfigMgr->GetBoolDefault("PreserveCustomChannels", false);
m_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION] = sConfigMgr->GetIntDefault("PreserveCustomChannelDuration", 14);
+ m_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_INTERVAL] = sConfigMgr->GetIntDefault("PreserveCustomChannelInterval", 5);
m_bool_configs[CONFIG_GRID_UNLOAD] = sConfigMgr->GetBoolDefault("GridUnload", true);
m_bool_configs[CONFIG_BASEMAP_LOAD_GRIDS] = sConfigMgr->GetBoolDefault("BaseMapLoadAllGrids", false);
if (m_bool_configs[CONFIG_BASEMAP_LOAD_GRIDS] && m_bool_configs[CONFIG_GRID_UNLOAD])
@@ -2310,6 +2311,8 @@ void World::SetInitialWorldSettings()
m_timers[WUPDATE_WHO_LIST].SetInterval(5 * IN_MILLISECONDS); // update who list cache every 5 seconds
+ m_timers[WUPDATE_CHANNEL_SAVE].SetInterval(getIntConfig(CONFIG_PRESERVE_CUSTOM_CHANNEL_INTERVAL) * MINUTE * IN_MILLISECONDS);
+
//to set mailtimer to return mails every day between 4 and 5 am
//mailtimer is increased when updating auctions
//one second is 1000 -(tested on win system)
@@ -2337,8 +2340,8 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Initialize AuctionHouseBot...");
sAuctionBot->Initialize();
- // Delete all custom channels which haven't been used for PreserveCustomChannelDuration days.
- Channel::CleanOldChannelsInDB();
+ TC_LOG_INFO("server.loading", "Initializing chat channels...");
+ ChannelMgr::LoadFromDB();
TC_LOG_INFO("server.loading", "Initializing Opcodes...");
opcodeTable.Initialize();
@@ -2490,6 +2493,20 @@ void World::Update(uint32 diff)
sWhoListStorageMgr->Update();
}
+ if (m_timers[WUPDATE_CHANNEL_SAVE].Passed())
+ {
+ m_timers[WUPDATE_CHANNEL_SAVE].Reset();
+
+ if (sWorld->getBoolConfig(CONFIG_PRESERVE_CUSTOM_CHANNELS))
+ {
+ ChannelMgr* mgr1 = ASSERT_NOTNULL(ChannelMgr::ForTeam(ALLIANCE));
+ mgr1->SaveToDB();
+ ChannelMgr* mgr2 = ASSERT_NOTNULL(ChannelMgr::ForTeam(HORDE));
+ if (mgr1 != mgr2)
+ mgr2->SaveToDB();
+ }
+ }
+
/// Handle daily quests reset time
if (currentGameTime > m_NextDailyQuestReset)
{
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index b3f4b2f20b0..36939ab6970 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -93,6 +93,7 @@ enum WorldTimers
WUPDATE_BLACKMARKET,
WUPDATE_CHECK_FILECHANGES,
WUPDATE_WHO_LIST,
+ WUPDATE_CHANNEL_SAVE,
WUPDATE_COUNT
};
@@ -358,6 +359,7 @@ enum WorldIntConfigs
CONFIG_MAX_RESULTS_LOOKUP_COMMANDS,
CONFIG_DB_PING_INTERVAL,
CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION,
+ CONFIG_PRESERVE_CUSTOM_CHANNEL_INTERVAL,
CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS,
CONFIG_LFG_OPTIONSMASK,
CONFIG_MAX_INSTANCES_PER_HOUR,
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index babb30f5c35..f12a58da1d2 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2015,6 +2015,13 @@ PartyLevelReq = 1
PreserveCustomChannels = 1
#
+# PreserveCustomChannelInterval
+# Description: Interval (in minutes) at which custom channel data is saved to the database
+# Default: 5 minutes
+
+PreserveCustomChannelInterval = 5
+
+#
# PreserveCustomChannelDuration
# Description: Time (in days) that needs to pass before the customs chat channels get
# cleaned up from the database. Only channels with ownership handout enabled