PageRenderTime 67ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/src/server/game/World/World.cpp

https://gitlab.com/IlluminatiCore/IlluminatiCore
C++ | 3320 lines | 2456 code | 615 blank | 249 comment | 415 complexity | 6c2eeb98ac9178a83534f1e962231a9b MD5 | raw file
Possible License(s): GPL-2.0, BSD-2-Clause
  1. /*
  2. * Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
  3. * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
  4. *
  5. * This program is free software; you can redistribute it and/or modify it
  6. * under the terms of the GNU General Public License as published by the
  7. * Free Software Foundation; either version 2 of the License, or (at your
  8. * option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful, but WITHOUT
  11. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  13. * more details.
  14. *
  15. * You should have received a copy of the GNU General Public License along
  16. * with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. /** \file
  19. \ingroup world
  20. */
  21. #include "World.h"
  22. #include "AchievementMgr.h"
  23. #include "ArenaTeamMgr.h"
  24. #include "AuctionHouseBot.h"
  25. #include "AuctionHouseMgr.h"
  26. #include "BattlefieldMgr.h"
  27. #include "BattlegroundMgr.h"
  28. #include "CalendarMgr.h"
  29. #include "Channel.h"
  30. #include "CharacterDatabaseCleaner.h"
  31. #include "Chat.h"
  32. #include "Config.h"
  33. #include "CreatureAIRegistry.h"
  34. #include "CreatureGroups.h"
  35. #include "CreatureTextMgr.h"
  36. #include "DatabaseEnv.h"
  37. #include "DisableMgr.h"
  38. #include "GameEventMgr.h"
  39. #include "GridNotifiersImpl.h"
  40. #include "GroupMgr.h"
  41. #include "GuildFinderMgr.h"
  42. #include "InstanceSaveMgr.h"
  43. #include "Language.h"
  44. #include "LFGMgr.h"
  45. #include "MapManager.h"
  46. #include "Memory.h"
  47. #include "MMapFactory.h"
  48. #include "ObjectMgr.h"
  49. #include "OutdoorPvPMgr.h"
  50. #include "Player.h"
  51. #include "PoolMgr.h"
  52. #include "ScriptMgr.h"
  53. #include "SkillDiscovery.h"
  54. #include "SkillExtraItems.h"
  55. #include "SmartAI.h"
  56. #include "SystemConfig.h"
  57. #include "TicketMgr.h"
  58. #include "TransportMgr.h"
  59. #include "Unit.h"
  60. #include "VMapFactory.h"
  61. #include "WardenCheckMgr.h"
  62. #include "WaypointMovementGenerator.h"
  63. #include "WeatherMgr.h"
  64. #include "WorldSession.h"
  65. std::atomic<bool> World::m_stopEvent(false);
  66. uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
  67. std::atomic<uint32> World::m_worldLoopCounter(0);
  68. float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
  69. float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
  70. float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
  71. int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
  72. int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
  73. int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
  74. /// World constructor
  75. World::World()
  76. {
  77. m_playerLimit = 0;
  78. m_allowedSecurityLevel = SEC_PLAYER;
  79. m_allowMovement = true;
  80. m_ShutdownMask = 0;
  81. m_ShutdownTimer = 0;
  82. m_gameTime = time(NULL);
  83. m_startTime = m_gameTime;
  84. m_maxActiveSessionCount = 0;
  85. m_maxQueuedSessionCount = 0;
  86. m_PlayerCount = 0;
  87. m_MaxPlayerCount = 0;
  88. m_NextDailyQuestReset = 0;
  89. m_NextWeeklyQuestReset = 0;
  90. m_NextMonthlyQuestReset = 0;
  91. m_NextRandomBGReset = 0;
  92. m_NextGuildReset = 0;
  93. m_NextCurrencyReset = 0;
  94. m_defaultDbcLocale = LOCALE_enUS;
  95. m_availableDbcLocaleMask = 0;
  96. mail_timer = 0;
  97. mail_timer_expires = 0;
  98. m_updateTime = 0;
  99. m_updateTimeSum = 0;
  100. m_updateTimeCount = 0;
  101. m_currentTime = 0;
  102. m_isClosed = false;
  103. m_CleaningFlags = 0;
  104. memset(rate_values, 0, sizeof(rate_values));
  105. memset(m_int_configs, 0, sizeof(m_int_configs));
  106. memset(m_bool_configs, 0, sizeof(m_bool_configs));
  107. memset(m_float_configs, 0, sizeof(m_float_configs));
  108. }
  109. /// World destructor
  110. World::~World()
  111. {
  112. ///- Empty the kicked session set
  113. while (!m_sessions.empty())
  114. {
  115. // not remove from queue, prevent loading new sessions
  116. delete m_sessions.begin()->second;
  117. m_sessions.erase(m_sessions.begin());
  118. }
  119. CliCommandHolder* command = NULL;
  120. while (cliCmdQueue.next(command))
  121. delete command;
  122. VMAP::VMapFactory::clear();
  123. MMAP::MMapFactory::clear();
  124. /// @todo free addSessQueue
  125. }
  126. /// Find a player in a specified zone
  127. Player* World::FindPlayerInZone(uint32 zone)
  128. {
  129. ///- circle through active sessions and return the first player found in the zone
  130. SessionMap::const_iterator itr;
  131. for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  132. {
  133. if (!itr->second)
  134. continue;
  135. Player* player = itr->second->GetPlayer();
  136. if (!player)
  137. continue;
  138. if (player->IsInWorld() && player->GetZoneId() == zone)
  139. return player;
  140. }
  141. return NULL;
  142. }
  143. bool World::IsClosed() const
  144. {
  145. return m_isClosed;
  146. }
  147. void World::SetClosed(bool val)
  148. {
  149. m_isClosed = val;
  150. // Invert the value, for simplicity for scripters.
  151. sScriptMgr->OnOpenStateChange(!val);
  152. }
  153. void World::SetMotd(const std::string& motd)
  154. {
  155. m_motd = motd;
  156. sScriptMgr->OnMotdChange(m_motd);
  157. }
  158. const char* World::GetMotd() const
  159. {
  160. return m_motd.c_str();
  161. }
  162. /// Find a session by its id
  163. WorldSession* World::FindSession(uint32 id) const
  164. {
  165. SessionMap::const_iterator itr = m_sessions.find(id);
  166. if (itr != m_sessions.end())
  167. return itr->second; // also can return NULL for kicked session
  168. else
  169. return NULL;
  170. }
  171. /// Remove a given session
  172. bool World::RemoveSession(uint32 id)
  173. {
  174. ///- Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation
  175. SessionMap::const_iterator itr = m_sessions.find(id);
  176. if (itr != m_sessions.end() && itr->second)
  177. {
  178. if (itr->second->PlayerLoading())
  179. return false;
  180. itr->second->KickPlayer();
  181. }
  182. return true;
  183. }
  184. void World::AddSession(WorldSession* s)
  185. {
  186. addSessQueue.add(s);
  187. }
  188. void World::AddSession_(WorldSession* s)
  189. {
  190. ASSERT(s);
  191. //NOTE - Still there is race condition in WorldSession* being used in the Sockets
  192. ///- kick already loaded player with same account (if any) and remove session
  193. ///- if player is in loading and want to load again, return
  194. if (!RemoveSession (s->GetAccountId()))
  195. {
  196. s->KickPlayer();
  197. delete s; // session not added yet in session list, so not listed in queue
  198. return;
  199. }
  200. // decrease session counts only at not reconnection case
  201. bool decrease_session = true;
  202. // if session already exist, prepare to it deleting at next world update
  203. // NOTE - KickPlayer() should be called on "old" in RemoveSession()
  204. {
  205. SessionMap::const_iterator old = m_sessions.find(s->GetAccountId());
  206. if (old != m_sessions.end())
  207. {
  208. // prevent decrease sessions count if session queued
  209. if (RemoveQueuedPlayer(old->second))
  210. decrease_session = false;
  211. // not remove replaced session form queue if listed
  212. delete old->second;
  213. }
  214. }
  215. m_sessions[s->GetAccountId()] = s;
  216. uint32 Sessions = GetActiveAndQueuedSessionCount();
  217. uint32 pLimit = GetPlayerAmountLimit();
  218. uint32 QueueSize = GetQueuedSessionCount(); //number of players in the queue
  219. //so we don't count the user trying to
  220. //login as a session and queue the socket that we are using
  221. if (decrease_session)
  222. --Sessions;
  223. if (pLimit > 0 && Sessions >= pLimit && !s->HasPermission(rbac::RBAC_PERM_SKIP_QUEUE) && !HasRecentlyDisconnected(s))
  224. {
  225. AddQueuedPlayer(s);
  226. UpdateMaxSessionCounters();
  227. TC_LOG_INFO("misc", "PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId(), ++QueueSize);
  228. return;
  229. }
  230. s->SendAuthResponse(AUTH_OK, false);
  231. s->SendAddonsInfo();
  232. s->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
  233. s->SendTutorialsData();
  234. UpdateMaxSessionCounters();
  235. // Updates the population
  236. if (pLimit > 0)
  237. {
  238. float popu = (float)GetActiveSessionCount(); // updated number of users on the server
  239. popu /= pLimit;
  240. popu *= 2;
  241. TC_LOG_INFO("misc", "Server Population (%f).", popu);
  242. }
  243. }
  244. bool World::HasRecentlyDisconnected(WorldSession* session)
  245. {
  246. if (!session)
  247. return false;
  248. if (uint32 tolerance = getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
  249. {
  250. for (DisconnectMap::iterator i = m_disconnects.begin(); i != m_disconnects.end();)
  251. {
  252. if (difftime(i->second, time(NULL)) < tolerance)
  253. {
  254. if (i->first == session->GetAccountId())
  255. return true;
  256. ++i;
  257. }
  258. else
  259. m_disconnects.erase(i++);
  260. }
  261. }
  262. return false;
  263. }
  264. int32 World::GetQueuePos(WorldSession* sess)
  265. {
  266. uint32 position = 1;
  267. for (Queue::const_iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position)
  268. if ((*iter) == sess)
  269. return position;
  270. return 0;
  271. }
  272. void World::AddQueuedPlayer(WorldSession* sess)
  273. {
  274. sess->SetInQueue(true);
  275. m_QueuedPlayer.push_back(sess);
  276. // The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
  277. sess->SendAuthResponse(AUTH_WAIT_QUEUE, true, GetQueuePos(sess));
  278. }
  279. bool World::RemoveQueuedPlayer(WorldSession* sess)
  280. {
  281. // sessions count including queued to remove (if removed_session set)
  282. uint32 sessions = GetActiveSessionCount();
  283. uint32 position = 1;
  284. Queue::iterator iter = m_QueuedPlayer.begin();
  285. // search to remove and count skipped positions
  286. bool found = false;
  287. for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
  288. {
  289. if (*iter == sess)
  290. {
  291. sess->SetInQueue(false);
  292. sess->ResetTimeOutTime();
  293. iter = m_QueuedPlayer.erase(iter);
  294. found = true; // removing queued session
  295. break;
  296. }
  297. }
  298. // iter point to next socked after removed or end()
  299. // position store position of removed socket and then new position next socket after removed
  300. // if session not queued then we need decrease sessions count
  301. if (!found && sessions)
  302. --sessions;
  303. // accept first in queue
  304. if ((!m_playerLimit || sessions < m_playerLimit) && !m_QueuedPlayer.empty())
  305. {
  306. WorldSession* pop_sess = m_QueuedPlayer.front();
  307. pop_sess->SetInQueue(false);
  308. pop_sess->ResetTimeOutTime();
  309. pop_sess->SendAuthWaitQue(0);
  310. pop_sess->SendAddonsInfo();
  311. pop_sess->SendClientCacheVersion(sWorld->getIntConfig(CONFIG_CLIENTCACHE_VERSION));
  312. pop_sess->SendAccountDataTimes(GLOBAL_CACHE_MASK);
  313. pop_sess->SendTutorialsData();
  314. m_QueuedPlayer.pop_front();
  315. // update iter to point first queued socket or end() if queue is empty now
  316. iter = m_QueuedPlayer.begin();
  317. position = 1;
  318. }
  319. // update position from iter to end()
  320. // iter point to first not updated socket, position store new position
  321. for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
  322. (*iter)->SendAuthWaitQue(position);
  323. return found;
  324. }
  325. /// Initialize config values
  326. void World::LoadConfigSettings(bool reload)
  327. {
  328. if (reload)
  329. {
  330. std::string configError;
  331. if (!sConfigMgr->Reload(configError))
  332. {
  333. TC_LOG_ERROR("misc", "World settings reload fail: %s.", configError.c_str());
  334. return;
  335. }
  336. sLog->LoadFromConfig();
  337. }
  338. m_defaultDbcLocale = LocaleConstant(sConfigMgr->GetIntDefault("DBC.Locale", 0));
  339. if (m_defaultDbcLocale >= TOTAL_LOCALES)
  340. {
  341. TC_LOG_ERROR("server.loading", "Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", TOTAL_LOCALES);
  342. m_defaultDbcLocale = LOCALE_enUS;
  343. }
  344. TC_LOG_INFO("server.loading", "Using %s DBC Locale", localeNames[m_defaultDbcLocale]);
  345. ///- Read the player limit and the Message of the day from the config file
  346. SetPlayerAmountLimit(sConfigMgr->GetIntDefault("PlayerLimit", 100));
  347. SetMotd(sConfigMgr->GetStringDefault("Motd", "Welcome to a Trinity Core Server."));
  348. ///- Read ticket system setting from the config file
  349. m_bool_configs[CONFIG_ALLOW_TICKETS] = sConfigMgr->GetBoolDefault("AllowTickets", true);
  350. ///- Get string for new logins (newly created characters)
  351. SetNewCharString(sConfigMgr->GetStringDefault("PlayerStart.String", ""));
  352. ///- Send server info on login?
  353. m_int_configs[CONFIG_ENABLE_SINFO_LOGIN] = sConfigMgr->GetIntDefault("Server.LoginInfo", 0);
  354. ///- Read all rates from the config file
  355. rate_values[RATE_HEALTH] = sConfigMgr->GetFloatDefault("Rate.Health", 1.0f);
  356. if (rate_values[RATE_HEALTH] < 0)
  357. {
  358. TC_LOG_ERROR("server.loading", "Rate.Health (%f) must be > 0. Using 1 instead.", rate_values[RATE_HEALTH]);
  359. rate_values[RATE_HEALTH] = 1;
  360. }
  361. rate_values[RATE_POWER_MANA] = sConfigMgr->GetFloatDefault("Rate.Mana", 1.0f);
  362. if (rate_values[RATE_POWER_MANA] < 0)
  363. {
  364. TC_LOG_ERROR("server.loading", "Rate.Mana (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_MANA]);
  365. rate_values[RATE_POWER_MANA] = 1;
  366. }
  367. rate_values[RATE_POWER_RAGE_INCOME] = sConfigMgr->GetFloatDefault("Rate.Rage.Income", 1.0f);
  368. rate_values[RATE_POWER_RAGE_LOSS] = sConfigMgr->GetFloatDefault("Rate.Rage.Loss", 1.0f);
  369. if (rate_values[RATE_POWER_RAGE_LOSS] < 0)
  370. {
  371. TC_LOG_ERROR("server.loading", "Rate.Rage.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RAGE_LOSS]);
  372. rate_values[RATE_POWER_RAGE_LOSS] = 1;
  373. }
  374. rate_values[RATE_POWER_RUNICPOWER_INCOME] = sConfigMgr->GetFloatDefault("Rate.RunicPower.Income", 1.0f);
  375. rate_values[RATE_POWER_RUNICPOWER_LOSS] = sConfigMgr->GetFloatDefault("Rate.RunicPower.Loss", 1.0f);
  376. if (rate_values[RATE_POWER_RUNICPOWER_LOSS] < 0)
  377. {
  378. TC_LOG_ERROR("server.loading", "Rate.RunicPower.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RUNICPOWER_LOSS]);
  379. rate_values[RATE_POWER_RUNICPOWER_LOSS] = 1;
  380. }
  381. rate_values[RATE_POWER_FOCUS] = sConfigMgr->GetFloatDefault("Rate.Focus", 1.0f);
  382. rate_values[RATE_POWER_ENERGY] = sConfigMgr->GetFloatDefault("Rate.Energy", 1.0f);
  383. rate_values[RATE_SKILL_DISCOVERY] = sConfigMgr->GetFloatDefault("Rate.Skill.Discovery", 1.0f);
  384. rate_values[RATE_DROP_ITEM_POOR] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Poor", 1.0f);
  385. rate_values[RATE_DROP_ITEM_NORMAL] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Normal", 1.0f);
  386. rate_values[RATE_DROP_ITEM_UNCOMMON] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Uncommon", 1.0f);
  387. rate_values[RATE_DROP_ITEM_RARE] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Rare", 1.0f);
  388. rate_values[RATE_DROP_ITEM_EPIC] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Epic", 1.0f);
  389. rate_values[RATE_DROP_ITEM_LEGENDARY] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Legendary", 1.0f);
  390. rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Artifact", 1.0f);
  391. rate_values[RATE_DROP_ITEM_REFERENCED] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Referenced", 1.0f);
  392. rate_values[RATE_DROP_ITEM_REFERENCED_AMOUNT] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.ReferencedAmount", 1.0f);
  393. rate_values[RATE_DROP_MONEY] = sConfigMgr->GetFloatDefault("Rate.Drop.Money", 1.0f);
  394. rate_values[RATE_XP_KILL] = sConfigMgr->GetFloatDefault("Rate.XP.Kill", 1.0f);
  395. rate_values[RATE_XP_QUEST] = sConfigMgr->GetFloatDefault("Rate.XP.Quest", 1.0f);
  396. rate_values[RATE_XP_EXPLORE] = sConfigMgr->GetFloatDefault("Rate.XP.Explore", 1.0f);
  397. rate_values[RATE_REPAIRCOST] = sConfigMgr->GetFloatDefault("Rate.RepairCost", 1.0f);
  398. if (rate_values[RATE_REPAIRCOST] < 0.0f)
  399. {
  400. TC_LOG_ERROR("server.loading", "Rate.RepairCost (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_REPAIRCOST]);
  401. rate_values[RATE_REPAIRCOST] = 0.0f;
  402. }
  403. rate_values[RATE_REPUTATION_GAIN] = sConfigMgr->GetFloatDefault("Rate.Reputation.Gain", 1.0f);
  404. rate_values[RATE_REPUTATION_LOWLEVEL_KILL] = sConfigMgr->GetFloatDefault("Rate.Reputation.LowLevel.Kill", 1.0f);
  405. rate_values[RATE_REPUTATION_LOWLEVEL_QUEST] = sConfigMgr->GetFloatDefault("Rate.Reputation.LowLevel.Quest", 1.0f);
  406. rate_values[RATE_REPUTATION_RECRUIT_A_FRIEND_BONUS] = sConfigMgr->GetFloatDefault("Rate.Reputation.RecruitAFriendBonus", 0.1f);
  407. rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f);
  408. rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f);
  409. rate_values[RATE_CREATURE_ELITE_RAREELITE_DAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.RAREELITE.Damage", 1.0f);
  410. rate_values[RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.Damage", 1.0f);
  411. rate_values[RATE_CREATURE_ELITE_RARE_DAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.RARE.Damage", 1.0f);
  412. rate_values[RATE_CREATURE_NORMAL_HP] = sConfigMgr->GetFloatDefault("Rate.Creature.Normal.HP", 1.0f);
  413. rate_values[RATE_CREATURE_ELITE_ELITE_HP] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.Elite.HP", 1.0f);
  414. rate_values[RATE_CREATURE_ELITE_RAREELITE_HP] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.RAREELITE.HP", 1.0f);
  415. rate_values[RATE_CREATURE_ELITE_WORLDBOSS_HP] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.HP", 1.0f);
  416. rate_values[RATE_CREATURE_ELITE_RARE_HP] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.RARE.HP", 1.0f);
  417. rate_values[RATE_CREATURE_NORMAL_SPELLDAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Normal.SpellDamage", 1.0f);
  418. rate_values[RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.Elite.SpellDamage", 1.0f);
  419. rate_values[RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.RAREELITE.SpellDamage", 1.0f);
  420. rate_values[RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1.0f);
  421. rate_values[RATE_CREATURE_ELITE_RARE_SPELLDAMAGE] = sConfigMgr->GetFloatDefault("Rate.Creature.Elite.RARE.SpellDamage", 1.0f);
  422. rate_values[RATE_CREATURE_AGGRO] = sConfigMgr->GetFloatDefault("Rate.Creature.Aggro", 1.0f);
  423. rate_values[RATE_REST_INGAME] = sConfigMgr->GetFloatDefault("Rate.Rest.InGame", 1.0f);
  424. rate_values[RATE_REST_OFFLINE_IN_TAVERN_OR_CITY] = sConfigMgr->GetFloatDefault("Rate.Rest.Offline.InTavernOrCity", 1.0f);
  425. rate_values[RATE_REST_OFFLINE_IN_WILDERNESS] = sConfigMgr->GetFloatDefault("Rate.Rest.Offline.InWilderness", 1.0f);
  426. rate_values[RATE_DAMAGE_FALL] = sConfigMgr->GetFloatDefault("Rate.Damage.Fall", 1.0f);
  427. rate_values[RATE_AUCTION_TIME] = sConfigMgr->GetFloatDefault("Rate.Auction.Time", 1.0f);
  428. rate_values[RATE_AUCTION_DEPOSIT] = sConfigMgr->GetFloatDefault("Rate.Auction.Deposit", 1.0f);
  429. rate_values[RATE_AUCTION_CUT] = sConfigMgr->GetFloatDefault("Rate.Auction.Cut", 1.0f);
  430. rate_values[RATE_HONOR] = sConfigMgr->GetFloatDefault("Rate.Honor", 1.0f);
  431. rate_values[RATE_INSTANCE_RESET_TIME] = sConfigMgr->GetFloatDefault("Rate.InstanceResetTime", 1.0f);
  432. rate_values[RATE_TALENT] = sConfigMgr->GetFloatDefault("Rate.Talent", 1.0f);
  433. if (rate_values[RATE_TALENT] < 0.0f)
  434. {
  435. TC_LOG_ERROR("server.loading", "Rate.Talent (%f) must be > 0. Using 1 instead.", rate_values[RATE_TALENT]);
  436. rate_values[RATE_TALENT] = 1.0f;
  437. }
  438. rate_values[RATE_MOVESPEED] = sConfigMgr->GetFloatDefault("Rate.MoveSpeed", 1.0f);
  439. if (rate_values[RATE_MOVESPEED] < 0)
  440. {
  441. TC_LOG_ERROR("server.loading", "Rate.MoveSpeed (%f) must be > 0. Using 1 instead.", rate_values[RATE_MOVESPEED]);
  442. rate_values[RATE_MOVESPEED] = 1.0f;
  443. }
  444. for (uint8 i = 0; i < MAX_MOVE_TYPE; ++i) playerBaseMoveSpeed[i] = baseMoveSpeed[i] * rate_values[RATE_MOVESPEED];
  445. rate_values[RATE_CORPSE_DECAY_LOOTED] = sConfigMgr->GetFloatDefault("Rate.Corpse.Decay.Looted", 0.5f);
  446. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = sConfigMgr->GetFloatDefault("TargetPosRecalculateRange", 1.5f);
  447. if (rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] < CONTACT_DISTANCE)
  448. {
  449. TC_LOG_ERROR("server.loading", "TargetPosRecalculateRange (%f) must be >= %f. Using %f instead.", rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], CONTACT_DISTANCE, CONTACT_DISTANCE);
  450. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = CONTACT_DISTANCE;
  451. }
  452. else if (rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] > NOMINAL_MELEE_RANGE)
  453. {
  454. TC_LOG_ERROR("server.loading", "TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.",
  455. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], NOMINAL_MELEE_RANGE, NOMINAL_MELEE_RANGE);
  456. rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = NOMINAL_MELEE_RANGE;
  457. }
  458. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = sConfigMgr->GetFloatDefault("DurabilityLoss.OnDeath", 10.0f);
  459. if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] < 0.0f)
  460. {
  461. TC_LOG_ERROR("server.loading", "DurabilityLoss.OnDeath (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
  462. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
  463. }
  464. if (rate_values[RATE_DURABILITY_LOSS_ON_DEATH] > 100.0f)
  465. {
  466. TC_LOG_ERROR("server.loading", "DurabilityLoss.OnDeath (%f) must be <= 100. Using 100.0 instead.", rate_values[RATE_DURABILITY_LOSS_ON_DEATH]);
  467. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = 0.0f;
  468. }
  469. rate_values[RATE_DURABILITY_LOSS_ON_DEATH] = rate_values[RATE_DURABILITY_LOSS_ON_DEATH] / 100.0f;
  470. rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfigMgr->GetFloatDefault("DurabilityLossChance.Damage", 0.5f);
  471. if (rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f)
  472. {
  473. TC_LOG_ERROR("server.loading", "DurabilityLossChance.Damage (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_DAMAGE]);
  474. rate_values[RATE_DURABILITY_LOSS_DAMAGE] = 0.0f;
  475. }
  476. rate_values[RATE_DURABILITY_LOSS_ABSORB] = sConfigMgr->GetFloatDefault("DurabilityLossChance.Absorb", 0.5f);
  477. if (rate_values[RATE_DURABILITY_LOSS_ABSORB] < 0.0f)
  478. {
  479. TC_LOG_ERROR("server.loading", "DurabilityLossChance.Absorb (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ABSORB]);
  480. rate_values[RATE_DURABILITY_LOSS_ABSORB] = 0.0f;
  481. }
  482. rate_values[RATE_DURABILITY_LOSS_PARRY] = sConfigMgr->GetFloatDefault("DurabilityLossChance.Parry", 0.05f);
  483. if (rate_values[RATE_DURABILITY_LOSS_PARRY] < 0.0f)
  484. {
  485. TC_LOG_ERROR("server.loading", "DurabilityLossChance.Parry (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_PARRY]);
  486. rate_values[RATE_DURABILITY_LOSS_PARRY] = 0.0f;
  487. }
  488. rate_values[RATE_DURABILITY_LOSS_BLOCK] = sConfigMgr->GetFloatDefault("DurabilityLossChance.Block", 0.05f);
  489. if (rate_values[RATE_DURABILITY_LOSS_BLOCK] < 0.0f)
  490. {
  491. TC_LOG_ERROR("server.loading", "DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_BLOCK]);
  492. rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
  493. }
  494. rate_values[RATE_MONEY_QUEST] = sConfigMgr->GetFloatDefault("Rate.Quest.Money.Reward", 1.0f);
  495. if (rate_values[RATE_MONEY_QUEST] < 0.0f)
  496. {
  497. TC_LOG_ERROR("server.loading", "Rate.Quest.Money.Reward (%f) must be >=0. Using 0 instead.", rate_values[RATE_MONEY_QUEST]);
  498. rate_values[RATE_MONEY_QUEST] = 0.0f;
  499. }
  500. rate_values[RATE_MONEY_MAX_LEVEL_QUEST] = sConfigMgr->GetFloatDefault("Rate.Quest.Money.Max.Level.Reward", 1.0f);
  501. if (rate_values[RATE_MONEY_MAX_LEVEL_QUEST] < 0.0f)
  502. {
  503. TC_LOG_ERROR("server.loading", "Rate.Quest.Money.Max.Level.Reward (%f) must be >=0. Using 0 instead.", rate_values[RATE_MONEY_MAX_LEVEL_QUEST]);
  504. rate_values[RATE_MONEY_MAX_LEVEL_QUEST] = 0.0f;
  505. }
  506. ///- Read other configuration items from the config file
  507. m_bool_configs[CONFIG_DURABILITY_LOSS_IN_PVP] = sConfigMgr->GetBoolDefault("DurabilityLoss.InPvP", false);
  508. m_int_configs[CONFIG_COMPRESSION] = sConfigMgr->GetIntDefault("Compression", 1);
  509. if (m_int_configs[CONFIG_COMPRESSION] < 1 || m_int_configs[CONFIG_COMPRESSION] > 9)
  510. {
  511. TC_LOG_ERROR("server.loading", "Compression level (%i) must be in range 1..9. Using default compression level (1).", m_int_configs[CONFIG_COMPRESSION]);
  512. m_int_configs[CONFIG_COMPRESSION] = 1;
  513. }
  514. m_bool_configs[CONFIG_ADDON_CHANNEL] = sConfigMgr->GetBoolDefault("AddonChannel", true);
  515. m_bool_configs[CONFIG_CLEAN_CHARACTER_DB] = sConfigMgr->GetBoolDefault("CleanCharacterDB", false);
  516. m_int_configs[CONFIG_PERSISTENT_CHARACTER_CLEAN_FLAGS] = sConfigMgr->GetIntDefault("PersistentCharacterCleanFlags", 0);
  517. m_int_configs[CONFIG_CHAT_CHANNEL_LEVEL_REQ] = sConfigMgr->GetIntDefault("ChatLevelReq.Channel", 1);
  518. m_int_configs[CONFIG_CHAT_WHISPER_LEVEL_REQ] = sConfigMgr->GetIntDefault("ChatLevelReq.Whisper", 1);
  519. m_int_configs[CONFIG_CHAT_SAY_LEVEL_REQ] = sConfigMgr->GetIntDefault("ChatLevelReq.Say", 1);
  520. m_int_configs[CONFIG_TRADE_LEVEL_REQ] = sConfigMgr->GetIntDefault("LevelReq.Trade", 1);
  521. m_int_configs[CONFIG_TICKET_LEVEL_REQ] = sConfigMgr->GetIntDefault("LevelReq.Ticket", 1);
  522. m_int_configs[CONFIG_AUCTION_LEVEL_REQ] = sConfigMgr->GetIntDefault("LevelReq.Auction", 1);
  523. m_int_configs[CONFIG_MAIL_LEVEL_REQ] = sConfigMgr->GetIntDefault("LevelReq.Mail", 1);
  524. m_bool_configs[CONFIG_PRESERVE_CUSTOM_CHANNELS] = sConfigMgr->GetBoolDefault("PreserveCustomChannels", false);
  525. m_int_configs[CONFIG_PRESERVE_CUSTOM_CHANNEL_DURATION] = sConfigMgr->GetIntDefault("PreserveCustomChannelDuration", 14);
  526. m_bool_configs[CONFIG_GRID_UNLOAD] = sConfigMgr->GetBoolDefault("GridUnload", true);
  527. m_int_configs[CONFIG_INTERVAL_SAVE] = sConfigMgr->GetIntDefault("PlayerSaveInterval", 15 * MINUTE * IN_MILLISECONDS);
  528. m_int_configs[CONFIG_INTERVAL_DISCONNECT_TOLERANCE] = sConfigMgr->GetIntDefault("DisconnectToleranceInterval", 0);
  529. m_bool_configs[CONFIG_STATS_SAVE_ONLY_ON_LOGOUT] = sConfigMgr->GetBoolDefault("PlayerSave.Stats.SaveOnlyOnLogout", true);
  530. m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = sConfigMgr->GetIntDefault("PlayerSave.Stats.MinLevel", 0);
  531. if (m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] > MAX_LEVEL)
  532. {
  533. TC_LOG_ERROR("server.loading", "PlayerSave.Stats.MinLevel (%i) must be in range 0..80. Using default, do not save character stats (0).", m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE]);
  534. m_int_configs[CONFIG_MIN_LEVEL_STAT_SAVE] = 0;
  535. }
  536. m_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfigMgr->GetIntDefault("GridCleanUpDelay", 5 * MINUTE * IN_MILLISECONDS);
  537. if (m_int_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY)
  538. {
  539. TC_LOG_ERROR("server.loading", "GridCleanUpDelay (%i) must be greater %u. Use this minimal value.", m_int_configs[CONFIG_INTERVAL_GRIDCLEAN], MIN_GRID_DELAY);
  540. m_int_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY;
  541. }
  542. if (reload)
  543. sMapMgr->SetGridCleanUpDelay(m_int_configs[CONFIG_INTERVAL_GRIDCLEAN]);
  544. m_int_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfigMgr->GetIntDefault("MapUpdateInterval", 100);
  545. if (m_int_configs[CONFIG_INTERVAL_MAPUPDATE] < MIN_MAP_UPDATE_DELAY)
  546. {
  547. TC_LOG_ERROR("server.loading", "MapUpdateInterval (%i) must be greater %u. Use this minimal value.", m_int_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
  548. m_int_configs[CONFIG_INTERVAL_MAPUPDATE] = MIN_MAP_UPDATE_DELAY;
  549. }
  550. if (reload)
  551. sMapMgr->SetMapUpdateInterval(m_int_configs[CONFIG_INTERVAL_MAPUPDATE]);
  552. m_int_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfigMgr->GetIntDefault("ChangeWeatherInterval", 10 * MINUTE * IN_MILLISECONDS);
  553. if (reload)
  554. {
  555. uint32 val = sConfigMgr->GetIntDefault("WorldServerPort", 8085);
  556. if (val != m_int_configs[CONFIG_PORT_WORLD])
  557. TC_LOG_ERROR("server.loading", "WorldServerPort option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_PORT_WORLD]);
  558. }
  559. else
  560. m_int_configs[CONFIG_PORT_WORLD] = sConfigMgr->GetIntDefault("WorldServerPort", 8085);
  561. m_int_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfigMgr->GetIntDefault("SocketTimeOutTime", 900000);
  562. m_int_configs[CONFIG_SESSION_ADD_DELAY] = sConfigMgr->GetIntDefault("SessionAddDelay", 10000);
  563. m_float_configs[CONFIG_GROUP_XP_DISTANCE] = sConfigMgr->GetFloatDefault("MaxGroupXPDistance", 74.0f);
  564. m_float_configs[CONFIG_MAX_RECRUIT_A_FRIEND_DISTANCE] = sConfigMgr->GetFloatDefault("MaxRecruitAFriendBonusDistance", 100.0f);
  565. /// @todo Add MonsterSight and GuarderSight (with meaning) in worldserver.conf or put them as define
  566. m_float_configs[CONFIG_SIGHT_MONSTER] = sConfigMgr->GetFloatDefault("MonsterSight", 50.0f);
  567. m_float_configs[CONFIG_SIGHT_GUARDER] = sConfigMgr->GetFloatDefault("GuarderSight", 50.0f);
  568. if (reload)
  569. {
  570. uint32 val = sConfigMgr->GetIntDefault("GameType", 0);
  571. if (val != m_int_configs[CONFIG_GAME_TYPE])
  572. TC_LOG_ERROR("server.loading", "GameType option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_GAME_TYPE]);
  573. }
  574. else
  575. m_int_configs[CONFIG_GAME_TYPE] = sConfigMgr->GetIntDefault("GameType", 0);
  576. if (reload)
  577. {
  578. uint32 val = sConfigMgr->GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
  579. if (val != m_int_configs[CONFIG_REALM_ZONE])
  580. TC_LOG_ERROR("server.loading", "RealmZone option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_REALM_ZONE]);
  581. }
  582. else
  583. m_int_configs[CONFIG_REALM_ZONE] = sConfigMgr->GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
  584. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CALENDAR]= sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Calendar", false);
  585. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Channel", false);
  586. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Group", false);
  587. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Guild", false);
  588. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfigMgr->GetBoolDefault("AllowTwoSide.Interaction.Auction", false);
  589. m_bool_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfigMgr->GetBoolDefault("AllowTwoSide.Trade", false);
  590. m_int_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfigMgr->GetIntDefault ("StrictPlayerNames", 0);
  591. m_int_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfigMgr->GetIntDefault ("StrictCharterNames", 0);
  592. m_int_configs[CONFIG_STRICT_PET_NAMES] = sConfigMgr->GetIntDefault ("StrictPetNames", 0);
  593. m_int_configs[CONFIG_MIN_PLAYER_NAME] = sConfigMgr->GetIntDefault ("MinPlayerName", 2);
  594. if (m_int_configs[CONFIG_MIN_PLAYER_NAME] < 1 || m_int_configs[CONFIG_MIN_PLAYER_NAME] > MAX_PLAYER_NAME)
  595. {
  596. TC_LOG_ERROR("server.loading", "MinPlayerName (%i) must be in range 1..%u. Set to 2.", m_int_configs[CONFIG_MIN_PLAYER_NAME], MAX_PLAYER_NAME);
  597. m_int_configs[CONFIG_MIN_PLAYER_NAME] = 2;
  598. }
  599. m_int_configs[CONFIG_MIN_CHARTER_NAME] = sConfigMgr->GetIntDefault ("MinCharterName", 2);
  600. if (m_int_configs[CONFIG_MIN_CHARTER_NAME] < 1 || m_int_configs[CONFIG_MIN_CHARTER_NAME] > MAX_CHARTER_NAME)
  601. {
  602. TC_LOG_ERROR("server.loading", "MinCharterName (%i) must be in range 1..%u. Set to 2.", m_int_configs[CONFIG_MIN_CHARTER_NAME], MAX_CHARTER_NAME);
  603. m_int_configs[CONFIG_MIN_CHARTER_NAME] = 2;
  604. }
  605. m_int_configs[CONFIG_MIN_PET_NAME] = sConfigMgr->GetIntDefault ("MinPetName", 2);
  606. if (m_int_configs[CONFIG_MIN_PET_NAME] < 1 || m_int_configs[CONFIG_MIN_PET_NAME] > MAX_PET_NAME)
  607. {
  608. TC_LOG_ERROR("server.loading", "MinPetName (%i) must be in range 1..%u. Set to 2.", m_int_configs[CONFIG_MIN_PET_NAME], MAX_PET_NAME);
  609. m_int_configs[CONFIG_MIN_PET_NAME] = 2;
  610. }
  611. m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled", 0);
  612. m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_RACEMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.RaceMask", 0);
  613. m_int_configs[CONFIG_CHARACTER_CREATING_DISABLED_CLASSMASK] = sConfigMgr->GetIntDefault("CharacterCreating.Disabled.ClassMask", 0);
  614. m_int_configs[CONFIG_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("CharactersPerRealm", 10);
  615. if (m_int_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_int_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
  616. {
  617. TC_LOG_ERROR("server.loading", "CharactersPerRealm (%i) must be in range 1..10. Set to 10.", m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
  618. m_int_configs[CONFIG_CHARACTERS_PER_REALM] = 10;
  619. }
  620. // must be after CONFIG_CHARACTERS_PER_REALM
  621. m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfigMgr->GetIntDefault("CharactersPerAccount", 50);
  622. if (m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] < m_int_configs[CONFIG_CHARACTERS_PER_REALM])
  623. {
  624. TC_LOG_ERROR("server.loading", "CharactersPerAccount (%i) can't be less than CharactersPerRealm (%i).", m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT], m_int_configs[CONFIG_CHARACTERS_PER_REALM]);
  625. m_int_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = m_int_configs[CONFIG_CHARACTERS_PER_REALM];
  626. }
  627. m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = sConfigMgr->GetIntDefault("HeroicCharactersPerRealm", 1);
  628. if (int32(m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]) < 0 || m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] > 10)
  629. {
  630. TC_LOG_ERROR("server.loading", "HeroicCharactersPerRealm (%i) must be in range 0..10. Set to 1.", m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM]);
  631. m_int_configs[CONFIG_HEROIC_CHARACTERS_PER_REALM] = 1;
  632. }
  633. m_int_configs[CONFIG_CHARACTER_CREATING_MIN_LEVEL_FOR_HEROIC_CHARACTER] = sConfigMgr->GetIntDefault("CharacterCreating.MinLevelForHeroicCharacter", 55);
  634. m_int_configs[CONFIG_SKIP_CINEMATICS] = sConfigMgr->GetIntDefault("SkipCinematics", 0);
  635. if (int32(m_int_configs[CONFIG_SKIP_CINEMATICS]) < 0 || m_int_configs[CONFIG_SKIP_CINEMATICS] > 2)
  636. {
  637. TC_LOG_ERROR("server.loading", "SkipCinematics (%i) must be in range 0..2. Set to 0.", m_int_configs[CONFIG_SKIP_CINEMATICS]);
  638. m_int_configs[CONFIG_SKIP_CINEMATICS] = 0;
  639. }
  640. if (reload)
  641. {
  642. uint32 val = sConfigMgr->GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
  643. if (val != m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  644. TC_LOG_ERROR("server.loading", "MaxPlayerLevel option can't be changed at config reload, using current value (%u).", m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  645. }
  646. else
  647. m_int_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
  648. if (m_int_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL)
  649. {
  650. TC_LOG_ERROR("server.loading", "MaxPlayerLevel (%i) must be in range 1..%u. Set to %u.", m_int_configs[CONFIG_MAX_PLAYER_LEVEL], MAX_LEVEL, MAX_LEVEL);
  651. m_int_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL;
  652. }
  653. m_int_configs[CONFIG_MIN_DUALSPEC_LEVEL] = sConfigMgr->GetIntDefault("MinDualSpecLevel", 40);
  654. m_int_configs[CONFIG_START_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("StartPlayerLevel", 1);
  655. if (m_int_configs[CONFIG_START_PLAYER_LEVEL] < 1)
  656. {
  657. TC_LOG_ERROR("server.loading", "StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 1.", m_int_configs[CONFIG_START_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  658. m_int_configs[CONFIG_START_PLAYER_LEVEL] = 1;
  659. }
  660. else if (m_int_configs[CONFIG_START_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  661. {
  662. TC_LOG_ERROR("server.loading", "StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.", m_int_configs[CONFIG_START_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  663. m_int_configs[CONFIG_START_PLAYER_LEVEL] = m_int_configs[CONFIG_MAX_PLAYER_LEVEL];
  664. }
  665. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("StartHeroicPlayerLevel", 55);
  666. if (m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] < 1)
  667. {
  668. TC_LOG_ERROR("server.loading", "StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 55.",
  669. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  670. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = 55;
  671. }
  672. else if (m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  673. {
  674. TC_LOG_ERROR("server.loading", "StartHeroicPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.",
  675. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL]);
  676. m_int_configs[CONFIG_START_HEROIC_PLAYER_LEVEL] = m_int_configs[CONFIG_MAX_PLAYER_LEVEL];
  677. }
  678. m_int_configs[CONFIG_START_PLAYER_MONEY] = sConfigMgr->GetIntDefault("StartPlayerMoney", 0);
  679. if (int32(m_int_configs[CONFIG_START_PLAYER_MONEY]) < 0)
  680. {
  681. TC_LOG_ERROR("server.loading", "StartPlayerMoney (%i) must be in range 0.." UI64FMTD ". Set to %u.", m_int_configs[CONFIG_START_PLAYER_MONEY], uint64(MAX_MONEY_AMOUNT), 0);
  682. m_int_configs[CONFIG_START_PLAYER_MONEY] = 0;
  683. }
  684. else if (m_int_configs[CONFIG_START_PLAYER_MONEY] > 0x7FFFFFFF-1) // TODO: (See MAX_MONEY_AMOUNT)
  685. {
  686. TC_LOG_ERROR("server.loading", "StartPlayerMoney (%i) must be in range 0..%u. Set to %u.",
  687. m_int_configs[CONFIG_START_PLAYER_MONEY], 0x7FFFFFFF-1, 0x7FFFFFFF-1);
  688. m_int_configs[CONFIG_START_PLAYER_MONEY] = 0x7FFFFFFF-1;
  689. }
  690. m_int_configs[CONFIG_CURRENCY_RESET_HOUR] = sConfigMgr->GetIntDefault("Currency.ResetHour", 3);
  691. if (m_int_configs[CONFIG_CURRENCY_RESET_HOUR] > 23)
  692. {
  693. TC_LOG_ERROR("server.loading", "Currency.ResetHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_CURRENCY_RESET_HOUR]);
  694. m_int_configs[CONFIG_CURRENCY_RESET_HOUR] = 3;
  695. }
  696. m_int_configs[CONFIG_CURRENCY_RESET_DAY] = sConfigMgr->GetIntDefault("Currency.ResetDay", 3);
  697. if (m_int_configs[CONFIG_CURRENCY_RESET_DAY] > 6)
  698. {
  699. TC_LOG_ERROR("server.loading", "Currency.ResetDay (%i) can't be load. Set to 3.", m_int_configs[CONFIG_CURRENCY_RESET_DAY]);
  700. m_int_configs[CONFIG_CURRENCY_RESET_DAY] = 3;
  701. }
  702. m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL] = sConfigMgr->GetIntDefault("Currency.ResetInterval", 7);
  703. if (int32(m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL]) <= 0)
  704. {
  705. TC_LOG_ERROR("server.loading", "Currency.ResetInterval (%i) must be > 0, set to default 7.", m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL]);
  706. m_int_configs[CONFIG_CURRENCY_RESET_INTERVAL] = 7;
  707. }
  708. m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS] = sConfigMgr->GetIntDefault("Currency.StartHonorPoints", 0);
  709. if (int32(m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS]) < 0)
  710. {
  711. TC_LOG_ERROR("server.loading", "Currency.StartHonorPoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS]);
  712. m_int_configs[CONFIG_CURRENCY_START_HONOR_POINTS] = 0;
  713. }
  714. m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] = sConfigMgr->GetIntDefault("Currency.MaxHonorPoints", 4000);
  715. if (int32(m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS]) < 0)
  716. {
  717. TC_LOG_ERROR("server.loading", "Currency.MaxHonorPoints (%i) can't be negative. Set to default 4000.", m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS]);
  718. m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] = 4000;
  719. }
  720. m_int_configs[CONFIG_CURRENCY_MAX_HONOR_POINTS] *= 100; //precision mod
  721. m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS] = sConfigMgr->GetIntDefault("Currency.StartJusticePoints", 0);
  722. if (int32(m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS]) < 0)
  723. {
  724. TC_LOG_ERROR("server.loading", "Currency.StartJusticePoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS]);
  725. m_int_configs[CONFIG_CURRENCY_START_JUSTICE_POINTS] = 0;
  726. }
  727. m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] = sConfigMgr->GetIntDefault("Currency.MaxJusticePoints", 4000);
  728. if (int32(m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS]) < 0)
  729. {
  730. TC_LOG_ERROR("server.loading", "Currency.MaxJusticePoints (%i) can't be negative. Set to default 4000.", m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS]);
  731. m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] = 4000;
  732. }
  733. m_int_configs[CONFIG_CURRENCY_MAX_JUSTICE_POINTS] *= 100; //precision mod
  734. m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS] = sConfigMgr->GetIntDefault("Currency.StartConquestPoints", 0);
  735. if (int32(m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS]) < 0)
  736. {
  737. TC_LOG_ERROR("server.loading", "Currency.StartConquestPoints (%i) must be >= 0, set to default 0.", m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS]);
  738. m_int_configs[CONFIG_CURRENCY_START_CONQUEST_POINTS] = 0;
  739. }
  740. m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] = sConfigMgr->GetIntDefault("Currency.ConquestPointsWeekCap", 1650);
  741. if (int32(m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP]) <= 0)
  742. {
  743. TC_LOG_ERROR("server.loading", "Currency.ConquestPointsWeekCap (%i) must be > 0, set to default 1650.", m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP]);
  744. m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] = 1650;
  745. }
  746. m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_WEEK_CAP] *= 100; //precision mod
  747. m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] = sConfigMgr->GetIntDefault("Currency.ConquestPointsArenaReward", 180);
  748. if (int32(m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD]) <= 0)
  749. {
  750. TC_LOG_ERROR("server.loading", "Currency.ConquestPointsArenaReward (%i) must be > 0, set to default 180.", m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD]);
  751. m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] = 180;
  752. }
  753. m_int_configs[CONFIG_CURRENCY_CONQUEST_POINTS_ARENA_REWARD] *= 100; //precision mod
  754. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = sConfigMgr->GetIntDefault("RecruitAFriend.MaxLevel", 60);
  755. if (m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] > m_int_configs[CONFIG_MAX_PLAYER_LEVEL])
  756. {
  757. TC_LOG_ERROR("server.loading", "RecruitAFriend.MaxLevel (%i) must be in the range 0..MaxLevel(%u). Set to %u.",
  758. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL], m_int_configs[CONFIG_MAX_PLAYER_LEVEL], 60);
  759. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL] = 60;
  760. }
  761. m_int_configs[CONFIG_MAX_RECRUIT_A_FRIEND_BONUS_PLAYER_LEVEL_DIFFERENCE] = sConfigMgr->GetIntDefault("RecruitAFriend.MaxDifference", 4);
  762. m_bool_configs[CONFIG_ALL_TAXI_PATHS] = sConfigMgr->GetBoolDefault("AllFlightPaths", false);
  763. m_bool_configs[CONFIG_INSTANT_TAXI] = sConfigMgr->GetBoolDefault("InstantFlightPaths", false);
  764. m_bool_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfigMgr->GetBoolDefault("Instance.IgnoreLevel", false);
  765. m_bool_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfigMgr->GetBoolDefault("Instance.IgnoreRaid", false);
  766. m_bool_configs[CONFIG_CAST_UNSTUCK] = sConfigMgr->GetBoolDefault("CastUnstuck", true);
  767. m_int_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfigMgr->GetIntDefault("Instance.ResetTimeHour", 4);
  768. m_int_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfigMgr->GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS);
  769. m_int_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfigMgr->GetIntDefault("MaxPrimaryTradeSkill", 2);
  770. m_int_configs[CONFIG_MIN_PETITION_SIGNS] = sConfigMgr->GetIntDefault("MinPetitionSigns", 9);
  771. if (m_int_configs[CONFIG_MIN_PETITION_SIGNS] > 9)
  772. {
  773. TC_LOG_ERROR("server.loading", "MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_int_configs[CONFIG_MIN_PETITION_SIGNS]);
  774. m_int_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
  775. }
  776. m_int_configs[CONFIG_GM_LOGIN_STATE] = sConfigMgr->GetIntDefault("GM.LoginState", 2);
  777. m_int_configs[CONFIG_GM_VISIBLE_STATE] = sConfigMgr->GetIntDefault("GM.Visible", 2);
  778. m_int_configs[CONFIG_GM_CHAT] = sConfigMgr->GetIntDefault("GM.Chat", 2);
  779. m_int_configs[CONFIG_GM_WHISPERING_TO] = sConfigMgr->GetIntDefault("GM.WhisperingTo", 2);
  780. m_int_configs[CONFIG_GM_FREEZE_DURATION] = sConfigMgr->GetIntDefault("GM.FreezeAuraDuration", 0);
  781. m_int_configs[CONFIG_GM_LEVEL_IN_GM_LIST] = sConfigMgr->GetIntDefault("GM.InGMList.Level", SEC_ADMINISTRATOR);
  782. m_int_configs[CONFIG_GM_LEVEL_IN_WHO_LIST] = sConfigMgr->GetIntDefault("GM.InWhoList.Level", SEC_ADMINISTRATOR);
  783. m_int_configs[CONFIG_START_GM_LEVEL] = sConfigMgr->GetIntDefault("GM.StartLevel", 1);
  784. if (m_int_configs[CONFIG_START_GM_LEVEL] < m_int_configs[CONFIG_START_PLAYER_LEVEL])
  785. {
  786. TC_LOG_ERROR("server.loading", "GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.",
  787. m_int_configs[CONFIG_START_GM_LEVEL], m_int_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_int_configs[CONFIG_START_PLAYER_LEVEL]);
  788. m_int_configs[CONFIG_START_GM_LEVEL] = m_int_configs[CONFIG_START_PLAYER_LEVEL];
  789. }
  790. else if (m_int_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL)
  791. {
  792. TC_LOG_ERROR("server.loading", "GM.StartLevel (%i) must be in range 1..%u. Set to %u.", m_int_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL);
  793. m_int_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
  794. }
  795. m_bool_configs[CONFIG_ALLOW_GM_GROUP] = sConfigMgr->GetBoolDefault("GM.AllowInvite", false);
  796. m_bool_configs[CONFIG_GM_LOWER_SECURITY] = sConfigMgr->GetBoolDefault("GM.LowerSecurity", false);
  797. m_float_configs[CONFIG_CHANCE_OF_GM_SURVEY] = sConfigMgr->GetFloatDefault("GM.TicketSystem.ChanceOfGMSurvey", 50.0f);
  798. m_int_configs[CONFIG_GROUP_VISIBILITY] = sConfigMgr->GetIntDefault("Visibility.GroupMode", 1);
  799. m_int_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfigMgr->GetIntDefault("MailDeliveryDelay", HOUR);
  800. m_int_configs[CONFIG_UPTIME_UPDATE] = sConfigMgr->GetIntDefault("UpdateUptimeInterval", 10);
  801. if (int32(m_int_configs[CONFIG_UPTIME_UPDATE]) <= 0)
  802. {
  803. TC_LOG_ERROR("server.loading", "UpdateUptimeInterval (%i) must be > 0, set to default 10.", m_int_configs[CONFIG_UPTIME_UPDATE]);
  804. m_int_configs[CONFIG_UPTIME_UPDATE] = 10;
  805. }
  806. if (reload)
  807. {
  808. m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS);
  809. m_timers[WUPDATE_UPTIME].Reset();
  810. }
  811. // log db cleanup interval
  812. m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = sConfigMgr->GetIntDefault("LogDB.Opt.ClearInterval", 10);
  813. if (int32(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]) <= 0)
  814. {
  815. TC_LOG_ERROR("server.loading", "LogDB.Opt.ClearInterval (%i) must be > 0, set to default 10.", m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
  816. m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] = 10;
  817. }
  818. if (reload)
  819. {
  820. m_timers[WUPDATE_CLEANDB].SetInterval(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL] * MINUTE * IN_MILLISECONDS);
  821. m_timers[WUPDATE_CLEANDB].Reset();
  822. }
  823. m_int_configs[CONFIG_LOGDB_CLEARTIME] = sConfigMgr->GetIntDefault("LogDB.Opt.ClearTime", 1209600); // 14 days default
  824. TC_LOG_INFO("server.loading", "Will clear `logs` table of entries older than %i seconds every %u minutes.",
  825. m_int_configs[CONFIG_LOGDB_CLEARTIME], m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]);
  826. m_int_configs[CONFIG_SKILL_CHANCE_ORANGE] = sConfigMgr->GetIntDefault("SkillChance.Orange", 100);
  827. m_int_configs[CONFIG_SKILL_CHANCE_YELLOW] = sConfigMgr->GetIntDefault("SkillChance.Yellow", 75);
  828. m_int_configs[CONFIG_SKILL_CHANCE_GREEN] = sConfigMgr->GetIntDefault("SkillChance.Green", 25);
  829. m_int_configs[CONFIG_SKILL_CHANCE_GREY] = sConfigMgr->GetIntDefault("SkillChance.Grey", 0);
  830. m_int_configs[CONFIG_SKILL_CHANCE_MINING_STEPS] = sConfigMgr->GetIntDefault("SkillChance.MiningSteps", 75);
  831. m_int_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfigMgr->GetIntDefault("SkillChance.SkinningSteps", 75);
  832. m_bool_configs[CONFIG_SKILL_PROSPECTING] = sConfigMgr->GetBoolDefault("SkillChance.Prospecting", false);
  833. m_bool_configs[CONFIG_SKILL_MILLING] = sConfigMgr->GetBoolDefault("SkillChance.Milling", false);
  834. m_int_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfigMgr->GetIntDefault("SkillGain.Crafting", 1);
  835. m_int_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfigMgr->GetIntDefault("SkillGain.Gathering", 1);
  836. m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfigMgr->GetIntDefault("MaxOverspeedPings", 2);
  837. if (m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] != 0 && m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] < 2)
  838. {
  839. TC_LOG_ERROR("server.loading", "MaxOverspeedPings (%i) must be in range 2..infinity (or 0 to disable check). Set to 2.", m_int_configs[CONFIG_MAX_OVERSPEED_PINGS]);
  840. m_int_configs[CONFIG_MAX_OVERSPEED_PINGS] = 2;
  841. }
  842. m_bool_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = sConfigMgr->GetBoolDefault("SaveRespawnTimeImmediately", true);
  843. m_bool_configs[CONFIG_WEATHER] = sConfigMgr->GetBoolDefault("ActivateWeather", true);
  844. m_int_configs[CONFIG_DISABLE_BREATHING] = sConfigMgr->GetIntDefault("DisableWaterBreath", SEC_CONSOLE);
  845. if (reload)
  846. {
  847. uint32 val = sConfigMgr->GetIntDefault("Expansion", 2);
  848. if (val != m_int_configs[CONFIG_EXPANSION])
  849. TC_LOG_ERROR("server.loading", "Expansion option can't be changed at worldserver.conf reload, using current value (%u).", m_int_configs[CONFIG_EXPANSION]);
  850. }
  851. else
  852. m_int_configs[CONFIG_EXPANSION] = sConfigMgr->GetIntDefault("Expansion", 2);
  853. m_int_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfigMgr->GetIntDefault("ChatFlood.MessageCount", 10);
  854. m_int_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfigMgr->GetIntDefault("ChatFlood.MessageDelay", 1);
  855. m_int_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfigMgr->GetIntDefault("ChatFlood.MuteTime", 10);
  856. m_bool_configs[CONFIG_EVENT_ANNOUNCE] = sConfigMgr->GetBoolDefault("Event.Announce", false);
  857. m_float_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = sConfigMgr->GetFloatDefault("CreatureFamilyFleeAssistanceRadius", 30.0f);
  858. m_float_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = sConfigMgr->GetFloatDefault("CreatureFamilyAssistanceRadius", 10.0f);
  859. m_int_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY] = sConfigMgr->GetIntDefault("CreatureFamilyAssistanceDelay", 1500);
  860. m_int_configs[CONFIG_CREATURE_FAMILY_FLEE_DELAY] = sConfigMgr->GetIntDefault("CreatureFamilyFleeDelay", 7000);
  861. m_int_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfigMgr->GetIntDefault("WorldBossLevelDiff", 3);
  862. m_bool_configs[CONFIG_QUEST_ENABLE_QUEST_TRACKER] = sConfigMgr->GetBoolDefault("Quests.EnableQuestTracker", false);
  863. // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100)
  864. m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfigMgr->GetIntDefault("Quests.LowLevelHideDiff", 4);
  865. if (m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] > MAX_LEVEL)
  866. m_int_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = MAX_LEVEL;
  867. m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfigMgr->GetIntDefault("Quests.HighLevelHideDiff", 7);
  868. if (m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] > MAX_LEVEL)
  869. m_int_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = MAX_LEVEL;
  870. m_bool_configs[CONFIG_QUEST_IGNORE_RAID] = sConfigMgr->GetBoolDefault("Quests.IgnoreRaid", false);
  871. m_bool_configs[CONFIG_QUEST_IGNORE_AUTO_ACCEPT] = sConfigMgr->GetBoolDefault("Quests.IgnoreAutoAccept", false);
  872. m_bool_configs[CONFIG_QUEST_IGNORE_AUTO_COMPLETE] = sConfigMgr->GetBoolDefault("Quests.IgnoreAutoComplete", false);
  873. m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = sConfigMgr->GetIntDefault("Battleground.Random.ResetHour", 6);
  874. if (m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] > 23)
  875. {
  876. TC_LOG_ERROR("server.loading", "Battleground.Random.ResetHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR]);
  877. m_int_configs[CONFIG_RANDOM_BG_RESET_HOUR] = 6;
  878. }
  879. m_int_configs[CONFIG_GUILD_RESET_HOUR] = sConfigMgr->GetIntDefault("Guild.ResetHour", 6);
  880. if (m_int_configs[CONFIG_GUILD_RESET_HOUR] > 23)
  881. {
  882. TC_LOG_ERROR("misc", "Guild.ResetHour (%i) can't be load. Set to 6.", m_int_configs[CONFIG_GUILD_RESET_HOUR]);
  883. m_int_configs[CONFIG_GUILD_RESET_HOUR] = 6;
  884. }
  885. m_bool_configs[CONFIG_DETECT_POS_COLLISION] = sConfigMgr->GetBoolDefault("DetectPosCollision", true);
  886. m_bool_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfigMgr->GetBoolDefault("Channel.RestrictedLfg", true);
  887. m_bool_configs[CONFIG_TALENTS_INSPECTING] = sConfigMgr->GetBoolDefault("TalentsInspecting", true);
  888. m_bool_configs[CONFIG_CHAT_FAKE_MESSAGE_PREVENTING] = sConfigMgr->GetBoolDefault("ChatFakeMessagePreventing", false);
  889. m_int_configs[CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY] = sConfigMgr->GetIntDefault("ChatStrictLinkChecking.Severity", 0);
  890. m_int_configs[CONFIG_CHAT_STRICT_LINK_CHECKING_KICK] = sConfigMgr->GetIntDefault("ChatStrictLinkChecking.Kick", 0);
  891. m_int_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfigMgr->GetIntDefault("Corpse.Decay.NORMAL", 60);
  892. m_int_configs[CONFIG_CORPSE_DECAY_RARE] = sConfigMgr->GetIntDefault("Corpse.Decay.RARE", 300);
  893. m_int_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfigMgr->GetIntDefault("Corpse.Decay.ELITE", 300);
  894. m_int_configs[CONFIG_CORPSE_DECAY_RAREELITE] = sConfigMgr->GetIntDefault("Corpse.Decay.RAREELITE", 300);
  895. m_int_configs[CONFIG_CORPSE_DECAY_WORLDBOSS] = sConfigMgr->GetIntDefault("Corpse.Decay.WORLDBOSS", 3600);
  896. m_int_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfigMgr->GetIntDefault ("Death.SicknessLevel", 11);
  897. m_bool_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfigMgr->GetBoolDefault("Death.CorpseReclaimDelay.PvP", true);
  898. m_bool_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfigMgr->GetBoolDefault("Death.CorpseReclaimDelay.PvE", true);
  899. m_bool_configs[CONFIG_DEATH_BONES_WORLD] = sConfigMgr->GetBoolDefault("Death.Bones.World", true);
  900. m_bool_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfigMgr->GetBoolDefault("Death.Bones.BattlegroundOrArena", true);
  901. m_bool_configs[CONFIG_DIE_COMMAND_MODE] = sConfigMgr->GetBoolDefault("Die.Command.Mode", true);
  902. m_float_configs[CONFIG_THREAT_RADIUS] = sConfigMgr->GetFloatDefault("ThreatRadius", 60.0f);
  903. // always use declined names in the russian client
  904. m_bool_configs[CONFIG_DECLINED_NAMES_USED] =
  905. (m_int_configs[CONFIG_REALM_ZONE] == REALM_ZONE_RUSSIAN) ? true : sConfigMgr->GetBoolDefault("DeclinedNames", false);
  906. m_float_configs[CONFIG_LISTEN_RANGE_SAY] = sConfigMgr->GetFloatDefault("ListenRange.Say", 25.0f);
  907. m_float_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfigMgr->GetFloatDefault("ListenRange.TextEmote", 25.0f);
  908. m_float_configs[CONFIG_LISTEN_RANGE_YELL] = sConfigMgr->GetFloatDefault("ListenRange.Yell", 300.0f);
  909. m_bool_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfigMgr->GetBoolDefault("Battleground.CastDeserter", true);
  910. m_bool_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
  911. m_bool_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);
  912. m_bool_configs[CONFIG_BATTLEGROUND_STORE_STATISTICS_ENABLE] = sConfigMgr->GetBoolDefault("Battleground.StoreStatistics.Enable", false);
  913. m_int_configs[CONFIG_BATTLEGROUND_INVITATION_TYPE] = sConfigMgr->GetIntDefault ("Battleground.InvitationType", 0);
  914. m_int_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfigMgr->GetIntDefault ("Battleground.PrematureFinishTimer", 5 * MINUTE * IN_MILLISECONDS);
  915. m_int_configs[CONFIG_BATTLEGROUND_PREMADE_GROUP_WAIT_FOR_MATCH] = sConfigMgr->GetIntDefault ("Battleground.PremadeGroupWaitForMatch", 30 * MINUTE * IN_MILLISECONDS);
  916. m_bool_configs[CONFIG_BG_XP_FOR_KILL] = sConfigMgr->GetBoolDefault("Battleground.GiveXPForKills", false);
  917. m_int_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfigMgr->GetIntDefault ("Arena.MaxRatingDifference", 150);
  918. m_int_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfigMgr->GetIntDefault ("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS);
  919. m_int_configs[CONFIG_ARENA_RATED_UPDATE_TIMER] = sConfigMgr->GetIntDefault ("Arena.RatedUpdateTimer", 5 * IN_MILLISECONDS);
  920. m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
  921. m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.PlayerOnly", false);
  922. m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 1);
  923. m_int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartRating", 0);
  924. m_int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartPersonalRating", 1000);
  925. m_int_configs[CONFIG_ARENA_START_MATCHMAKER_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartMatchmakerRating", 1500);
  926. m_bool_configs[CONFIG_ARENA_SEASON_IN_PROGRESS] = sConfigMgr->GetBoolDefault("Arena.ArenaSeason.InProgress", true);
  927. m_bool_configs[CONFIG_ARENA_LOG_EXTENDED_INFO] = sConfigMgr->GetBoolDefault("ArenaLog.ExtendedInfo", false);
  928. m_bool_configs[CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN] = sConfigMgr->GetBoolDefault("OffhandCheckAtSpellUnlearn", true);
  929. m_int_configs[CONFIG_CREATURE_PICKPOCKET_REFILL] = sConfigMgr->GetIntDefault("Creature.PickPocketRefillDelay", 10 * MINUTE);
  930. if (int32 clientCacheId = sConfigMgr->GetIntDefault("ClientCacheVersion", 0))
  931. {
  932. // overwrite DB/old value
  933. if (clientCacheId > 0)
  934. {
  935. m_int_configs[CONFIG_CLIENTCACHE_VERSION] = clientCacheId;
  936. TC_LOG_INFO("server.loading", "Client cache version set to: %u", clientCacheId);
  937. }
  938. else
  939. TC_LOG_ERROR("server.loading", "ClientCacheVersion can't be negative %d, ignored.", clientCacheId);
  940. }
  941. m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = sConfigMgr->GetIntDefault("Guild.NewsLogRecordsCount", GUILD_NEWSLOG_MAX_RECORDS);
  942. if (m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] > GUILD_NEWSLOG_MAX_RECORDS)
  943. m_int_configs[CONFIG_GUILD_NEWS_LOG_COUNT] = GUILD_NEWSLOG_MAX_RECORDS;
  944. m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = sConfigMgr->GetIntDefault("Guild.EventLogRecordsCount", GUILD_EVENTLOG_MAX_RECORDS);
  945. if (m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] > GUILD_EVENTLOG_MAX_RECORDS)
  946. m_int_configs[CONFIG_GUILD_EVENT_LOG_COUNT] = GUILD_EVENTLOG_MAX_RECORDS;
  947. m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = sConfigMgr->GetIntDefault("Guild.BankEventLogRecordsCount", GUILD_BANKLOG_MAX_RECORDS);
  948. if (m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] > GUILD_BANKLOG_MAX_RECORDS)
  949. m_int_configs[CONFIG_GUILD_BANK_EVENT_LOG_COUNT] = GUILD_BANKLOG_MAX_RECORDS;
  950. //visibility on continents
  951. m_MaxVisibleDistanceOnContinents = sConfigMgr->GetFloatDefault("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
  952. if (m_MaxVisibleDistanceOnContinents < 45*sWorld->getRate(RATE_CREATURE_AGGRO))
  953. {
  954. TC_LOG_ERROR("server.loading", "Visibility.Distance.Continents can't be less max aggro radius %f", 45*sWorld->getRate(RATE_CREATURE_AGGRO));
  955. m_MaxVisibleDistanceOnContinents = 45*sWorld->getRate(RATE_CREATURE_AGGRO);
  956. }
  957. else if (m_MaxVisibleDistanceOnContinents > MAX_VISIBILITY_DISTANCE)
  958. {
  959. TC_LOG_ERROR("server.loading", "Visibility.Distance.Continents can't be greater %f", MAX_VISIBILITY_DISTANCE);
  960. m_MaxVisibleDistanceOnContinents = MAX_VISIBILITY_DISTANCE;
  961. }
  962. //visibility in instances
  963. m_MaxVisibleDistanceInInstances = sConfigMgr->GetFloatDefault("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
  964. if (m_MaxVisibleDistanceInInstances < 45*sWorld->getRate(RATE_CREATURE_AGGRO))
  965. {
  966. TC_LOG_ERROR("server.loading", "Visibility.Distance.Instances can't be less max aggro radius %f", 45*sWorld->getRate(RATE_CREATURE_AGGRO));
  967. m_MaxVisibleDistanceInInstances = 45*sWorld->getRate(RATE_CREATURE_AGGRO);
  968. }
  969. else if (m_MaxVisibleDistanceInInstances > MAX_VISIBILITY_DISTANCE)
  970. {
  971. TC_LOG_ERROR("server.loading", "Visibility.Distance.Instances can't be greater %f", MAX_VISIBILITY_DISTANCE);
  972. m_MaxVisibleDistanceInInstances = MAX_VISIBILITY_DISTANCE;
  973. }
  974. //visibility in BG/Arenas
  975. m_MaxVisibleDistanceInBGArenas = sConfigMgr->GetFloatDefault("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
  976. if (m_MaxVisibleDistanceInBGArenas < 45*sWorld->getRate(RATE_CREATURE_AGGRO))
  977. {
  978. TC_LOG_ERROR("server.loading", "Visibility.Distance.BGArenas can't be less max aggro radius %f", 45*sWorld->getRate(RATE_CREATURE_AGGRO));
  979. m_MaxVisibleDistanceInBGArenas = 45*sWorld->getRate(RATE_CREATURE_AGGRO);
  980. }
  981. else if (m_MaxVisibleDistanceInBGArenas > MAX_VISIBILITY_DISTANCE)
  982. {
  983. TC_LOG_ERROR("server.loading", "Visibility.Distance.BGArenas can't be greater %f", MAX_VISIBILITY_DISTANCE);
  984. m_MaxVisibleDistanceInBGArenas = MAX_VISIBILITY_DISTANCE;
  985. }
  986. m_visibility_notify_periodOnContinents = sConfigMgr->GetIntDefault("Visibility.Notify.Period.OnContinents", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
  987. m_visibility_notify_periodInInstances = sConfigMgr->GetIntDefault("Visibility.Notify.Period.InInstances", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
  988. m_visibility_notify_periodInBGArenas = sConfigMgr->GetIntDefault("Visibility.Notify.Period.InBGArenas", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
  989. ///- Load the CharDelete related config options
  990. m_int_configs[CONFIG_CHARDELETE_METHOD] = sConfigMgr->GetIntDefault("CharDelete.Method", 0);
  991. m_int_configs[CONFIG_CHARDELETE_MIN_LEVEL] = sConfigMgr->GetIntDefault("CharDelete.MinLevel", 0);
  992. m_int_configs[CONFIG_CHARDELETE_HEROIC_MIN_LEVEL] = sConfigMgr->GetIntDefault("CharDelete.Heroic.MinLevel", 0);
  993. m_int_configs[CONFIG_CHARDELETE_KEEP_DAYS] = sConfigMgr->GetIntDefault("CharDelete.KeepDays", 30);
  994. ///- Read the "Data" directory from the config file
  995. std::string dataPath = sConfigMgr->GetStringDefault("DataDir", "./");
  996. if (dataPath.empty() || (dataPath.at(dataPath.length()-1) != '/' && dataPath.at(dataPath.length()-1) != '\\'))
  997. dataPath.push_back('/');
  998. #if PLATFORM == PLATFORM_UNIX || PLATFORM == PLATFORM_APPLE
  999. if (dataPath[0] == '~')
  1000. {
  1001. const char* home = getenv("HOME");
  1002. if (home)
  1003. dataPath.replace(0, 1, home);
  1004. }
  1005. #endif
  1006. if (reload)
  1007. {
  1008. if (dataPath != m_dataPath)
  1009. TC_LOG_ERROR("server.loading", "DataDir option can't be changed at worldserver.conf reload, using current value (%s).", m_dataPath.c_str());
  1010. }
  1011. else
  1012. {
  1013. m_dataPath = dataPath;
  1014. TC_LOG_INFO("server.loading", "Using DataDir %s", m_dataPath.c_str());
  1015. }
  1016. m_bool_configs[CONFIG_ENABLE_MMAPS] = sConfigMgr->GetBoolDefault("mmap.enablePathFinding", false);
  1017. TC_LOG_INFO("server.loading", "WORLD: MMap data directory is: %smmaps", m_dataPath.c_str());
  1018. m_bool_configs[CONFIG_VMAP_INDOOR_CHECK] = sConfigMgr->GetBoolDefault("vmap.enableIndoorCheck", 0);
  1019. bool enableIndoor = sConfigMgr->GetBoolDefault("vmap.enableIndoorCheck", true);
  1020. bool enableLOS = sConfigMgr->GetBoolDefault("vmap.enableLOS", true);
  1021. bool enableHeight = sConfigMgr->GetBoolDefault("vmap.enableHeight", true);
  1022. if (!enableHeight)
  1023. TC_LOG_ERROR("server.loading", "VMap height checking disabled! Creatures movements and other various things WILL be broken! Expect no support.");
  1024. VMAP::VMapFactory::createOrGetVMapManager()->setEnableLineOfSightCalc(enableLOS);
  1025. VMAP::VMapFactory::createOrGetVMapManager()->setEnableHeightCalc(enableHeight);
  1026. TC_LOG_INFO("server.loading", "VMap support included. LineOfSight: %i, getHeight: %i, indoorCheck: %i", enableLOS, enableHeight, enableIndoor);
  1027. TC_LOG_INFO("server.loading", "VMap data directory is: %svmaps", m_dataPath.c_str());
  1028. m_int_configs[CONFIG_MAX_WHO] = sConfigMgr->GetIntDefault("MaxWhoListReturns", 49);
  1029. m_bool_configs[CONFIG_START_ALL_SPELLS] = sConfigMgr->GetBoolDefault("PlayerStart.AllSpells", false);
  1030. if (m_bool_configs[CONFIG_START_ALL_SPELLS])
  1031. TC_LOG_WARN("server.loading", "PlayerStart.AllSpells enabled - may not function as intended!");
  1032. m_int_configs[CONFIG_HONOR_AFTER_DUEL] = sConfigMgr->GetIntDefault("HonorPointsAfterDuel", 0);
  1033. m_bool_configs[CONFIG_START_ALL_EXPLORED] = sConfigMgr->GetBoolDefault("PlayerStart.MapsExplored", false);
  1034. m_bool_configs[CONFIG_START_ALL_REP] = sConfigMgr->GetBoolDefault("PlayerStart.AllReputation", false);
  1035. m_bool_configs[CONFIG_ALWAYS_MAXSKILL] = sConfigMgr->GetBoolDefault("AlwaysMaxWeaponSkill", false);
  1036. m_bool_configs[CONFIG_PVP_TOKEN_ENABLE] = sConfigMgr->GetBoolDefault("PvPToken.Enable", false);
  1037. m_int_configs[CONFIG_PVP_TOKEN_MAP_TYPE] = sConfigMgr->GetIntDefault("PvPToken.MapAllowType", 4);
  1038. m_int_configs[CONFIG_PVP_TOKEN_ID] = sConfigMgr->GetIntDefault("PvPToken.ItemID", 29434);
  1039. m_int_configs[CONFIG_PVP_TOKEN_COUNT] = sConfigMgr->GetIntDefault("PvPToken.ItemCount", 1);
  1040. if (m_int_configs[CONFIG_PVP_TOKEN_COUNT] < 1)
  1041. m_int_configs[CONFIG_PVP_TOKEN_COUNT] = 1;
  1042. m_bool_configs[CONFIG_ALLOW_TRACK_BOTH_RESOURCES] = sConfigMgr->GetBoolDefault("AllowTrackBothResources", false);
  1043. m_bool_configs[CONFIG_NO_RESET_TALENT_COST] = sConfigMgr->GetBoolDefault("NoResetTalentsCost", false);
  1044. m_bool_configs[CONFIG_SHOW_KICK_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowKickInWorld", false);
  1045. m_bool_configs[CONFIG_SHOW_MUTE_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowMuteInWorld", false);
  1046. m_bool_configs[CONFIG_SHOW_BAN_IN_WORLD] = sConfigMgr->GetBoolDefault("ShowBanInWorld", false);
  1047. m_int_configs[CONFIG_INTERVAL_LOG_UPDATE] = sConfigMgr->GetIntDefault("RecordUpdateTimeDiffInterval", 60000);
  1048. m_int_configs[CONFIG_MIN_LOG_UPDATE] = sConfigMgr->GetIntDefault("MinRecordUpdateTimeDiff", 100);
  1049. m_int_configs[CONFIG_NUMTHREADS] = sConfigMgr->GetIntDefault("MapUpdate.Threads", 1);
  1050. m_int_configs[CONFIG_MAX_RESULTS_LOOKUP_COMMANDS] = sConfigMgr->GetIntDefault("Command.LookupMaxResults", 0);
  1051. // Warden
  1052. m_bool_configs[CONFIG_WARDEN_ENABLED] = sConfigMgr->GetBoolDefault("Warden.Enabled", false);
  1053. m_int_configs[CONFIG_WARDEN_NUM_MEM_CHECKS] = sConfigMgr->GetIntDefault("Warden.NumMemChecks", 3);
  1054. m_int_configs[CONFIG_WARDEN_NUM_OTHER_CHECKS] = sConfigMgr->GetIntDefault("Warden.NumOtherChecks", 7);
  1055. m_int_configs[CONFIG_WARDEN_CLIENT_BAN_DURATION] = sConfigMgr->GetIntDefault("Warden.BanDuration", 86400);
  1056. m_int_configs[CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF] = sConfigMgr->GetIntDefault("Warden.ClientCheckHoldOff", 30);
  1057. m_int_configs[CONFIG_WARDEN_CLIENT_FAIL_ACTION] = sConfigMgr->GetIntDefault("Warden.ClientCheckFailAction", 0);
  1058. m_int_configs[CONFIG_WARDEN_CLIENT_RESPONSE_DELAY] = sConfigMgr->GetIntDefault("Warden.ClientResponseDelay", 600);
  1059. // Dungeon finder
  1060. m_int_configs[CONFIG_LFG_OPTIONSMASK] = sConfigMgr->GetIntDefault("DungeonFinder.OptionsMask", 1);
  1061. // DBC_ItemAttributes
  1062. m_bool_configs[CONFIG_DBC_ENFORCE_ITEM_ATTRIBUTES] = sConfigMgr->GetBoolDefault("DBC.EnforceItemAttributes", true);
  1063. // Accountpassword Secruity
  1064. m_int_configs[CONFIG_ACC_PASSCHANGESEC] = sConfigMgr->GetIntDefault("Account.PasswordChangeSecurity", 0);
  1065. // Random Battleground Rewards
  1066. m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorFirst", 27000);
  1067. m_int_configs[CONFIG_BG_REWARD_WINNER_CONQUEST_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerConquestFirst", 10000);
  1068. m_int_configs[CONFIG_BG_REWARD_WINNER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerHonorLast", 13500);
  1069. m_int_configs[CONFIG_BG_REWARD_WINNER_CONQUEST_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardWinnerConquestLast", 5000);
  1070. m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_FIRST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorFirst", 4500);
  1071. m_int_configs[CONFIG_BG_REWARD_LOSER_HONOR_LAST] = sConfigMgr->GetIntDefault("Battleground.RewardLoserHonorLast", 3500);
  1072. // Max instances per hour
  1073. m_int_configs[CONFIG_MAX_INSTANCES_PER_HOUR] = sConfigMgr->GetIntDefault("AccountInstancesPerHour", 5);
  1074. // Anounce reset of instance to whole party
  1075. m_bool_configs[CONFIG_INSTANCES_RESET_ANNOUNCE] = sConfigMgr->GetBoolDefault("InstancesResetAnnounce", false);
  1076. // AutoBroadcast
  1077. m_bool_configs[CONFIG_AUTOBROADCAST] = sConfigMgr->GetBoolDefault("AutoBroadcast.On", false);
  1078. m_int_configs[CONFIG_AUTOBROADCAST_CENTER] = sConfigMgr->GetIntDefault("AutoBroadcast.Center", 0);
  1079. m_int_configs[CONFIG_AUTOBROADCAST_INTERVAL] = sConfigMgr->GetIntDefault("AutoBroadcast.Timer", 60000);
  1080. if (reload)
  1081. {
  1082. m_timers[WUPDATE_AUTOBROADCAST].SetInterval(m_int_configs[CONFIG_AUTOBROADCAST_INTERVAL]);
  1083. m_timers[WUPDATE_AUTOBROADCAST].Reset();
  1084. }
  1085. // MySQL ping time interval
  1086. m_int_configs[CONFIG_DB_PING_INTERVAL] = sConfigMgr->GetIntDefault("MaxPingTime", 30);
  1087. // Guild save interval
  1088. m_bool_configs[CONFIG_GUILD_LEVELING_ENABLED] = sConfigMgr->GetBoolDefault("Guild.LevelingEnabled", true);
  1089. m_int_configs[CONFIG_GUILD_SAVE_INTERVAL] = sConfigMgr->GetIntDefault("Guild.SaveInterval", 15);
  1090. m_int_configs[CONFIG_GUILD_MAX_LEVEL] = sConfigMgr->GetIntDefault("Guild.MaxLevel", 25);
  1091. m_int_configs[CONFIG_GUILD_UNDELETABLE_LEVEL] = sConfigMgr->GetIntDefault("Guild.UndeletableLevel", 4);
  1092. rate_values[RATE_XP_GUILD_MODIFIER] = sConfigMgr->GetFloatDefault("Guild.XPModifier", 0.25f);
  1093. m_int_configs[CONFIG_GUILD_DAILY_XP_CAP] = sConfigMgr->GetIntDefault("Guild.DailyXPCap", 7807500);
  1094. m_int_configs[CONFIG_GUILD_WEEKLY_REP_CAP] = sConfigMgr->GetIntDefault("Guild.WeeklyReputationCap", 4375);
  1095. // misc
  1096. m_bool_configs[CONFIG_PDUMP_NO_PATHS] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowPaths", true);
  1097. m_bool_configs[CONFIG_PDUMP_NO_OVERWRITE] = sConfigMgr->GetBoolDefault("PlayerDump.DisallowOverwrite", true);
  1098. m_bool_configs[CONFIG_UI_QUESTLEVELS_IN_DIALOGS] = sConfigMgr->GetBoolDefault("UI.ShowQuestLevelsInDialogs", false);
  1099. // Wintergrasp battlefield
  1100. m_bool_configs[CONFIG_WINTERGRASP_ENABLE] = sConfigMgr->GetBoolDefault("Wintergrasp.Enable", false);
  1101. m_int_configs[CONFIG_WINTERGRASP_PLR_MAX] = sConfigMgr->GetIntDefault("Wintergrasp.PlayerMax", 100);
  1102. m_int_configs[CONFIG_WINTERGRASP_PLR_MIN] = sConfigMgr->GetIntDefault("Wintergrasp.PlayerMin", 0);
  1103. m_int_configs[CONFIG_WINTERGRASP_PLR_MIN_LVL] = sConfigMgr->GetIntDefault("Wintergrasp.PlayerMinLvl", 77);
  1104. m_int_configs[CONFIG_WINTERGRASP_BATTLETIME] = sConfigMgr->GetIntDefault("Wintergrasp.BattleTimer", 30);
  1105. m_int_configs[CONFIG_WINTERGRASP_NOBATTLETIME] = sConfigMgr->GetIntDefault("Wintergrasp.NoBattleTimer", 150);
  1106. m_int_configs[CONFIG_WINTERGRASP_RESTART_AFTER_CRASH] = sConfigMgr->GetIntDefault("Wintergrasp.CrashRestartTimer", 10);
  1107. // Stats limits
  1108. m_bool_configs[CONFIG_STATS_LIMITS_ENABLE] = sConfigMgr->GetBoolDefault("Stats.Limits.Enable", false);
  1109. m_float_configs[CONFIG_STATS_LIMITS_DODGE] = sConfigMgr->GetFloatDefault("Stats.Limits.Dodge", 95.0f);
  1110. m_float_configs[CONFIG_STATS_LIMITS_PARRY] = sConfigMgr->GetFloatDefault("Stats.Limits.Parry", 95.0f);
  1111. m_float_configs[CONFIG_STATS_LIMITS_BLOCK] = sConfigMgr->GetFloatDefault("Stats.Limits.Block", 95.0f);
  1112. m_float_configs[CONFIG_STATS_LIMITS_CRIT] = sConfigMgr->GetFloatDefault("Stats.Limits.Crit", 95.0f);
  1113. //packet spoof punishment
  1114. m_int_configs[CONFIG_PACKET_SPOOF_POLICY] = sConfigMgr->GetIntDefault("PacketSpoof.Policy", (uint32)WorldSession::DosProtection::POLICY_KICK);
  1115. m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] = sConfigMgr->GetIntDefault("PacketSpoof.BanMode", (uint32)BAN_ACCOUNT);
  1116. if (m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] == BAN_CHARACTER || m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] > BAN_IP)
  1117. m_int_configs[CONFIG_PACKET_SPOOF_BANMODE] = BAN_ACCOUNT;
  1118. m_int_configs[CONFIG_PACKET_SPOOF_BANDURATION] = sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400);
  1119. m_bool_configs[CONFIG_IP_BASED_ACTION_LOGGING] = sConfigMgr->GetBoolDefault("Allow.IP.Based.Action.Logging", false);
  1120. // AHBot
  1121. m_int_configs[CONFIG_AHBOT_UPDATE_INTERVAL] = sConfigMgr->GetIntDefault("AuctionHouseBot.Update.Interval", 20);
  1122. m_bool_configs[CONFIG_CALCULATE_CREATURE_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Creature.Zone.Area.Data", false);
  1123. m_bool_configs[CONFIG_CALCULATE_GAMEOBJECT_ZONE_AREA_DATA] = sConfigMgr->GetBoolDefault("Calculate.Gameoject.Zone.Area.Data", false);
  1124. // call ScriptMgr if we're reloading the configuration
  1125. if (reload)
  1126. sScriptMgr->OnConfigLoad(reload);
  1127. }
  1128. extern void LoadGameObjectModelList();
  1129. /// Initialize the World
  1130. void World::SetInitialWorldSettings()
  1131. {
  1132. ///- Server startup begin
  1133. uint32 startupBegin = getMSTime();
  1134. ///- Initialize the random number generator
  1135. srand((unsigned int)time(NULL));
  1136. ///- Initialize detour memory management
  1137. dtAllocSetCustom(dtCustomAlloc, dtCustomFree);
  1138. ///- Initialize VMapManager function pointers (to untangle game/collision circular deps)
  1139. if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager()))
  1140. {
  1141. vmmgr2->GetLiquidFlagsPtr = &GetLiquidFlags;
  1142. vmmgr2->IsVMAPDisabledForPtr = &DisableMgr::IsVMAPDisabledFor;
  1143. }
  1144. ///- Initialize config settings
  1145. LoadConfigSettings();
  1146. ///- Initialize Allowed Security Level
  1147. LoadDBAllowedSecurityLevel();
  1148. ///- Init highest guids before any table loading to prevent using not initialized guids in some code.
  1149. sObjectMgr->SetHighestGuids();
  1150. ///- Check the existence of the map files for all races' startup areas.
  1151. if (!MapManager::ExistMapAndVMap(0, -6240.32f, 331.033f)
  1152. || !MapManager::ExistMapAndVMap(0, -8949.95f, -132.493f)
  1153. || !MapManager::ExistMapAndVMap(1, -618.518f, -4251.67f)
  1154. || !MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f)
  1155. || !MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f)
  1156. || !MapManager::ExistMapAndVMap(1, -2917.58f, -257.98f)
  1157. || (m_int_configs[CONFIG_EXPANSION] && (
  1158. !MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) ||
  1159. !MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f))))
  1160. {
  1161. TC_LOG_ERROR("server.loading", "Correct *.map files not found in path '%smaps' or *.vmtree/*.vmtile files in '%svmaps'. Please place *.map/*.vmtree/*.vmtile files in appropriate directories or correct the DataDir value in the worldserver.conf file.", m_dataPath.c_str(), m_dataPath.c_str());
  1162. exit(1);
  1163. }
  1164. ///- Initialize pool manager
  1165. sPoolMgr->Initialize();
  1166. ///- Initialize game event manager
  1167. sGameEventMgr->Initialize();
  1168. ///- Loading strings. Getting no records means core load has to be canceled because no error message can be output.
  1169. TC_LOG_INFO("server.loading", "Loading Trinity strings...");
  1170. if (!sObjectMgr->LoadTrinityStrings())
  1171. exit(1); // Error message displayed in function already
  1172. ///- Update the realm entry in the database with the realm type from the config file
  1173. //No SQL injection as values are treated as integers
  1174. // not send custom type REALM_FFA_PVP to realm list
  1175. uint32 server_type = IsFFAPvPRealm() ? uint32(REALM_TYPE_PVP) : getIntConfig(CONFIG_GAME_TYPE);
  1176. uint32 realm_zone = getIntConfig(CONFIG_REALM_ZONE);
  1177. LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmHandle.Index); // One-time query
  1178. ///- Remove the bones (they should not exist in DB though) and old corpses after a restart
  1179. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_OLD_CORPSES);
  1180. stmt->setUInt32(0, 3 * DAY);
  1181. CharacterDatabase.Execute(stmt);
  1182. ///- Load the DBC files
  1183. TC_LOG_INFO("server.loading", "Initialize data stores...");
  1184. LoadDBCStores(m_dataPath);
  1185. LoadDB2Stores(m_dataPath);
  1186. TC_LOG_INFO("server.loading", "Loading SpellInfo store...");
  1187. sSpellMgr->LoadSpellInfoStore();
  1188. TC_LOG_INFO("server.loading", "Loading SpellInfo corrections...");
  1189. sSpellMgr->LoadSpellInfoCorrections();
  1190. TC_LOG_INFO("server.loading", "Loading SkillLineAbilityMultiMap Data...");
  1191. sSpellMgr->LoadSkillLineAbilityMap();
  1192. TC_LOG_INFO("server.loading", "Loading SpellInfo custom attributes...");
  1193. sSpellMgr->LoadSpellInfoCustomAttributes();
  1194. TC_LOG_INFO("server.loading", "Loading GameObject models...");
  1195. LoadGameObjectModelList();
  1196. TC_LOG_INFO("server.loading", "Loading Script Names...");
  1197. sObjectMgr->LoadScriptNames();
  1198. TC_LOG_INFO("server.loading", "Loading Instance Template...");
  1199. sObjectMgr->LoadInstanceTemplate();
  1200. // Must be called before `creature_respawn`/`gameobject_respawn` tables
  1201. TC_LOG_INFO("server.loading", "Loading instances...");
  1202. sInstanceSaveMgr->LoadInstances();
  1203. TC_LOG_INFO("server.loading", "Loading Broadcast texts...");
  1204. sObjectMgr->LoadBroadcastTexts();
  1205. sObjectMgr->LoadBroadcastTextLocales();
  1206. TC_LOG_INFO("server.loading", "Loading Localization strings...");
  1207. uint32 oldMSTime = getMSTime();
  1208. sObjectMgr->LoadCreatureLocales();
  1209. sObjectMgr->LoadGameObjectLocales();
  1210. sObjectMgr->LoadItemLocales();
  1211. sObjectMgr->LoadQuestLocales();
  1212. sObjectMgr->LoadNpcTextLocales();
  1213. sObjectMgr->LoadPageTextLocales();
  1214. sObjectMgr->LoadGossipMenuItemsLocales();
  1215. sObjectMgr->LoadPointOfInterestLocales();
  1216. sObjectMgr->SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
  1217. TC_LOG_INFO("server.loading", ">> Localization strings loaded in %u ms", GetMSTimeDiffToNow(oldMSTime));
  1218. TC_LOG_INFO("server.loading", "Loading Account Roles and Permissions...");
  1219. sAccountMgr->LoadRBAC();
  1220. TC_LOG_INFO("server.loading", "Loading Page Texts...");
  1221. sObjectMgr->LoadPageTexts();
  1222. TC_LOG_INFO("server.loading", "Loading Game Object Templates..."); // must be after LoadPageTexts
  1223. sObjectMgr->LoadGameObjectTemplate();
  1224. TC_LOG_INFO("server.loading", "Loading Transport templates...");
  1225. sTransportMgr->LoadTransportTemplates();
  1226. TC_LOG_INFO("server.loading", "Loading Spell Rank Data...");
  1227. sSpellMgr->LoadSpellRanks();
  1228. TC_LOG_INFO("server.loading", "Loading Spell Required Data...");
  1229. sSpellMgr->LoadSpellRequired();
  1230. TC_LOG_INFO("server.loading", "Loading Spell Group types...");
  1231. sSpellMgr->LoadSpellGroups();
  1232. TC_LOG_INFO("server.loading", "Loading Spell Learn Skills...");
  1233. sSpellMgr->LoadSpellLearnSkills(); // must be after LoadSpellRanks
  1234. TC_LOG_INFO("server.loading", "Loading Spell Learn Spells...");
  1235. sSpellMgr->LoadSpellLearnSpells();
  1236. TC_LOG_INFO("server.loading", "Loading Spell Proc Event conditions...");
  1237. sSpellMgr->LoadSpellProcEvents();
  1238. TC_LOG_INFO("server.loading", "Loading Spell Proc conditions and data...");
  1239. sSpellMgr->LoadSpellProcs();
  1240. TC_LOG_INFO("server.loading", "Loading Spell Bonus Data...");
  1241. sSpellMgr->LoadSpellBonusess();
  1242. TC_LOG_INFO("server.loading", "Loading Aggro Spells Definitions...");
  1243. sSpellMgr->LoadSpellThreats();
  1244. TC_LOG_INFO("server.loading", "Loading Spell Group Stack Rules...");
  1245. sSpellMgr->LoadSpellGroupStackRules();
  1246. TC_LOG_INFO("server.loading", "Loading Spell Phase Dbc Info...");
  1247. sObjectMgr->LoadPhaseInfo();
  1248. TC_LOG_INFO("server.loading", "Loading NPC Texts...");
  1249. sObjectMgr->LoadGossipText();
  1250. TC_LOG_INFO("server.loading", "Loading Enchant Spells Proc datas...");
  1251. sSpellMgr->LoadSpellEnchantProcData();
  1252. TC_LOG_INFO("server.loading", "Loading Item Random Enchantments Table...");
  1253. LoadRandomEnchantmentsTable();
  1254. TC_LOG_INFO("server.loading", "Loading Disables"); // must be before loading quests and items
  1255. DisableMgr::LoadDisables();
  1256. TC_LOG_INFO("server.loading", "Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
  1257. sObjectMgr->LoadItemTemplates();
  1258. TC_LOG_INFO("server.loading", "Loading Item set names..."); // must be after LoadItemPrototypes
  1259. sObjectMgr->LoadItemTemplateAddon();
  1260. TC_LOG_INFO("misc", "Loading Item Scripts..."); // must be after LoadItemPrototypes
  1261. sObjectMgr->LoadItemScriptNames();
  1262. TC_LOG_INFO("server.loading", "Loading Creature Model Based Info Data...");
  1263. sObjectMgr->LoadCreatureModelInfo();
  1264. TC_LOG_INFO("server.loading", "Loading Creature templates...");
  1265. sObjectMgr->LoadCreatureTemplates();
  1266. TC_LOG_INFO("server.loading", "Loading Equipment templates..."); // must be after LoadCreatureTemplates
  1267. sObjectMgr->LoadEquipmentTemplates();
  1268. TC_LOG_INFO("server.loading", "Loading Creature template addons...");
  1269. sObjectMgr->LoadCreatureTemplateAddons();
  1270. TC_LOG_INFO("server.loading", "Loading Reputation Reward Rates...");
  1271. sObjectMgr->LoadReputationRewardRate();
  1272. TC_LOG_INFO("server.loading", "Loading Creature Reputation OnKill Data...");
  1273. sObjectMgr->LoadReputationOnKill();
  1274. TC_LOG_INFO("server.loading", "Loading Reputation Spillover Data...");
  1275. sObjectMgr->LoadReputationSpilloverTemplate();
  1276. TC_LOG_INFO("server.loading", "Loading Points Of Interest Data...");
  1277. sObjectMgr->LoadPointsOfInterest();
  1278. TC_LOG_INFO("server.loading", "Loading Creature Base Stats...");
  1279. sObjectMgr->LoadCreatureClassLevelStats();
  1280. TC_LOG_INFO("server.loading", "Loading Creature Data...");
  1281. sObjectMgr->LoadCreatures();
  1282. TC_LOG_INFO("server.loading", "Loading Temporary Summon Data...");
  1283. sObjectMgr->LoadTempSummons(); // must be after LoadCreatureTemplates() and LoadGameObjectTemplates()
  1284. TC_LOG_INFO("server.loading", "Loading pet levelup spells...");
  1285. sSpellMgr->LoadPetLevelupSpellMap();
  1286. TC_LOG_INFO("server.loading", "Loading pet default spells additional to levelup spells...");
  1287. sSpellMgr->LoadPetDefaultSpells();
  1288. TC_LOG_INFO("server.loading", "Loading Creature Addon Data...");
  1289. sObjectMgr->LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
  1290. TC_LOG_INFO("server.loading", "Loading Gameobject Data...");
  1291. sObjectMgr->LoadGameobjects();
  1292. TC_LOG_INFO("server.loading", "Loading Creature Linked Respawn...");
  1293. sObjectMgr->LoadLinkedRespawn(); // must be after LoadCreatures(), LoadGameObjects()
  1294. TC_LOG_INFO("server.loading", "Loading Weather Data...");
  1295. WeatherMgr::LoadWeatherData();
  1296. TC_LOG_INFO("server.loading", "Loading Quests...");
  1297. sObjectMgr->LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
  1298. TC_LOG_INFO("server.loading", "Checking Quest Disables");
  1299. DisableMgr::CheckQuestDisables(); // must be after loading quests
  1300. TC_LOG_INFO("server.loading", "Loading Quest POI");
  1301. sObjectMgr->LoadQuestPOI();
  1302. TC_LOG_INFO("server.loading", "Loading Quests Starters and Enders...");
  1303. sObjectMgr->LoadQuestStartersAndEnders(); // must be after quest load
  1304. TC_LOG_INFO("server.loading", "Loading Objects Pooling Data...");
  1305. sPoolMgr->LoadFromDB();
  1306. TC_LOG_INFO("server.loading", "Loading Game Event Data..."); // must be after loading pools fully
  1307. sGameEventMgr->LoadFromDB();
  1308. TC_LOG_INFO("server.loading", "Loading UNIT_NPC_FLAG_SPELLCLICK Data..."); // must be after LoadQuests
  1309. sObjectMgr->LoadNPCSpellClickSpells();
  1310. TC_LOG_INFO("server.loading", "Loading Vehicle Template Accessories...");
  1311. sObjectMgr->LoadVehicleTemplateAccessories(); // must be after LoadCreatureTemplates() and LoadNPCSpellClickSpells()
  1312. TC_LOG_INFO("server.loading", "Loading Vehicle Accessories...");
  1313. sObjectMgr->LoadVehicleAccessories(); // must be after LoadCreatureTemplates() and LoadNPCSpellClickSpells()
  1314. TC_LOG_INFO("server.loading", "Loading SpellArea Data..."); // must be after quest load
  1315. sSpellMgr->LoadSpellAreas();
  1316. TC_LOG_INFO("server.loading", "Loading AreaTrigger definitions...");
  1317. sObjectMgr->LoadAreaTriggerTeleports();
  1318. TC_LOG_INFO("server.loading", "Loading Access Requirements...");
  1319. sObjectMgr->LoadAccessRequirements(); // must be after item template load
  1320. TC_LOG_INFO("server.loading", "Loading Quest Area Triggers...");
  1321. sObjectMgr->LoadQuestAreaTriggers(); // must be after LoadQuests
  1322. TC_LOG_INFO("server.loading", "Loading Tavern Area Triggers...");
  1323. sObjectMgr->LoadTavernAreaTriggers();
  1324. TC_LOG_INFO("server.loading", "Loading AreaTrigger script names...");
  1325. sObjectMgr->LoadAreaTriggerScripts();
  1326. TC_LOG_INFO("server.loading", "Loading LFG entrance positions..."); // Must be after areatriggers
  1327. sLFGMgr->LoadLFGDungeons();
  1328. TC_LOG_INFO("server.loading", "Loading Dungeon boss data...");
  1329. sObjectMgr->LoadInstanceEncounters();
  1330. TC_LOG_INFO("server.loading", "Loading LFG rewards...");
  1331. sLFGMgr->LoadRewards();
  1332. TC_LOG_INFO("server.loading", "Loading Graveyard-zone links...");
  1333. sObjectMgr->LoadGraveyardZones();
  1334. TC_LOG_INFO("server.loading", "Loading Graveyard Orientations...");
  1335. sObjectMgr->LoadGraveyardOrientations();
  1336. TC_LOG_INFO("server.loading", "Loading spell pet auras...");
  1337. sSpellMgr->LoadSpellPetAuras();
  1338. TC_LOG_INFO("server.loading", "Loading Spell target coordinates...");
  1339. sSpellMgr->LoadSpellTargetPositions();
  1340. TC_LOG_INFO("server.loading", "Loading enchant custom attributes...");
  1341. sSpellMgr->LoadEnchantCustomAttr();
  1342. TC_LOG_INFO("server.loading", "Loading linked spells...");
  1343. sSpellMgr->LoadSpellLinked();
  1344. TC_LOG_INFO("server.loading", "Loading Player Create Data...");
  1345. sObjectMgr->LoadPlayerInfo();
  1346. TC_LOG_INFO("server.loading", "Loading Exploration BaseXP Data...");
  1347. sObjectMgr->LoadExplorationBaseXP();
  1348. TC_LOG_INFO("server.loading", "Loading Pet Name Parts...");
  1349. sObjectMgr->LoadPetNames();
  1350. CharacterDatabaseCleaner::CleanDatabase();
  1351. TC_LOG_INFO("server.loading", "Loading the max pet number...");
  1352. sObjectMgr->LoadPetNumber();
  1353. TC_LOG_INFO("server.loading", "Loading pet level stats...");
  1354. sObjectMgr->LoadPetLevelInfo();
  1355. TC_LOG_INFO("server.loading", "Loading Player Corpses...");
  1356. sObjectMgr->LoadCorpses();
  1357. TC_LOG_INFO("server.loading", "Loading Player level dependent mail rewards...");
  1358. sObjectMgr->LoadMailLevelRewards();
  1359. // Loot tables
  1360. LoadLootTables();
  1361. TC_LOG_INFO("server.loading", "Loading Skill Discovery Table...");
  1362. LoadSkillDiscoveryTable();
  1363. TC_LOG_INFO("server.loading", "Loading Skill Extra Item Table...");
  1364. LoadSkillExtraItemTable();
  1365. TC_LOG_INFO("server.loading", "Loading Skill Fishing base level requirements...");
  1366. sObjectMgr->LoadFishingBaseSkillLevel();
  1367. TC_LOG_INFO("server.loading", "Loading Achievements...");
  1368. sAchievementMgr->LoadAchievementReferenceList();
  1369. TC_LOG_INFO("server.loading", "Loading Achievement Criteria Lists...");
  1370. sAchievementMgr->LoadAchievementCriteriaList();
  1371. TC_LOG_INFO("server.loading", "Loading Achievement Criteria Data...");
  1372. sAchievementMgr->LoadAchievementCriteriaData();
  1373. TC_LOG_INFO("server.loading", "Loading Achievement Rewards...");
  1374. sAchievementMgr->LoadRewards();
  1375. TC_LOG_INFO("server.loading", "Loading Achievement Reward Locales...");
  1376. sAchievementMgr->LoadRewardLocales();
  1377. TC_LOG_INFO("server.loading", "Loading Completed Achievements...");
  1378. sAchievementMgr->LoadCompletedAchievements();
  1379. ///- Load dynamic data tables from the database
  1380. TC_LOG_INFO("server.loading", "Loading Item Auctions...");
  1381. sAuctionMgr->LoadAuctionItems();
  1382. TC_LOG_INFO("server.loading", "Loading Auctions...");
  1383. sAuctionMgr->LoadAuctions();
  1384. TC_LOG_INFO("server.loading", "Loading Guild XP for level...");
  1385. sGuildMgr->LoadGuildXpForLevel();
  1386. TC_LOG_INFO("server.loading", "Loading Guild rewards...");
  1387. sGuildMgr->LoadGuildRewards();
  1388. TC_LOG_INFO("server.loading", "Loading Guilds...");
  1389. sGuildMgr->LoadGuilds();
  1390. sGuildFinderMgr->LoadFromDB();
  1391. TC_LOG_INFO("server.loading", "Loading ArenaTeams...");
  1392. sArenaTeamMgr->LoadArenaTeams();
  1393. TC_LOG_INFO("server.loading", "Loading Groups...");
  1394. sGroupMgr->LoadGroups();
  1395. TC_LOG_INFO("server.loading", "Loading ReservedNames...");
  1396. sObjectMgr->LoadReservedPlayersNames();
  1397. TC_LOG_INFO("server.loading", "Loading GameObjects for quests...");
  1398. sObjectMgr->LoadGameObjectForQuests();
  1399. TC_LOG_INFO("server.loading", "Loading BattleMasters...");
  1400. sBattlegroundMgr->LoadBattleMastersEntry(); // must be after load CreatureTemplate
  1401. TC_LOG_INFO("server.loading", "Loading GameTeleports...");
  1402. sObjectMgr->LoadGameTele();
  1403. TC_LOG_INFO("server.loading", "Loading Gossip menu...");
  1404. sObjectMgr->LoadGossipMenu();
  1405. TC_LOG_INFO("server.loading", "Loading Gossip menu options...");
  1406. sObjectMgr->LoadGossipMenuItems();
  1407. TC_LOG_INFO("server.loading", "Loading Vendors...");
  1408. sObjectMgr->LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
  1409. TC_LOG_INFO("server.loading", "Loading Trainers...");
  1410. sObjectMgr->LoadTrainerSpell(); // must be after load CreatureTemplate
  1411. TC_LOG_INFO("server.loading", "Loading Waypoints...");
  1412. sWaypointMgr->Load();
  1413. TC_LOG_INFO("server.loading", "Loading SmartAI Waypoints...");
  1414. sSmartWaypointMgr->LoadFromDB();
  1415. TC_LOG_INFO("server.loading", "Loading Creature Formations...");
  1416. sFormationMgr->LoadCreatureFormations();
  1417. TC_LOG_INFO("server.loading", "Loading World States..."); // must be loaded before battleground, outdoor PvP and conditions
  1418. LoadWorldStates();
  1419. TC_LOG_INFO("server.loading", "Loading Phase definitions...");
  1420. sObjectMgr->LoadPhaseDefinitions();
  1421. TC_LOG_INFO("server.loading", "Loading Conditions...");
  1422. sConditionMgr->LoadConditions();
  1423. TC_LOG_INFO("server.loading", "Loading faction change achievement pairs...");
  1424. sObjectMgr->LoadFactionChangeAchievements();
  1425. TC_LOG_INFO("server.loading", "Loading faction change spell pairs...");
  1426. sObjectMgr->LoadFactionChangeSpells();
  1427. TC_LOG_INFO("server.loading", "Loading faction change item pairs...");
  1428. sObjectMgr->LoadFactionChangeItems();
  1429. TC_LOG_INFO("server.loading", "Loading faction change reputation pairs...");
  1430. sObjectMgr->LoadFactionChangeReputations();
  1431. TC_LOG_INFO("server.loading", "Loading faction change title pairs...");
  1432. sObjectMgr->LoadFactionChangeTitles();
  1433. TC_LOG_INFO("server.loading", "Loading GM tickets...");
  1434. sTicketMgr->LoadTickets();
  1435. TC_LOG_INFO("server.loading", "Loading GM surveys...");
  1436. sTicketMgr->LoadSurveys();
  1437. TC_LOG_INFO("server.loading", "Loading client addons...");
  1438. AddonMgr::LoadFromDB();
  1439. ///- Handle outdated emails (delete/return)
  1440. TC_LOG_INFO("server.loading", "Returning old mails...");
  1441. sObjectMgr->ReturnOrDeleteOldMails(false);
  1442. TC_LOG_INFO("server.loading", "Loading Autobroadcasts...");
  1443. LoadAutobroadcasts();
  1444. ///- Load and initialize scripts
  1445. sObjectMgr->LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
  1446. sObjectMgr->LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
  1447. sObjectMgr->LoadWaypointScripts();
  1448. TC_LOG_INFO("server.loading", "Loading spell script names...");
  1449. sObjectMgr->LoadSpellScriptNames();
  1450. TC_LOG_INFO("server.loading", "Loading Creature Texts...");
  1451. sCreatureTextMgr->LoadCreatureTexts();
  1452. TC_LOG_INFO("server.loading", "Loading Creature Text Locales...");
  1453. sCreatureTextMgr->LoadCreatureTextLocales();
  1454. TC_LOG_INFO("server.loading", "Initializing Scripts...");
  1455. sScriptMgr->Initialize();
  1456. sScriptMgr->OnConfigLoad(false); // must be done after the ScriptMgr has been properly initialized
  1457. TC_LOG_INFO("server.loading", "Validating spell scripts...");
  1458. sObjectMgr->ValidateSpellScripts();
  1459. TC_LOG_INFO("server.loading", "Loading SmartAI scripts...");
  1460. sSmartScriptMgr->LoadSmartAIFromDB();
  1461. TC_LOG_INFO("server.loading", "Loading Calendar data...");
  1462. sCalendarMgr->LoadFromDB();
  1463. ///- Initialize game time and timers
  1464. TC_LOG_INFO("server.loading", "Initialize game time and timers");
  1465. m_gameTime = time(NULL);
  1466. m_startTime = m_gameTime;
  1467. LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, %u, 0, '%s')",
  1468. realmHandle.Index, uint32(m_startTime), _FULLVERSION); // One-time query
  1469. m_timers[WUPDATE_WEATHERS].SetInterval(1*IN_MILLISECONDS);
  1470. m_timers[WUPDATE_AUCTIONS].SetInterval(MINUTE*IN_MILLISECONDS);
  1471. m_timers[WUPDATE_UPTIME].SetInterval(m_int_configs[CONFIG_UPTIME_UPDATE]*MINUTE*IN_MILLISECONDS);
  1472. //Update "uptime" table based on configuration entry in minutes.
  1473. m_timers[WUPDATE_CORPSES].SetInterval(20 * MINUTE * IN_MILLISECONDS);
  1474. //erase corpses every 20 minutes
  1475. m_timers[WUPDATE_CLEANDB].SetInterval(m_int_configs[CONFIG_LOGDB_CLEARINTERVAL]*MINUTE*IN_MILLISECONDS);
  1476. // clean logs table every 14 days by default
  1477. m_timers[WUPDATE_AUTOBROADCAST].SetInterval(getIntConfig(CONFIG_AUTOBROADCAST_INTERVAL));
  1478. m_timers[WUPDATE_DELETECHARS].SetInterval(DAY*IN_MILLISECONDS); // check for chars to delete every day
  1479. // for AhBot
  1480. m_timers[WUPDATE_AHBOT].SetInterval(getIntConfig(CONFIG_AHBOT_UPDATE_INTERVAL) * IN_MILLISECONDS); // every 20 sec
  1481. m_timers[WUPDATE_PINGDB].SetInterval(getIntConfig(CONFIG_DB_PING_INTERVAL)*MINUTE*IN_MILLISECONDS); // Mysql ping time in minutes
  1482. m_timers[WUPDATE_GUILDSAVE].SetInterval(getIntConfig(CONFIG_GUILD_SAVE_INTERVAL) * MINUTE * IN_MILLISECONDS);
  1483. //to set mailtimer to return mails every day between 4 and 5 am
  1484. //mailtimer is increased when updating auctions
  1485. //one second is 1000 -(tested on win system)
  1486. /// @todo Get rid of magic numbers
  1487. tm localTm;
  1488. localtime_r(&m_gameTime, &localTm);
  1489. mail_timer = ((((localTm.tm_hour + 20) % 24)* HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval());
  1490. //1440
  1491. mail_timer_expires = ((DAY * IN_MILLISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval()));
  1492. TC_LOG_INFO("server.loading", "Mail timer set to: " UI64FMTD ", mail return is called every " UI64FMTD " minutes", uint64(mail_timer), uint64(mail_timer_expires));
  1493. ///- Initilize static helper structures
  1494. AIRegistry::Initialize();
  1495. ///- Initialize MapManager
  1496. TC_LOG_INFO("server.loading", "Starting Map System");
  1497. sMapMgr->Initialize();
  1498. TC_LOG_INFO("server.loading", "Starting Game Event system...");
  1499. uint32 nextGameEvent = sGameEventMgr->StartSystem();
  1500. m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); //depend on next event
  1501. // Delete all characters which have been deleted X days before
  1502. Player::DeleteOldCharacters();
  1503. TC_LOG_INFO("server.loading", "Initialize AuctionHouseBot...");
  1504. sAuctionBot->Initialize();
  1505. // Delete all custom channels which haven't been used for PreserveCustomChannelDuration days.
  1506. Channel::CleanOldChannelsInDB();
  1507. TC_LOG_INFO("server.loading", "Starting Arena Season...");
  1508. sGameEventMgr->StartArenaSeason();
  1509. sTicketMgr->Initialize();
  1510. ///- Initialize Battlegrounds
  1511. TC_LOG_INFO("server.loading", "Starting Battleground System");
  1512. sBattlegroundMgr->LoadBattlegroundTemplates();
  1513. ///- Initialize outdoor pvp
  1514. TC_LOG_INFO("server.loading", "Starting Outdoor PvP System");
  1515. sOutdoorPvPMgr->InitOutdoorPvP();
  1516. ///- Initialize Battlefield
  1517. TC_LOG_INFO("server.loading", "Starting Battlefield System");
  1518. sBattlefieldMgr->InitBattlefield();
  1519. TC_LOG_INFO("server.loading", "Loading Transports...");
  1520. sTransportMgr->SpawnContinentTransports();
  1521. ///- Initialize Warden
  1522. TC_LOG_INFO("server.loading", "Loading Warden Checks...");
  1523. sWardenCheckMgr->LoadWardenChecks();
  1524. TC_LOG_INFO("server.loading", "Loading Warden Action Overrides...");
  1525. sWardenCheckMgr->LoadWardenOverrides();
  1526. TC_LOG_INFO("server.loading", "Deleting expired bans...");
  1527. LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate"); // One-time query
  1528. TC_LOG_INFO("server.loading", "Calculate next daily quest reset time...");
  1529. InitDailyQuestResetTime();
  1530. TC_LOG_INFO("server.loading", "Calculate next weekly quest reset time...");
  1531. InitWeeklyQuestResetTime();
  1532. TC_LOG_INFO("server.loading", "Calculate next monthly quest reset time...");
  1533. InitMonthlyQuestResetTime();
  1534. TC_LOG_INFO("server.loading", "Calculate random battleground reset time...");
  1535. InitRandomBGResetTime();
  1536. TC_LOG_INFO("server.loading", "Calculate guild limitation(s) reset time...");
  1537. InitGuildResetTime();
  1538. TC_LOG_INFO("server.loading", "Calculate next currency reset time...");
  1539. InitCurrencyResetTime();
  1540. LoadCharacterNameData();
  1541. TC_LOG_INFO("misc", "Initializing Opcodes...");
  1542. opcodeTable.Initialize();
  1543. TC_LOG_INFO("misc", "Loading hotfix info...");
  1544. sObjectMgr->LoadHotfixData();
  1545. TC_LOG_INFO("server.loading", "Loading missing KeyChains...");
  1546. sObjectMgr->LoadMissingKeyChains();
  1547. uint32 startupDuration = GetMSTimeDiffToNow(startupBegin);
  1548. TC_LOG_INFO("server.worldserver", "World initialized in %u minutes %u seconds", (startupDuration / 60000), ((startupDuration % 60000) / 1000));
  1549. if (uint32 realmId = sConfigMgr->GetIntDefault("RealmID", 0)) // 0 reserved for auth
  1550. sLog->SetRealmId(realmId);
  1551. }
  1552. void World::RecordTimeDiff(const char *text, ...)
  1553. {
  1554. if (m_updateTimeCount != 1)
  1555. return;
  1556. if (!text)
  1557. {
  1558. m_currentTime = getMSTime();
  1559. return;
  1560. }
  1561. uint32 thisTime = getMSTime();
  1562. uint32 diff = getMSTimeDiff(m_currentTime, thisTime);
  1563. if (diff > m_int_configs[CONFIG_MIN_LOG_UPDATE])
  1564. {
  1565. va_list ap;
  1566. char str[256];
  1567. va_start(ap, text);
  1568. vsnprintf(str, 256, text, ap);
  1569. va_end(ap);
  1570. TC_LOG_INFO("misc", "Difftime %s: %u.", str, diff);
  1571. }
  1572. m_currentTime = thisTime;
  1573. }
  1574. void World::LoadAutobroadcasts()
  1575. {
  1576. uint32 oldMSTime = getMSTime();
  1577. m_Autobroadcasts.clear();
  1578. m_AutobroadcastsWeights.clear();
  1579. uint32 realmId = sConfigMgr->GetIntDefault("RealmID", 0);
  1580. PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_AUTOBROADCAST);
  1581. stmt->setInt32(0, realmId);
  1582. PreparedQueryResult result = LoginDatabase.Query(stmt);
  1583. if (!result)
  1584. {
  1585. TC_LOG_INFO("server.loading", ">> Loaded 0 autobroadcasts definitions. DB table `autobroadcast` is empty for this realm!");
  1586. return;
  1587. }
  1588. uint32 count = 0;
  1589. do
  1590. {
  1591. Field* fields = result->Fetch();
  1592. uint8 id = fields[0].GetUInt8();
  1593. m_Autobroadcasts[id] = fields[2].GetString();
  1594. m_AutobroadcastsWeights[id] = fields[1].GetUInt8();
  1595. ++count;
  1596. } while (result->NextRow());
  1597. TC_LOG_INFO("server.loading", ">> Loaded %u autobroadcast definitions in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
  1598. }
  1599. /// Update the World !
  1600. void World::Update(uint32 diff)
  1601. {
  1602. m_updateTime = diff;
  1603. if (m_int_configs[CONFIG_INTERVAL_LOG_UPDATE] && diff > m_int_configs[CONFIG_MIN_LOG_UPDATE])
  1604. {
  1605. if (m_updateTimeSum > m_int_configs[CONFIG_INTERVAL_LOG_UPDATE])
  1606. {
  1607. TC_LOG_DEBUG("misc", "Update time diff: %u. Players online: %u.", m_updateTimeSum / m_updateTimeCount, GetActiveSessionCount());
  1608. m_updateTimeSum = m_updateTime;
  1609. m_updateTimeCount = 1;
  1610. }
  1611. else
  1612. {
  1613. m_updateTimeSum += m_updateTime;
  1614. ++m_updateTimeCount;
  1615. }
  1616. }
  1617. ///- Update the different timers
  1618. for (int i = 0; i < WUPDATE_COUNT; ++i)
  1619. {
  1620. if (m_timers[i].GetCurrent() >= 0)
  1621. m_timers[i].Update(diff);
  1622. else
  1623. m_timers[i].SetCurrent(0);
  1624. }
  1625. ///- Update the game time and check for shutdown time
  1626. _UpdateGameTime();
  1627. /// Handle daily quests reset time
  1628. if (m_gameTime > m_NextDailyQuestReset)
  1629. {
  1630. ResetDailyQuests();
  1631. m_NextDailyQuestReset += DAY;
  1632. }
  1633. /// Handle weekly quests reset time
  1634. if (m_gameTime > m_NextWeeklyQuestReset)
  1635. ResetWeeklyQuests();
  1636. /// Handle monthly quests reset time
  1637. if (m_gameTime > m_NextMonthlyQuestReset)
  1638. ResetMonthlyQuests();
  1639. if (m_gameTime > m_NextRandomBGReset)
  1640. ResetRandomBG();
  1641. if (m_gameTime > m_NextGuildReset)
  1642. ResetGuildCap();
  1643. if (m_gameTime > m_NextCurrencyReset)
  1644. ResetCurrencyWeekCap();
  1645. /// <ul><li> Handle auctions when the timer has passed
  1646. if (m_timers[WUPDATE_AUCTIONS].Passed())
  1647. {
  1648. m_timers[WUPDATE_AUCTIONS].Reset();
  1649. ///- Update mails (return old mails with item, or delete them)
  1650. //(tested... works on win)
  1651. if (++mail_timer > mail_timer_expires)
  1652. {
  1653. mail_timer = 0;
  1654. sObjectMgr->ReturnOrDeleteOldMails(true);
  1655. }
  1656. ///- Handle expired auctions
  1657. sAuctionMgr->Update();
  1658. }
  1659. /// <li> Handle AHBot operations
  1660. if (m_timers[WUPDATE_AHBOT].Passed())
  1661. {
  1662. sAuctionBot->Update();
  1663. m_timers[WUPDATE_AHBOT].Reset();
  1664. }
  1665. /// <li> Handle session updates when the timer has passed
  1666. RecordTimeDiff(NULL);
  1667. UpdateSessions(diff);
  1668. RecordTimeDiff("UpdateSessions");
  1669. /// <li> Handle weather updates when the timer has passed
  1670. if (m_timers[WUPDATE_WEATHERS].Passed())
  1671. {
  1672. m_timers[WUPDATE_WEATHERS].Reset();
  1673. WeatherMgr::Update(uint32(m_timers[WUPDATE_WEATHERS].GetInterval()));
  1674. }
  1675. /// <li> Update uptime table
  1676. if (m_timers[WUPDATE_UPTIME].Passed())
  1677. {
  1678. uint32 tmpDiff = uint32(m_gameTime - m_startTime);
  1679. uint32 maxOnlinePlayers = GetMaxPlayerCount();
  1680. m_timers[WUPDATE_UPTIME].Reset();
  1681. PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_UPTIME_PLAYERS);
  1682. stmt->setUInt32(0, tmpDiff);
  1683. stmt->setUInt16(1, uint16(maxOnlinePlayers));
  1684. stmt->setUInt32(2, realmHandle.Index);
  1685. stmt->setUInt32(3, uint32(m_startTime));
  1686. LoginDatabase.Execute(stmt);
  1687. }
  1688. /// <li> Clean logs table
  1689. if (sWorld->getIntConfig(CONFIG_LOGDB_CLEARTIME) > 0) // if not enabled, ignore the timer
  1690. {
  1691. if (m_timers[WUPDATE_CLEANDB].Passed())
  1692. {
  1693. m_timers[WUPDATE_CLEANDB].Reset();
  1694. PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_OLD_LOGS);
  1695. stmt->setUInt32(0, sWorld->getIntConfig(CONFIG_LOGDB_CLEARTIME));
  1696. stmt->setUInt32(1, uint32(time(0)));
  1697. LoginDatabase.Execute(stmt);
  1698. }
  1699. }
  1700. /// <li> Handle all other objects
  1701. ///- Update objects when the timer has passed (maps, transport, creatures, ...)
  1702. RecordTimeDiff(NULL);
  1703. sMapMgr->Update(diff);
  1704. RecordTimeDiff("UpdateMapMgr");
  1705. if (sWorld->getBoolConfig(CONFIG_AUTOBROADCAST))
  1706. {
  1707. if (m_timers[WUPDATE_AUTOBROADCAST].Passed())
  1708. {
  1709. m_timers[WUPDATE_AUTOBROADCAST].Reset();
  1710. SendAutoBroadcast();
  1711. }
  1712. }
  1713. sBattlegroundMgr->Update(diff);
  1714. RecordTimeDiff("UpdateBattlegroundMgr");
  1715. sOutdoorPvPMgr->Update(diff);
  1716. RecordTimeDiff("UpdateOutdoorPvPMgr");
  1717. sBattlefieldMgr->Update(diff);
  1718. RecordTimeDiff("BattlefieldMgr");
  1719. ///- Delete all characters which have been deleted X days before
  1720. if (m_timers[WUPDATE_DELETECHARS].Passed())
  1721. {
  1722. m_timers[WUPDATE_DELETECHARS].Reset();
  1723. Player::DeleteOldCharacters();
  1724. }
  1725. sLFGMgr->Update(diff);
  1726. RecordTimeDiff("UpdateLFGMgr");
  1727. // execute callbacks from sql queries that were queued recently
  1728. ProcessQueryCallbacks();
  1729. RecordTimeDiff("ProcessQueryCallbacks");
  1730. ///- Erase corpses once every 20 minutes
  1731. if (m_timers[WUPDATE_CORPSES].Passed())
  1732. {
  1733. m_timers[WUPDATE_CORPSES].Reset();
  1734. sObjectAccessor->RemoveOldCorpses();
  1735. }
  1736. ///- Process Game events when necessary
  1737. if (m_timers[WUPDATE_EVENTS].Passed())
  1738. {
  1739. m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
  1740. uint32 nextGameEvent = sGameEventMgr->Update();
  1741. m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
  1742. m_timers[WUPDATE_EVENTS].Reset();
  1743. }
  1744. ///- Ping to keep MySQL connections alive
  1745. if (m_timers[WUPDATE_PINGDB].Passed())
  1746. {
  1747. m_timers[WUPDATE_PINGDB].Reset();
  1748. TC_LOG_DEBUG("misc", "Ping MySQL to keep connection alive");
  1749. CharacterDatabase.KeepAlive();
  1750. LoginDatabase.KeepAlive();
  1751. WorldDatabase.KeepAlive();
  1752. }
  1753. if (m_timers[WUPDATE_GUILDSAVE].Passed())
  1754. {
  1755. m_timers[WUPDATE_GUILDSAVE].Reset();
  1756. sGuildMgr->SaveGuilds();
  1757. }
  1758. // update the instance reset times
  1759. sInstanceSaveMgr->Update();
  1760. // And last, but not least handle the issued cli commands
  1761. ProcessCliCommands();
  1762. sScriptMgr->OnWorldUpdate(diff);
  1763. }
  1764. void World::ForceGameEventUpdate()
  1765. {
  1766. m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
  1767. uint32 nextGameEvent = sGameEventMgr->Update();
  1768. m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
  1769. m_timers[WUPDATE_EVENTS].Reset();
  1770. }
  1771. /// Send a packet to all players (except self if mentioned)
  1772. void World::SendGlobalMessage(WorldPacket* packet, WorldSession* self, uint32 team)
  1773. {
  1774. SessionMap::const_iterator itr;
  1775. for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1776. {
  1777. if (itr->second &&
  1778. itr->second->GetPlayer() &&
  1779. itr->second->GetPlayer()->IsInWorld() &&
  1780. itr->second != self &&
  1781. (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
  1782. {
  1783. itr->second->SendPacket(packet);
  1784. }
  1785. }
  1786. }
  1787. /// Send a packet to all GMs (except self if mentioned)
  1788. void World::SendGlobalGMMessage(WorldPacket* packet, WorldSession* self, uint32 team)
  1789. {
  1790. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1791. {
  1792. // check if session and can receive global GM Messages and its not self
  1793. WorldSession* session = itr->second;
  1794. if (!session || session == self || !session->HasPermission(rbac::RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE))
  1795. continue;
  1796. // Player should be in world
  1797. Player* player = session->GetPlayer();
  1798. if (!player || !player->IsInWorld())
  1799. continue;
  1800. // Send only to same team, if team is given
  1801. if (!team || player->GetTeam() == team)
  1802. session->SendPacket(packet);
  1803. }
  1804. }
  1805. namespace Trinity
  1806. {
  1807. class WorldWorldTextBuilder
  1808. {
  1809. public:
  1810. typedef std::vector<WorldPacket*> WorldPacketList;
  1811. explicit WorldWorldTextBuilder(uint32 textId, va_list* args = NULL) : i_textId(textId), i_args(args) { }
  1812. void operator()(WorldPacketList& data_list, LocaleConstant loc_idx)
  1813. {
  1814. char const* text = sObjectMgr->GetTrinityString(i_textId, loc_idx);
  1815. if (i_args)
  1816. {
  1817. // we need copy va_list before use or original va_list will corrupted
  1818. va_list ap;
  1819. va_copy(ap, *i_args);
  1820. char str[2048];
  1821. vsnprintf(str, 2048, text, ap);
  1822. va_end(ap);
  1823. do_helper(data_list, &str[0]);
  1824. }
  1825. else
  1826. do_helper(data_list, (char*)text);
  1827. }
  1828. private:
  1829. char* lineFromMessage(char*& pos) { char* start = strtok(pos, "\n"); pos = NULL; return start; }
  1830. void do_helper(WorldPacketList& data_list, char* text)
  1831. {
  1832. char* pos = text;
  1833. while (char* line = lineFromMessage(pos))
  1834. {
  1835. WorldPacket* data = new WorldPacket();
  1836. ChatHandler::BuildChatPacket(*data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, NULL, line);
  1837. data_list.push_back(data);
  1838. }
  1839. }
  1840. uint32 i_textId;
  1841. va_list* i_args;
  1842. };
  1843. } // namespace Trinity
  1844. /// Send a System Message to all players (except self if mentioned)
  1845. void World::SendWorldText(uint32 string_id, ...)
  1846. {
  1847. va_list ap;
  1848. va_start(ap, string_id);
  1849. Trinity::WorldWorldTextBuilder wt_builder(string_id, &ap);
  1850. Trinity::LocalizedPacketListDo<Trinity::WorldWorldTextBuilder> wt_do(wt_builder);
  1851. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1852. {
  1853. if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld())
  1854. continue;
  1855. wt_do(itr->second->GetPlayer());
  1856. }
  1857. va_end(ap);
  1858. }
  1859. /// Send a System Message to all GMs (except self if mentioned)
  1860. void World::SendGMText(uint32 string_id, ...)
  1861. {
  1862. va_list ap;
  1863. va_start(ap, string_id);
  1864. Trinity::WorldWorldTextBuilder wt_builder(string_id, &ap);
  1865. Trinity::LocalizedPacketListDo<Trinity::WorldWorldTextBuilder> wt_do(wt_builder);
  1866. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1867. {
  1868. // Session should have permissions to receive global gm messages
  1869. WorldSession* session = itr->second;
  1870. if (!session || !session->HasPermission(rbac::RBAC_PERM_RECEIVE_GLOBAL_GM_TEXTMESSAGE))
  1871. continue;
  1872. // Player should be in world
  1873. Player* player = session->GetPlayer();
  1874. if (!player || !player->IsInWorld())
  1875. continue;
  1876. wt_do(player);
  1877. }
  1878. va_end(ap);
  1879. }
  1880. /// DEPRECATED, only for debug purpose. Send a System Message to all players (except self if mentioned)
  1881. void World::SendGlobalText(const char* text, WorldSession* self)
  1882. {
  1883. WorldPacket data;
  1884. // need copy to prevent corruption by strtok call in LineFromMessage original string
  1885. char* buf = strdup(text);
  1886. char* pos = buf;
  1887. while (char* line = ChatHandler::LineFromMessage(pos))
  1888. {
  1889. ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, NULL, line);
  1890. SendGlobalMessage(&data, self);
  1891. }
  1892. free(buf);
  1893. }
  1894. /// Send a packet to all players (or players selected team) in the zone (except self if mentioned)
  1895. bool World::SendZoneMessage(uint32 zone, WorldPacket* packet, WorldSession* self, uint32 team)
  1896. {
  1897. bool foundPlayerToSend = false;
  1898. SessionMap::const_iterator itr;
  1899. for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1900. {
  1901. if (itr->second &&
  1902. itr->second->GetPlayer() &&
  1903. itr->second->GetPlayer()->IsInWorld() &&
  1904. itr->second->GetPlayer()->GetZoneId() == zone &&
  1905. itr->second != self &&
  1906. (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
  1907. {
  1908. itr->second->SendPacket(packet);
  1909. foundPlayerToSend = true;
  1910. }
  1911. }
  1912. return foundPlayerToSend;
  1913. }
  1914. /// Send a System Message to all players in the zone (except self if mentioned)
  1915. void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, uint32 team)
  1916. {
  1917. WorldPacket data;
  1918. ChatHandler::BuildChatPacket(data, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, NULL, text);
  1919. SendZoneMessage(zone, &data, self, team);
  1920. }
  1921. /// Kick (and save) all players
  1922. void World::KickAll()
  1923. {
  1924. m_QueuedPlayer.clear(); // prevent send queue update packet and login queued sessions
  1925. // session not removed at kick and will removed in next update tick
  1926. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1927. itr->second->KickPlayer();
  1928. }
  1929. /// Kick (and save) all players with security level less `sec`
  1930. void World::KickAllLess(AccountTypes sec)
  1931. {
  1932. // session not removed at kick and will removed in next update tick
  1933. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  1934. if (itr->second->GetSecurity() < sec)
  1935. itr->second->KickPlayer();
  1936. }
  1937. /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
  1938. BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, std::string const& duration, std::string const& reason, std::string const& author)
  1939. {
  1940. uint32 duration_secs = TimeStringToSecs(duration);
  1941. return BanAccount(mode, nameOrIP, duration_secs, reason, author);
  1942. }
  1943. /// Ban an account or ban an IP address, duration is in seconds if positive, otherwise permban
  1944. BanReturn World::BanAccount(BanMode mode, std::string const& nameOrIP, uint32 duration_secs, std::string const& reason, std::string const& author)
  1945. {
  1946. PreparedQueryResult resultAccounts = PreparedQueryResult(NULL); //used for kicking
  1947. PreparedStatement* stmt = NULL;
  1948. ///- Update the database with ban information
  1949. switch (mode)
  1950. {
  1951. case BAN_IP:
  1952. // No SQL injection with prepared statements
  1953. stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_BY_IP);
  1954. stmt->setString(0, nameOrIP);
  1955. resultAccounts = LoginDatabase.Query(stmt);
  1956. stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_BANNED);
  1957. stmt->setString(0, nameOrIP);
  1958. stmt->setUInt32(1, duration_secs);
  1959. stmt->setString(2, author);
  1960. stmt->setString(3, reason);
  1961. LoginDatabase.Execute(stmt);
  1962. break;
  1963. case BAN_ACCOUNT:
  1964. // No SQL injection with prepared statements
  1965. stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_ACCOUNT_ID_BY_NAME);
  1966. stmt->setString(0, nameOrIP);
  1967. resultAccounts = LoginDatabase.Query(stmt);
  1968. break;
  1969. case BAN_CHARACTER:
  1970. // No SQL injection with prepared statements
  1971. stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_ACCOUNT_BY_NAME);
  1972. stmt->setString(0, nameOrIP);
  1973. resultAccounts = CharacterDatabase.Query(stmt);
  1974. break;
  1975. default:
  1976. return BAN_SYNTAX_ERROR;
  1977. }
  1978. if (!resultAccounts)
  1979. {
  1980. if (mode == BAN_IP)
  1981. return BAN_SUCCESS; // ip correctly banned but nobody affected (yet)
  1982. else
  1983. return BAN_NOTFOUND; // Nobody to ban
  1984. }
  1985. ///- Disconnect all affected players (for IP it can be several)
  1986. SQLTransaction trans = LoginDatabase.BeginTransaction();
  1987. do
  1988. {
  1989. Field* fieldsAccount = resultAccounts->Fetch();
  1990. uint32 account = fieldsAccount[0].GetUInt32();
  1991. if (mode != BAN_IP)
  1992. {
  1993. // make sure there is only one active ban
  1994. stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED);
  1995. stmt->setUInt32(0, account);
  1996. trans->Append(stmt);
  1997. // No SQL injection with prepared statements
  1998. stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_ACCOUNT_BANNED);
  1999. stmt->setUInt32(0, account);
  2000. stmt->setUInt32(1, duration_secs);
  2001. stmt->setString(2, author);
  2002. stmt->setString(3, reason);
  2003. trans->Append(stmt);
  2004. }
  2005. if (WorldSession* sess = FindSession(account))
  2006. if (std::string(sess->GetPlayerName()) != author)
  2007. sess->KickPlayer();
  2008. } while (resultAccounts->NextRow());
  2009. LoginDatabase.CommitTransaction(trans);
  2010. return BAN_SUCCESS;
  2011. }
  2012. /// Remove a ban from an account or IP address
  2013. bool World::RemoveBanAccount(BanMode mode, std::string const& nameOrIP)
  2014. {
  2015. PreparedStatement* stmt = NULL;
  2016. if (mode == BAN_IP)
  2017. {
  2018. stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_IP_NOT_BANNED);
  2019. stmt->setString(0, nameOrIP);
  2020. LoginDatabase.Execute(stmt);
  2021. }
  2022. else
  2023. {
  2024. uint32 account = 0;
  2025. if (mode == BAN_ACCOUNT)
  2026. account = AccountMgr::GetId(nameOrIP);
  2027. else if (mode == BAN_CHARACTER)
  2028. account = sObjectMgr->GetPlayerAccountIdByPlayerName(nameOrIP);
  2029. if (!account)
  2030. return false;
  2031. //NO SQL injection as account is uint32
  2032. stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_ACCOUNT_NOT_BANNED);
  2033. stmt->setUInt32(0, account);
  2034. LoginDatabase.Execute(stmt);
  2035. }
  2036. return true;
  2037. }
  2038. /// Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
  2039. BanReturn World::BanCharacter(std::string const& name, std::string const& duration, std::string const& reason, std::string const& author)
  2040. {
  2041. Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name);
  2042. uint32 guid = 0;
  2043. uint32 duration_secs = TimeStringToSecs(duration);
  2044. /// Pick a player to ban if not online
  2045. if (!pBanned)
  2046. {
  2047. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME);
  2048. stmt->setString(0, name);
  2049. PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt);
  2050. if (!resultCharacter)
  2051. return BAN_NOTFOUND; // Nobody to ban
  2052. guid = (*resultCharacter)[0].GetUInt32();
  2053. }
  2054. else
  2055. guid = pBanned->GetGUIDLow();
  2056. // make sure there is only one active ban
  2057. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN);
  2058. stmt->setUInt32(0, guid);
  2059. CharacterDatabase.Execute(stmt);
  2060. stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_CHARACTER_BAN);
  2061. stmt->setUInt32(0, guid);
  2062. stmt->setUInt32(1, duration_secs);
  2063. stmt->setString(2, author);
  2064. stmt->setString(3, reason);
  2065. CharacterDatabase.Execute(stmt);
  2066. if (pBanned)
  2067. pBanned->GetSession()->KickPlayer();
  2068. return BAN_SUCCESS;
  2069. }
  2070. /// Remove a ban from a character
  2071. bool World::RemoveBanCharacter(std::string const& name)
  2072. {
  2073. Player* pBanned = ObjectAccessor::FindConnectedPlayerByName(name);
  2074. uint32 guid = 0;
  2075. /// Pick a player to ban if not online
  2076. if (!pBanned)
  2077. {
  2078. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_GUID_BY_NAME);
  2079. stmt->setString(0, name);
  2080. PreparedQueryResult resultCharacter = CharacterDatabase.Query(stmt);
  2081. if (!resultCharacter)
  2082. return false;
  2083. guid = (*resultCharacter)[0].GetUInt32();
  2084. }
  2085. else
  2086. guid = pBanned->GetGUIDLow();
  2087. if (!guid)
  2088. return false;
  2089. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_CHARACTER_BAN);
  2090. stmt->setUInt32(0, guid);
  2091. CharacterDatabase.Execute(stmt);
  2092. return true;
  2093. }
  2094. /// Update the game time
  2095. void World::_UpdateGameTime()
  2096. {
  2097. ///- update the time
  2098. time_t thisTime = time(NULL);
  2099. uint32 elapsed = uint32(thisTime - m_gameTime);
  2100. m_gameTime = thisTime;
  2101. ///- if there is a shutdown timer
  2102. if (!IsStopped() && m_ShutdownTimer > 0 && elapsed > 0)
  2103. {
  2104. ///- ... and it is overdue, stop the world (set m_stopEvent)
  2105. if (m_ShutdownTimer <= elapsed)
  2106. {
  2107. if (!(m_ShutdownMask & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0)
  2108. m_stopEvent = true; // exist code already set
  2109. else
  2110. m_ShutdownTimer = 1; // minimum timer value to wait idle state
  2111. }
  2112. ///- ... else decrease it and if necessary display a shutdown countdown to the users
  2113. else
  2114. {
  2115. m_ShutdownTimer -= elapsed;
  2116. ShutdownMsg();
  2117. }
  2118. }
  2119. }
  2120. /// Shutdown the server
  2121. void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode, const std::string& reason)
  2122. {
  2123. // ignore if server shutdown at next tick
  2124. if (IsStopped())
  2125. return;
  2126. m_ShutdownMask = options;
  2127. m_ExitCode = exitcode;
  2128. ///- If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions)
  2129. if (time == 0)
  2130. {
  2131. if (!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0)
  2132. m_stopEvent = true; // exist code already set
  2133. else
  2134. m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick
  2135. }
  2136. ///- Else set the shutdown timer and warn users
  2137. else
  2138. {
  2139. m_ShutdownTimer = time;
  2140. ShutdownMsg(true, nullptr, reason);
  2141. }
  2142. sScriptMgr->OnShutdownInitiate(ShutdownExitCode(exitcode), ShutdownMask(options));
  2143. }
  2144. /// Display a shutdown message to the user(s)
  2145. void World::ShutdownMsg(bool show, Player* player, const std::string& reason)
  2146. {
  2147. // not show messages for idle shutdown mode
  2148. if (m_ShutdownMask & SHUTDOWN_MASK_IDLE)
  2149. return;
  2150. ///- Display a message every 12 hours, hours, 5 minutes, minute, 5 seconds and finally seconds
  2151. if (show ||
  2152. (m_ShutdownTimer < 5* MINUTE && (m_ShutdownTimer % 15) == 0) || // < 5 min; every 15 sec
  2153. (m_ShutdownTimer < 15 * MINUTE && (m_ShutdownTimer % MINUTE) == 0) || // < 15 min ; every 1 min
  2154. (m_ShutdownTimer < 30 * MINUTE && (m_ShutdownTimer % (5 * MINUTE)) == 0) || // < 30 min ; every 5 min
  2155. (m_ShutdownTimer < 12 * HOUR && (m_ShutdownTimer % HOUR) == 0) || // < 12 h ; every 1 h
  2156. (m_ShutdownTimer > 12 * HOUR && (m_ShutdownTimer % (12 * HOUR)) == 0)) // > 12 h ; every 12 h
  2157. {
  2158. std::string str = secsToTimeString(m_ShutdownTimer);
  2159. if (!reason.empty())
  2160. str += " - " + reason;
  2161. ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_TIME : SERVER_MSG_SHUTDOWN_TIME;
  2162. SendServerMessage(msgid, str.c_str(), player);
  2163. TC_LOG_DEBUG("misc", "Server is %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"), str.c_str());
  2164. }
  2165. }
  2166. /// Cancel a planned server shutdown
  2167. void World::ShutdownCancel()
  2168. {
  2169. // nothing cancel or too later
  2170. if (!m_ShutdownTimer || m_stopEvent)
  2171. return;
  2172. ServerMessageType msgid = (m_ShutdownMask & SHUTDOWN_MASK_RESTART) ? SERVER_MSG_RESTART_CANCELLED : SERVER_MSG_SHUTDOWN_CANCELLED;
  2173. m_ShutdownMask = 0;
  2174. m_ShutdownTimer = 0;
  2175. m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value
  2176. SendServerMessage(msgid);
  2177. TC_LOG_DEBUG("misc", "Server %s cancelled.", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shuttingdown"));
  2178. sScriptMgr->OnShutdownCancel();
  2179. }
  2180. /// Send a server message to the user(s)
  2181. void World::SendServerMessage(ServerMessageType type, const char *text, Player* player)
  2182. {
  2183. WorldPacket data(SMSG_SERVER_MESSAGE, 50); // guess size
  2184. data << uint32(type);
  2185. if (type <= SERVER_MSG_STRING)
  2186. data << text;
  2187. if (player)
  2188. player->GetSession()->SendPacket(&data);
  2189. else
  2190. SendGlobalMessage(&data);
  2191. }
  2192. void World::UpdateSessions(uint32 diff)
  2193. {
  2194. ///- Add new sessions
  2195. WorldSession* sess = NULL;
  2196. while (addSessQueue.next(sess))
  2197. AddSession_ (sess);
  2198. ///- Then send an update signal to remaining ones
  2199. for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
  2200. {
  2201. next = itr;
  2202. ++next;
  2203. ///- and remove not active sessions from the list
  2204. WorldSession* pSession = itr->second;
  2205. WorldSessionFilter updater(pSession);
  2206. if (!pSession->Update(diff, updater)) // As interval = 0
  2207. {
  2208. if (!RemoveQueuedPlayer(itr->second) && itr->second && getIntConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
  2209. m_disconnects[itr->second->GetAccountId()] = time(NULL);
  2210. RemoveQueuedPlayer(pSession);
  2211. m_sessions.erase(itr);
  2212. delete pSession;
  2213. }
  2214. }
  2215. }
  2216. // This handles the issued and queued CLI commands
  2217. void World::ProcessCliCommands()
  2218. {
  2219. CliCommandHolder::Print* zprint = NULL;
  2220. void* callbackArg = NULL;
  2221. CliCommandHolder* command = NULL;
  2222. while (cliCmdQueue.next(command))
  2223. {
  2224. TC_LOG_INFO("misc", "CLI command under processing...");
  2225. zprint = command->m_print;
  2226. callbackArg = command->m_callbackArg;
  2227. CliHandler handler(callbackArg, zprint);
  2228. handler.ParseCommands(command->m_command);
  2229. if (command->m_commandFinished)
  2230. command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage());
  2231. delete command;
  2232. }
  2233. }
  2234. void World::SendAutoBroadcast()
  2235. {
  2236. if (m_Autobroadcasts.empty())
  2237. return;
  2238. uint32 weight = 0;
  2239. AutobroadcastsWeightMap selectionWeights;
  2240. std::string msg;
  2241. for (AutobroadcastsWeightMap::const_iterator it = m_AutobroadcastsWeights.begin(); it != m_AutobroadcastsWeights.end(); ++it)
  2242. {
  2243. if (it->second)
  2244. {
  2245. weight += it->second;
  2246. selectionWeights[it->first] = it->second;
  2247. }
  2248. }
  2249. if (weight)
  2250. {
  2251. uint32 selectedWeight = urand(0, weight - 1);
  2252. weight = 0;
  2253. for (AutobroadcastsWeightMap::const_iterator it = selectionWeights.begin(); it != selectionWeights.end(); ++it)
  2254. {
  2255. weight += it->second;
  2256. if (selectedWeight < weight)
  2257. {
  2258. msg = m_Autobroadcasts[it->first];
  2259. break;
  2260. }
  2261. }
  2262. }
  2263. else
  2264. msg = m_Autobroadcasts[urand(0, m_Autobroadcasts.size())];
  2265. uint32 abcenter = sWorld->getIntConfig(CONFIG_AUTOBROADCAST_CENTER);
  2266. if (abcenter == 0)
  2267. sWorld->SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
  2268. else if (abcenter == 1)
  2269. {
  2270. WorldPacket data(SMSG_NOTIFICATION, 2 + msg.length());
  2271. data.WriteBits(msg.length(), 13);
  2272. data.FlushBits();
  2273. data.WriteString(msg);
  2274. sWorld->SendGlobalMessage(&data);
  2275. }
  2276. else if (abcenter == 2)
  2277. {
  2278. sWorld->SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
  2279. WorldPacket data(SMSG_NOTIFICATION, 2 + msg.length());
  2280. data.WriteBits(msg.length(), 13);
  2281. data.FlushBits();
  2282. data.WriteString(msg);
  2283. sWorld->SendGlobalMessage(&data);
  2284. }
  2285. TC_LOG_DEBUG("misc", "AutoBroadcast: '%s'", msg.c_str());
  2286. }
  2287. void World::UpdateRealmCharCount(uint32 accountId)
  2288. {
  2289. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHARACTER_COUNT);
  2290. stmt->setUInt32(0, accountId);
  2291. m_realmCharCallbacks.push_back(CharacterDatabase.AsyncQuery(stmt));
  2292. }
  2293. void World::_UpdateRealmCharCount(PreparedQueryResult resultCharCount)
  2294. {
  2295. if (resultCharCount)
  2296. {
  2297. Field* fields = resultCharCount->Fetch();
  2298. uint32 accountId = fields[0].GetUInt32();
  2299. uint8 charCount = uint8(fields[1].GetUInt64());
  2300. PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_DEL_REALM_CHARACTERS_BY_REALM);
  2301. stmt->setUInt32(0, accountId);
  2302. stmt->setUInt32(1, realmHandle.Index);
  2303. LoginDatabase.Execute(stmt);
  2304. stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_REALM_CHARACTERS);
  2305. stmt->setUInt8(0, charCount);
  2306. stmt->setUInt32(1, accountId);
  2307. stmt->setUInt32(2, realmHandle.Index);
  2308. LoginDatabase.Execute(stmt);
  2309. }
  2310. }
  2311. void World::InitWeeklyQuestResetTime()
  2312. {
  2313. time_t wstime = uint64(sWorld->getWorldState(WS_WEEKLY_QUEST_RESET_TIME));
  2314. time_t curtime = time(NULL);
  2315. m_NextWeeklyQuestReset = wstime < curtime ? curtime : time_t(wstime);
  2316. }
  2317. void World::InitDailyQuestResetTime()
  2318. {
  2319. time_t mostRecentQuestTime;
  2320. QueryResult result = CharacterDatabase.Query("SELECT MAX(time) FROM character_queststatus_daily");
  2321. if (result)
  2322. {
  2323. Field* fields = result->Fetch();
  2324. mostRecentQuestTime = time_t(fields[0].GetUInt32());
  2325. }
  2326. else
  2327. mostRecentQuestTime = 0;
  2328. // client built-in time for reset is 6:00 AM
  2329. // FIX ME: client not show day start time
  2330. time_t curTime = time(NULL);
  2331. tm localTm;
  2332. localtime_r(&curTime, &localTm);
  2333. localTm.tm_hour = 6;
  2334. localTm.tm_min = 0;
  2335. localTm.tm_sec = 0;
  2336. // current day reset time
  2337. time_t curDayResetTime = mktime(&localTm);
  2338. // last reset time before current moment
  2339. time_t resetTime = (curTime < curDayResetTime) ? curDayResetTime - DAY : curDayResetTime;
  2340. // need reset (if we have quest time before last reset time (not processed by some reason)
  2341. if (mostRecentQuestTime && mostRecentQuestTime <= resetTime)
  2342. m_NextDailyQuestReset = mostRecentQuestTime;
  2343. else // plan next reset time
  2344. m_NextDailyQuestReset = (curTime >= curDayResetTime) ? curDayResetTime + DAY : curDayResetTime;
  2345. }
  2346. void World::InitMonthlyQuestResetTime()
  2347. {
  2348. time_t wstime = uint64(sWorld->getWorldState(WS_MONTHLY_QUEST_RESET_TIME));
  2349. time_t curtime = time(NULL);
  2350. m_NextMonthlyQuestReset = wstime < curtime ? curtime : time_t(wstime);
  2351. }
  2352. void World::InitRandomBGResetTime()
  2353. {
  2354. time_t bgtime = uint64(sWorld->getWorldState(WS_BG_DAILY_RESET_TIME));
  2355. if (!bgtime)
  2356. m_NextRandomBGReset = time_t(time(NULL)); // game time not yet init
  2357. // generate time by config
  2358. time_t curTime = time(NULL);
  2359. tm localTm;
  2360. localtime_r(&curTime, &localTm);
  2361. localTm.tm_hour = getIntConfig(CONFIG_RANDOM_BG_RESET_HOUR);
  2362. localTm.tm_min = 0;
  2363. localTm.tm_sec = 0;
  2364. // current day reset time
  2365. time_t nextDayResetTime = mktime(&localTm);
  2366. // next reset time before current moment
  2367. if (curTime >= nextDayResetTime)
  2368. nextDayResetTime += DAY;
  2369. // normalize reset time
  2370. m_NextRandomBGReset = bgtime < curTime ? nextDayResetTime - DAY : nextDayResetTime;
  2371. if (!bgtime)
  2372. sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset));
  2373. }
  2374. void World::InitGuildResetTime()
  2375. {
  2376. time_t gtime = uint64(getWorldState(WS_GUILD_DAILY_RESET_TIME));
  2377. if (!gtime)
  2378. m_NextGuildReset = time_t(time(NULL)); // game time not yet init
  2379. // generate time by config
  2380. time_t curTime = time(NULL);
  2381. tm localTm;
  2382. localtime_r(&curTime, &localTm);
  2383. localTm.tm_hour = getIntConfig(CONFIG_GUILD_RESET_HOUR);
  2384. localTm.tm_min = 0;
  2385. localTm.tm_sec = 0;
  2386. // current day reset time
  2387. time_t nextDayResetTime = mktime(&localTm);
  2388. // next reset time before current moment
  2389. if (curTime >= nextDayResetTime)
  2390. nextDayResetTime += DAY;
  2391. // normalize reset time
  2392. m_NextGuildReset = gtime < curTime ? nextDayResetTime - DAY : nextDayResetTime;
  2393. if (!gtime)
  2394. sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
  2395. }
  2396. void World::InitCurrencyResetTime()
  2397. {
  2398. time_t currencytime = uint64(sWorld->getWorldState(WS_CURRENCY_RESET_TIME));
  2399. if (!currencytime)
  2400. m_NextCurrencyReset = time_t(time(NULL)); // game time not yet init
  2401. // generate time by config
  2402. time_t curTime = time(NULL);
  2403. tm localTm = *localtime(&curTime);
  2404. localTm.tm_wday = getIntConfig(CONFIG_CURRENCY_RESET_DAY);
  2405. localTm.tm_hour = getIntConfig(CONFIG_CURRENCY_RESET_HOUR);
  2406. localTm.tm_min = 0;
  2407. localTm.tm_sec = 0;
  2408. // current week reset time
  2409. time_t nextWeekResetTime = mktime(&localTm);
  2410. // next reset time before current moment
  2411. if (curTime >= nextWeekResetTime)
  2412. nextWeekResetTime += getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL) * DAY;
  2413. // normalize reset time
  2414. m_NextCurrencyReset = currencytime < curTime ? nextWeekResetTime - getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL) * DAY : nextWeekResetTime;
  2415. if (!currencytime)
  2416. sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
  2417. }
  2418. void World::ResetDailyQuests()
  2419. {
  2420. TC_LOG_INFO("misc", "Daily quests reset for all characters.");
  2421. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_DAILY);
  2422. CharacterDatabase.Execute(stmt);
  2423. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2424. if (itr->second->GetPlayer())
  2425. itr->second->GetPlayer()->ResetDailyQuestStatus();
  2426. // change available dailies
  2427. sPoolMgr->ChangeDailyQuests();
  2428. }
  2429. void World::ResetCurrencyWeekCap()
  2430. {
  2431. CharacterDatabase.Execute("UPDATE `character_currency` SET `week_count` = 0");
  2432. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2433. if (itr->second->GetPlayer())
  2434. itr->second->GetPlayer()->ResetCurrencyWeekCap();
  2435. m_NextCurrencyReset = time_t(m_NextCurrencyReset + DAY * getIntConfig(CONFIG_CURRENCY_RESET_INTERVAL));
  2436. sWorld->setWorldState(WS_CURRENCY_RESET_TIME, uint64(m_NextCurrencyReset));
  2437. }
  2438. void World::LoadDBAllowedSecurityLevel()
  2439. {
  2440. PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_REALMLIST_SECURITY_LEVEL);
  2441. stmt->setInt32(0, int32(realmHandle.Index));
  2442. PreparedQueryResult result = LoginDatabase.Query(stmt);
  2443. if (result)
  2444. SetPlayerSecurityLimit(AccountTypes(result->Fetch()->GetUInt8()));
  2445. }
  2446. void World::SetPlayerSecurityLimit(AccountTypes _sec)
  2447. {
  2448. AccountTypes sec = _sec < SEC_CONSOLE ? _sec : SEC_PLAYER;
  2449. bool update = sec > m_allowedSecurityLevel;
  2450. m_allowedSecurityLevel = sec;
  2451. if (update)
  2452. KickAllLess(m_allowedSecurityLevel);
  2453. }
  2454. void World::ResetWeeklyQuests()
  2455. {
  2456. TC_LOG_INFO("misc", "Weekly quests reset for all characters.");
  2457. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_WEEKLY);
  2458. CharacterDatabase.Execute(stmt);
  2459. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2460. if (itr->second->GetPlayer())
  2461. itr->second->GetPlayer()->ResetWeeklyQuestStatus();
  2462. m_NextWeeklyQuestReset = time_t(m_NextWeeklyQuestReset + WEEK);
  2463. sWorld->setWorldState(WS_WEEKLY_QUEST_RESET_TIME, uint64(m_NextWeeklyQuestReset));
  2464. // change available weeklies
  2465. sPoolMgr->ChangeWeeklyQuests();
  2466. }
  2467. void World::ResetMonthlyQuests()
  2468. {
  2469. TC_LOG_INFO("misc", "Monthly quests reset for all characters.");
  2470. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_MONTHLY);
  2471. CharacterDatabase.Execute(stmt);
  2472. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2473. if (itr->second->GetPlayer())
  2474. itr->second->GetPlayer()->ResetMonthlyQuestStatus();
  2475. // generate time
  2476. time_t curTime = time(NULL);
  2477. tm localTm;
  2478. localtime_r(&curTime, &localTm);
  2479. int month = localTm.tm_mon;
  2480. int year = localTm.tm_year;
  2481. ++month;
  2482. // month 11 is december, next is january (0)
  2483. if (month > 11)
  2484. {
  2485. month = 0;
  2486. year += 1;
  2487. }
  2488. // reset time for next month
  2489. localTm.tm_year = year;
  2490. localTm.tm_mon = month;
  2491. localTm.tm_mday = 1; // don't know if we really need config option for day / hour
  2492. localTm.tm_hour = 0;
  2493. localTm.tm_min = 0;
  2494. localTm.tm_sec = 0;
  2495. time_t nextMonthResetTime = mktime(&localTm);
  2496. // plan next reset time
  2497. m_NextMonthlyQuestReset = (curTime >= nextMonthResetTime) ? nextMonthResetTime + MONTH : nextMonthResetTime;
  2498. sWorld->setWorldState(WS_MONTHLY_QUEST_RESET_TIME, uint64(m_NextMonthlyQuestReset));
  2499. }
  2500. void World::ResetEventSeasonalQuests(uint16 event_id)
  2501. {
  2502. TC_LOG_INFO("misc", "Seasonal quests reset for all characters.");
  2503. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_RESET_CHARACTER_QUESTSTATUS_SEASONAL_BY_EVENT);
  2504. stmt->setUInt16(0, event_id);
  2505. CharacterDatabase.Execute(stmt);
  2506. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2507. if (itr->second->GetPlayer())
  2508. itr->second->GetPlayer()->ResetSeasonalQuestStatus(event_id);
  2509. }
  2510. void World::ResetRandomBG()
  2511. {
  2512. TC_LOG_INFO("misc", "Random BG status reset for all characters.");
  2513. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_BATTLEGROUND_RANDOM);
  2514. CharacterDatabase.Execute(stmt);
  2515. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2516. if (itr->second->GetPlayer())
  2517. itr->second->GetPlayer()->SetRandomWinner(false);
  2518. m_NextRandomBGReset = time_t(m_NextRandomBGReset + DAY);
  2519. sWorld->setWorldState(WS_BG_DAILY_RESET_TIME, uint64(m_NextRandomBGReset));
  2520. }
  2521. void World::ResetGuildCap()
  2522. {
  2523. m_NextGuildReset = time_t(m_NextGuildReset + DAY);
  2524. sWorld->setWorldState(WS_GUILD_DAILY_RESET_TIME, uint64(m_NextGuildReset));
  2525. uint32 week = getWorldState(WS_GUILD_WEEKLY_RESET_TIME);
  2526. week = week < 7 ? week + 1 : 1;
  2527. TC_LOG_INFO("misc", "Guild Daily Cap reset. Week: %u", week == 1);
  2528. sWorld->setWorldState(WS_GUILD_WEEKLY_RESET_TIME, week);
  2529. sGuildMgr->ResetTimes(week == 1);
  2530. }
  2531. void World::UpdateMaxSessionCounters()
  2532. {
  2533. m_maxActiveSessionCount = std::max(m_maxActiveSessionCount, uint32(m_sessions.size()-m_QueuedPlayer.size()));
  2534. m_maxQueuedSessionCount = std::max(m_maxQueuedSessionCount, uint32(m_QueuedPlayer.size()));
  2535. }
  2536. void World::LoadDBVersion()
  2537. {
  2538. QueryResult result = WorldDatabase.Query("SELECT db_version, cache_id FROM version LIMIT 1");
  2539. if (result)
  2540. {
  2541. Field* fields = result->Fetch();
  2542. m_DBVersion = fields[0].GetString();
  2543. // will be overwrite by config values if different and non-0
  2544. m_int_configs[CONFIG_CLIENTCACHE_VERSION] = fields[1].GetUInt32();
  2545. }
  2546. if (m_DBVersion.empty())
  2547. m_DBVersion = "Unknown world database.";
  2548. }
  2549. void World::UpdateAreaDependentAuras()
  2550. {
  2551. SessionMap::const_iterator itr;
  2552. for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2553. if (itr->second && itr->second->GetPlayer() && itr->second->GetPlayer()->IsInWorld())
  2554. {
  2555. itr->second->GetPlayer()->UpdateAreaDependentAuras(itr->second->GetPlayer()->GetAreaId());
  2556. itr->second->GetPlayer()->UpdateZoneDependentAuras(itr->second->GetPlayer()->GetZoneId());
  2557. }
  2558. }
  2559. void World::LoadWorldStates()
  2560. {
  2561. uint32 oldMSTime = getMSTime();
  2562. QueryResult result = CharacterDatabase.Query("SELECT entry, value FROM worldstates");
  2563. if (!result)
  2564. {
  2565. TC_LOG_INFO("server.loading", ">> Loaded 0 world states. DB table `worldstates` is empty!");
  2566. return;
  2567. }
  2568. uint32 count = 0;
  2569. do
  2570. {
  2571. Field* fields = result->Fetch();
  2572. m_worldstates[fields[0].GetUInt32()] = fields[1].GetUInt32();
  2573. ++count;
  2574. }
  2575. while (result->NextRow());
  2576. TC_LOG_INFO("server.loading", ">> Loaded %u world states in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
  2577. }
  2578. // Setting a worldstate will save it to DB
  2579. void World::setWorldState(uint32 index, uint64 value)
  2580. {
  2581. WorldStatesMap::const_iterator it = m_worldstates.find(index);
  2582. if (it != m_worldstates.end())
  2583. {
  2584. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_WORLDSTATE);
  2585. stmt->setUInt32(0, uint32(value));
  2586. stmt->setUInt32(1, index);
  2587. CharacterDatabase.Execute(stmt);
  2588. }
  2589. else
  2590. {
  2591. PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_WORLDSTATE);
  2592. stmt->setUInt32(0, index);
  2593. stmt->setUInt32(1, uint32(value));
  2594. CharacterDatabase.Execute(stmt);
  2595. }
  2596. m_worldstates[index] = value;
  2597. }
  2598. uint64 World::getWorldState(uint32 index) const
  2599. {
  2600. WorldStatesMap::const_iterator it = m_worldstates.find(index);
  2601. return it != m_worldstates.end() ? it->second : 0;
  2602. }
  2603. void World::ProcessQueryCallbacks()
  2604. {
  2605. PreparedQueryResult result;
  2606. for (std::deque<std::future<PreparedQueryResult>>::iterator itr = m_realmCharCallbacks.begin(); itr != m_realmCharCallbacks.end(); )
  2607. {
  2608. if ((*itr).wait_for(std::chrono::seconds(0)) != std::future_status::ready)
  2609. {
  2610. ++itr;
  2611. continue;
  2612. }
  2613. result = (*itr).get();
  2614. _UpdateRealmCharCount(result);
  2615. itr = m_realmCharCallbacks.erase(itr);
  2616. }
  2617. }
  2618. /**
  2619. * @brief Loads several pieces of information on server startup with the GUID
  2620. * There is no further database query necessary.
  2621. * These are a number of methods that work into the calling function.
  2622. *
  2623. * @param guid Requires a guid to call
  2624. * @return Name, Gender, Race, Class and Level of player character
  2625. * Example Usage:
  2626. * @code
  2627. * CharacterNameData const* nameData = sWorld->GetCharacterNameData(GUID);
  2628. * if (!nameData)
  2629. * return;
  2630. *
  2631. * std::string playerName = nameData->m_name;
  2632. * uint8 playerGender = nameData->m_gender;
  2633. * uint8 playerRace = nameData->m_race;
  2634. * uint8 playerClass = nameData->m_class;
  2635. * uint8 playerLevel = nameData->m_level;
  2636. * @endcode
  2637. **/
  2638. void World::LoadCharacterNameData()
  2639. {
  2640. TC_LOG_INFO("server.loading", "Loading character name data");
  2641. QueryResult result = CharacterDatabase.Query("SELECT guid, name, race, gender, class, level FROM characters WHERE deleteDate IS NULL");
  2642. if (!result)
  2643. {
  2644. TC_LOG_INFO("server.loading", "No character name data loaded, empty query");
  2645. return;
  2646. }
  2647. uint32 count = 0;
  2648. do
  2649. {
  2650. Field* fields = result->Fetch();
  2651. AddCharacterNameData(ObjectGuid(HIGHGUID_PLAYER, fields[0].GetUInt32()), fields[1].GetString(),
  2652. fields[3].GetUInt8() /*gender*/, fields[2].GetUInt8() /*race*/, fields[4].GetUInt8() /*class*/, fields[5].GetUInt8() /*level*/);
  2653. ++count;
  2654. } while (result->NextRow());
  2655. TC_LOG_INFO("server.loading", "Loaded name data for %u characters", count);
  2656. }
  2657. void World::AddCharacterNameData(ObjectGuid guid, std::string const& name, uint8 gender, uint8 race, uint8 playerClass, uint8 level)
  2658. {
  2659. CharacterNameData& data = _characterNameDataMap[guid];
  2660. data.m_name = name;
  2661. data.m_race = race;
  2662. data.m_gender = gender;
  2663. data.m_class = playerClass;
  2664. data.m_level = level;
  2665. }
  2666. void World::UpdateCharacterNameData(ObjectGuid guid, std::string const& name, uint8 gender /*= GENDER_NONE*/, uint8 race /*= RACE_NONE*/)
  2667. {
  2668. std::map<ObjectGuid, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid);
  2669. if (itr == _characterNameDataMap.end())
  2670. return;
  2671. itr->second.m_name = name;
  2672. if (gender != GENDER_NONE)
  2673. itr->second.m_gender = gender;
  2674. if (race != RACE_NONE)
  2675. itr->second.m_race = race;
  2676. WorldPacket data(SMSG_INVALIDATE_PLAYER, 8);
  2677. data << guid;
  2678. SendGlobalMessage(&data);
  2679. }
  2680. void World::UpdateCharacterNameDataLevel(ObjectGuid guid, uint8 level)
  2681. {
  2682. std::map<ObjectGuid, CharacterNameData>::iterator itr = _characterNameDataMap.find(guid);
  2683. if (itr == _characterNameDataMap.end())
  2684. return;
  2685. itr->second.m_level = level;
  2686. }
  2687. CharacterNameData const* World::GetCharacterNameData(ObjectGuid guid) const
  2688. {
  2689. std::map<ObjectGuid, CharacterNameData>::const_iterator itr = _characterNameDataMap.find(guid);
  2690. if (itr != _characterNameDataMap.end())
  2691. return &itr->second;
  2692. else
  2693. return NULL;
  2694. }
  2695. void World::UpdatePhaseDefinitions()
  2696. {
  2697. }
  2698. void World::ReloadRBAC()
  2699. {
  2700. // Passive reload, we mark the data as invalidated and next time a permission is checked it will be reloaded
  2701. TC_LOG_INFO("rbac", "World::ReloadRBAC()");
  2702. for (SessionMap::const_iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
  2703. if (WorldSession* session = itr->second)
  2704. session->InvalidateRBACData();
  2705. }