OregonCore  revision 3611e8a-git
Your Favourite TBC server
World.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the OregonCore Project. See AUTHORS file for Copyright information
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License as published by the
6  * Free Software Foundation; either version 2 of the License, or (at your
7  * option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12  * more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include "Common.h"
19 #include "Database/DatabaseEnv.h"
20 #include "Config/Config.h"
21 #include "SystemConfig.h"
22 #include "Log.h"
23 #include "Console.h"
24 #include "Opcodes.h"
25 #include "WorldSession.h"
26 #include "WorldPacket.h"
27 #include "Weather.h"
28 #include "Player.h"
29 #include "SkillExtraItems.h"
30 #include "SkillDiscovery.h"
31 #include "World.h"
32 #include "AccountMgr.h"
33 #include "AuctionHouseMgr.h"
34 #include "ObjectMgr.h"
35 #include "SpellMgr.h"
36 #include "Chat.h"
37 #include "DBCStores.h"
38 #include "LootMgr.h"
39 #include "ItemEnchantmentMgr.h"
40 #include "MapManager.h"
41 #include "CreatureAIRegistry.h"
42 #include "BattlegroundMgr.h"
43 #include "OutdoorPvPMgr.h"
44 #include "TemporarySummon.h"
45 #include "AuctionHouseBot.h"
47 #include "VMapFactory.h"
48 #include "MoveMap.h"
49 #include "GameEventMgr.h"
50 #include "PoolMgr.h"
51 #include "Database/DatabaseImpl.h"
52 #include "GridNotifiersImpl.h"
53 #include "CellImpl.h"
54 #include "InstanceSaveMgr.h"
55 #include "SmartAI.h"
56 #include "TicketMgr.h"
57 #include "Util.h"
58 #include "Language.h"
59 #include "CreatureGroups.h"
60 #include "Transports.h"
61 #include "CreatureEventAIMgr.h"
62 #include "CreatureTextMgr.h"
63 #include "ScriptMgr.h"
64 #include "WardenDataStorage.h"
65 #include "DisableMgr.h"
66 #include "ConditionMgr.h"
67 #include "VMapManager2.h"
68 #include "M2Stores.h"
69 
70 #include <ace/Dirent.h>
71 
73 
74 volatile bool World::m_stopEvent = false;
77 
81 
85 
86 // World constructor
88 {
89  m_playerLimit = 0;
91  m_allowMovement = true;
92  m_ShutdownMask = 0;
93  m_ShutdownTimer = 0;
94  m_gameTime = time(NULL);
98  m_resultQueue = NULL;
100  m_scheduledScripts = 0;
101 
104 
105  m_updateTimeSum = 0;
106  m_updateTimeCount = 0;
107 }
108 
109 // World destructor
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 
120  // Empty the WeatherMap
121  for (WeatherMap::iterator itr = m_weathers.begin(); itr != m_weathers.end(); ++itr)
122  delete itr->second;
123 
124  m_weathers.clear();
125 
126  CliCommandHolder* command = NULL;
127  while (cliCmdQueue.next(command))
128  delete command;
129 
132 
133  delete m_resultQueue;
134 
135  //TODO free addSessQueue
136 }
137 
138 // Find a player in a specified zone
140 {
141  // circle through active sessions and return the first player found in the zone
142  SessionMap::iterator itr;
143  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
144  {
145  if (!itr->second)
146  continue;
147  Player* player = itr->second->GetPlayer();
148  if (!player)
149  continue;
150  if (player->IsInWorld() && player->GetZoneId() == zone)
151  return player;
152  }
153  return NULL;
154 }
155 
156 // Find a session by its id
158 {
159  SessionMap::const_iterator itr = m_sessions.find(id);
160 
161  if (itr != m_sessions.end())
162  return itr->second; // also can return NULL for kicked session
163  else
164  return NULL;
165 }
166 
167 // Remove a given session
169 {
170  // Find the session, kick the user, but we can't delete session at this moment to prevent iterator invalidation
171  SessionMap::iterator itr = m_sessions.find(id);
172 
173  if (itr != m_sessions.end() && itr->second)
174  {
175  if (itr->second->PlayerLoading())
176  return false;
177  itr->second->KickPlayer();
178  }
179 
180  return true;
181 }
182 
184 {
185  addSessQueue.add(s);
186 }
187 
188 void
190 {
191  ASSERT (s);
192 
193  //NOTE - Still there is race condition in WorldSession* being used in the Sockets
194 
195  // kick already loaded player with same account (if any) and remove session
196  // if player is in loading and want to load again, return
197  if (!RemoveSession (s->GetAccountId ()))
198  {
199  s->KickPlayer ();
200  delete s; // session not added yet in session list, so not listed in queue
201  return;
202  }
203 
204  // decrease session counts only at not reconnection case
205  bool decrease_session = true;
206 
207  // if session already exist, prepare to it deleting at next world update
208  // NOTE - KickPlayer() should be called on "old" in RemoveSession()
209  {
210  SessionMap::const_iterator old = m_sessions.find(s->GetAccountId ());
211 
212  if (old != m_sessions.end())
213  {
214  // prevent decrease sessions count if session queued
215  if (RemoveQueuedPlayer(old->second))
216  decrease_session = false;
217  // not remove replaced session form queue if listed
218  delete old->second;
219  }
220  }
221 
222  m_sessions[s->GetAccountId ()] = s;
223 
225  uint32 pLimit = GetPlayerAmountLimit ();
226  uint32 QueueSize = GetQueueSize (); //number of players in the queue
227 
228  //so we don't count the user trying to
229  //login as a session and queue the socket that we are using
230  if (decrease_session)
231  --Sessions;
232 
233  if (pLimit > 0 && Sessions >= pLimit && s->GetSecurity () == SEC_PLAYER && !HasRecentlyDisconnected(s))
234  {
235  AddQueuedPlayer (s);
237  sLog.outDetail ("PlayerQueue: Account id %u is in Queue Position (%u).", s->GetAccountId (), ++QueueSize);
238  return;
239  }
240 
241  WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
242  packet << uint8 (AUTH_OK);
243  packet << uint32 (0); // BillingTimeRemaining
244  packet << uint8 (0); // BillingPlanFlags
245  packet << uint32 (0); // BillingTimeRested
246  packet << uint8 (s->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
247  s->SendPacket (&packet);
248 
250 
251  // Updates the population
252  if (pLimit > 0)
253  {
254  float popu = GetActiveSessionCount (); // updated number of users on the server
255  popu /= pLimit;
256  popu *= 2;
257  LoginDatabase.PExecute ("UPDATE realmlist SET population = '%f' WHERE id = '%d'", popu, realmID);
258  sLog.outDetail ("Server Population (%f).", popu);
259  }
260 }
261 
263 {
264  if (!session) return false;
265 
267  {
268  for (DisconnectMap::iterator i = m_disconnects.begin(); i != m_disconnects.end();)
269  {
270  if (difftime(i->second, time(NULL)) < tolerance)
271  {
272  if (i->first == session->GetAccountId())
273  return true;
274  ++i;
275  }
276  else
277  i = m_disconnects.erase(i++);
278  }
279  }
280  return false;
281 }
282 
284 {
285  uint32 position = 1;
286 
287  for (Queue::iterator iter = m_QueuedPlayer.begin(); iter != m_QueuedPlayer.end(); ++iter, ++position)
288  if ((*iter) == sess)
289  return position;
290 
291  return 0;
292 }
293 
295 {
296  sess->SetInQueue(true);
297  m_QueuedPlayer.push_back(sess);
298 
299  // The 1st SMSG_AUTH_RESPONSE needs to contain other info too.
300  WorldPacket packet(SMSG_AUTH_RESPONSE, 1 + 4 + 1 + 4 + 1);
301  packet << uint8(AUTH_WAIT_QUEUE);
302  packet << uint32(0); // BillingTimeRemaining
303  packet << uint8(0); // BillingPlanFlags
304  packet << uint32(0); // BillingTimeRested
305  packet << uint8(sess->Expansion()); // 0 - normal, 1 - TBC, must be set in database manually for each account
306  packet << uint32(GetQueuePos(sess)); // Queue position
307  sess->SendPacket(&packet);
308 
309  //sess->SendAuthWaitQue (GetQueuePos (sess));
310 }
311 
313 {
314  // sessions count including queued to remove (if removed_session set)
315  uint32 sessions = GetActiveSessionCount();
316 
317  uint32 position = 1;
318  Queue::iterator iter = m_QueuedPlayer.begin();
319 
320  // search to remove and count skipped positions
321  bool found = false;
322 
323  for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
324  {
325  if (*iter == sess)
326  {
327  sess->SetInQueue(false);
328  iter = m_QueuedPlayer.erase(iter);
329  found = true; // removing queued session
330  break;
331  }
332  }
333 
334  // iter point to next socked after removed or end()
335  // position store position of removed socket and then new position next socket after removed
336 
337  // if session not queued then we need decrease sessions count
338  if (!found && sessions)
339  --sessions;
340 
341  // accept first in queue
342  if ((!m_playerLimit || sessions < uint32(m_playerLimit)) && !m_QueuedPlayer.empty())
343  {
344  WorldSession* pop_sess = m_QueuedPlayer.front();
345  pop_sess->SetInQueue(false);
346  pop_sess->SendAuthWaitQue(0);
347  m_QueuedPlayer.pop_front();
348 
349  // update iter to point first queued socket or end() if queue is empty now
350  iter = m_QueuedPlayer.begin();
351  position = 1;
352  }
353 
354  // update position from iter to end()
355  // iter point to first not updated socket, position store new position
356  for (; iter != m_QueuedPlayer.end(); ++iter, ++position)
357  (*iter)->SendAuthWaitQue(position);
358 
359  return found;
360 }
361 
362 // Find a Weather object by the given zoneid
364 {
365  WeatherMap::const_iterator itr = m_weathers.find(id);
366 
367  if (itr != m_weathers.end())
368  return itr->second;
369  else
370  return 0;
371 }
372 
373 // Remove a Weather object for the given zoneid
375 {
376  // not called at the moment. Kept for completeness
377  WeatherMap::iterator itr = m_weathers.find(id);
378 
379  if (itr != m_weathers.end())
380  {
381  delete itr->second;
382  m_weathers.erase(itr);
383  }
384 }
385 
386 // Add a Weather object to the list
388 {
389  WeatherZoneChances const* weatherChances = sObjectMgr.GetWeatherChances(zone_id);
390 
391  // zone not have weather, ignore
392  if (!weatherChances)
393  return NULL;
394 
395  Weather* w = new Weather(zone_id, weatherChances);
396  m_weathers[w->GetZone()] = w;
397  w->ReGenerate();
398  w->UpdateWeather();
399  return w;
400 }
401 
402 // Initialize config values
403 void World::LoadConfigSettings(bool reload)
404 {
405  if (reload)
406  {
407  if (!sConfig.Reload())
408  {
409  sLog.outError("World settings reload fail: can't read settings from %s.", sConfig.GetFilename().c_str());
410  return;
411  }
412  }
413 
414  // Read the player limit and the Message of the day from the config file
415  SetPlayerLimit(sConfig.GetIntDefault("PlayerLimit", DEFAULT_PLAYER_LIMIT), true);
416  SetMotd(sConfig.GetStringDefault("Motd", "Welcome to a Oregon Core Server."));
417 
418  // Get string for new logins (newly created characters)
419  SetNewCharString(sConfig.GetStringDefault("PlayerStart.String", ""));
420 
421  // Send server info on login?
422  m_configs[CONFIG_ENABLE_SINFO_LOGIN] = sConfig.GetIntDefault("Server.LoginInfo", 0);
423 
424  // Read all rates from the config file
425  rate_values[RATE_HEALTH] = sConfig.GetFloatDefault("Rate.Health", 1);
426  if (rate_values[RATE_HEALTH] < 0)
427  {
428  sLog.outError("Rate.Health (%f) must be > 0. Using 1 instead.", rate_values[RATE_HEALTH]);
430  }
431  rate_values[RATE_POWER_MANA] = sConfig.GetFloatDefault("Rate.Mana", 1);
432  if (rate_values[RATE_POWER_MANA] < 0)
433  {
434  sLog.outError("Rate.Mana (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_MANA]);
436  }
437  rate_values[RATE_POWER_RAGE_INCOME] = sConfig.GetFloatDefault("Rate.Rage.Income", 1);
438  rate_values[RATE_POWER_RAGE_LOSS] = sConfig.GetFloatDefault("Rate.Rage.Loss", 1);
440  {
441  sLog.outError("Rate.Rage.Loss (%f) must be > 0. Using 1 instead.", rate_values[RATE_POWER_RAGE_LOSS]);
443  }
444  rate_values[RATE_POWER_FOCUS] = sConfig.GetFloatDefault("Rate.Focus", 1.0f);
445  rate_values[RATE_POWER_ENERGY] = sConfig.GetFloatDefault("Rate.Energy", 1.0f);
446  rate_values[RATE_LOYALTY] = sConfig.GetFloatDefault("Rate.Loyalty", 1.0f);
447  rate_values[RATE_SKILL_DISCOVERY] = sConfig.GetFloatDefault("Rate.Skill.Discovery", 1.0f);
448  rate_values[RATE_DROP_ITEM_POOR] = sConfig.GetFloatDefault("Rate.Drop.Item.Poor", 1.0f);
449  rate_values[RATE_DROP_ITEM_NORMAL] = sConfig.GetFloatDefault("Rate.Drop.Item.Normal", 1.0f);
450  rate_values[RATE_DROP_ITEM_UNCOMMON] = sConfig.GetFloatDefault("Rate.Drop.Item.Uncommon", 1.0f);
451  rate_values[RATE_DROP_ITEM_RARE] = sConfig.GetFloatDefault("Rate.Drop.Item.Rare", 1.0f);
452  rate_values[RATE_DROP_ITEM_EPIC] = sConfig.GetFloatDefault("Rate.Drop.Item.Epic", 1.0f);
453  rate_values[RATE_DROP_ITEM_LEGENDARY] = sConfig.GetFloatDefault("Rate.Drop.Item.Legendary", 1.0f);
454  rate_values[RATE_DROP_ITEM_ARTIFACT] = sConfig.GetFloatDefault("Rate.Drop.Item.Artifact", 1.0f);
455  rate_values[RATE_DROP_ITEM_REFERENCED] = sConfig.GetFloatDefault("Rate.Drop.Item.Referenced", 1.0f);
456  rate_values[RATE_DROP_MONEY] = sConfig.GetFloatDefault("Rate.Drop.Money", 1.0f);
457  rate_values[RATE_XP_KILL] = sConfig.GetFloatDefault("Rate.XP.Kill", 1.0f);
458  rate_values[RATE_XP_QUEST] = sConfig.GetFloatDefault("Rate.XP.Quest", 1.0f);
459  rate_values[RATE_XP_EXPLORE] = sConfig.GetFloatDefault("Rate.XP.Explore", 1.0f);
460  rate_values[RATE_XP_PAST_70] = sConfig.GetFloatDefault("Rate.XP.PastLevel70", 1.0f);
461  rate_values[RATE_REPUTATION_GAIN] = sConfig.GetFloatDefault("Rate.Reputation.Gain", 1.0f);
462  rate_values[RATE_CREATURE_NORMAL_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.Damage", 1.0f);
463  rate_values[RATE_CREATURE_ELITE_ELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.Damage", 1.0f);
464  rate_values[RATE_CREATURE_ELITE_RAREELITE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RAREELITE.Damage", 1.0f);
465  rate_values[RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.Damage", 1.0f);
466  rate_values[RATE_CREATURE_ELITE_RARE_DAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RARE.Damage", 1.0f);
467  rate_values[RATE_CREATURE_NORMAL_HP] = sConfig.GetFloatDefault("Rate.Creature.Normal.HP", 1.0f);
468  rate_values[RATE_CREATURE_ELITE_ELITE_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.HP", 1.0f);
469  rate_values[RATE_CREATURE_ELITE_RAREELITE_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.RAREELITE.HP", 1.0f);
470  rate_values[RATE_CREATURE_ELITE_WORLDBOSS_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.HP", 1.0f);
471  rate_values[RATE_CREATURE_ELITE_RARE_HP] = sConfig.GetFloatDefault("Rate.Creature.Elite.RARE.HP", 1.0f);
472  rate_values[RATE_CREATURE_NORMAL_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Normal.SpellDamage", 1.0f);
473  rate_values[RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.Elite.SpellDamage", 1.0f);
474  rate_values[RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RAREELITE.SpellDamage", 1.0f);
475  rate_values[RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.WORLDBOSS.SpellDamage", 1.0f);
476  rate_values[RATE_CREATURE_ELITE_RARE_SPELLDAMAGE] = sConfig.GetFloatDefault("Rate.Creature.Elite.RARE.SpellDamage", 1.0f);
477  rate_values[RATE_CREATURE_AGGRO] = sConfig.GetFloatDefault("Rate.Creature.Aggro", 1.0f);
478  rate_values[RATE_REST_INGAME] = sConfig.GetFloatDefault("Rate.Rest.InGame", 1.0f);
479  rate_values[RATE_REST_OFFLINE_IN_TAVERN_OR_CITY] = sConfig.GetFloatDefault("Rate.Rest.Offline.InTavernOrCity", 1.0f);
480  rate_values[RATE_REST_OFFLINE_IN_WILDERNESS] = sConfig.GetFloatDefault("Rate.Rest.Offline.InWilderness", 1.0f);
481  rate_values[RATE_DAMAGE_FALL] = sConfig.GetFloatDefault("Rate.Damage.Fall", 1.0f);
482  rate_values[RATE_AUCTION_TIME] = sConfig.GetFloatDefault("Rate.Auction.Time", 1.0f);
483  rate_values[RATE_AUCTION_DEPOSIT] = sConfig.GetFloatDefault("Rate.Auction.Deposit", 1.0f);
484  rate_values[RATE_AUCTION_CUT] = sConfig.GetFloatDefault("Rate.Auction.Cut", 1.0f);
485  rate_values[RATE_HONOR] = sConfig.GetFloatDefault("Rate.Honor", 1.0f);
486  rate_values[RATE_MINING_AMOUNT] = sConfig.GetFloatDefault("Rate.Mining.Amount", 1.0f);
487  rate_values[RATE_MINING_NEXT] = sConfig.GetFloatDefault("Rate.Mining.Next", 1.0f);
488  rate_values[RATE_INSTANCE_RESET_TIME] = sConfig.GetFloatDefault("Rate.InstanceResetTime", 1.0f);
489  rate_values[RATE_TALENT] = sConfig.GetFloatDefault("Rate.Talent", 1.0f);
490  if (rate_values[RATE_TALENT] < 0.0f)
491  {
492  sLog.outError("Rate.Talent (%f) must be > 0. Using 1 instead.", rate_values[RATE_TALENT]);
493  rate_values[RATE_TALENT] = 1.0f;
494  }
495  rate_values[RATE_RAF_BONUS_XP] = sConfig.GetIntDefault("RAF.BonusXPGain", 3);
496  if (rate_values[RATE_TALENT] < 0.0f)
497  {
498  sLog.outError("RAF.BonusXPGain (%f) must be > 0. Using 3 instead.", rate_values[RATE_RAF_BONUS_XP]);
500  }
501  rate_values[RATE_RAF_GRANTABLE_LEVELS_PER_LEVEL] = std::max<float>(0.f, sConfig.GetFloatDefault("RAF.GrantableLevelsPerLevel", .5f));
502  rate_values[RATE_CORPSE_DECAY_LOOTED] = sConfig.GetFloatDefault("Rate.Corpse.Decay.Looted", 0.5f);
503 
504  rate_values[RATE_TARGET_POS_RECALCULATION_RANGE] = sConfig.GetFloatDefault("TargetPosRecalculateRange", 1.5f);
506  {
507  sLog.outError("TargetPosRecalculateRange (%f) must be >= %f. Using %f instead.", rate_values[RATE_TARGET_POS_RECALCULATION_RANGE], CONTACT_DISTANCE, CONTACT_DISTANCE);
509  }
511  {
512  sLog.outError("TargetPosRecalculateRange (%f) must be <= %f. Using %f instead.",
515  }
516 
517  rate_values[RATE_DURABILITY_LOSS_DAMAGE] = sConfig.GetFloatDefault("DurabilityLossChance.Damage", 0.5f);
518  if (rate_values[RATE_DURABILITY_LOSS_DAMAGE] < 0.0f)
519  {
520  sLog.outError("DurabilityLossChance.Damage (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_DAMAGE]);
521  rate_values[RATE_DURABILITY_LOSS_DAMAGE] = 0.0f;
522  }
523  rate_values[RATE_DURABILITY_LOSS_ABSORB] = sConfig.GetFloatDefault("DurabilityLossChance.Absorb", 0.5f);
524  if (rate_values[RATE_DURABILITY_LOSS_ABSORB] < 0.0f)
525  {
526  sLog.outError("DurabilityLossChance.Absorb (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_ABSORB]);
527  rate_values[RATE_DURABILITY_LOSS_ABSORB] = 0.0f;
528  }
529  rate_values[RATE_DURABILITY_LOSS_PARRY] = sConfig.GetFloatDefault("DurabilityLossChance.Parry", 0.05f);
530  if (rate_values[RATE_DURABILITY_LOSS_PARRY] < 0.0f)
531  {
532  sLog.outError("DurabilityLossChance.Parry (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_PARRY]);
533  rate_values[RATE_DURABILITY_LOSS_PARRY] = 0.0f;
534  }
535  rate_values[RATE_DURABILITY_LOSS_BLOCK] = sConfig.GetFloatDefault("DurabilityLossChance.Block", 0.05f);
536  if (rate_values[RATE_DURABILITY_LOSS_BLOCK] < 0.0f)
537  {
538  sLog.outError("DurabilityLossChance.Block (%f) must be >=0. Using 0.0 instead.", rate_values[RATE_DURABILITY_LOSS_BLOCK]);
539  rate_values[RATE_DURABILITY_LOSS_BLOCK] = 0.0f;
540  }
541 
542  // Read other configuration items from the config file
543 
544  m_configs[CONFIG_COMPRESSION] = sConfig.GetIntDefault("Compression", 1);
545  if (m_configs[CONFIG_COMPRESSION] < 1 || m_configs[CONFIG_COMPRESSION] > 9)
546  {
547  sLog.outError("Compression level (%i) must be in range 1..9. Using default compression level (1).", m_configs[CONFIG_COMPRESSION]);
548  m_configs[CONFIG_COMPRESSION] = 1;
549  }
550  m_configs[CONFIG_ADDON_CHANNEL] = sConfig.GetBoolDefault("AddonChannel", true);
551  m_configs[CONFIG_GRID_UNLOAD] = sConfig.GetBoolDefault("GridUnload", true);
552  m_configs[CONFIG_INTERVAL_SAVE] = sConfig.GetIntDefault("PlayerSaveInterval", 900000);
553  m_configs[CONFIG_INTERVAL_DISCONNECT_TOLERANCE] = sConfig.GetIntDefault("DisconnectToleranceInterval", 0);
554 
555  m_configs[CONFIG_INTERVAL_GRIDCLEAN] = sConfig.GetIntDefault("GridCleanUpDelay", 60000);
556  //if (m_configs[CONFIG_INTERVAL_GRIDCLEAN] < MIN_GRID_DELAY)
557  //{
558  // sLog.outError("GridCleanUpDelay (%i) must be greater %u. Use this minimal value.", m_configs[CONFIG_INTERVAL_GRIDCLEAN], MIN_GRID_DELAY);
559  // m_configs[CONFIG_INTERVAL_GRIDCLEAN] = MIN_GRID_DELAY;
560  //}
561  if (reload)
563 
564  m_configs[CONFIG_INTERVAL_MAPUPDATE] = sConfig.GetIntDefault("MapUpdateInterval", 100);
566  {
567  sLog.outError("MapUpdateInterval (%i) must be greater %u. Use this minimal value.", m_configs[CONFIG_INTERVAL_MAPUPDATE], MIN_MAP_UPDATE_DELAY);
569  }
570  if (reload)
572 
573  m_configs[CONFIG_INTERVAL_CHANGEWEATHER] = sConfig.GetIntDefault("ChangeWeatherInterval", 10 * MINUTE * IN_MILLISECONDS);
574 
575  if (reload)
576  {
577  uint32 val = sConfig.GetIntDefault("WorldServerPort", DEFAULT_WORLDSERVER_PORT);
578  if (val != m_configs[CONFIG_PORT_WORLD])
579  sLog.outError("WorldServerPort option can't be changed at Oregond.conf reload, using current value (%u).", m_configs[CONFIG_PORT_WORLD]);
580  }
581  else
582  m_configs[CONFIG_PORT_WORLD] = sConfig.GetIntDefault("WorldServerPort", DEFAULT_WORLDSERVER_PORT);
583 
584  if (reload)
585  {
586  uint32 val = sConfig.GetIntDefault("SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME);
587  if (val != m_configs[CONFIG_SOCKET_SELECTTIME])
588  sLog.outError("SocketSelectTime option can't be changed at Oregond.conf reload, using current value (%u).", m_configs[CONFIG_SOCKET_SELECTTIME]);
589  }
590  else
591  m_configs[CONFIG_SOCKET_SELECTTIME] = sConfig.GetIntDefault("SocketSelectTime", DEFAULT_SOCKET_SELECT_TIME);
592 
593  m_configs[CONFIG_SOCKET_TIMEOUTTIME] = sConfig.GetIntDefault("SocketTimeOutTime", 900000);
594  m_configs[CONFIG_SESSION_ADD_DELAY] = sConfig.GetIntDefault("SessionAddDelay", 10000);
595 
596  m_configs[CONFIG_GROUP_XP_DISTANCE] = sConfig.GetIntDefault("MaxGroupXPDistance", 74);
597  // todo Add MonsterSight and GuarderSight (with meaning) in Oregond.conf or put them as define
598  m_configs[CONFIG_SIGHT_MONSTER] = sConfig.GetIntDefault("MonsterSight", 50);
599  m_configs[CONFIG_SIGHT_GUARDER] = sConfig.GetIntDefault("GuarderSight", 50);
600 
601  if (reload)
602  {
603  uint32 val = sConfig.GetIntDefault("GameType", 0);
604  if (val != m_configs[CONFIG_GAME_TYPE])
605  sLog.outError("GameType option can't be changed at Oregond.conf reload, using current value (%u).", m_configs[CONFIG_GAME_TYPE]);
606  }
607  else
608  m_configs[CONFIG_GAME_TYPE] = sConfig.GetIntDefault("GameType", 0);
609 
610  if (reload)
611  {
612  uint32 val = sConfig.GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
613  if (val != m_configs[CONFIG_REALM_ZONE])
614  sLog.outError("RealmZone option can't be changed at Oregond.conf reload, using current value (%u).", m_configs[CONFIG_REALM_ZONE]);
615  }
616  else
617  m_configs[CONFIG_REALM_ZONE] = sConfig.GetIntDefault("RealmZone", REALM_ZONE_DEVELOPMENT);
618 
619  m_configs[CONFIG_ALLOW_TWO_SIDE_ACCOUNTS] = sConfig.GetBoolDefault("AllowTwoSide.Accounts", false);
620  m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Chat", false);
621  m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Channel", false);
622  m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Group", false);
623  m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Guild", false);
624  m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Auction", false);
625  m_configs[CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL] = sConfig.GetBoolDefault("AllowTwoSide.Interaction.Mail", false);
626  m_configs[CONFIG_ALLOW_TWO_SIDE_WHO_LIST] = sConfig.GetBoolDefault("AllowTwoSide.WhoList", false);
627  m_configs[CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND] = sConfig.GetBoolDefault("AllowTwoSide.AddFriend", false);
628  m_configs[CONFIG_ALLOW_TWO_SIDE_TRADE] = sConfig.GetBoolDefault("AllowTwoSide.trade", false);
629  m_configs[CONFIG_STRICT_PLAYER_NAMES] = sConfig.GetIntDefault ("StrictPlayerNames", 0);
630  m_configs[CONFIG_STRICT_CHARTER_NAMES] = sConfig.GetIntDefault ("StrictCharterNames", 0);
631  m_configs[CONFIG_STRICT_PET_NAMES] = sConfig.GetIntDefault ("StrictPetNames", 0);
632 
633  m_configs[CONFIG_CHARACTERS_CREATING_DISABLED] = sConfig.GetIntDefault ("CharactersCreatingDisabled", 0);
634 
635  m_configs[CONFIG_CHARACTERS_PER_REALM] = sConfig.GetIntDefault("CharactersPerRealm", 10);
636  if (m_configs[CONFIG_CHARACTERS_PER_REALM] < 1 || m_configs[CONFIG_CHARACTERS_PER_REALM] > 10)
637  {
638  sLog.outError("CharactersPerRealm (%i) must be in range 1..10. Set to 10.", m_configs[CONFIG_CHARACTERS_PER_REALM]);
639  m_configs[CONFIG_CHARACTERS_PER_REALM] = 10;
640  }
641 
642  // must be after CONFIG_CHARACTERS_PER_REALM
643  m_configs[CONFIG_CHARACTERS_PER_ACCOUNT] = sConfig.GetIntDefault("CharactersPerAccount", 50);
645  {
646  sLog.outError("CharactersPerAccount (%i) can't be less than CharactersPerRealm (%i).", m_configs[CONFIG_CHARACTERS_PER_ACCOUNT], m_configs[CONFIG_CHARACTERS_PER_REALM]);
648  }
649 
650  m_configs[CONFIG_SKIP_CINEMATICS] = sConfig.GetIntDefault("SkipCinematics", 0);
651  if (int32(m_configs[CONFIG_SKIP_CINEMATICS]) < 0 || m_configs[CONFIG_SKIP_CINEMATICS] > 2)
652  {
653  sLog.outError("SkipCinematics (%i) must be in range 0..2. Set to 0.", m_configs[CONFIG_SKIP_CINEMATICS]);
654  m_configs[CONFIG_SKIP_CINEMATICS] = 0;
655  }
656 
657  if (reload)
658  {
659  uint32 val = sConfig.GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
660  if (val != m_configs[CONFIG_MAX_PLAYER_LEVEL])
661  sLog.outError("MaxPlayerLevel option can't be changed at config reload, using current value (%u).", m_configs[CONFIG_MAX_PLAYER_LEVEL]);
662  }
663  else
664  m_configs[CONFIG_MAX_PLAYER_LEVEL] = sConfig.GetIntDefault("MaxPlayerLevel", DEFAULT_MAX_LEVEL);
665 
666  if (m_configs[CONFIG_MAX_PLAYER_LEVEL] > MAX_LEVEL)
667  {
668  sLog.outError("MaxPlayerLevel (%i) must be in range 1..%u. Set to %u.", m_configs[CONFIG_MAX_PLAYER_LEVEL], MAX_LEVEL, MAX_LEVEL);
669  m_configs[CONFIG_MAX_PLAYER_LEVEL] = MAX_LEVEL;
670  }
671 
672  m_configs[CONFIG_START_PLAYER_LEVEL] = sConfig.GetIntDefault("StartPlayerLevel", 1);
673  if (m_configs[CONFIG_START_PLAYER_LEVEL] < 1)
674  {
675  sLog.outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to 1.", m_configs[CONFIG_START_PLAYER_LEVEL], m_configs[CONFIG_MAX_PLAYER_LEVEL]);
676  m_configs[CONFIG_START_PLAYER_LEVEL] = 1;
677  }
678  else if (m_configs[CONFIG_START_PLAYER_LEVEL] > m_configs[CONFIG_MAX_PLAYER_LEVEL])
679  {
680  sLog.outError("StartPlayerLevel (%i) must be in range 1..MaxPlayerLevel(%u). Set to %u.", m_configs[CONFIG_START_PLAYER_LEVEL], m_configs[CONFIG_MAX_PLAYER_LEVEL], m_configs[CONFIG_MAX_PLAYER_LEVEL]);
681  m_configs[CONFIG_START_PLAYER_LEVEL] = m_configs[CONFIG_MAX_PLAYER_LEVEL];
682  }
683 
684  m_configs[CONFIG_START_PLAYER_MONEY] = sConfig.GetIntDefault("StartPlayerMoney", 0);
685  if (int32(m_configs[CONFIG_START_PLAYER_MONEY]) < 0)
686  {
687  sLog.outError("StartPlayerMoney (%i) must be in range 0..%u. Set to %u.", m_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, 0);
688  m_configs[CONFIG_START_PLAYER_MONEY] = 0;
689  }
690  else if (m_configs[CONFIG_START_PLAYER_MONEY] > MAX_MONEY_AMOUNT)
691  {
692  sLog.outError("StartPlayerMoney (%i) must be in range 0..%u. Set to %u.",
693  m_configs[CONFIG_START_PLAYER_MONEY], MAX_MONEY_AMOUNT, MAX_MONEY_AMOUNT);
695  }
696 
697  m_configs[CONFIG_MAX_HONOR_POINTS] = sConfig.GetIntDefault("MaxHonorPoints", 75000);
698  if (int32(m_configs[CONFIG_MAX_HONOR_POINTS]) < 0)
699  {
700  sLog.outError("MaxHonorPoints (%i) can't be negative. Set to 0.", m_configs[CONFIG_MAX_HONOR_POINTS]);
701  m_configs[CONFIG_MAX_HONOR_POINTS] = 0;
702  }
703 
704  m_configs[CONFIG_START_HONOR_POINTS] = sConfig.GetIntDefault("StartHonorPoints", 0);
705  if (int32(m_configs[CONFIG_START_HONOR_POINTS]) < 0)
706  {
707  sLog.outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
708  m_configs[CONFIG_START_HONOR_POINTS], m_configs[CONFIG_MAX_HONOR_POINTS], 0);
709  m_configs[CONFIG_START_HONOR_POINTS] = 0;
710  }
711  else if (m_configs[CONFIG_START_HONOR_POINTS] > m_configs[CONFIG_MAX_HONOR_POINTS])
712  {
713  sLog.outError("StartHonorPoints (%i) must be in range 0..MaxHonorPoints(%u). Set to %u.",
714  m_configs[CONFIG_START_HONOR_POINTS], m_configs[CONFIG_MAX_HONOR_POINTS], m_configs[CONFIG_MAX_HONOR_POINTS]);
715  m_configs[CONFIG_START_HONOR_POINTS] = m_configs[CONFIG_MAX_HONOR_POINTS];
716  }
717 
718  m_configs[CONFIG_MAX_ARENA_POINTS] = sConfig.GetIntDefault("MaxArenaPoints", 5000);
719  if (int32(m_configs[CONFIG_MAX_ARENA_POINTS]) < 0)
720  {
721  sLog.outError("MaxArenaPoints (%i) can't be negative. Set to 0.", m_configs[CONFIG_MAX_ARENA_POINTS]);
722  m_configs[CONFIG_MAX_ARENA_POINTS] = 0;
723  }
724 
725  m_configs[CONFIG_START_ARENA_POINTS] = sConfig.GetIntDefault("StartArenaPoints", 0);
726  if (int32(m_configs[CONFIG_START_ARENA_POINTS]) < 0)
727  {
728  sLog.outError("StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
729  m_configs[CONFIG_START_ARENA_POINTS], m_configs[CONFIG_MAX_ARENA_POINTS], 0);
730  m_configs[CONFIG_START_ARENA_POINTS] = 0;
731  }
732  else if (m_configs[CONFIG_START_ARENA_POINTS] > m_configs[CONFIG_MAX_ARENA_POINTS])
733  {
734  sLog.outError("StartArenaPoints (%i) must be in range 0..MaxArenaPoints(%u). Set to %u.",
735  m_configs[CONFIG_START_ARENA_POINTS], m_configs[CONFIG_MAX_ARENA_POINTS], m_configs[CONFIG_MAX_ARENA_POINTS]);
736  m_configs[CONFIG_START_ARENA_POINTS] = m_configs[CONFIG_MAX_ARENA_POINTS];
737  }
738 
739  // Custom Flight Path Config Options
740  m_configs[CONFIG_ALL_TAXI_PATHS] = sConfig.GetBoolDefault("AllFlightPaths", false);
741  m_configs[CONFIG_INSTANT_TAXI] = sConfig.GetBoolDefault("InstantFlightPaths", false);
742 
743  m_configs[CONFIG_INSTANCE_IGNORE_LEVEL] = sConfig.GetBoolDefault("Instance.IgnoreLevel", false);
744  m_configs[CONFIG_INSTANCE_IGNORE_RAID] = sConfig.GetBoolDefault("Instance.IgnoreRaid", false);
745 
746  m_configs[CONFIG_CAST_UNSTUCK] = sConfig.GetBoolDefault("CastUnstuck", true);
747  m_configs[CONFIG_INSTANCE_RESET_TIME_HOUR] = sConfig.GetIntDefault("Instance.ResetTimeHour", 4);
748  m_configs[CONFIG_INSTANCE_UNLOAD_DELAY] = sConfig.GetIntDefault("Instance.UnloadDelay", 30 * MINUTE * IN_MILLISECONDS);
749 
750  m_configs[CONFIG_MAX_PRIMARY_TRADE_SKILL] = sConfig.GetIntDefault("MaxPrimaryTradeSkill", 2);
751  m_configs[CONFIG_MIN_PETITION_SIGNS] = sConfig.GetIntDefault("MinPetitionSigns", 9);
752  if (m_configs[CONFIG_MIN_PETITION_SIGNS] > 9)
753  {
754  sLog.outError("MinPetitionSigns (%i) must be in range 0..9. Set to 9.", m_configs[CONFIG_MIN_PETITION_SIGNS]);
755  m_configs[CONFIG_MIN_PETITION_SIGNS] = 9;
756  }
757 
758  m_configs[CONFIG_GM_LOGIN_STATE] = sConfig.GetIntDefault("GM.LoginState", 2);
759  m_configs[CONFIG_GM_VISIBLE_STATE] = sConfig.GetIntDefault("GM.Visible", 2);
760  m_configs[CONFIG_GM_CHAT] = sConfig.GetIntDefault("GM.Chat", 2);
761  m_configs[CONFIG_GM_WISPERING_TO] = sConfig.GetIntDefault("GM.WhisperingTo", 2);
762  m_configs[CONFIG_GM_IN_GM_LIST] = sConfig.GetBoolDefault("GM.InGMList", false);
763  m_configs[CONFIG_GM_IN_WHO_LIST] = sConfig.GetBoolDefault("GM.InWhoList", false);
764  m_configs[CONFIG_GM_MAIL] = sConfig.GetBoolDefault("GM.Mail", false);
765  m_configs[CONFIG_GM_LOG_TRADE] = sConfig.GetBoolDefault("GM.LogTrade", false);
766  m_configs[CONFIG_START_GM_LEVEL] = sConfig.GetIntDefault("GM.StartLevel", 1);
767  m_configs[CONFIG_ALLOW_GM_GROUP] = sConfig.GetBoolDefault("GM.AllowInvite", false);
768  m_configs[CONFIG_ALLOW_GM_FRIEND] = sConfig.GetBoolDefault("GM.AllowFriend", false);
769  if (m_configs[CONFIG_START_GM_LEVEL] < m_configs[CONFIG_START_PLAYER_LEVEL])
770  {
771  sLog.outError("GM.StartLevel (%i) must be in range StartPlayerLevel(%u)..%u. Set to %u.",
772  m_configs[CONFIG_START_GM_LEVEL], m_configs[CONFIG_START_PLAYER_LEVEL], MAX_LEVEL, m_configs[CONFIG_START_PLAYER_LEVEL]);
773  m_configs[CONFIG_START_GM_LEVEL] = m_configs[CONFIG_START_PLAYER_LEVEL];
774  }
775  else if (m_configs[CONFIG_START_GM_LEVEL] > MAX_LEVEL)
776  {
777  sLog.outError("GM.StartLevel (%i) must be in range 1..%u. Set to %u.", m_configs[CONFIG_START_GM_LEVEL], MAX_LEVEL, MAX_LEVEL);
778  m_configs[CONFIG_START_GM_LEVEL] = MAX_LEVEL;
779  }
780 
781  m_configs[CONFIG_CHANCE_OF_GM_SURVEY] = sConfig.GetFloatDefault("GM.TicketSystem.ChanceOfGMSurvey", 0.0f);
782 
783  m_configs[CONFIG_GROUP_VISIBILITY] = sConfig.GetIntDefault("Visibility.GroupMode", 1);
784 
785  m_configs[CONFIG_MAIL_DELIVERY_DELAY] = sConfig.GetIntDefault("MailDeliveryDelay", HOUR);
786 
787  m_configs[CONFIG_EXTERNAL_MAIL] = sConfig.GetIntDefault("ExternalMail", 0);
788  m_configs[CONFIG_EXTERNAL_MAIL_INTERVAL] = sConfig.GetIntDefault("ExternalMailInterval", 1);
789 
790  m_configs[CONFIG_UPTIME_UPDATE] = sConfig.GetIntDefault("UpdateUptimeInterval", 10);
791  if (int32(m_configs[CONFIG_UPTIME_UPDATE]) <= 0)
792  {
793  sLog.outError("UpdateUptimeInterval (%i) must be > 0, set to default 10.", m_configs[CONFIG_UPTIME_UPDATE]);
794  m_configs[CONFIG_UPTIME_UPDATE] = 10;
795  }
796  if (reload)
797  {
798  m_timers[WUPDATE_UPTIME].SetInterval(m_configs[CONFIG_UPTIME_UPDATE]*MINUTE * IN_MILLISECONDS);
800  }
801 
802  // log db cleanup interval
803  m_configs[CONFIG_LOGDB_CLEARINTERVAL] = sConfig.GetIntDefault("LogDB.Opt.ClearInterval", 10);
804  if (int32(m_configs[CONFIG_LOGDB_CLEARINTERVAL]) <= 0)
805  {
806  sLog.outError("LogDB.Opt.ClearInterval (%i) must be > 0, set to default 10.", m_configs[CONFIG_LOGDB_CLEARINTERVAL]);
807  m_configs[CONFIG_LOGDB_CLEARINTERVAL] = 10;
808  }
809  if (reload)
810  {
811  m_timers[WUPDATE_CLEANDB].SetInterval(m_configs[CONFIG_LOGDB_CLEARINTERVAL] * MINUTE * IN_MILLISECONDS);
813  }
814  m_configs[CONFIG_LOGDB_CLEARTIME] = sConfig.GetIntDefault("LogDB.Opt.ClearTime", 1209600); // 14 days default
815  sLog.outString("Will clear `logs` table of entries older than %i seconds every %u minutes.",
816  m_configs[CONFIG_LOGDB_CLEARTIME], m_configs[CONFIG_LOGDB_CLEARINTERVAL]);
817 
818  m_configs[CONFIG_SKILL_CHANCE_ORANGE] = sConfig.GetIntDefault("SkillChance.Orange", 100);
819  m_configs[CONFIG_SKILL_CHANCE_YELLOW] = sConfig.GetIntDefault("SkillChance.Yellow", 75);
820  m_configs[CONFIG_SKILL_CHANCE_GREEN] = sConfig.GetIntDefault("SkillChance.Green", 25);
821  m_configs[CONFIG_SKILL_CHANCE_GREY] = sConfig.GetIntDefault("SkillChance.Grey", 0);
822 
823  m_configs[CONFIG_SKILL_CHANCE_MINING_STEPS] = sConfig.GetIntDefault("SkillChance.MiningSteps", 75);
824  m_configs[CONFIG_SKILL_CHANCE_SKINNING_STEPS] = sConfig.GetIntDefault("SkillChance.SkinningSteps", 75);
825 
826  m_configs[CONFIG_SKILL_PROSPECTING] = sConfig.GetBoolDefault("SkillChance.Prospecting", false);
827 
828  m_configs[CONFIG_SKILL_GAIN_CRAFTING] = sConfig.GetIntDefault("SkillGain.Crafting", 1);
829  m_configs[CONFIG_SKILL_GAIN_DEFENSE] = sConfig.GetIntDefault("SkillGain.Defense", 1);
830  m_configs[CONFIG_SKILL_GAIN_GATHERING] = sConfig.GetIntDefault("SkillGain.Gathering", 1);
831  m_configs[CONFIG_SKILL_GAIN_WEAPON] = sConfig.GetIntDefault("SkillGain.Weapon", 1);
832  m_configs[CONFIG_MAX_OVERSPEED_PINGS] = sConfig.GetIntDefault("MaxOverspeedPings", 2);
833  m_configs[CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY] = sConfig.GetBoolDefault("SaveRespawnTimeImmediately", true);
834  m_configs[CONFIG_WEATHER] = sConfig.GetBoolDefault("ActivateWeather", true);
835 
836  m_configs[CONFIG_DISABLE_BREATHING] = sConfig.GetIntDefault("DisableWaterBreath", SEC_CONSOLE);
837 
838  m_configs[CONFIG_ALWAYS_MAX_SKILL_FOR_LEVEL] = sConfig.GetBoolDefault("AlwaysMaxSkillForLevel", false);
839 
840  if (reload)
841  {
842  uint32 val = sConfig.GetIntDefault("Expansion", 1);
843  if (val != m_configs[CONFIG_EXPANSION])
844  sLog.outError("Expansion option can't be changed at Oregond.conf reload, using current value (%u).", m_configs[CONFIG_EXPANSION]);
845  }
846  else
847  m_configs[CONFIG_EXPANSION] = sConfig.GetIntDefault("Expansion", 1);
848 
849  m_configs[CONFIG_CHATFLOOD_MESSAGE_COUNT] = sConfig.GetIntDefault("ChatFlood.MessageCount", 10);
850  m_configs[CONFIG_CHATFLOOD_MESSAGE_DELAY] = sConfig.GetIntDefault("ChatFlood.MessageDelay", 1);
851  m_configs[CONFIG_CHATFLOOD_MUTE_TIME] = sConfig.GetIntDefault("ChatFlood.MuteTime", 10);
852 
853  m_configs[CONFIG_EVENT_ANNOUNCE] = sConfig.GetIntDefault("Event.Announce", 0);
854 
855  m_configs[CONFIG_CREATURE_PICKPOCKET_REFILL] = sConfig.GetIntDefault("Creature.PickPocketRefillDelay", 10 * MINUTE);
856 
857  m_configs[CONFIG_CREATURE_FAMILY_FLEE_ASSISTANCE_RADIUS] = sConfig.GetIntDefault("CreatureFamilyFleeAssistanceRadius", 30);
858  m_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_RADIUS] = sConfig.GetIntDefault("CreatureFamilyAssistanceRadius", 10);
859  m_configs[CONFIG_CREATURE_FAMILY_ASSISTANCE_DELAY] = sConfig.GetIntDefault("CreatureFamilyAssistanceDelay", 1500);
860  m_configs[CONFIG_CREATURE_FAMILY_FLEE_DELAY] = sConfig.GetIntDefault("CreatureFamilyFleeDelay", 7000);
861 
862  m_configs[CONFIG_WORLD_BOSS_LEVEL_DIFF] = sConfig.GetIntDefault("WorldBossLevelDiff", 3);
863 
864  // note: disable value (-1) will assigned as 0xFFFFFFF, to prevent overflow at calculations limit it to max possible player level MAX_LEVEL(100)
865  m_configs[CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.LowLevelHideDiff", 4);
868  m_configs[CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF] = sConfig.GetIntDefault("Quests.HighLevelHideDiff", 7);
871 
872  m_configs[CONFIG_DETECT_POS_COLLISION] = sConfig.GetBoolDefault("DetectPosCollision", true);
873 
874  m_configs[CONFIG_RESTRICTED_LFG_CHANNEL] = sConfig.GetBoolDefault("Channel.RestrictedLfg", true);
875  m_configs[CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL] = sConfig.GetBoolDefault("Channel.SilentlyGMJoin", false);
876 
877  m_configs[CONFIG_TALENTS_INSPECTING] = sConfig.GetBoolDefault("TalentsInspecting", true);
878  m_configs[CONFIG_CHAT_FAKE_MESSAGE_PREVENTING] = sConfig.GetBoolDefault("ChatFakeMessagePreventing", false);
879  m_configs[CONFIG_CHAT_STRICT_LINK_CHECKING_SEVERITY] = sConfig.GetIntDefault("ChatStrictLinkChecking.Severity", 0);
880  m_configs[CONFIG_CHAT_STRICT_LINK_CHECKING_KICK] = sConfig.GetIntDefault("ChatStrictLinkChecking.Kick", 0);
881 
882  m_configs[CONFIG_CORPSE_DECAY_NORMAL] = sConfig.GetIntDefault("Corpse.Decay.NORMAL", 60);
883  m_configs[CONFIG_CORPSE_DECAY_RARE] = sConfig.GetIntDefault("Corpse.Decay.RARE", 300);
884  m_configs[CONFIG_CORPSE_DECAY_ELITE] = sConfig.GetIntDefault("Corpse.Decay.ELITE", 300);
885  m_configs[CONFIG_CORPSE_DECAY_RAREELITE] = sConfig.GetIntDefault("Corpse.Decay.RAREELITE", 300);
886  m_configs[CONFIG_CORPSE_DECAY_WORLDBOSS] = sConfig.GetIntDefault("Corpse.Decay.WORLDBOSS", 3600);
887 
888  m_configs[CONFIG_DEATH_SICKNESS_LEVEL] = sConfig.GetIntDefault ("Death.SicknessLevel", 11);
889  m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvP", true);
890  m_configs[CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE] = sConfig.GetBoolDefault("Death.CorpseReclaimDelay.PvE", true);
891  m_configs[CONFIG_DEATH_BONES_WORLD] = sConfig.GetBoolDefault("Death.Bones.World", true);
892  m_configs[CONFIG_DEATH_BONES_BG_OR_ARENA] = sConfig.GetBoolDefault("Death.Bones.BattlegroundOrArena", true);
893 
894  m_configs[CONFIG_DIE_COMMAND_MODE] = sConfig.GetBoolDefault("Die.Command.Mode", true);
895 
896  m_configs[CONFIG_THREAT_RADIUS] = sConfig.GetIntDefault("ThreatRadius", 60);
897 
898  // always use declined names in the russian client
899  m_configs[CONFIG_DECLINED_NAMES_USED] =
900  (m_configs[CONFIG_REALM_ZONE] == REALM_ZONE_RUSSIAN) ? true : sConfig.GetBoolDefault("DeclinedNames", false);
901 
902  m_configs[CONFIG_LISTEN_RANGE_SAY] = sConfig.GetIntDefault("ListenRange.Say", 25);
903  m_configs[CONFIG_LISTEN_RANGE_TEXTEMOTE] = sConfig.GetIntDefault("ListenRange.TextEmote", 25);
904  m_configs[CONFIG_LISTEN_RANGE_YELL] = sConfig.GetIntDefault("ListenRange.Yell", 300);
905 
906  m_configs[CONFIG_BATTLEGROUND_CAST_DESERTER] = sConfig.GetBoolDefault("Battleground.CastDeserter", true);
907  m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.Enable", false);
908  m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.PlayerOnly", false);
909  m_configs[CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ONSTART] = sConfig.GetBoolDefault("Battleground.QueueAnnouncer.OnStart", false);
910  m_configs[CONFIG_BATTLEGROUND_PREMATURE_REWARD] = sConfig.GetBoolDefault("Battleground.PrematureReward", true);
911  m_configs[CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER] = sConfig.GetIntDefault("Battleground.PrematureFinishTimer", 5 * MINUTE * IN_MILLISECONDS);
912  m_configs[CONFIG_BATTLEGROUND_WRATH_LEAVE_MODE] = sConfig.GetBoolDefault("Battleground.LeaveWrathMode", false);
913  m_configs[CONFIG_ARENA_MAX_RATING_DIFFERENCE] = sConfig.GetIntDefault("Arena.MaxRatingDifference", 0);
914  m_configs[CONFIG_ARENA_RATING_DISCARD_TIMER] = sConfig.GetIntDefault("Arena.RatingDiscardTimer", 10 * MINUTE * IN_MILLISECONDS);
915  m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfig.GetBoolDefault("Arena.AutoDistributePoints", false);
916  m_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfig.GetIntDefault("Arena.AutoDistributeInterval", 7);
917  m_configs[CONFIG_ARENA_HIDE_FROM_SOCIAL] = sConfig.GetBoolDefault("Arena.HideFromSocial", false);
918  m_configs[CONFIG_ARENA_LOG_EXTENDED_INFO] = sConfig.GetBoolDefault("ArenaLogExtendedInfo", false);
919  m_configs[CONFIG_INSTANT_LOGOUT] = sConfig.GetIntDefault("InstantLogout", SEC_MODERATOR);
920 
921  //visibility on continents
922  m_MaxVisibleDistanceOnContinents = sConfig.GetFloatDefault("Visibility.Distance.Continents", DEFAULT_VISIBILITY_DISTANCE);
924  {
925  sLog.outError("Visibility.Distance.Continents can't be less max aggro radius %f", 45 * sWorld.getRate(RATE_CREATURE_AGGRO));
927  }
929  {
930  sLog.outError("Visibility.Distance.Continents can't be greater %f", MAX_VISIBILITY_DISTANCE);
932  }
933 
934  //visibility in instances
935  m_MaxVisibleDistanceInInstances = sConfig.GetFloatDefault("Visibility.Distance.Instances", DEFAULT_VISIBILITY_INSTANCE);
937  {
938  sLog.outError("Visibility.Distance.Instances can't be less max aggro radius %f", 45 * sWorld.getRate(RATE_CREATURE_AGGRO));
940  }
942  {
943  sLog.outError("Visibility.Distance.Instances can't be greater %f",MAX_VISIBILITY_DISTANCE);
945  }
946 
947  //visibility in BG/Arenas
948  m_MaxVisibleDistanceInBGArenas = sConfig.GetFloatDefault("Visibility.Distance.BGArenas", DEFAULT_VISIBILITY_BGARENAS);
950  {
951  sLog.outError("Visibility.Distance.BGArenas can't be less max aggro radius %f", 45 * sWorld.getRate(RATE_CREATURE_AGGRO));
953  }
955  {
956  sLog.outError("Visibility.Distance.BGArenas can't be greater %f",MAX_VISIBILITY_DISTANCE);
958  }
959 
961  m_configs[CONFIG_CHARDELETE_METHOD] = sConfig.GetIntDefault("CharDelete.Method", 0);
962  m_configs[CONFIG_CHARDELETE_MIN_LEVEL] = sConfig.GetIntDefault("CharDelete.MinLevel", 0);
963  m_configs[CONFIG_CHARDELETE_KEEP_DAYS] = sConfig.GetIntDefault("CharDelete.KeepDays", 30);
964 
965  m_visibility_notify_periodOnContinents = sConfig.GetIntDefault("Visibility.Notify.Period.OnContinents", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
966  m_visibility_notify_periodInInstances = sConfig.GetIntDefault("Visibility.Notify.Period.InInstances", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
967  m_visibility_notify_periodInBGArenas = sConfig.GetIntDefault("Visibility.Notify.Period.InBGArenas", DEFAULT_VISIBILITY_NOTIFY_PERIOD);
968 
970  std::string dataPath = sConfig.GetStringDefault("DataDir", "./");
971  if (dataPath.empty() || (dataPath.at(dataPath.length() - 1) != '/' && dataPath.at(dataPath.length() - 1) != '\\'))
972  dataPath.append("/");
973 
974  if (reload)
975  {
976  if (dataPath != m_dataPath)
977  sLog.outError("DataDir option can't be changed at oregoncore.conf reload, using current value (%s).", m_dataPath.c_str());
978  }
979  else
980  {
981  m_dataPath = dataPath;
982  sLog.outString("Using DataDir %s", m_dataPath.c_str());
983  }
984 
985  bool enableIndoor = sConfig.GetBoolDefault("vmap.enableIndoorCheck", true);
986  bool enableLOS = sConfig.GetBoolDefault("vmap.enableLOS", true);
987  bool enableHeight = sConfig.GetBoolDefault("vmap.enableHeight", true);
988  bool enablePetLOS = sConfig.GetBoolDefault("vmap.petLOS", true);
989  std::string ignoreSpellIds = sConfig.GetStringDefault("vmap.ignoreSpellIds", "");
990 
991  if (!enableHeight)
992  sLog.outError("VMap height checking disabled! Creatures movements and other various things WILL be broken! Expect no support.");
993 
997  sLog.outString("WORLD: VMap support included. LineOfSight:%i, getHeight:%i, indoorCheck:%i, PetLOS:%i", enableLOS, enableHeight, enableIndoor, enablePetLOS);
998  sLog.outString("WORLD: VMap data directory is: %svmaps", m_dataPath.c_str());
999 
1000  m_configs[CONFIG_PET_LOS] = enablePetLOS;
1001  m_configs[CONFIG_VMAP_TOTEM] = sConfig.GetBoolDefault("vmap.totem", false);
1002  m_configs[CONFIG_MAX_WHO] = sConfig.GetIntDefault("MaxWhoListReturns", 49);
1003 
1004  m_configs[CONFIG_BG_START_MUSIC] = sConfig.GetBoolDefault("MusicInBattleground", false);
1005  m_configs[CONFIG_START_ALL_SPELLS] = sConfig.GetBoolDefault("PlayerStart.AllSpells", false);
1006  m_configs[CONFIG_HONOR_AFTER_DUEL] = sConfig.GetIntDefault("HonorPointsAfterDuel", 0);
1007  m_configs[CONFIG_START_ALL_EXPLORED] = sConfig.GetBoolDefault("PlayerStart.MapsExplored", false);
1008  m_configs[CONFIG_START_ALL_REP] = sConfig.GetBoolDefault("PlayerStart.AllReputation", false);
1009  m_configs[CONFIG_ALWAYS_MAXSKILL] = sConfig.GetBoolDefault("AlwaysMaxWeaponSkill", false);
1010  m_configs[CONFIG_PVP_TOKEN_ENABLE] = sConfig.GetBoolDefault("PvPToken.Enable", false);
1011  m_configs[CONFIG_PVP_TOKEN_MAP_TYPE] = sConfig.GetIntDefault("PvPToken.MapAllowType", 4);
1012  m_configs[CONFIG_PVP_TOKEN_ID] = sConfig.GetIntDefault("PvPToken.ItemID", 29434);
1013  m_configs[CONFIG_PVP_TOKEN_COUNT] = sConfig.GetIntDefault("PvPToken.ItemCount", 1);
1014  m_configs[CONFIG_NO_RESET_TALENT_COST] = sConfig.GetBoolDefault("NoResetTalentsCost", false);
1015  m_configs[CONFIG_SHOW_KICK_IN_WORLD] = sConfig.GetBoolDefault("ShowKickInWorld", false);
1016  m_configs[CONFIG_INTERVAL_LOG_UPDATE] = sConfig.GetIntDefault("RecordUpdateTimeDiffInterval", 60000);
1017  m_configs[CONFIG_MIN_LOG_UPDATE] = sConfig.GetIntDefault("MinRecordUpdateTimeDiff", 100);
1018  m_configs[CONFIG_NUMTHREADS] = sConfig.GetIntDefault("MapUpdate.Threads", 1);
1019  m_configs[CONFIG_DUEL_MOD] = sConfig.GetBoolDefault("DuelMod.Enable", false);
1020  m_configs[CONFIG_DUEL_CD_RESET] = sConfig.GetBoolDefault("DuelMod.Cooldowns", false);
1021  m_configs[CONFIG_AUTOBROADCAST_TIMER] = sConfig.GetIntDefault("AutoBroadcast.Timer", 60000);
1022  m_configs[CONFIG_AUTOBROADCAST_ENABLED] = sConfig.GetIntDefault("AutoBroadcast.On", 0);
1023  m_configs[CONFIG_AUTOBROADCAST_CENTER] = sConfig.GetIntDefault("AutoBroadcast.Center", 0);
1024 
1025  m_configs[CONFIG_MAX_RESULTS_LOOKUP_COMMANDS] = sConfig.GetIntDefault("Command.LookupMaxResults", 0);
1026 
1027  // chat logging
1028  m_configs[CONFIG_CHATLOG_CHANNEL] = sConfig.GetBoolDefault("ChatLogs.Channel", false);
1029  m_configs[CONFIG_CHATLOG_WHISPER] = sConfig.GetBoolDefault("ChatLogs.Whisper", false);
1030  m_configs[CONFIG_CHATLOG_SYSCHAN] = sConfig.GetBoolDefault("ChatLogs.SysChan", false);
1031  m_configs[CONFIG_CHATLOG_PARTY] = sConfig.GetBoolDefault("ChatLogs.Party", false);
1032  m_configs[CONFIG_CHATLOG_RAID] = sConfig.GetBoolDefault("ChatLogs.Raid", false);
1033  m_configs[CONFIG_CHATLOG_GUILD] = sConfig.GetBoolDefault("ChatLogs.Guild", false);
1034  m_configs[CONFIG_CHATLOG_PUBLIC] = sConfig.GetBoolDefault("ChatLogs.Public", false);
1035  m_configs[CONFIG_CHATLOG_ADDON] = sConfig.GetBoolDefault("ChatLogs.Addon", false);
1036  m_configs[CONFIG_CHATLOG_BGROUND] = sConfig.GetBoolDefault("ChatLogs.Battleground", false);
1037 
1038  // warden
1039  m_configs[CONFIG_WARDEN_ENABLED] = sConfig.GetBoolDefault("Warden.Enabled", false);
1040  m_configs[CONFIG_WARDEN_KICK] = sConfig.GetBoolDefault("Warden.Kick", false);
1041  m_configs[CONFIG_WARDEN_NUM_CHECKS] = sConfig.GetIntDefault("Warden.NumChecks", 3);
1042  m_configs[CONFIG_WARDEN_CLIENT_CHECK_HOLDOFF] = sConfig.GetIntDefault("Warden.ClientCheckHoldOff", 30);
1043  m_configs[CONFIG_WARDEN_CLIENT_RESPONSE_DELAY] = sConfig.GetIntDefault("Warden.ClientResponseDelay", 15);
1044 
1045  // Refer-A-Friend
1046  m_configs[CONFIG_RAF_LEVEL_LIMIT] = sConfig.GetIntDefault("RAF.LevelLimit", 60);
1047 
1048  // mmaps
1049  m_configs[CONFIG_BOOL_MMAP_ENABLED] = sConfig.GetBoolDefault("mmap.enabled", true);
1050  std::string ignoreMMapIds = sConfig.GetStringDefault("mmap.ignoreMapIds", "");
1051  MMAP::MMapFactory::preventPathfindingOnMaps(ignoreMMapIds.c_str());
1052  sLog.outString("WORLD: MMap pathfinding %sabled.", getConfig(CONFIG_BOOL_MMAP_ENABLED) ? "en" : "dis");
1053 
1054  // Misc
1055  m_configs[CONFIG_UI_QUESTLEVELS_IN_DIALOGS] = sConfig.GetBoolDefault("UI.ShowQuestLevelsInDialogs", false);
1056  m_configs[CONFIG_HEALTH_IN_PERCENTS] = sConfig.GetBoolDefault("HealthInPercents", true);
1057 
1058  // SQLUpdater
1059  m_configs[CONFIG_SQLUPDATER_ENABLED] = sConfig.GetBoolDefault("DatabaseUpdater.Enabled", false);
1060  m_SQLUpdatesPath = sConfig.GetStringDefault("DatabaseUpdater.PathToUpdates", "");
1061  if (!m_SQLUpdatesPath.size() || (*m_SQLUpdatesPath.rbegin() != '\\' && *m_SQLUpdatesPath.rbegin() != '/'))
1062  #if PLATFORM == PLATFORM_WINDOWS
1063  m_SQLUpdatesPath += '\\';
1064  #else
1065  m_SQLUpdatesPath += '/';
1066  #endif
1067 }
1068 
1070 {
1071  const struct
1072  {
1073  // db pointer
1074  Database* db;
1075  // path - sql/updates/(path)
1076  const char* path;
1077  } updates[]
1078  =
1079  {
1080  { &LoginDatabase, "realmd" },
1081  { &WorldDatabase, "world" },
1082  { &CharacterDatabase, "characters" }
1083  };
1084 
1085  // directory path
1086  std::string path;
1087  // label used for console output
1088  std::stringstream label;
1089  // files to be applied
1090  std::vector<std::string> files;
1091  // already applied before (from db)
1092  std::set<std::string> alreadyAppliedFiles;
1093 
1094  // iterate all three databases
1095  for (uint32 i = 0; i < 3; i++)
1096  {
1097  // clear from previous iteration
1098  files.clear();
1099  // clear from previous iteration
1100  alreadyAppliedFiles.clear();
1101 
1102  // refresh path
1103  path = m_SQLUpdatesPath;
1104  path += updates[i].path;
1105 
1106  // Get updates that were alraedy applied before
1107  if (QueryResult_AutoPtr result = updates[i].db->Query("SELECT `update` FROM `updates`"))
1108  {
1109  do
1110  alreadyAppliedFiles.insert(result->Fetch()[0].GetString());
1111  while (result->NextRow());
1112  }
1113 
1114  // Record current working directory
1115  char cwd[PATH_MAX];
1116  ACE_OS::getcwd(cwd, PATH_MAX);
1117 
1118  // Change current directory to sql/updates/(path)
1119  if (-1 == ACE_OS::chdir(path.c_str()))
1120  sLog.outFatal("Can't change directory to %s: %s", path.c_str(), strerror(errno));
1121 
1122  // get files in sql/updates/(path)/ directory
1123  if (ACE_DIR* dir = ACE_OS::opendir(path.c_str()))
1124  {
1125  while (ACE_DIRENT* entry = ACE_OS::readdir(dir))
1126  // continue only if file is not already applied
1127  if (alreadyAppliedFiles.find(entry->d_name) == alreadyAppliedFiles.end())
1128  // make sure the file is an .sql one
1129  if (!strcmp(entry->d_name + strlen(entry->d_name) - 4, ".sql"))
1130  files.push_back(entry->d_name);
1131 
1132  ACE_OS::closedir(dir);
1133  }
1134  else
1135  sLog.outFatal("Can't open %s: %s", path.c_str(), strerror(errno));
1136 
1137  // sort our files in ascending order
1138  std::sort(files.begin(), files.end());
1139 
1140  // iterate not applied files now
1141  for (size_t j = 0; j < files.size(); ++j)
1142  {
1143  label.str("");
1144  label << "Applying " << files[j].c_str() << " (" << (j + 1) << '/' << files.size() << ')';
1145  sConsole.SetLoadingLabel(label.str().c_str());
1146 
1147  if (updates[i].db->ExecuteFile(files[j].c_str()))
1148  {
1149  updates[i].db->escape_string(files[j]);
1150  updates[i].db->DirectPExecute("INSERT INTO `updates` VALUES ('%s', NOW())", files[j].c_str());
1151  }
1152  else
1153  sLog.outFatal("Failed to apply %s. See db_errors.log for more details.", files[j].c_str());
1154  }
1155 
1156  // Return to original working directory
1157  if (-1 == ACE_OS::chdir(cwd))
1158  sLog.outFatal("Can't change directory to %s: %s", cwd, strerror(errno));
1159  }
1160 }
1161 
1162 extern void LoadGameObjectModelList();
1163 
1164 // Initialize the World
1166 {
1167  // Initialize the random number generator
1168  srand((unsigned int)time(NULL));
1169 
1170  // Initialize VMapManager's function pointers to fix linking between game/collision
1171  if (VMAP::VMapManager2* vmapMgr = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager()))
1172  vmapMgr->GetLiquidFlagsPtr = &GetLiquidFlags; // implemented in DBCStores.cpp
1173 
1174  // Time for server startup
1175  uint32 uStartTime = getMSTime();
1176 
1177  // Initialize detour memory management
1178  dtAllocSetCustom(dtCustomAlloc, dtCustomFree);
1179 
1180  // Initialize config settings
1182 
1183  // Init highest guids before any table loading to prevent using not initialized guids in some code.
1184  sObjectMgr.SetHighestGuids();
1185 
1186  // Check the existence of the map files for all races' startup areas.
1187  if ((!MapManager::ExistMapAndVMap(0, -6240.32f, 331.033f)
1188  || !MapManager::ExistMapAndVMap(0, -8949.95f, -132.493f)
1189  || !MapManager::ExistMapAndVMap(1, -618.518f, -4251.67f)
1190  || !MapManager::ExistMapAndVMap(0, 1676.35f, 1677.45f)
1191  || !MapManager::ExistMapAndVMap(1, 10311.3f, 832.463f)
1192  || !MapManager::ExistMapAndVMap(1, -2917.58f, -257.98f)
1193  || m_configs[CONFIG_EXPANSION]) &&
1194  (!MapManager::ExistMapAndVMap(530, 10349.6f, -6357.29f) || !MapManager::ExistMapAndVMap(530, -3961.64f, -13931.2f)))
1195  sLog.outError("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 oregoncore.conf file.", m_dataPath.c_str(), m_dataPath.c_str());
1196 
1197  // Loading strings. Getting no records means core load has to be canceled because no error message can be output.
1198  sConsole.SetLoadingLabel("Loading Oregon strings...");
1199  if (!sObjectMgr.LoadOregonStrings())
1200  exit(1); // Error message displayed in function already
1201 
1202  // Update the realm entry in the database with the realm type from the config file
1203  //No SQL injection as values are treated as integers
1204 
1205  // not send custom type REALM_FFA_PVP to realm list
1207  uint32 realm_zone = getConfig(CONFIG_REALM_ZONE);
1208  LoginDatabase.PExecute("UPDATE realmlist SET icon = %u, timezone = %u WHERE id = '%d'", server_type, realm_zone, realmID);
1209 
1210  // Remove the bones (they should not exist in DB though) and old corpses after a restart
1211  CharacterDatabase.PExecute("DELETE FROM corpse WHERE corpse_type = '0' OR time < (UNIX_TIMESTAMP()-'%u')", 3 * DAY);
1212 
1214  {
1215  sConsole.SetLoadingLabel("Applying SQL Updates...");
1216  LoadSQLUpdates();
1217  }
1218 
1219  // Load the DBC files
1220  sConsole.SetLoadingLabel("Initialize data stores...");
1222  DetectDBCLang();
1223 
1224  std::vector<uint32> mapIds;
1225  for (uint32 mapId = 0; mapId < sMapStore.GetNumRows(); mapId++)
1226  if (sMapStore.LookupEntry(mapId))
1227  mapIds.push_back(mapId);
1228 
1229  if (VMAP::VMapManager2* vmmgr2 = dynamic_cast<VMAP::VMapManager2*>(VMAP::VMapFactory::createOrGetVMapManager()))
1230  vmmgr2->InitializeThreadUnsafe(mapIds);
1231 
1233  mmmgr->InitializeThreadUnsafe(mapIds);
1234 
1236 
1237  sConsole.SetLoadingLabel("Loading Script Names...");
1238  sObjectMgr.LoadScriptNames();
1239 
1240  sConsole.SetLoadingLabel("Loading Instance Template...");
1241  sObjectMgr.LoadInstanceTemplate();
1242 
1243  sConsole.SetLoadingLabel("Loading SkillLineAbilityMultiMap Data...");
1244  sSpellMgr.LoadSkillLineAbilityMap();
1245 
1246  // Clean up and pack instances
1247  sConsole.SetLoadingLabel("Cleaning up instances...");
1248  sInstanceSaveMgr.CleanupInstances(); // must be called before `creature_respawn`/`gameobject_respawn` tables
1249 
1250  sConsole.SetLoadingLabel("Packing instances...");
1251  sInstanceSaveMgr.PackInstances();
1252 
1253  sConsole.SetLoadingLabel("Loading Localization strings...");
1254  sObjectMgr.LoadCreatureLocales();
1255  sObjectMgr.LoadGameObjectLocales();
1256  sObjectMgr.LoadItemLocales();
1257  sObjectMgr.LoadQuestLocales();
1258  sObjectMgr.LoadNpcTextLocales();
1259  sObjectMgr.LoadPageTextLocales();
1260  sObjectMgr.LoadGossipMenuItemsLocales();
1261  sObjectMgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
1262  sConsole.SetLoadingLabel(">>> Localization strings loaded");
1263 
1264  sConsole.SetLoadingLabel("Loading Page Texts...");
1265  sObjectMgr.LoadPageTexts();
1266 
1267  sConsole.SetLoadingLabel("Loading Game Object Templates..."); // must be after LoadPageTexts
1268  sObjectMgr.LoadGameobjectInfo();
1269 
1270  sConsole.SetLoadingLabel("Loading Spell Chain Data...");
1271  sSpellMgr.LoadSpellChains();
1272 
1273  sConsole.SetLoadingLabel("Loading Spell Required Data...");
1274  sSpellMgr.LoadSpellRequired();
1275 
1276  sConsole.SetLoadingLabel("Loading Spell Group types...");
1277  sSpellMgr.LoadSpellGroups();
1278 
1279  sConsole.SetLoadingLabel("Loading Spell Learn Skills...");
1280  sSpellMgr.LoadSpellLearnSkills(); // must be after LoadSpellChains
1281 
1282  sConsole.SetLoadingLabel("Loading Spell Learn Spells...");
1283  sSpellMgr.LoadSpellLearnSpells();
1284 
1285  sConsole.SetLoadingLabel("Loading Spell Proc Event conditions...");
1286  sSpellMgr.LoadSpellProcEvents();
1287 
1288  sConsole.SetLoadingLabel("Loading Spell Dummy Conditions...");
1289  sSpellMgr.LoadSpellDummyCondition();
1290 
1291  sConsole.SetLoadingLabel("Loading Aggro Spells Definitions...");
1292  sSpellMgr.LoadSpellThreats();
1293 
1294  sConsole.SetLoadingLabel("Loading NPC Texts...");
1295  sObjectMgr.LoadGossipText();
1296 
1297  sConsole.SetLoadingLabel("Loading Spell Group Stack Rules...");
1298  sSpellMgr.LoadSpellGroupStackRules();
1299 
1300  sConsole.SetLoadingLabel("Loading Enchant Spells Proc datas...");
1301  sSpellMgr.LoadSpellEnchantProcData();
1302 
1303  sConsole.SetLoadingLabel("Loading Item Random Enchantments Table...");
1305 
1306  sConsole.SetLoadingLabel("Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
1307  sObjectMgr.LoadItemTemplates();
1308 
1309  sConsole.SetLoadingLabel("Loading Item Texts...");
1310  sObjectMgr.LoadItemTexts();
1311 
1312  sConsole.SetLoadingLabel("Loading Creature Model Based Info Data...");
1313  sObjectMgr.LoadCreatureModelInfo();
1314 
1315  sConsole.SetLoadingLabel("Loading Equipment templates...");
1316  sObjectMgr.LoadEquipmentTemplates();
1317 
1318  sConsole.SetLoadingLabel("Loading Creature Base Stats...");
1319  sObjectMgr.LoadCreatureClassLevelStats();
1320 
1321  sConsole.SetLoadingLabel("Loading Creature templates...");
1322  sObjectMgr.LoadCreatureTemplates();
1323 
1324  sConsole.SetLoadingLabel("Loading Creature Reputation OnKill Data...");
1325  sObjectMgr.LoadReputationOnKill();
1326 
1327  sConsole.SetLoadingLabel("Loading Reputation Spillover Data...");
1328  sObjectMgr.LoadReputationSpilloverTemplate();
1329 
1330  sConsole.SetLoadingLabel("Loading Pet Create Spells...");
1331  sObjectMgr.LoadPetCreateSpells();
1332 
1333  sConsole.SetLoadingLabel("Loading Creature Data...");
1334  sObjectMgr.LoadCreatures();
1335 
1336  sConsole.SetLoadingLabel("Loading Temporary Summon Data...");
1337  sObjectMgr.LoadTempSummons(); // must be after LoadCreatureTemplates() and LoadGameObjectTemplates()
1338 
1339  sConsole.SetLoadingLabel("Loading Creature Linked Respawn...");
1340  sObjectMgr.LoadCreatureLinkedRespawn(); // must be after LoadCreatures()
1341 
1342  sConsole.SetLoadingLabel("Loading Creature Addon Data...");
1343  sObjectMgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
1344 
1345  sConsole.SetLoadingLabel("Loading Creature Respawn Data..."); // must be after PackInstances()
1346  sObjectMgr.LoadCreatureRespawnTimes();
1347 
1348  sConsole.SetLoadingLabel("Loading Gameobject Data...");
1349  sObjectMgr.LoadGameobjects();
1350 
1351  sConsole.SetLoadingLabel("Loading Gameobject Respawn Data..."); // must be after PackInstances()
1352  sObjectMgr.LoadGameobjectRespawnTimes();
1353 
1354  sConsole.SetLoadingLabel("Loading Objects Pooling Data...");
1355  sPoolMgr.LoadFromDB();
1356 
1357  sConsole.SetLoadingLabel("Loading Weather Data...");
1358  sObjectMgr.LoadWeatherZoneChances();
1359 
1360  sConsole.SetLoadingLabel("Loading Disables");
1361  sDisableMgr.LoadDisables(); // must be before loading quests
1362 
1363  sConsole.SetLoadingLabel("Loading Quests...");
1364  sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
1365 
1366  sConsole.SetLoadingLabel("Checking Quest Disables");
1367  sDisableMgr.CheckQuestDisables(); // must be after loading quests
1368 
1369  sConsole.SetLoadingLabel("Loading Quests Relations...");
1370  sObjectMgr.LoadQuestRelations(); // must be after quest load
1371 
1372  sConsole.SetLoadingLabel("Loading Quest Pooling Data...");
1373  sPoolMgr.LoadQuestPools();
1374 
1375  sConsole.SetLoadingLabel("Loading Game Event Data..."); // must be after loading pools fully
1376  sGameEventMgr.LoadFromDB();
1377 
1378  sConsole.SetLoadingLabel("Loading AreaTrigger definitions...");
1379  sObjectMgr.LoadAreaTriggerTeleports();
1380 
1381  sConsole.SetLoadingLabel("Loading Access Requirements...");
1382  sObjectMgr.LoadAccessRequirements(); // must be after item template load
1383 
1384  sConsole.SetLoadingLabel("Loading Quest Area Triggers...");
1385  sObjectMgr.LoadQuestAreaTriggers(); // must be after LoadQuests
1386 
1387  sConsole.SetLoadingLabel("Loading Tavern Area Triggers...");
1388  sObjectMgr.LoadTavernAreaTriggers();
1389 
1390  sConsole.SetLoadingLabel("Loading AreaTrigger script names...");
1391  sObjectMgr.LoadAreaTriggerScripts();
1392 
1393  sConsole.SetLoadingLabel("Loading Graveyard-zone links...");
1394  sObjectMgr.LoadGraveyardZones();
1395 
1396  sConsole.SetLoadingLabel("Loading Spell target coordinates...");
1397  sSpellMgr.LoadSpellTargetPositions();
1398 
1399  sConsole.SetLoadingLabel("Loading SpellAffect definitions...");
1400  sSpellMgr.LoadSpellAffects();
1401 
1402  sConsole.SetLoadingLabel("Loading spell pet auras...");
1403  sSpellMgr.LoadSpellPetAuras();
1404 
1405  sConsole.SetLoadingLabel("Loading spell extra attributes...");
1406  sSpellMgr.LoadSpellCustomAttr();
1407 
1408  sLog.outString("Loading GameObject models...");
1410 
1411  sConsole.SetLoadingLabel("Loading linked spells...");
1412  sSpellMgr.LoadSpellLinked();
1413 
1414  sConsole.SetLoadingLabel("Loading custom spell cooldowns...");
1415  sSpellMgr.LoadSpellCustomCooldowns();
1416 
1417  sConsole.SetLoadingLabel("Loading Player Create Data...");
1418  sObjectMgr.LoadPlayerInfo();
1419 
1420  sConsole.SetLoadingLabel("Loading Exploration BaseXP Data...");
1421  sObjectMgr.LoadExplorationBaseXP();
1422 
1423  sConsole.SetLoadingLabel("Loading Pet Name Parts...");
1424  sObjectMgr.LoadPetNames();
1425 
1426  sConsole.SetLoadingLabel("Loading the max pet number...");
1427  sObjectMgr.LoadPetNumber();
1428 
1429  sConsole.SetLoadingLabel("Loading pet level stats...");
1430  sObjectMgr.LoadPetLevelInfo();
1431 
1432  sConsole.SetLoadingLabel("Loading Player Corpses...");
1433  sObjectMgr.LoadCorpses();
1434 
1435  sConsole.SetLoadingLabel("Loading Loot Tables...");
1436  LoadLootTables();
1437 
1438  sConsole.SetLoadingLabel("Loading Skill Discovery Table...");
1440 
1441  sConsole.SetLoadingLabel("Loading Skill Extra Item Table...");
1443 
1444  sConsole.SetLoadingLabel("Loading Skill Fishing base level requirements...");
1445  sObjectMgr.LoadFishingBaseSkillLevel();
1446 
1447  // Load dynamic data tables from the database
1448  sConsole.SetLoadingLabel("Loading Item Auctions...");
1449  sAuctionMgr->LoadAuctionItems();
1450  sConsole.SetLoadingLabel("Loading Auctions...");
1451  sAuctionMgr->LoadAuctions();
1452 
1453  sConsole.SetLoadingLabel("Loading Guilds...");
1454  sObjectMgr.LoadGuilds();
1455 
1456  sConsole.SetLoadingLabel("Loading ArenaTeams...");
1457  sObjectMgr.LoadArenaTeams();
1458 
1459  sConsole.SetLoadingLabel("Loading Groups...");
1460  sObjectMgr.LoadGroups();
1461 
1462  sConsole.SetLoadingLabel("Loading ReservedNames...");
1463  sObjectMgr.LoadReservedPlayersNames();
1464 
1465  sConsole.SetLoadingLabel("Loading GameObjects for quests...");
1466  sObjectMgr.LoadGameObjectForQuests();
1467 
1468  sConsole.SetLoadingLabel("Loading BattleMasters...");
1469  sObjectMgr.LoadBattleMastersEntry();
1470 
1471  sConsole.SetLoadingLabel("Loading GameTeleports...");
1472  sObjectMgr.LoadGameTele();
1473 
1474  sConsole.SetLoadingLabel("Loading Npc Text Id...");
1475  sObjectMgr.LoadNpcTextId(); // must be after load Creature and NpcText
1476 
1477  sConsole.SetLoadingLabel( "Loading Gossip scripts...");
1478  sObjectMgr.LoadGossipScripts(); // must be before gossip menu options
1479 
1480  sConsole.SetLoadingLabel("Loading Gossip menu...");
1481  sObjectMgr.LoadGossipMenu();
1482 
1483  sConsole.SetLoadingLabel("Loading Gossip menu options...");
1484  sObjectMgr.LoadGossipMenuItems();
1485 
1486  sConsole.SetLoadingLabel("Loading Vendors...");
1487  sObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
1488 
1489  sConsole.SetLoadingLabel("Loading Trainers...");
1490  sObjectMgr.LoadTrainerSpell(); // must be after load CreatureTemplate
1491 
1492  sConsole.SetLoadingLabel("Loading Waypoints...");
1493  sWaypointMgr->Load();
1494 
1495  sConsole.SetLoadingLabel("Loading SmartAI Waypoints...");
1496  sSmartWaypointMgr->LoadFromDB();
1497 
1498  sConsole.SetLoadingLabel("Loading Creature Formations...");
1499  sFormationMgr.LoadCreatureFormations();
1500 
1501  sConsole.SetLoadingLabel("Loading Conditions...");
1502  sConditionMgr.LoadConditions();
1503 
1504  sConsole.SetLoadingLabel("Loading GM tickets...");
1505  ticketmgr.LoadGMTickets();
1506 
1507  sConsole.SetLoadingLabel("Loading GM surveys...");
1508  ticketmgr.LoadGMSurveys();
1509 
1510  // Handle outdated emails (delete/return)
1511  sConsole.SetLoadingLabel("Returning old mails...");
1512  sObjectMgr.ReturnOrDeleteOldMails(false);
1513 
1514  sConsole.SetLoadingLabel("Loading Autobroadcasts...");
1516 
1517  sConsole.SetLoadingLabel("Loading Ip2nation...");
1518  LoadIp2nation();
1519 
1520  sConsole.SetLoadingLabel("Loading Refer-A-Friend...");
1521  sObjectMgr.LoadReferredFriends();
1522 
1523  sConsole.SetLoadingLabel("Loading Opcode Protection...");
1525 
1526  // Load and initialize scripts
1527  sConsole.SetLoadingLabel("Loading Scripts...");
1528  sObjectMgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
1529  sObjectMgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
1530  sObjectMgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
1531  sObjectMgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
1532  sObjectMgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
1533  sObjectMgr.LoadWaypointScripts();
1534 
1535  sConsole.SetLoadingLabel("Loading Scripts text locales..."); // must be after Load*Scripts calls
1536  sObjectMgr.LoadDbScriptStrings();
1537 
1538  sConsole.SetLoadingLabel("Loading CreatureEventAI Texts...");
1539  CreatureEAI_Mgr.LoadCreatureEventAI_Texts(false); // false, will checked in LoadCreatureEventAI_Scripts
1540 
1541  sConsole.SetLoadingLabel("Loading CreatureEventAI Summons...");
1542  CreatureEAI_Mgr.LoadCreatureEventAI_Summons(false); // false, will checked in LoadCreatureEventAI_Scripts
1543 
1544  sConsole.SetLoadingLabel("Loading CreatureEventAI Scripts...");
1545  CreatureEAI_Mgr.LoadCreatureEventAI_Scripts();
1546 
1547  sConsole.SetLoadingLabel("Loading Creature Texts...");
1548  sCreatureTextMgr->LoadCreatureTexts();
1549 
1550  sConsole.SetLoadingLabel("Loading Creature Text Locales...");
1551  sCreatureTextMgr->LoadCreatureTextLocales();
1552 
1553  sConsole.SetLoadingLabel("Loading SmartAI scripts...");
1554  sSmartScriptMgr->LoadSmartAIFromDB();
1555 
1556  sConsole.SetLoadingLabel("Initializing Scripts...");
1557  sScriptMgr.ScriptsInit();
1558 
1559  // Initialize game time and timers
1560  sLog.outDebug("DEBUG:: Initialize game time and timers");
1561  m_gameTime = time(NULL);
1563 
1564  tm local;
1565  time_t curr;
1566  time(&curr);
1567  local = *(localtime(&curr)); // dereference and assign
1568 
1569  LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, " UI64FMTD ", 0, '%s')",
1571 
1578  //Update "uptime" table based on configuration entry in minutes.
1579  m_timers[WUPDATE_CORPSES].SetInterval(20 * MINUTE * IN_MILLISECONDS);
1580  //erase corpses every 20 minutes
1582  // clean logs table every 14 days by default
1583 
1584  m_timers[WUPDATE_DELETECHARS].SetInterval(DAY * IN_MILLISECONDS); // check for chars to delete every day
1585 
1586  //to set mailtimer to return mails every day between 4 and 5 am
1587  //mailtimer is increased when updating auctions
1588  //one second is 1000 -(tested on win system)
1589 
1590  // handle timer for external mail
1592 
1593  mail_timer = ((((localtime(&m_gameTime)->tm_hour + 20) % 24) * HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval());
1594  //1440
1595  mail_timer_expires = ((DAY * IN_MILLISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval()));
1596  sLog.outDebug("Mail timer set to: %u, mail return is called every %u minutes", mail_timer, mail_timer_expires);
1597 
1598  // Initialize static helper structures
1601 
1602  // Initialize MapManager
1603  sConsole.SetLoadingLabel("Starting Map System");
1605 
1606  sConsole.SetLoadingLabel("Starting Game Event system...");
1607  uint32 nextGameEvent = sGameEventMgr.Initialize();
1608  m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); //depend on next event
1609 
1610  // Load Warden Data
1611  sConsole.SetLoadingLabel("Loading Warden Data..." );
1613 
1614  // Initialize Battlegrounds
1615  sConsole.SetLoadingLabel("Starting Battleground System");
1616  sBattlegroundMgr.CreateInitialBattlegrounds();
1617  sBattlegroundMgr.InitAutomaticArenaPointDistribution();
1618 
1619  // Initialize outdoor pvp
1620  sConsole.SetLoadingLabel("Starting Outdoor PvP System");
1621  sOutdoorPvPMgr.InitOutdoorPvP();
1622 
1623  //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager
1624  sConsole.SetLoadingLabel("Loading Transports...");
1626 
1627  sConsole.SetLoadingLabel("Loading Transports Events...");
1628  sObjectMgr.LoadTransportEvents();
1629 
1630  sConsole.SetLoadingLabel("Deleting expired bans...", false);
1631  LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate");
1632 
1633  sConsole.SetLoadingLabel("Starting objects Pooling system...", false);
1634  sPoolMgr.Initialize();
1635 
1636  sConsole.SetLoadingLabel("Calculate next daily quest reset time...", false);
1638 
1639  sConsole.SetLoadingLabel("Initialize AuctionHouseBot...", false);
1640  auctionbot.Initialize();
1641 
1642  // Delete all characters which have been deleted X days before
1644 
1645  sConsole.SetLoadingLabel("WORLD: World initialized");
1646 
1647  // Print startup time
1648  uint32 uStartInterval = getMSTimeDiff(uStartTime, getMSTime());
1649  sLog.outString( "SERVER STARTUP TIME: %i minutes %i seconds", uStartInterval / 60000, (uStartInterval % 60000) / 1000 );
1650 }
1651 
1653 {
1654  uint8 m_lang_confid = sConfig.GetIntDefault("DBC.Locale", 255);
1655 
1656  if (m_lang_confid != 255 && m_lang_confid >= MAX_LOCALE)
1657  {
1658  sLog.outError("Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", MAX_LOCALE);
1659  m_lang_confid = LOCALE_enUS;
1660  }
1661 
1662  ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1);
1663 
1664  std::string availableLocalsStr;
1665 
1666  uint8 default_locale = MAX_LOCALE;
1667  for (uint8 i = default_locale - 1; i < MAX_LOCALE; --i) // -1 will be 255 due to uint8
1668  {
1669  if (strlen(race->name[i]) > 0) // check by race names
1670  {
1671  default_locale = i;
1672  m_availableDbcLocaleMask |= (1 << i);
1673  availableLocalsStr += localeNames[i];
1674  availableLocalsStr += " ";
1675  }
1676  }
1677 
1678  if (default_locale != m_lang_confid && m_lang_confid < MAX_LOCALE &&
1679  (m_availableDbcLocaleMask & (1 << m_lang_confid)))
1680  default_locale = m_lang_confid;
1681 
1682  if (default_locale >= MAX_LOCALE)
1683  sLog.outFatal("Unable to determine your DBC Locale! (corrupt DBC?)");
1684 
1685  m_defaultDbcLocale = LocaleConstant(default_locale);
1686 
1687  sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
1688 }
1689 
1690 void World::RecordTimeDiff(const char* text, ...)
1691 {
1692  if (m_updateTimeCount != 1)
1693  return;
1694  if (!text)
1695  {
1697  return;
1698  }
1699 
1700  uint32 thisTime = getMSTime();
1701  uint32 diff = getMSTimeDiff(m_currentTime, thisTime);
1702 
1703  if (diff >= m_configs[CONFIG_MIN_LOG_UPDATE])
1704  {
1705  va_list ap;
1706  char str[256];
1707  va_start(ap, text);
1708  vsnprintf(str, 256, text, ap);
1709  va_end(ap);
1710  sLog.outDetail("Difftime %s: %u.", str, diff);
1711  }
1712 
1713  m_currentTime = thisTime;
1714 }
1715 
1717 {
1718  m_Autobroadcasts.clear();
1719 
1720  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT text FROM autobroadcast");
1721 
1722  if (!result)
1723  {
1724  sLog.outString(">> Loaded 0 autobroadcasts definitions");
1725  return;
1726  }
1727 
1728  uint32 count = 0;
1729 
1730  do
1731  {
1732  Field* fields = result->Fetch();
1733  std::string message = fields[0].GetCppString();
1734  m_Autobroadcasts.push_back(message);
1735  ++count;
1736  }
1737 
1738  while (result->NextRow());
1739 
1740  sLog.outString( ">> Loaded %u autobroadcasts definitions", count);
1741 }
1742 
1743 
1745 {
1746  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT count(c.code) FROM ip2nationCountries c, ip2nation i WHERE c.code = i.country");
1747  uint32 count = 0;
1748 
1749  if (result)
1750  {
1751  Field* fields = result->Fetch();
1752  count = fields[0].GetUInt32();
1753  }
1754 
1755  sLog.outString(">> Loaded %u ip2nation definitions", count);
1756 }
1757 
1759 {
1760  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT `opcode`, `threshold`, `interval`, `penalty` FROM opcode_protection");
1761  uint64 count = 0;
1762 
1763  if (result)
1764  {
1765  do
1766  {
1767  Field* field = result->Fetch();
1769 
1770  uint32 opcode = field[0].GetUInt32();
1771  if (opcode >= NUM_MSG_TYPES)
1772  continue;
1773 
1774  prop.threshold = field[1].GetUInt32();
1775  prop.interval = field[2].GetUInt32();
1776  prop.penalty = (OpcodePenalty) field[3].GetUInt8();
1777 
1778  opcodeTable[opcode].status |= STATUS_PROTECTED;
1779  _protectedOpcodesProperties[opcode] = prop;
1780 
1781  count++;
1782  }
1783  while (result->NextRow());
1784  }
1785 
1786  sLog.outString(">> Loaded %lu opcode protections.", count);
1787 }
1788 
1790 {
1791  return _protectedOpcodesProperties[opcode];
1792 }
1793 
1794 // Update the World !
1796 {
1797  m_updateTime = uint32(diff);
1799  {
1800  if (m_updateTimeSum > m_configs[CONFIG_INTERVAL_LOG_UPDATE] && uint32(diff) >= m_configs[CONFIG_MIN_LOG_UPDATE])
1801  {
1802  sLog.outBasic("Update time diff: %u. Players online: %u.", m_updateTimeSum / m_updateTimeCount, GetActiveSessionCount());
1804  m_updateTimeCount = 1;
1805  }
1806  else
1807  {
1810  }
1811  }
1812 
1813  // Update the different timers
1814  for (int i = 0; i < WUPDATE_COUNT; ++i)
1815  {
1816  if (m_timers[i].GetCurrent() >= 0)
1817  m_timers[i].Update(diff);
1818  else
1819  m_timers[i].SetCurrent(0);
1820  }
1821 
1822  // Update the game time and check for shutdown time
1823  _UpdateGameTime();
1824 
1825  // Handle daily quests reset time
1827  {
1828  ResetDailyQuests();
1830  }
1831 
1832  // Handle external mail
1833  if (m_configs[CONFIG_EXTERNAL_MAIL] != 0)
1834  {
1835  extmail_timer.Update(diff);
1836  if (extmail_timer.Passed())
1837  {
1839  extmail_timer.Reset();
1840  }
1841  }
1842 
1843  // Handle auctions when the timer has passed
1844  if (m_timers[WUPDATE_AUCTIONS].Passed())
1845  {
1846  auctionbot.Update();
1848 
1849  // Update mails (return old mails with item, or delete them)
1850  //(tested... works on win)
1852  {
1853  mail_timer = 0;
1854  sObjectMgr.ReturnOrDeleteOldMails(true);
1855  }
1856 
1857  // Handle expired auctions
1858  sAuctionMgr->Update();
1859  }
1860 
1861  // Handle session updates when the timer has passed
1862  RecordTimeDiff(NULL);
1863  UpdateSessions(diff);
1864  RecordTimeDiff("UpdateSessions");
1865 
1866  // Handle weather updates when the timer has passed
1867  if (m_timers[WUPDATE_WEATHERS].Passed())
1868  {
1870 
1871  // Send an update signal to Weather objects
1872  WeatherMap::iterator itr, next;
1873  for (itr = m_weathers.begin(); itr != m_weathers.end(); itr = next)
1874  {
1875  next = itr;
1876  ++next;
1877 
1878  // and remove Weather objects for zones with no player
1879  //As interval > WorldTick
1880  if (!itr->second->Update(m_timers[WUPDATE_WEATHERS].GetInterval()))
1881  {
1882  delete itr->second;
1883  m_weathers.erase(itr);
1884  }
1885  }
1886  }
1887 
1888  // Update uptime table
1889  if (m_timers[WUPDATE_UPTIME].Passed())
1890  {
1891  uint32 tmpDiff = (m_gameTime - m_startTime);
1892  uint32 maxClientsNum = sWorld.GetMaxActiveSessionCount();
1893 
1895  LoginDatabase.PExecute("UPDATE uptime SET uptime = %d, maxplayers = %d WHERE starttime = " UI64FMTD, tmpDiff, maxClientsNum, uint64(m_startTime));
1896  }
1897 
1898  // Clean logs table
1899  if (sWorld.getConfig(CONFIG_LOGDB_CLEARTIME) > 0) // if not enabled, ignore the timer
1900  {
1901  if (m_timers[WUPDATE_CLEANDB].Passed())
1902  {
1904  LoginDatabase.PExecute("DELETE FROM logs WHERE (time + %u) < " UI64FMTD ";",
1905  sWorld.getConfig(CONFIG_LOGDB_CLEARTIME), uint64(time(0)));
1906  }
1907  }
1908 
1909  // Handle all other objects
1910  // Update objects when the timer has passed (maps, transport, creatures,...)
1911  MapManager::Instance().Update(diff); // As interval = 0
1912 
1914  {
1915  if (m_timers[WUPDATE_AUTOBROADCAST].Passed())
1916  {
1919  }
1920  }
1921 
1922  sBattlegroundMgr.Update(diff);
1923  RecordTimeDiff("UpdateBattlegroundMgr");
1924 
1925  sOutdoorPvPMgr.Update(diff);
1926  RecordTimeDiff("UpdateOutdoorPvPMgr");
1927 
1929  if (m_timers[WUPDATE_DELETECHARS].Passed())
1930  {
1933  }
1934 
1935  // execute callbacks from sql queries that were queued recently
1937  RecordTimeDiff("UpdateResultQueue");
1938 
1939  // Erase corpses once every 20 minutes
1940  if (m_timers[WUPDATE_CORPSES].Passed())
1941  {
1944  }
1945 
1946  // Process Game events when necessary
1947  if (m_timers[WUPDATE_EVENTS].Passed())
1948  {
1949  m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
1950  uint32 nextGameEvent = sGameEventMgr.Update();
1951  m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
1953  }
1954 
1955  // update the instance reset times
1956  sInstanceSaveMgr.Update();
1957 
1958  // And last, but not least handle the issued cli commands
1960 }
1961 
1963 {
1964  m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
1965  uint32 nextGameEvent = sGameEventMgr.Update();
1966  m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
1968 }
1969 
1970 // Send a packet to all players (except self if mentioned)
1972 {
1973  SessionMap::iterator itr;
1974  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1975  {
1976  if (itr->second &&
1977  itr->second->GetPlayer() &&
1978  itr->second->GetPlayer()->IsInWorld() &&
1979  itr->second != self &&
1980  (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
1981  itr->second->SendPacket(packet);
1982  }
1983 }
1984 
1985 // Send a packet to all GMs (except self if mentioned)
1987 {
1988  SessionMap::iterator itr;
1989  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1990  {
1991  if (itr->second &&
1992  itr->second->GetPlayer() &&
1993  itr->second->GetPlayer()->IsInWorld() &&
1994  itr->second != self &&
1995  itr->second->GetSecurity() > SEC_PLAYER &&
1996  (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
1997  itr->second->SendPacket(packet);
1998  }
1999 }
2000 
2001 // Send a System Message to all players (except self if mentioned)
2002 void World::SendWorldText(int32 string_id, ...)
2003 {
2004  std::vector<std::vector<WorldPacket*> > data_cache; // 0 = default, i => i-1 locale index
2005 
2006  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2007  {
2008  if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld())
2009  continue;
2010 
2011  uint32 loc_idx = itr->second->GetSessionDbLocaleIndex();
2012  uint32 cache_idx = loc_idx + 1;
2013 
2014  std::vector<WorldPacket*>* data_list;
2015 
2016  // create if not cached yet
2017  if (data_cache.size() < cache_idx + 1 || data_cache[cache_idx].empty())
2018  {
2019  if (data_cache.size() < cache_idx + 1)
2020  data_cache.resize(cache_idx + 1);
2021 
2022  data_list = &data_cache[cache_idx];
2023 
2024  char const* text = sObjectMgr.GetOregonString(string_id, loc_idx);
2025 
2026  char buf[1000];
2027 
2028  va_list argptr;
2029  va_start(argptr, string_id);
2030  vsnprintf(buf, 1000, text, argptr);
2031  va_end(argptr);
2032 
2033  char* pos = &buf[0];
2034 
2035  while (char* line = ChatHandler::LineFromMessage(pos))
2036  {
2037  WorldPacket* data = new WorldPacket();
2038  ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
2039  data_list->push_back(data);
2040  }
2041  }
2042  else
2043  data_list = &data_cache[cache_idx];
2044 
2045  for (uint32 i = 0; i < data_list->size(); ++i)
2046  itr->second->SendPacket((*data_list)[i]);
2047  }
2048 
2049  // free memory
2050  for (uint32 i = 0; i < data_cache.size(); ++i)
2051  for (uint32 j = 0; j < data_cache[i].size(); ++j)
2052  delete data_cache[i][j];
2053 }
2054 
2055 void World::SendGMText(int32 string_id, ...)
2056 {
2057  std::vector<std::vector<WorldPacket*> > data_cache; // 0 = default, i => i-1 locale index
2058 
2059  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2060  {
2061  if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld())
2062  continue;
2063 
2064  uint32 loc_idx = itr->second->GetSessionDbLocaleIndex();
2065  uint32 cache_idx = loc_idx + 1;
2066 
2067  std::vector<WorldPacket*>* data_list;
2068 
2069  // create if not cached yet
2070  if (data_cache.size() < cache_idx + 1 || data_cache[cache_idx].empty())
2071  {
2072  if (data_cache.size() < cache_idx + 1)
2073  data_cache.resize(cache_idx + 1);
2074 
2075  data_list = &data_cache[cache_idx];
2076 
2077  char const* text = sObjectMgr.GetOregonString(string_id, loc_idx);
2078 
2079  char buf[1000];
2080 
2081  va_list argptr;
2082  va_start(argptr, string_id);
2083  vsnprintf(buf, 1000, text, argptr);
2084  va_end(argptr);
2085 
2086  char* pos = &buf[0];
2087 
2088  while (char* line = ChatHandler::LineFromMessage(pos))
2089  {
2090  WorldPacket* data = new WorldPacket();
2091  ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
2092  data_list->push_back(data);
2093  }
2094  }
2095  else
2096  data_list = &data_cache[cache_idx];
2097 
2098  for (uint32 i = 0; i < data_list->size(); ++i)
2099  if (itr->second->GetSecurity() > SEC_PLAYER)
2100  itr->second->SendPacket((*data_list)[i]);
2101  }
2102 
2103  // free memory
2104  for (uint32 i = 0; i < data_cache.size(); ++i)
2105  for (uint32 j = 0; j < data_cache[i].size(); ++j)
2106  delete data_cache[i][j];
2107 }
2108 
2109 // Send a System Message to all players (except self if mentioned)
2110 void World::SendGlobalText(const char* text, WorldSession* self)
2111 {
2112  WorldPacket data;
2113 
2114  // need copy to prevent corruption by strtok call in LineFromMessage original string
2115  char* buf = strdup(text);
2116  char* pos = buf;
2117 
2118  while (char* line = ChatHandler::LineFromMessage(pos))
2119  {
2120  ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
2121  SendGlobalMessage(&data, self);
2122  }
2123 
2124  free(buf);
2125 }
2126 
2127 // Send a packet to all players (or players selected team) in the zone (except self if mentioned)
2129 {
2130  bool foundPlayerToSend = false;
2131  SessionMap::iterator itr;
2132 
2133  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2134  {
2135  if (itr->second &&
2136  itr->second->GetPlayer() &&
2137  itr->second->GetPlayer()->IsInWorld() &&
2138  itr->second->GetPlayer()->GetZoneId() == zone &&
2139  itr->second != self &&
2140  (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
2141  {
2142  itr->second->SendPacket(packet);
2143  foundPlayerToSend = true;
2144  }
2145  }
2146 
2147  return foundPlayerToSend;
2148 }
2149 
2150 // Send a System Message to all players in the zone (except self if mentioned)
2151 void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, uint32 team)
2152 {
2153  WorldPacket data;
2154  ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, text, NULL);
2155  SendZoneMessage(zone, &data, self, team);
2156 }
2157 
2158 // Kick (and save) all players
2160 {
2161  m_QueuedPlayer.clear(); // prevent send queue update packet and login queued sessions
2162 
2163  // session not removed at kick and will removed in next update tick
2164  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2165  itr->second->KickPlayer();
2166 }
2167 
2168 // Kick (and save) all players with security level less `sec`
2170 {
2171  // session not removed at kick and will removed in next update tick
2172  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2173  if (itr->second->GetSecurity() < sec)
2174  itr->second->KickPlayer();
2175 }
2176 
2177 // Kick (and save) the designated player
2178 bool World::KickPlayer(const std::string& playerName)
2179 {
2180  SessionMap::iterator itr;
2181 
2182  // session not removed at kick and will removed in next update tick
2183  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2184  {
2185  if (!itr->second)
2186  continue;
2187  Player* player = itr->second->GetPlayer();
2188  if (!player)
2189  continue;
2190  if (player->IsInWorld())
2191  {
2192  if (playerName == player->GetName())
2193  {
2194  itr->second->KickPlayer();
2195  return true;
2196  }
2197  }
2198  }
2199  return false;
2200 }
2201 
2202 // Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
2203 BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
2204 {
2205  LoginDatabase.escape_string(nameOrIP);
2206  LoginDatabase.escape_string(reason);
2207  std::string safe_author = author;
2208  LoginDatabase.escape_string(safe_author);
2209 
2210  uint32 duration_secs = TimeStringToSecs(duration);
2211  QueryResult_AutoPtr resultAccounts = QueryResult_AutoPtr(NULL); //used for kicking
2212 
2213  // Update the database with ban information
2214  switch (mode)
2215  {
2216  case BAN_IP:
2217  //No SQL injection as strings are escaped
2218  resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'", nameOrIP.c_str());
2219  LoginDatabase.PExecute("INSERT INTO ip_banned VALUES ('%s',UNIX_TIMESTAMP(),UNIX_TIMESTAMP()+%u,'%s','%s')", nameOrIP.c_str(), duration_secs, safe_author.c_str(), reason.c_str());
2220  break;
2221  case BAN_ACCOUNT:
2222  //No SQL injection as string is escaped
2223  resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", nameOrIP.c_str());
2224  break;
2225  case BAN_CHARACTER:
2226  //No SQL injection as string is escaped
2227  resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", nameOrIP.c_str());
2228  break;
2229  default:
2230  return BAN_SYNTAX_ERROR;
2231  }
2232 
2233  if (!resultAccounts)
2234  {
2235  if (mode == BAN_IP)
2236  return BAN_SUCCESS; // ip correctly banned but nobody affected (yet)
2237  else
2238  return BAN_NOTFOUND; // Nobody to ban
2239  }
2240 
2241  // Disconnect all affected players (for IP it can be several)
2242  do
2243  {
2244  Field* fieldsAccount = resultAccounts->Fetch();
2245  uint32 account = fieldsAccount->GetUInt32();
2246 
2247  if (mode != BAN_IP)
2248  {
2249  //No SQL injection as strings are escaped
2250  LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
2251  account, duration_secs, safe_author.c_str(), reason.c_str());
2252  }
2253 
2254  if (WorldSession* sess = FindSession(account))
2255  if (std::string(sess->GetPlayerName()) != author)
2256  sess->KickPlayer();
2257  }
2258  while (resultAccounts->NextRow());
2259 
2260  return BAN_SUCCESS;
2261 }
2262 
2263 // Remove a ban from an account or IP address
2264 bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
2265 {
2266  if (mode == BAN_IP)
2267  {
2268  LoginDatabase.escape_string(nameOrIP);
2269  LoginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'", nameOrIP.c_str());
2270  }
2271  else
2272  {
2273  uint32 account = 0;
2274  if (mode == BAN_ACCOUNT)
2275  account = sAccountMgr->GetId (nameOrIP);
2276  else if (mode == BAN_CHARACTER)
2277  account = sObjectMgr.GetPlayerAccountIdByPlayerName (nameOrIP);
2278 
2279  if (!account)
2280  return false;
2281 
2282  //NO SQL injection as account is uint32
2283  LoginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'", account);
2284  }
2285  return true;
2286 }
2287 
2288 // Update the game time
2290 {
2291  // update the time
2292  time_t thisTime = time(NULL);
2293  uint32 elapsed = uint32(thisTime - m_gameTime);
2294  m_gameTime = thisTime;
2295 
2296  // if there is a shutdown timer
2297  if (!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0)
2298  {
2299  // ... and it is overdue, stop the world (set m_stopEvent)
2300  if (m_ShutdownTimer <= elapsed)
2301  {
2303  {
2305  m_stopEvent = true; // exist code already set
2306  }
2307  else
2308  m_ShutdownTimer = 1; // minimum timer value to wait idle state
2309  }
2310  // ... else decrease it and if necessary display a shutdown countdown to the users
2311  else
2312  {
2313  m_ShutdownTimer -= elapsed;
2314 
2315  ShutdownMsg();
2316  }
2317  }
2318 }
2319 
2320 // Shutdown the server
2321 void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
2322 {
2323  // ignore if server shutdown at next tick
2324  if (m_stopEvent)
2325  return;
2326 
2327  m_ShutdownMask = options;
2328  m_ExitCode = exitcode;
2329 
2330  // If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions)
2331  if (time == 0)
2332  {
2333  if (!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0)
2334  m_stopEvent = true; // exist code already set
2335  else
2336  m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick
2337  }
2338  // Else set the shutdown timer and warn users
2339  else
2340  {
2341  m_ShutdownTimer = time;
2342  ShutdownMsg(true);
2343  }
2344 }
2345 
2346 // Display a shutdown message to the user(s)
2347 void World::ShutdownMsg(bool show, Player* player)
2348 {
2349  // not show messages for idle shutdown mode
2351  return;
2352 
2353  // Display a message every 12 hours, 1 hour, 5 minutes, 1 minute and 15 seconds
2354  if (show ||
2355  (m_ShutdownTimer <= 15) || // every sec down from 15 secs
2356  (m_ShutdownTimer < 5 * MINUTE && (m_ShutdownTimer % 15) == 0) || // < 5 min; every 15 sec
2357  (m_ShutdownTimer < 15 * MINUTE && (m_ShutdownTimer % MINUTE) == 0) || // < 15 min; every 1 min
2358  (m_ShutdownTimer < 30 * MINUTE && (m_ShutdownTimer % (5 * MINUTE)) == 0) || // < 30 min; every 5 min
2359  (m_ShutdownTimer < 12 * HOUR && (m_ShutdownTimer % HOUR) == 0) || // < 12 h; every 1 h
2360  (m_ShutdownTimer >= 12 * HOUR && (m_ShutdownTimer % (12 * HOUR)) == 0)) // >= 12 h; every 12 h
2361  {
2362  std::string str = secsToTimeString(m_ShutdownTimer);
2363 
2365 
2366  SendServerMessage(msgid, str.c_str(), player);
2367  DEBUG_LOG("Server is %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutting down"), str.c_str());
2368  }
2369 }
2370 
2371 // Cancel a planned server shutdown
2373 {
2374  // nothing cancel or too later
2375  if (!m_ShutdownTimer || m_stopEvent)
2376  return;
2377 
2379 
2380  m_ShutdownMask = 0;
2381  m_ShutdownTimer = 0;
2382  m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value
2383  SendServerMessage(msgid);
2384 
2385  DEBUG_LOG("Server %s cancelled.", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutdown"));
2386 }
2387 
2388 // Send a server message to the user(s)
2389 void World::SendServerMessage(ServerMessageType type, const char* text, Player* player)
2390 {
2391  WorldPacket data(SMSG_SERVER_MESSAGE, 50); // guess size
2392  data << uint32(type);
2393  if (type <= SERVER_MSG_STRING)
2394  data << text;
2395 
2396  if (player)
2397  player->GetSession()->SendPacket(&data);
2398  else
2399  SendGlobalMessage(&data);
2400 }
2401 
2402 void World::UpdateSessions(time_t diff)
2403 {
2404  // Add new sessions
2405  WorldSession* sess;
2406  while (addSessQueue.next(sess))
2407  AddSession_ (sess);
2408 
2409  // Then send an update signal to remaining ones
2410  for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
2411  {
2412  next = itr;
2413  ++next;
2414 
2415  if (!itr->second)
2416  continue;
2417 
2418  // and remove not active sessions from the list
2419  if (!itr->second->Update(diff)) // As interval = 0
2420  {
2421  if (!RemoveQueuedPlayer(itr->second) && itr->second && getConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
2422  m_disconnects[itr->second->GetAccountId()] = time(NULL);
2423  delete itr->second;
2424  m_sessions.erase(itr);
2425  }
2426  }
2427 }
2428 
2429 // This handles the issued and queued CLI commands
2431 {
2432  CliCommandHolder::Print* zprint = NULL;
2433  void* callbackArg = NULL;
2434  CliCommandHolder* command;
2435  while (cliCmdQueue.next(command))
2436  {
2437  sLog.outDebug("CLI command under processing...");
2438  zprint = command->m_print;
2439  callbackArg = command->m_callbackArg;
2440  CliHandler handler(callbackArg, zprint);
2441  handler.ParseCommands(command->m_command);
2442 
2443  if (command->m_commandFinished)
2444  command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage());
2445 
2446  delete command;
2447  }
2448 }
2449 
2451 {
2452  if (m_Autobroadcasts.empty())
2453  return;
2454 
2455  std::string msg;
2456 
2457  std::list<std::string>::const_iterator itr = m_Autobroadcasts.begin();
2458  std::advance(itr, rand() % m_Autobroadcasts.size());
2459  msg = *itr;
2460 
2461  uint32 abcenter = sConfig.GetIntDefault("AutoBroadcast.Center", 0);
2462 
2463  if (abcenter == 0)
2464  sWorld.SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
2465 
2466  else if (abcenter == 1)
2467  {
2468  WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1));
2469  data << msg;
2470  sWorld.SendGlobalMessage(&data);
2471  }
2472 
2473  else if (abcenter == 2)
2474  {
2475  sWorld.SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
2476 
2477  WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1));
2478  data << msg;
2479  sWorld.SendGlobalMessage(&data);
2480  }
2481 
2482  sLog.outString("AutoBroadcast: '%s'", msg.c_str());
2483 }
2484 
2486 {
2489 }
2490 
2492 {
2493  m_resultQueue->Update();
2494 }
2495 
2497 {
2499  "SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId);
2500 }
2501 
2503 {
2504  if (resultCharCount)
2505  {
2506  Field* fields = resultCharCount->Fetch();
2507  uint32 charCount = fields[0].GetUInt32();
2508 
2509  LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
2510  LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
2511  }
2512 }
2513 
2515 {
2516  time_t mostRecentQuestTime;
2517 
2518  QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(time) FROM character_queststatus_daily");
2519  if (result)
2520  {
2521  Field* fields = result->Fetch();
2522  mostRecentQuestTime = (time_t)fields[0].GetUInt64();
2523  }
2524  else
2525  mostRecentQuestTime = 0;
2526 
2527  // client built-in time for reset is 6:00 AM
2528  // FIX ME: client not show day start time
2529  time_t curTime = time(NULL);
2530  tm localTm = *localtime(&curTime);
2531  localTm.tm_hour = 6;
2532  localTm.tm_min = 0;
2533  localTm.tm_sec = 0;
2534 
2535  // current day reset time
2536  time_t curDayResetTime = mktime(&localTm);
2537 
2538  // last reset time before current moment
2539  time_t resetTime = (curTime < curDayResetTime) ? curDayResetTime - DAY : curDayResetTime;
2540 
2541  // need reset (if we have quest time before last reset time (not processed by some reason)
2542  if (mostRecentQuestTime && mostRecentQuestTime <= resetTime)
2543  m_NextDailyQuestReset = mostRecentQuestTime;
2544  else
2545  {
2546  // plan next reset time
2547  m_NextDailyQuestReset = (curTime >= curDayResetTime) ? curDayResetTime + DAY : curDayResetTime;
2548  }
2549 }
2550 
2552 {
2553  QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT allowedSecurityLevel from realmlist WHERE id = '%d'", realmID);
2554  if (result)
2555  {
2556  m_allowedSecurityLevel = AccountTypes(result->Fetch()->GetUInt16());
2557  sLog.outDebug("Allowed Level: %u Result %u", m_allowedSecurityLevel, result->Fetch()->GetUInt16());
2558  }
2559 }
2560 
2562 {
2563  sLog.outDetail("Daily quests reset for all characters.");
2564  CharacterDatabase.Execute("DELETE FROM character_queststatus_daily");
2565  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2566  if (itr->second->GetPlayer())
2567  itr->second->GetPlayer()->ResetDailyQuestStatus();
2568 
2569  // change available dailies
2570  sPoolMgr.ChangeDailyQuests();
2571 }
2572 
2573 void World::SetPlayerLimit(int32 limit, bool /*needUpdate*/)
2574 {
2575  m_playerLimit = limit;
2576 }
2577 
2579 {
2582 }
2583 
2585 {
2586  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT db_version FROM version LIMIT 1");
2587  if (result)
2588  {
2589  Field* fields = result->Fetch();
2590 
2591  m_DBVersion = fields[0].GetString();
2592  }
2593  else
2594  m_DBVersion = "unknown world database";
2595 }
2596 
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
Definition: World.cpp:2203
WorldSession * FindSession(uint32 id) const
Definition: World.cpp:157
uint8 Expansion() const
Definition: WorldSession.h:121
uint32 mail_timer_expires
Definition: World.h:799
void KickAll()
Definition: World.cpp:2159
void SetNewCharString(std::string str)
Definition: World.h:551
void LoadOpcodeProtection()
Definition: World.cpp:1758
void UpdateMaxSessionCounters()
Definition: World.cpp:2578
uint32 GetLiquidFlags(uint32 liquidType)
Definition: DBCStores.cpp:714
#define sConfig
Definition: Config.h:52
time_t GetInterval() const
Definition: Timer.h:126
OpcodePenalty
What should happen if the threshold per interval is passed.
Definition: World.h:440
CommandFinished * m_commandFinished
Definition: World.h:423
void LoadLootTables()
Definition: LootMgr.h:431
void SendZoneText(uint32 zone, const char *text, WorldSession *self=0, uint32 team=0)
Definition: World.cpp:2151
void SetResultQueue(SqlResultQueue *queue)
Definition: Database.cpp:332
char * m_command
Definition: World.h:420
#define CreatureEAI_Mgr
void LoadConfigSettings(bool reload=false)
Definition: World.cpp:403
Using this opcode is time protected.
Definition: Opcodes.h:1104
OpcodeHandler opcodeTable[NUM_MSG_TYPES]
Definition: Opcodes.cpp:22
time_t m_NextDailyQuestReset
Definition: World.h:840
#define sOutdoorPvPMgr
Definition: OutdoorPvPMgr.h:79
void Update(uint32 diff)
Definition: World.cpp:1795
#define sDisableMgr
Definition: DisableMgr.h:73
void setEnableLineOfSightCalc(bool pVal)
Definition: IVMapManager.h:78
void SendGlobalMessage(WorldPacket *packet, WorldSession *self=0, uint32 team=0)
Definition: World.cpp:1971
bool SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self=0, uint32 team=0)
Definition: World.cpp:2128
DatabaseType WorldDatabase
Accessor to the world database.
Definition: Main.cpp:53
static char * LineFromMessage(char *&pos)
Definition: Chat.h:61
std::string m_SQLUpdatesPath
Definition: World.h:854
#define DEFAULT_VISIBILITY_INSTANCE
Definition: Object.h:41
void SendWorldText(int32 string_id,...)
Definition: World.cpp:2002
static void InitVisibleBits()
Definition: Player.cpp:3649
uint32 m_updateTimeCount
Definition: World.h:801
uint32 GetActiveAndQueuedSessionCount() const
Definition: World.h:472
void * dtCustomAlloc(int size, dtAllocHint)
Definition: MoveMap.h:29
#define auctionbot
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition: Timer.h:78
void _UpdateGameTime()
Definition: World.cpp:2289
ACE_Based::LockedQueue< CliCommandHolder *, ACE_Thread_Mutex > cliCmdQueue
Definition: World.h:836
QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:400
IntervalTimer extmail_timer
Definition: World.h:797
void SendAuthWaitQue(uint32 position)
static float m_MaxVisibleDistanceInInstances
Definition: World.h:828
void DetectDBCLang()
Definition: World.cpp:1652
AccountTypes
Definition: Common.h:188
Definition: World.h:457
void UpdateAllowedSecurity()
Definition: World.cpp:2551
SqlResultQueue * m_resultQueue
Definition: World.h:837
Definition: Field.h:24
void SendGMText(int32 string_id,...)
Definition: World.cpp:2055
#define sConsole
Definition: Console.h:99
void LoadDBVersion()
Definition: World.cpp:2584
SessionMap m_sessions
Definition: World.h:807
void SendGlobalText(const char *text, WorldSession *self)
Definition: World.cpp:2110
std::list< std::string > m_Autobroadcasts
Definition: World.h:853
bool Execute(const char *sql)
Definition: Database.cpp:420
uint32 GetZoneId() const
Definition: Object.cpp:1176
uint32 getMSTime()
Definition: Timer.h:32
static void clear()
Definition: MoveMap.cpp:67
#define DEFAULT_VISIBILITY_NOTIFY_PERIOD
Definition: NGrid.h:28
void Update(time_t diff)
Definition: Timer.h:104
static uint8 m_ExitCode
Definition: World.h:787
#define sLog
Log class singleton.
Definition: Log.h:187
#define MAX_MONEY_AMOUNT
Definition: Player.h:742
AccountTypes m_allowedSecurityLevel
Definition: World.h:818
void UpdateRealmCharCount(uint32 accid)
Definition: World.cpp:2496
time_t m_gameTime
Definition: World.h:795
bool HasRecentlyDisconnected(WorldSession *)
Definition: World.cpp:262
ACE_INT32 int32
Definition: Define.h:67
void RemoveWeather(uint32 zone_id)
Definition: World.cpp:374
bool next(T &result)
Definition: LockedQueue.h:68
uint32 m_maxActiveSessionCount
Definition: World.h:810
unsigned long escape_string(char *to, const char *from, unsigned long length)
Definition: Database.cpp:212
uint32 m_availableDbcLocaleMask
Definition: World.h:820
QueryResult_AutoPtr Query(const char *sql)
Definition: Database.cpp:383
WeatherMap m_weathers
Definition: World.h:805
Weather * AddWeather(uint32 zone_id)
Definition: World.cpp:387
void SetInQueue(bool state)
Definition: WorldSession.h:129
#define DEFAULT_SOCKET_SELECT_TIME
Definition: SystemConfig.h:49
static bool ExistMapAndVMap(uint32 mapid, float x, float y)
Definition: MapManager.cpp:256
BanMode
void ShutdownCancel()
Definition: World.cpp:2372
bool Passed()
Definition: Timer.h:109
uint32 mail_timer
Definition: World.h:798
uint32 GetAccountId() const
Definition: WorldSession.h:100
int ParseCommands(const char *text)
Definition: Chat.cpp:935
World()
Definition: World.cpp:87
static void SendExternalMails()
Definition: Mail.cpp:1065
void LoadAutobroadcasts()
Definition: World.cpp:1716
unsigned long status
Definition: Opcodes.h:1112
~World()
Definition: World.cpp:110
void LoadSkillExtraItemTable()
#define sObjectMgr
Definition: ObjectMgr.h:1285
void SendPacket(WorldPacket const *packet)
static void clear()
void UpdateSessions(time_t diff)
Definition: World.cpp:2402
DBCStorage< MapEntry > sMapStore(MapEntryfmt)
std::string m_DBVersion
Definition: World.h:850
const char * GetString() const
Definition: Field.h:41
void SetInterval(time_t interval)
Definition: Timer.h:122
#define DEFAULT_MAX_LEVEL
Definition: DBCEnums.h:24
BanReturn
uint32 threshold
Sets the maximum count one protected packet per Interval can be processed per session.
Definition: World.h:449
Definition: Common.h:181
void AddSession_(WorldSession *s)
Definition: World.cpp:189
void SendGlobalGMMessage(WorldPacket *packet, WorldSession *self=0, uint32 team=0)
Definition: World.cpp:1986
Queue m_QueuedPlayer
Definition: World.h:843
void Print(void *, const char *)
Definition: World.h:416
void InitDailyQuestResetTime()
Definition: World.cpp:2514
Definition: Common.h:179
IntervalTimer m_timers[WUPDATE_COUNT]
Definition: World.h:796
void SetInitialWorldSettings()
Definition: World.cpp:1165
void UpdateResultQueue()
Definition: World.cpp:2491
void LoadGameObjectModelList()
char const * localeNames[MAX_LOCALE]
Definition: Common.cpp:20
void LoadSkillDiscoveryTable()
Print * m_print
Definition: World.h:421
bool ReGenerate()
Definition: Weather.cpp:60
Player * FindPlayerInZone(uint32 zone)
Definition: World.cpp:139
ACE_UINT8 uint8
Definition: Define.h:73
#define sWaypointMgr
#define UI64FMTD
Definition: Common.h:149
DBCStorage< ChrRacesEntry > sChrRacesStore(ChrRacesEntryfmt)
std::string GetCppString() const
Definition: Field.h:52
void ShutdownMsg(bool show=false, Player *player=NULL)
Definition: World.cpp:2347
const bool & IsInWorld() const
Definition: Object.h:129
time_t m_startTime
Definition: World.h:794
uint32 GetQueueSize() const
Definition: World.h:522
const uint8 MAX_LOCALE
Definition: Common.h:224
#define sPoolMgr
Definition: PoolMgr.h:162
DatabaseType LoginDatabase
Accessor to the realm/login database.
Definition: Main.cpp:55
void Update(time_t)
Definition: MapManager.cpp:225
#define DEFAULT_VISIBILITY_BGARENAS
Definition: Object.h:42
uint32 TimeStringToSecs(const std::string &timestring)
Definition: Util.cpp:171
INSTANTIATE_SINGLETON_1(World)
void * m_callbackArg
Definition: World.h:419
uint32 m_updateTime
Definition: World.h:800
void AddSession(WorldSession *s)
Definition: World.cpp:183
OpcodePenalty penalty
What should happen if the threshold per interval is passed.
Definition: World.h:451
bool KickPlayer(const std::string &playerName)
Definition: World.cpp:2178
void InitializeThreadUnsafe(const std::vector< uint32 > &mapIds)
Definition: MoveMap.cpp:92
static int32 m_visibility_notify_periodInBGArenas
Definition: World.h:833
#define sSpellMgr
Definition: SpellMgr.h:1239
std::string m_dataPath
Definition: World.h:824
static int32 m_visibility_notify_periodOnContinents
Definition: World.h:831
#define sCreatureTextMgr
CWardenDataStorage WardenDataStorage
Definition: WardenWin.cpp:35
uint32 m_ShutdownMask
Definition: World.h:789
void dtCustomFree(void *ptr)
Definition: MoveMap.h:34
void SetPlayerLimit(int32 limit, bool needUpdate=false)
Definition: World.cpp:2573
uint32 m_configs[CONFIG_VALUE_COUNT]
Definition: World.h:816
#define DEBUG_LOG(...)
Definition: Log.h:194
#define sSmartWaypointMgr
#define MIN_MAP_UPDATE_DELAY
Definition: GridDefines.h:41
bool RemoveQueuedPlayer(WorldSession *session)
Definition: World.cpp:312
bool AsyncPQuery(Class *object, void(Class::*method)(QueryResult_AutoPtr), const char *format,...) ATTR_PRINTF(4
Definition: DatabaseImpl.h:128
DisconnectMap m_disconnects
Definition: World.h:809
#define sConditionMgr
Definition: ConditionMgr.h:312
Weather * FindWeather(uint32 id) const
Definition: World.cpp:363
static int32 m_visibility_notify_periodInInstances
Definition: World.h:832
bool PExecute(const char *format,...) ATTR_PRINTF(2
Definition: Database.cpp:441
uint32 m_maxQueuedSessionCount
Definition: World.h:811
#define sAccountMgr
Definition: AccountMgr.h:60
void add(const T &item)
Definition: LockedQueue.h:55
#define _FULLVERSION
Definition: SystemConfig.h:40
static void DeleteOldCharacters()
Definition: Player.cpp:4109
#define sInstanceSaveMgr
uint32 GetPlayerAmountLimit() const
Definition: World.h:500
ProtectedOpcodeProperties const & GetProtectedOpcodeProperties(uint32 opcode)
Definition: World.cpp:1789
float rate_values[MAX_RATES]
Definition: World.h:815
std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
Definition: Util.cpp:148
static float m_MaxVisibleDistanceInBGArenas
Definition: World.h:829
bool IsFFAPvPRealm()
Definition: World.h:678
bool RemoveBanAccount(BanMode mode, std::string nameOrIP)
Definition: World.cpp:2264
#define DEFAULT_PLAYER_LIMIT
Definition: SystemConfig.h:46
void setEnableHeightCalc(bool pVal)
Definition: IVMapManager.h:83
uint32 m_updateTimeSum
Definition: World.h:800
#define MAX_VISIBILITY_DISTANCE
Definition: Object.h:38
Protected Opcode.
Definition: World.h:447
const char * GetName() const
Definition: Object.h:692
ACE_Based::LockedQueue< WorldSession *, ACE_Thread_Mutex > addSessQueue
Definition: World.h:847
void LoadRandomEnchantmentsTable()
ACE_UINT64 uint64
Definition: Define.h:70
void InitResultQueue()
Definition: World.cpp:2485
void SetMotd(std::string motd)
Definition: World.h:540
void SendServerMessage(ServerMessageType type, const char *text="", Player *player=NULL)
Definition: World.cpp:2389
static volatile bool m_stopEvent
Definition: World.h:786
void Init(bool reload=false)
void SendAutoBroadcast()
Definition: World.cpp:2450
#define sGameEventMgr
Definition: GameEventMgr.h:179
void LoadTransports()
Definition: Transports.cpp:26
static void preventSpellsFromBeingTestedForLoS(const char *pSpellIdString)
Definition: VMapFactory.cpp:77
bool UpdateWeather()
Definition: Weather.cpp:198
void Reset()
Definition: Timer.h:113
#define NUM_MSG_TYPES
Definition: Opcodes.h:1095
uint32 GetZone()
Definition: Weather.h:57
ACE_Refcounted_Auto_Ptr< QueryResult, ACE_Null_Mutex > QueryResult_AutoPtr
Definition: QueryResult.h:113
uint32 interval
Interval for threshold, in milliseconds.&#39;.
Definition: World.h:450
uint32 m_currentTime
Definition: World.h:802
LocaleConstant m_defaultDbcLocale
Definition: World.h:819
bool m_allowMovement
Definition: World.h:822
uint32 realmID
Id of the realm.
Definition: Main.cpp:57
Definition: Common.h:180
void _UpdateRealmCharCount(QueryResult_AutoPtr resultCharCount, uint32 accountId)
Definition: World.cpp:2502
uint32 m_ShutdownTimer
Definition: World.h:788
void RecordTimeDiff(const char *text,...)
Definition: World.cpp:1690
ServerMessageType
Definition: World.h:43
void ResetDailyQuests()
Definition: World.cpp:2561
#define NOMINAL_MELEE_RANGE
Definition: Object.h:47
ACE_Atomic_Op< ACE_Thread_Mutex, long > m_scheduledScripts
Definition: World.h:792
static void preventPathfindingOnMaps(const char *ignoreMapIds)
Definition: MoveMap.cpp:42
#define sFormationMgr
#define sAuctionMgr
#define sBattlegroundMgr
uint32 GetDefaultDbcLocale() const
Definition: World.h:561
bool RemoveSession(uint32 id)
Definition: World.cpp:168
void ProcessCliCommands()
Definition: World.cpp:2430
void AddQueuedPlayer(WorldSession *)
Definition: World.cpp:294
static IVMapManager * createOrGetVMapManager()
#define ASSERT
Definition: Errors.h:33
void LoadSQLUpdates()
Definition: World.cpp:1069
void SetMapUpdateInterval(uint32 t)
Definition: MapManager.h:72
void Initialize(void)
Definition: MapManager.cpp:53
char * name[16]
Definition: DBCStructure.h:164
static MMapManager * createOrGetMMapManager()
Definition: MoveMap.cpp:34
static volatile uint32 m_worldLoopCounter
Definition: World.h:460
#define sScriptMgr
Definition: Group.h:526
uint32 getConfig(uint32 index) const
Definition: World.h:665
void SetGridCleanUpDelay(uint32 t)
Definition: MapManager.h:64
WorldSession * GetSession() const
Definition: Player.h:1959
LocaleConstant
Definition: Common.h:211
#define sWorld
Definition: World.h:860
void SetCurrent(time_t current)
Definition: Timer.h:118
void LoadM2Cameras(std::string const &dataPath)
Definition: M2Stores.cpp:164
int32 GetQueuePos(WorldSession *)
Definition: World.cpp:283
bool HasSentErrorMessage()
Definition: Chat.h:84
#define CONTACT_DISTANCE
Definition: Object.h:34
void KickAllLess(AccountTypes sec)
Definition: World.cpp:2169
DatabaseType CharacterDatabase
Accessor to the character database.
Definition: Main.cpp:54
void uint32 GetSecurity() const
Definition: WorldSession.h:96
void LoadDBCStores(const std::string &dataPath)
Definition: DBCStores.cpp:220
ACE_UINT32 uint32
Definition: Define.h:71
static float m_MaxVisibleDistanceOnContinents
Definition: World.h:827
static Player * GetPlayer(WorldObject &object, uint64 guid)
Definition: Unit.cpp:10597
Definition: Player.h:922
#define ticketmgr
Definition: TicketMgr.h:94
int32 m_playerLimit
Definition: World.h:817
UNORDERED_MAP< uint32, ProtectedOpcodeProperties > _protectedOpcodesProperties
Definition: World.h:855
#define MAX_LEVEL
Definition: DBCEnums.h:28
#define DEFAULT_WORLDSERVER_PORT
Definition: SystemConfig.h:47
void ForceGameEventUpdate()
Definition: World.cpp:1962
#define vsnprintf
Definition: Common.h:131
uint32 GetActiveSessionCount() const
Definition: World.h:476
static void FillMessageData(WorldPacket *data, WorldSession *session, uint8 type, uint32 language, const char *channelName, uint64 target_guid, const char *message, Unit *speaker)
Definition: Chat.cpp:1515
#define sSmartScriptMgr
#define DEFAULT_VISIBILITY_DISTANCE
Definition: Object.h:40
void LoadIp2nation()
Definition: World.cpp:1744
void ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
Definition: World.cpp:2321