OregonCore  revision be9e804-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 <https://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 "Utilities/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.LoadPointOfInterestLocales();
1262  sObjectMgr.SetDBCLocaleIndex(GetDefaultDbcLocale()); // Get once for all the locale index of DBC language (console/broadcasts)
1263  sConsole.SetLoadingLabel(">>> Localization strings loaded");
1264 
1265  sConsole.SetLoadingLabel("Loading Page Texts...");
1266  sObjectMgr.LoadPageTexts();
1267 
1268  sConsole.SetLoadingLabel("Loading Game Object Templates..."); // must be after LoadPageTexts
1269  sObjectMgr.LoadGameobjectInfo();
1270 
1271  sConsole.SetLoadingLabel("Loading Spell Chain Data...");
1272  sSpellMgr.LoadSpellChains();
1273 
1274  sConsole.SetLoadingLabel("Loading Spell Required Data...");
1275  sSpellMgr.LoadSpellRequired();
1276 
1277  sConsole.SetLoadingLabel("Loading Spell Group types...");
1278  sSpellMgr.LoadSpellGroups();
1279 
1280  sConsole.SetLoadingLabel("Loading Spell Learn Skills...");
1281  sSpellMgr.LoadSpellLearnSkills(); // must be after LoadSpellChains
1282 
1283  sConsole.SetLoadingLabel("Loading Spell Learn Spells...");
1284  sSpellMgr.LoadSpellLearnSpells();
1285 
1286  sConsole.SetLoadingLabel("Loading Spell Proc Event conditions...");
1287  sSpellMgr.LoadSpellProcEvents();
1288 
1289  sConsole.SetLoadingLabel("Loading Spell Dummy Conditions...");
1290  sSpellMgr.LoadSpellDummyCondition();
1291 
1292  sConsole.SetLoadingLabel("Loading Aggro Spells Definitions...");
1293  sSpellMgr.LoadSpellThreats();
1294 
1295  sConsole.SetLoadingLabel("Loading NPC Texts...");
1296  sObjectMgr.LoadGossipText();
1297 
1298  sConsole.SetLoadingLabel("Loading Spell Group Stack Rules...");
1299  sSpellMgr.LoadSpellGroupStackRules();
1300 
1301  sConsole.SetLoadingLabel("Loading Enchant Spells Proc datas...");
1302  sSpellMgr.LoadSpellEnchantProcData();
1303 
1304  sConsole.SetLoadingLabel("Loading Item Random Enchantments Table...");
1306 
1307  sConsole.SetLoadingLabel("Loading Items..."); // must be after LoadRandomEnchantmentsTable and LoadPageTexts
1308  sObjectMgr.LoadItemTemplates();
1309 
1310  sConsole.SetLoadingLabel("Loading Item Texts...");
1311  sObjectMgr.LoadItemTexts();
1312 
1313  sConsole.SetLoadingLabel("Loading Creature Model Based Info Data...");
1314  sObjectMgr.LoadCreatureModelInfo();
1315 
1316  sConsole.SetLoadingLabel("Loading Equipment templates...");
1317  sObjectMgr.LoadEquipmentTemplates();
1318 
1319  sConsole.SetLoadingLabel("Loading Creature Base Stats...");
1320  sObjectMgr.LoadCreatureClassLevelStats();
1321 
1322  sConsole.SetLoadingLabel("Loading Creature templates...");
1323  sObjectMgr.LoadCreatureTemplates();
1324 
1325  sConsole.SetLoadingLabel("Loading Creature Reputation OnKill Data...");
1326  sObjectMgr.LoadReputationOnKill();
1327 
1328  sConsole.SetLoadingLabel("Loading Reputation Spillover Data...");
1329  sObjectMgr.LoadReputationSpilloverTemplate();
1330 
1331  sConsole.SetLoadingLabel("Loading Points Of Interest Data...");
1332  sObjectMgr.LoadPointsOfInterest();
1333 
1334  sConsole.SetLoadingLabel("Loading Pet Create Spells...");
1335  sObjectMgr.LoadPetCreateSpells();
1336 
1337  sConsole.SetLoadingLabel("Loading Creature Data...");
1338  sObjectMgr.LoadCreatures();
1339 
1340  sConsole.SetLoadingLabel("Loading Temporary Summon Data...");
1341  sObjectMgr.LoadTempSummons(); // must be after LoadCreatureTemplates() and LoadGameObjectTemplates()
1342 
1343  sConsole.SetLoadingLabel("Loading Creature Linked Respawn...");
1344  sObjectMgr.LoadCreatureLinkedRespawn(); // must be after LoadCreatures()
1345 
1346  sConsole.SetLoadingLabel("Loading Creature Addon Data...");
1347  sObjectMgr.LoadCreatureAddons(); // must be after LoadCreatureTemplates() and LoadCreatures()
1348 
1349  sConsole.SetLoadingLabel("Loading Creature Respawn Data..."); // must be after PackInstances()
1350  sObjectMgr.LoadCreatureRespawnTimes();
1351 
1352  sConsole.SetLoadingLabel("Loading Gameobject Data...");
1353  sObjectMgr.LoadGameobjects();
1354 
1355  sConsole.SetLoadingLabel("Loading Gameobject Respawn Data..."); // must be after PackInstances()
1356  sObjectMgr.LoadGameobjectRespawnTimes();
1357 
1358  sConsole.SetLoadingLabel("Loading Objects Pooling Data...");
1359  sPoolMgr.LoadFromDB();
1360 
1361  sConsole.SetLoadingLabel("Loading Weather Data...");
1362  sObjectMgr.LoadWeatherZoneChances();
1363 
1364  sConsole.SetLoadingLabel("Loading Disables");
1365  sDisableMgr.LoadDisables(); // must be before loading quests
1366 
1367  sConsole.SetLoadingLabel("Loading Quests...");
1368  sObjectMgr.LoadQuests(); // must be loaded after DBCs, creature_template, item_template, gameobject tables
1369 
1370  sConsole.SetLoadingLabel("Checking Quest Disables");
1371  sDisableMgr.CheckQuestDisables(); // must be after loading quests
1372 
1373  sConsole.SetLoadingLabel("Loading Quests Starters and Enders...");
1374  sObjectMgr.LoadQuestStartersAndEnders(); // must be after quest load
1375 
1376  sConsole.SetLoadingLabel("Loading Quest Pooling Data...");
1377  sPoolMgr.LoadQuestPools();
1378 
1379  sConsole.SetLoadingLabel("Loading Game Event Data..."); // must be after loading pools fully
1380  sGameEventMgr.LoadFromDB();
1381 
1382  sConsole.SetLoadingLabel("Loading AreaTrigger definitions...");
1383  sObjectMgr.LoadAreaTriggerTeleports();
1384 
1385  sConsole.SetLoadingLabel("Loading Access Requirements...");
1386  sObjectMgr.LoadAccessRequirements(); // must be after item template load
1387 
1388  sConsole.SetLoadingLabel("Loading Quest Area Triggers...");
1389  sObjectMgr.LoadQuestAreaTriggers(); // must be after LoadQuests
1390 
1391  sConsole.SetLoadingLabel("Loading Tavern Area Triggers...");
1392  sObjectMgr.LoadTavernAreaTriggers();
1393 
1394  sConsole.SetLoadingLabel("Loading AreaTrigger script names...");
1395  sObjectMgr.LoadAreaTriggerScripts();
1396 
1397  sConsole.SetLoadingLabel("Loading Graveyard-zone links...");
1398  sObjectMgr.LoadGraveyardZones();
1399 
1400  sConsole.SetLoadingLabel("Loading Spell target coordinates...");
1401  sSpellMgr.LoadSpellTargetPositions();
1402 
1403  sConsole.SetLoadingLabel("Loading SpellAffect definitions...");
1404  sSpellMgr.LoadSpellAffects();
1405 
1406  sConsole.SetLoadingLabel("Loading spell pet auras...");
1407  sSpellMgr.LoadSpellPetAuras();
1408 
1409  sConsole.SetLoadingLabel("Loading spell extra attributes...");
1410  sSpellMgr.LoadSpellCustomAttr();
1411 
1412  sLog.outString("Loading GameObject models...");
1414 
1415  sConsole.SetLoadingLabel("Loading linked spells...");
1416  sSpellMgr.LoadSpellLinked();
1417 
1418  sConsole.SetLoadingLabel("Loading custom spell cooldowns...");
1419  sSpellMgr.LoadSpellCustomCooldowns();
1420 
1421  sConsole.SetLoadingLabel("Loading Player Create Data...");
1422  sObjectMgr.LoadPlayerInfo();
1423 
1424  sConsole.SetLoadingLabel("Loading Exploration BaseXP Data...");
1425  sObjectMgr.LoadExplorationBaseXP();
1426 
1427  sConsole.SetLoadingLabel("Loading Pet Name Parts...");
1428  sObjectMgr.LoadPetNames();
1429 
1430  sConsole.SetLoadingLabel("Loading the max pet number...");
1431  sObjectMgr.LoadPetNumber();
1432 
1433  sConsole.SetLoadingLabel("Loading pet level stats...");
1434  sObjectMgr.LoadPetLevelInfo();
1435 
1436  sConsole.SetLoadingLabel("Loading Player Corpses...");
1437  sObjectMgr.LoadCorpses();
1438 
1439  sConsole.SetLoadingLabel("Loading Loot Tables...");
1440  LoadLootTables();
1441 
1442  sConsole.SetLoadingLabel("Loading Skill Discovery Table...");
1444 
1445  sConsole.SetLoadingLabel("Loading Skill Extra Item Table...");
1447 
1448  sConsole.SetLoadingLabel("Loading Skill Fishing base level requirements...");
1449  sObjectMgr.LoadFishingBaseSkillLevel();
1450 
1451  // Load dynamic data tables from the database
1452  sConsole.SetLoadingLabel("Loading Item Auctions...");
1453  sAuctionMgr->LoadAuctionItems();
1454  sConsole.SetLoadingLabel("Loading Auctions...");
1455  sAuctionMgr->LoadAuctions();
1456 
1457  sConsole.SetLoadingLabel("Loading Guilds...");
1458  sObjectMgr.LoadGuilds();
1459 
1460  sConsole.SetLoadingLabel("Loading ArenaTeams...");
1461  sObjectMgr.LoadArenaTeams();
1462 
1463  sConsole.SetLoadingLabel("Loading Groups...");
1464  sObjectMgr.LoadGroups();
1465 
1466  sConsole.SetLoadingLabel("Loading ReservedNames...");
1467  sObjectMgr.LoadReservedPlayersNames();
1468 
1469  sConsole.SetLoadingLabel("Loading GameObjects for quests...");
1470  sObjectMgr.LoadGameObjectForQuests();
1471 
1472  sConsole.SetLoadingLabel("Loading BattleMasters...");
1473  sObjectMgr.LoadBattleMastersEntry();
1474 
1475  sConsole.SetLoadingLabel("Loading GameTeleports...");
1476  sObjectMgr.LoadGameTele();
1477 
1478  sConsole.SetLoadingLabel("Loading Npc Text Id...");
1479  sObjectMgr.LoadNpcTextId(); // must be after load Creature and NpcText
1480 
1481  sConsole.SetLoadingLabel( "Loading Gossip scripts...");
1482  sObjectMgr.LoadGossipScripts(); // must be before gossip menu options
1483 
1484  sConsole.SetLoadingLabel("Loading Gossip menu...");
1485  sObjectMgr.LoadGossipMenu();
1486 
1487  sConsole.SetLoadingLabel("Loading Gossip menu options...");
1488  sObjectMgr.LoadGossipMenuItems();
1489 
1490  sConsole.SetLoadingLabel("Loading Vendors...");
1491  sObjectMgr.LoadVendors(); // must be after load CreatureTemplate and ItemTemplate
1492 
1493  sConsole.SetLoadingLabel("Loading Trainers...");
1494  sObjectMgr.LoadTrainerSpell(); // must be after load CreatureTemplate
1495 
1496  sConsole.SetLoadingLabel("Loading Waypoints...");
1497  sWaypointMgr->Load();
1498 
1499  sConsole.SetLoadingLabel("Loading SmartAI Waypoints...");
1500  sSmartWaypointMgr->LoadFromDB();
1501 
1502  sConsole.SetLoadingLabel("Loading Creature Formations...");
1503  sFormationMgr.LoadCreatureFormations();
1504 
1505  sConsole.SetLoadingLabel("Loading Conditions...");
1506  sConditionMgr.LoadConditions();
1507 
1508  sConsole.SetLoadingLabel("Loading GM tickets...");
1509  ticketmgr.LoadGMTickets();
1510 
1511  sConsole.SetLoadingLabel("Loading GM surveys...");
1512  ticketmgr.LoadGMSurveys();
1513 
1514  // Handle outdated emails (delete/return)
1515  sConsole.SetLoadingLabel("Returning old mails...");
1516  sObjectMgr.ReturnOrDeleteOldMails(false);
1517 
1518  sConsole.SetLoadingLabel("Loading Autobroadcasts...");
1520 
1521  sConsole.SetLoadingLabel("Loading Ip2nation...");
1522  LoadIp2nation();
1523 
1524  sConsole.SetLoadingLabel("Loading Refer-A-Friend...");
1525  sObjectMgr.LoadReferredFriends();
1526 
1527  sConsole.SetLoadingLabel("Loading Opcode Protection...");
1529 
1530  // Load and initialize scripts
1531  sConsole.SetLoadingLabel("Loading Scripts...");
1532  sObjectMgr.LoadQuestStartScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
1533  sObjectMgr.LoadQuestEndScripts(); // must be after load Creature/Gameobject(Template/Data) and QuestTemplate
1534  sObjectMgr.LoadSpellScripts(); // must be after load Creature/Gameobject(Template/Data)
1535  sObjectMgr.LoadGameObjectScripts(); // must be after load Creature/Gameobject(Template/Data)
1536  sObjectMgr.LoadEventScripts(); // must be after load Creature/Gameobject(Template/Data)
1537  sObjectMgr.LoadWaypointScripts();
1538 
1539  sConsole.SetLoadingLabel("Loading Scripts text locales..."); // must be after Load*Scripts calls
1540  sObjectMgr.LoadDbScriptStrings();
1541 
1542  sConsole.SetLoadingLabel("Loading CreatureEventAI Texts...");
1543  CreatureEAI_Mgr.LoadCreatureEventAI_Texts(false); // false, will checked in LoadCreatureEventAI_Scripts
1544 
1545  sConsole.SetLoadingLabel("Loading CreatureEventAI Summons...");
1546  CreatureEAI_Mgr.LoadCreatureEventAI_Summons(false); // false, will checked in LoadCreatureEventAI_Scripts
1547 
1548  sConsole.SetLoadingLabel("Loading CreatureEventAI Scripts...");
1549  CreatureEAI_Mgr.LoadCreatureEventAI_Scripts();
1550 
1551  sConsole.SetLoadingLabel("Loading Creature Texts...");
1552  sCreatureTextMgr->LoadCreatureTexts();
1553 
1554  sConsole.SetLoadingLabel("Loading Creature Text Locales...");
1555  sCreatureTextMgr->LoadCreatureTextLocales();
1556 
1557  sConsole.SetLoadingLabel("Loading SmartAI scripts...");
1558  sSmartScriptMgr->LoadSmartAIFromDB();
1559 
1560  sConsole.SetLoadingLabel("Initializing Scripts...");
1561  sScriptMgr.ScriptsInit();
1562 
1563  // Initialize game time and timers
1564  sLog.outDebug("DEBUG:: Initialize game time and timers");
1565  m_gameTime = time(NULL);
1567 
1568  tm local;
1569  time_t curr;
1570  time(&curr);
1571  local = *(localtime(&curr)); // dereference and assign
1572 
1573  LoginDatabase.PExecute("INSERT INTO uptime (realmid, starttime, uptime, revision) VALUES(%u, " UI64FMTD ", 0, '%s')",
1575 
1582  //Update "uptime" table based on configuration entry in minutes.
1583  m_timers[WUPDATE_CORPSES].SetInterval(20 * MINUTE * IN_MILLISECONDS);
1584  //erase corpses every 20 minutes
1586  // clean logs table every 14 days by default
1587 
1588  m_timers[WUPDATE_DELETECHARS].SetInterval(DAY * IN_MILLISECONDS); // check for chars to delete every day
1589 
1590  //to set mailtimer to return mails every day between 4 and 5 am
1591  //mailtimer is increased when updating auctions
1592  //one second is 1000 -(tested on win system)
1593 
1594  // handle timer for external mail
1596 
1597  mail_timer = ((((localtime(&m_gameTime)->tm_hour + 20) % 24) * HOUR * IN_MILLISECONDS) / m_timers[WUPDATE_AUCTIONS].GetInterval());
1598  //1440
1599  mail_timer_expires = ((DAY * IN_MILLISECONDS) / (m_timers[WUPDATE_AUCTIONS].GetInterval()));
1600  sLog.outDebug("Mail timer set to: %u, mail return is called every %u minutes", mail_timer, mail_timer_expires);
1601 
1602  // Initialize static helper structures
1605 
1606  // Initialize MapManager
1607  sConsole.SetLoadingLabel("Starting Map System");
1609 
1610  sConsole.SetLoadingLabel("Starting Game Event system...");
1611  uint32 nextGameEvent = sGameEventMgr.Initialize();
1612  m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent); //depend on next event
1613 
1614  // Load Warden Data
1615  sConsole.SetLoadingLabel("Loading Warden Data..." );
1617 
1618  // Initialize Battlegrounds
1619  sConsole.SetLoadingLabel("Starting Battleground System");
1620  sBattlegroundMgr.CreateInitialBattlegrounds();
1621  sBattlegroundMgr.InitAutomaticArenaPointDistribution();
1622 
1623  // Initialize outdoor pvp
1624  sConsole.SetLoadingLabel("Starting Outdoor PvP System");
1625  sOutdoorPvPMgr.InitOutdoorPvP();
1626 
1627  //Not sure if this can be moved up in the sequence (with static data loading) as it uses MapManager
1628  sConsole.SetLoadingLabel("Loading Transports...");
1630 
1631  sConsole.SetLoadingLabel("Loading Transports Events...");
1632  sObjectMgr.LoadTransportEvents();
1633 
1634  sConsole.SetLoadingLabel("Deleting expired bans...", false);
1635  LoginDatabase.Execute("DELETE FROM ip_banned WHERE unbandate <= UNIX_TIMESTAMP() AND unbandate<>bandate");
1636 
1637  sConsole.SetLoadingLabel("Starting objects Pooling system...", false);
1638  sPoolMgr.Initialize();
1639 
1640  sConsole.SetLoadingLabel("Calculate next daily quest reset time...", false);
1642 
1643  sConsole.SetLoadingLabel("Initialize AuctionHouseBot...", false);
1644  auctionbot.Initialize();
1645 
1646  // Delete all characters which have been deleted X days before
1648 
1649  sConsole.SetLoadingLabel("WORLD: World initialized");
1650 
1651  // Print startup time
1652  uint32 uStartInterval = getMSTimeDiff(uStartTime, getMSTime());
1653  sLog.outString( "SERVER STARTUP TIME: %i minutes %i seconds", uStartInterval / 60000, (uStartInterval % 60000) / 1000 );
1654 }
1655 
1657 {
1658  uint8 m_lang_confid = sConfig.GetIntDefault("DBC.Locale", 255);
1659 
1660  if (m_lang_confid != 255 && m_lang_confid >= MAX_LOCALE)
1661  {
1662  sLog.outError("Incorrect DBC.Locale! Must be >= 0 and < %d (set to 0)", MAX_LOCALE);
1663  m_lang_confid = LOCALE_enUS;
1664  }
1665 
1666  ChrRacesEntry const* race = sChrRacesStore.LookupEntry(1);
1667 
1668  std::string availableLocalsStr;
1669 
1670  uint8 default_locale = MAX_LOCALE;
1671  for (uint8 i = default_locale - 1; i < MAX_LOCALE; --i) // -1 will be 255 due to uint8
1672  {
1673  if (strlen(race->name[i]) > 0) // check by race names
1674  {
1675  default_locale = i;
1676  m_availableDbcLocaleMask |= (1 << i);
1677  availableLocalsStr += localeNames[i];
1678  availableLocalsStr += " ";
1679  }
1680  }
1681 
1682  if (default_locale != m_lang_confid && m_lang_confid < MAX_LOCALE &&
1683  (m_availableDbcLocaleMask & (1 << m_lang_confid)))
1684  default_locale = m_lang_confid;
1685 
1686  if (default_locale >= MAX_LOCALE)
1687  sLog.outFatal("Unable to determine your DBC Locale! (corrupt DBC?)");
1688 
1689  m_defaultDbcLocale = LocaleConstant(default_locale);
1690 
1691  sLog.outString("Using %s DBC Locale as default. All available DBC locales: %s", localeNames[m_defaultDbcLocale], availableLocalsStr.empty() ? "<none>" : availableLocalsStr.c_str());
1692 }
1693 
1694 void World::RecordTimeDiff(const char* text, ...)
1695 {
1696  if (m_updateTimeCount != 1)
1697  return;
1698  if (!text)
1699  {
1701  return;
1702  }
1703 
1704  uint32 thisTime = getMSTime();
1705  uint32 diff = getMSTimeDiff(m_currentTime, thisTime);
1706 
1707  if (diff >= m_configs[CONFIG_MIN_LOG_UPDATE])
1708  {
1709  va_list ap;
1710  char str[256];
1711  va_start(ap, text);
1712  vsnprintf(str, 256, text, ap);
1713  va_end(ap);
1714  sLog.outDetail("Difftime %s: %u.", str, diff);
1715  }
1716 
1717  m_currentTime = thisTime;
1718 }
1719 
1721 {
1722  m_Autobroadcasts.clear();
1723 
1724  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT text FROM autobroadcast");
1725 
1726  if (!result)
1727  {
1728  sLog.outString(">> Loaded 0 autobroadcasts definitions");
1729  return;
1730  }
1731 
1732  uint32 count = 0;
1733 
1734  do
1735  {
1736  Field* fields = result->Fetch();
1737  std::string message = fields[0].GetCppString();
1738  m_Autobroadcasts.push_back(message);
1739  ++count;
1740  }
1741 
1742  while (result->NextRow());
1743 
1744  sLog.outString( ">> Loaded %u autobroadcasts definitions", count);
1745 }
1746 
1747 
1749 {
1750  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT count(c.code) FROM ip2nationCountries c, ip2nation i WHERE c.code = i.country");
1751  uint32 count = 0;
1752 
1753  if (result)
1754  {
1755  Field* fields = result->Fetch();
1756  count = fields[0].GetUInt32();
1757  }
1758 
1759  sLog.outString(">> Loaded %u ip2nation definitions", count);
1760 }
1761 
1763 {
1764  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT `opcode`, `threshold`, `interval`, `penalty` FROM opcode_protection");
1765  uint64 count = 0;
1766 
1767  if (result)
1768  {
1769  do
1770  {
1771  Field* field = result->Fetch();
1773 
1774  uint32 opcode = field[0].GetUInt32();
1775  if (opcode >= NUM_MSG_TYPES)
1776  continue;
1777 
1778  prop.threshold = field[1].GetUInt32();
1779  prop.interval = field[2].GetUInt32();
1780  prop.penalty = (OpcodePenalty) field[3].GetUInt8();
1781 
1782  opcodeTable[opcode].status |= STATUS_PROTECTED;
1783  _protectedOpcodesProperties[opcode] = prop;
1784 
1785  count++;
1786  }
1787  while (result->NextRow());
1788  }
1789 
1790  sLog.outString(">> Loaded %lu opcode protections.", count);
1791 }
1792 
1794 {
1795  return _protectedOpcodesProperties[opcode];
1796 }
1797 
1798 // Update the World !
1800 {
1801  m_updateTime = uint32(diff);
1803  {
1804  if (m_updateTimeSum > m_configs[CONFIG_INTERVAL_LOG_UPDATE] && uint32(diff) >= m_configs[CONFIG_MIN_LOG_UPDATE])
1805  {
1806  sLog.outBasic("Update time diff: %u. Players online: %u.", m_updateTimeSum / m_updateTimeCount, GetActiveSessionCount());
1808  m_updateTimeCount = 1;
1809  }
1810  else
1811  {
1814  }
1815  }
1816 
1817  // Update the different timers
1818  for (int i = 0; i < WUPDATE_COUNT; ++i)
1819  {
1820  if (m_timers[i].GetCurrent() >= 0)
1821  m_timers[i].Update(diff);
1822  else
1823  m_timers[i].SetCurrent(0);
1824  }
1825 
1826  // Update the game time and check for shutdown time
1827  _UpdateGameTime();
1828 
1829  // Handle daily quests reset time
1831  {
1832  ResetDailyQuests();
1834  }
1835 
1836  // Handle external mail
1837  if (m_configs[CONFIG_EXTERNAL_MAIL] != 0)
1838  {
1839  extmail_timer.Update(diff);
1840  if (extmail_timer.Passed())
1841  {
1843  extmail_timer.Reset();
1844  }
1845  }
1846 
1847  // Handle auctions when the timer has passed
1848  if (m_timers[WUPDATE_AUCTIONS].Passed())
1849  {
1850  auctionbot.Update();
1852 
1853  // Update mails (return old mails with item, or delete them)
1854  //(tested... works on win)
1856  {
1857  mail_timer = 0;
1858  sObjectMgr.ReturnOrDeleteOldMails(true);
1859  }
1860 
1861  // Handle expired auctions
1862  sAuctionMgr->Update();
1863  }
1864 
1865  // Handle session updates when the timer has passed
1866  RecordTimeDiff(NULL);
1867  UpdateSessions(diff);
1868  RecordTimeDiff("UpdateSessions");
1869 
1870  // Handle weather updates when the timer has passed
1871  if (m_timers[WUPDATE_WEATHERS].Passed())
1872  {
1874 
1875  // Send an update signal to Weather objects
1876  WeatherMap::iterator itr, next;
1877  for (itr = m_weathers.begin(); itr != m_weathers.end(); itr = next)
1878  {
1879  next = itr;
1880  ++next;
1881 
1882  // and remove Weather objects for zones with no player
1883  //As interval > WorldTick
1884  if (!itr->second->Update(m_timers[WUPDATE_WEATHERS].GetInterval()))
1885  {
1886  delete itr->second;
1887  m_weathers.erase(itr);
1888  }
1889  }
1890  }
1891 
1892  // Update uptime table
1893  if (m_timers[WUPDATE_UPTIME].Passed())
1894  {
1895  uint32 tmpDiff = (m_gameTime - m_startTime);
1896  uint32 maxClientsNum = sWorld.GetMaxActiveSessionCount();
1897 
1899  LoginDatabase.PExecute("UPDATE uptime SET uptime = %d, maxplayers = %d WHERE starttime = " UI64FMTD, tmpDiff, maxClientsNum, uint64(m_startTime));
1900  }
1901 
1902  // Clean logs table
1903  if (sWorld.getConfig(CONFIG_LOGDB_CLEARTIME) > 0) // if not enabled, ignore the timer
1904  {
1905  if (m_timers[WUPDATE_CLEANDB].Passed())
1906  {
1908  LoginDatabase.PExecute("DELETE FROM logs WHERE (time + %u) < " UI64FMTD ";",
1909  sWorld.getConfig(CONFIG_LOGDB_CLEARTIME), uint64(time(0)));
1910  }
1911  }
1912 
1913  // Handle all other objects
1914  // Update objects when the timer has passed (maps, transport, creatures,...)
1915  MapManager::Instance().Update(diff); // As interval = 0
1916 
1918  {
1919  if (m_timers[WUPDATE_AUTOBROADCAST].Passed())
1920  {
1923  }
1924  }
1925 
1926  sBattlegroundMgr.Update(diff);
1927  RecordTimeDiff("UpdateBattlegroundMgr");
1928 
1929  sOutdoorPvPMgr.Update(diff);
1930  RecordTimeDiff("UpdateOutdoorPvPMgr");
1931 
1933  if (m_timers[WUPDATE_DELETECHARS].Passed())
1934  {
1937  }
1938 
1939  // execute callbacks from sql queries that were queued recently
1941  RecordTimeDiff("UpdateResultQueue");
1942 
1943  // Erase corpses once every 20 minutes
1944  if (m_timers[WUPDATE_CORPSES].Passed())
1945  {
1948  }
1949 
1950  // Process Game events when necessary
1951  if (m_timers[WUPDATE_EVENTS].Passed())
1952  {
1953  m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
1954  uint32 nextGameEvent = sGameEventMgr.Update();
1955  m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
1957  }
1958 
1959  // update the instance reset times
1960  sInstanceSaveMgr.Update();
1961 
1962  // And last, but not least handle the issued cli commands
1964 }
1965 
1967 {
1968  m_timers[WUPDATE_EVENTS].Reset(); // to give time for Update() to be processed
1969  uint32 nextGameEvent = sGameEventMgr.Update();
1970  m_timers[WUPDATE_EVENTS].SetInterval(nextGameEvent);
1972 }
1973 
1974 // Send a packet to all players (except self if mentioned)
1976 {
1977  SessionMap::iterator itr;
1978  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1979  {
1980  if (itr->second &&
1981  itr->second->GetPlayer() &&
1982  itr->second->GetPlayer()->IsInWorld() &&
1983  itr->second != self &&
1984  (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
1985  itr->second->SendPacket(packet);
1986  }
1987 }
1988 
1989 // Send a packet to all GMs (except self if mentioned)
1991 {
1992  SessionMap::iterator itr;
1993  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
1994  {
1995  if (itr->second &&
1996  itr->second->GetPlayer() &&
1997  itr->second->GetPlayer()->IsInWorld() &&
1998  itr->second != self &&
1999  itr->second->GetSecurity() > SEC_PLAYER &&
2000  (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
2001  itr->second->SendPacket(packet);
2002  }
2003 }
2004 
2005 // Send a System Message to all players (except self if mentioned)
2006 void World::SendWorldText(int32 string_id, ...)
2007 {
2008  std::vector<std::vector<WorldPacket*> > data_cache; // 0 = default, i => i-1 locale index
2009 
2010  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2011  {
2012  if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld())
2013  continue;
2014 
2015  uint32 loc_idx = itr->second->GetSessionDbLocaleIndex();
2016  uint32 cache_idx = loc_idx + 1;
2017 
2018  std::vector<WorldPacket*>* data_list;
2019 
2020  // create if not cached yet
2021  if (data_cache.size() < cache_idx + 1 || data_cache[cache_idx].empty())
2022  {
2023  if (data_cache.size() < cache_idx + 1)
2024  data_cache.resize(cache_idx + 1);
2025 
2026  data_list = &data_cache[cache_idx];
2027 
2028  char const* text = sObjectMgr.GetOregonString(string_id, loc_idx);
2029 
2030  char buf[1000];
2031 
2032  va_list argptr;
2033  va_start(argptr, string_id);
2034  vsnprintf(buf, 1000, text, argptr);
2035  va_end(argptr);
2036 
2037  char* pos = &buf[0];
2038 
2039  while (char* line = ChatHandler::LineFromMessage(pos))
2040  {
2041  WorldPacket* data = new WorldPacket();
2042  ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
2043  data_list->push_back(data);
2044  }
2045  }
2046  else
2047  data_list = &data_cache[cache_idx];
2048 
2049  for (uint32 i = 0; i < data_list->size(); ++i)
2050  itr->second->SendPacket((*data_list)[i]);
2051  }
2052 
2053  // free memory
2054  for (uint32 i = 0; i < data_cache.size(); ++i)
2055  for (uint32 j = 0; j < data_cache[i].size(); ++j)
2056  delete data_cache[i][j];
2057 }
2058 
2059 void World::SendGMText(int32 string_id, ...)
2060 {
2061  std::vector<std::vector<WorldPacket*> > data_cache; // 0 = default, i => i-1 locale index
2062 
2063  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2064  {
2065  if (!itr->second || !itr->second->GetPlayer() || !itr->second->GetPlayer()->IsInWorld())
2066  continue;
2067 
2068  uint32 loc_idx = itr->second->GetSessionDbLocaleIndex();
2069  uint32 cache_idx = loc_idx + 1;
2070 
2071  std::vector<WorldPacket*>* data_list;
2072 
2073  // create if not cached yet
2074  if (data_cache.size() < cache_idx + 1 || data_cache[cache_idx].empty())
2075  {
2076  if (data_cache.size() < cache_idx + 1)
2077  data_cache.resize(cache_idx + 1);
2078 
2079  data_list = &data_cache[cache_idx];
2080 
2081  char const* text = sObjectMgr.GetOregonString(string_id, loc_idx);
2082 
2083  char buf[1000];
2084 
2085  va_list argptr;
2086  va_start(argptr, string_id);
2087  vsnprintf(buf, 1000, text, argptr);
2088  va_end(argptr);
2089 
2090  char* pos = &buf[0];
2091 
2092  while (char* line = ChatHandler::LineFromMessage(pos))
2093  {
2094  WorldPacket* data = new WorldPacket();
2095  ChatHandler::FillMessageData(data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
2096  data_list->push_back(data);
2097  }
2098  }
2099  else
2100  data_list = &data_cache[cache_idx];
2101 
2102  for (uint32 i = 0; i < data_list->size(); ++i)
2103  if (itr->second->GetSecurity() > SEC_PLAYER)
2104  itr->second->SendPacket((*data_list)[i]);
2105  }
2106 
2107  // free memory
2108  for (uint32 i = 0; i < data_cache.size(); ++i)
2109  for (uint32 j = 0; j < data_cache[i].size(); ++j)
2110  delete data_cache[i][j];
2111 }
2112 
2113 // Send a System Message to all players (except self if mentioned)
2114 void World::SendGlobalText(const char* text, WorldSession* self)
2115 {
2116  WorldPacket data;
2117 
2118  // need copy to prevent corruption by strtok call in LineFromMessage original string
2119  char* buf = strdup(text);
2120  char* pos = buf;
2121 
2122  while (char* line = ChatHandler::LineFromMessage(pos))
2123  {
2124  ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, line, NULL);
2125  SendGlobalMessage(&data, self);
2126  }
2127 
2128  free(buf);
2129 }
2130 
2131 // Send a packet to all players (or players selected team) in the zone (except self if mentioned)
2133 {
2134  bool foundPlayerToSend = false;
2135  SessionMap::iterator itr;
2136 
2137  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2138  {
2139  if (itr->second &&
2140  itr->second->GetPlayer() &&
2141  itr->second->GetPlayer()->IsInWorld() &&
2142  itr->second->GetPlayer()->GetZoneId() == zone &&
2143  itr->second != self &&
2144  (team == 0 || itr->second->GetPlayer()->GetTeam() == team))
2145  {
2146  itr->second->SendPacket(packet);
2147  foundPlayerToSend = true;
2148  }
2149  }
2150 
2151  return foundPlayerToSend;
2152 }
2153 
2154 // Send a System Message to all players in the zone (except self if mentioned)
2155 void World::SendZoneText(uint32 zone, const char* text, WorldSession* self, uint32 team)
2156 {
2157  WorldPacket data;
2158  ChatHandler::FillMessageData(&data, NULL, CHAT_MSG_SYSTEM, LANG_UNIVERSAL, NULL, 0, text, NULL);
2159  SendZoneMessage(zone, &data, self, team);
2160 }
2161 
2162 // Kick (and save) all players
2164 {
2165  m_QueuedPlayer.clear(); // prevent send queue update packet and login queued sessions
2166 
2167  // session not removed at kick and will removed in next update tick
2168  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2169  itr->second->KickPlayer();
2170 }
2171 
2172 // Kick (and save) all players with security level less `sec`
2174 {
2175  // session not removed at kick and will removed in next update tick
2176  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2177  if (itr->second->GetSecurity() < sec)
2178  itr->second->KickPlayer();
2179 }
2180 
2181 // Kick (and save) the designated player
2182 bool World::KickPlayer(const std::string& playerName)
2183 {
2184  SessionMap::iterator itr;
2185 
2186  // session not removed at kick and will removed in next update tick
2187  for (itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2188  {
2189  if (!itr->second)
2190  continue;
2191  Player* player = itr->second->GetPlayer();
2192  if (!player)
2193  continue;
2194  if (player->IsInWorld())
2195  {
2196  if (playerName == player->GetName())
2197  {
2198  itr->second->KickPlayer();
2199  return true;
2200  }
2201  }
2202  }
2203  return false;
2204 }
2205 
2206 // Ban an account or ban an IP address, duration will be parsed using TimeStringToSecs if it is positive, otherwise permban
2207 BanReturn World::BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
2208 {
2209  LoginDatabase.escape_string(nameOrIP);
2210  LoginDatabase.escape_string(reason);
2211  std::string safe_author = author;
2212  LoginDatabase.escape_string(safe_author);
2213 
2214  uint32 duration_secs = TimeStringToSecs(duration);
2215  QueryResult_AutoPtr resultAccounts = QueryResult_AutoPtr(NULL); //used for kicking
2216 
2217  // Update the database with ban information
2218  switch (mode)
2219  {
2220  case BAN_IP:
2221  //No SQL injection as strings are escaped
2222  resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE last_ip = '%s'", nameOrIP.c_str());
2223  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());
2224  break;
2225  case BAN_ACCOUNT:
2226  //No SQL injection as string is escaped
2227  resultAccounts = LoginDatabase.PQuery("SELECT id FROM account WHERE username = '%s'", nameOrIP.c_str());
2228  break;
2229  case BAN_CHARACTER:
2230  //No SQL injection as string is escaped
2231  resultAccounts = CharacterDatabase.PQuery("SELECT account FROM characters WHERE name = '%s'", nameOrIP.c_str());
2232  break;
2233  default:
2234  return BAN_SYNTAX_ERROR;
2235  }
2236 
2237  if (!resultAccounts)
2238  {
2239  if (mode == BAN_IP)
2240  return BAN_SUCCESS; // ip correctly banned but nobody affected (yet)
2241  else
2242  return BAN_NOTFOUND; // Nobody to ban
2243  }
2244 
2245  // Disconnect all affected players (for IP it can be several)
2246  do
2247  {
2248  Field* fieldsAccount = resultAccounts->Fetch();
2249  uint32 account = fieldsAccount->GetUInt32();
2250 
2251  if (mode != BAN_IP)
2252  {
2253  //No SQL injection as strings are escaped
2254  LoginDatabase.PExecute("INSERT INTO account_banned VALUES ('%u', UNIX_TIMESTAMP(), UNIX_TIMESTAMP()+%u, '%s', '%s', '1')",
2255  account, duration_secs, safe_author.c_str(), reason.c_str());
2256  }
2257 
2258  if (WorldSession* sess = FindSession(account))
2259  if (std::string(sess->GetPlayerName()) != author)
2260  sess->KickPlayer();
2261  }
2262  while (resultAccounts->NextRow());
2263 
2264  return BAN_SUCCESS;
2265 }
2266 
2267 // Remove a ban from an account or IP address
2268 bool World::RemoveBanAccount(BanMode mode, std::string nameOrIP)
2269 {
2270  if (mode == BAN_IP)
2271  {
2272  LoginDatabase.escape_string(nameOrIP);
2273  LoginDatabase.PExecute("DELETE FROM ip_banned WHERE ip = '%s'", nameOrIP.c_str());
2274  }
2275  else
2276  {
2277  uint32 account = 0;
2278  if (mode == BAN_ACCOUNT)
2279  account = sAccountMgr->GetId (nameOrIP);
2280  else if (mode == BAN_CHARACTER)
2281  account = sObjectMgr.GetPlayerAccountIdByPlayerName (nameOrIP);
2282 
2283  if (!account)
2284  return false;
2285 
2286  //NO SQL injection as account is uint32
2287  LoginDatabase.PExecute("UPDATE account_banned SET active = '0' WHERE id = '%u'", account);
2288  }
2289  return true;
2290 }
2291 
2292 // Update the game time
2294 {
2295  // update the time
2296  time_t thisTime = time(NULL);
2297  uint32 elapsed = uint32(thisTime - m_gameTime);
2298  m_gameTime = thisTime;
2299 
2300  // if there is a shutdown timer
2301  if (!m_stopEvent && m_ShutdownTimer > 0 && elapsed > 0)
2302  {
2303  // ... and it is overdue, stop the world (set m_stopEvent)
2304  if (m_ShutdownTimer <= elapsed)
2305  {
2307  {
2309  m_stopEvent = true; // exist code already set
2310  }
2311  else
2312  m_ShutdownTimer = 1; // minimum timer value to wait idle state
2313  }
2314  // ... else decrease it and if necessary display a shutdown countdown to the users
2315  else
2316  {
2317  m_ShutdownTimer -= elapsed;
2318 
2319  ShutdownMsg();
2320  }
2321  }
2322 }
2323 
2324 // Shutdown the server
2325 void World::ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
2326 {
2327  // ignore if server shutdown at next tick
2328  if (m_stopEvent)
2329  return;
2330 
2331  m_ShutdownMask = options;
2332  m_ExitCode = exitcode;
2333 
2334  // If the shutdown time is 0, set m_stopEvent (except if shutdown is 'idle' with remaining sessions)
2335  if (time == 0)
2336  {
2337  if (!(options & SHUTDOWN_MASK_IDLE) || GetActiveAndQueuedSessionCount() == 0)
2338  m_stopEvent = true; // exist code already set
2339  else
2340  m_ShutdownTimer = 1; //So that the session count is re-evaluated at next world tick
2341  }
2342  // Else set the shutdown timer and warn users
2343  else
2344  {
2345  m_ShutdownTimer = time;
2346  ShutdownMsg(true);
2347  }
2348 }
2349 
2350 // Display a shutdown message to the user(s)
2351 void World::ShutdownMsg(bool show, Player* player)
2352 {
2353  // not show messages for idle shutdown mode
2355  return;
2356 
2357  // Display a message every 12 hours, 1 hour, 5 minutes, 1 minute and 15 seconds
2358  if (show ||
2359  (m_ShutdownTimer <= 15) || // every sec down from 15 secs
2360  (m_ShutdownTimer < 5 * MINUTE && (m_ShutdownTimer % 15) == 0) || // < 5 min; every 15 sec
2361  (m_ShutdownTimer < 15 * MINUTE && (m_ShutdownTimer % MINUTE) == 0) || // < 15 min; every 1 min
2362  (m_ShutdownTimer < 30 * MINUTE && (m_ShutdownTimer % (5 * MINUTE)) == 0) || // < 30 min; every 5 min
2363  (m_ShutdownTimer < 12 * HOUR && (m_ShutdownTimer % HOUR) == 0) || // < 12 h; every 1 h
2364  (m_ShutdownTimer >= 12 * HOUR && (m_ShutdownTimer % (12 * HOUR)) == 0)) // >= 12 h; every 12 h
2365  {
2366  std::string str = secsToTimeString(m_ShutdownTimer);
2367 
2369 
2370  SendServerMessage(msgid, str.c_str(), player);
2371  DEBUG_LOG("Server is %s in %s", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutting down"), str.c_str());
2372  }
2373 }
2374 
2375 // Cancel a planned server shutdown
2377 {
2378  // nothing cancel or too later
2379  if (!m_ShutdownTimer || m_stopEvent)
2380  return;
2381 
2383 
2384  m_ShutdownMask = 0;
2385  m_ShutdownTimer = 0;
2386  m_ExitCode = SHUTDOWN_EXIT_CODE; // to default value
2387  SendServerMessage(msgid);
2388 
2389  DEBUG_LOG("Server %s cancelled.", (m_ShutdownMask & SHUTDOWN_MASK_RESTART ? "restart" : "shutdown"));
2390 }
2391 
2392 // Send a server message to the user(s)
2393 void World::SendServerMessage(ServerMessageType type, const char* text, Player* player)
2394 {
2395  WorldPacket data(SMSG_SERVER_MESSAGE, 50); // guess size
2396  data << uint32(type);
2397  if (type <= SERVER_MSG_STRING)
2398  data << text;
2399 
2400  if (player)
2401  player->GetSession()->SendPacket(&data);
2402  else
2403  SendGlobalMessage(&data);
2404 }
2405 
2406 void World::UpdateSessions(time_t diff)
2407 {
2408  // Add new sessions
2409  WorldSession* sess;
2410  while (addSessQueue.next(sess))
2411  AddSession_ (sess);
2412 
2413  // Then send an update signal to remaining ones
2414  for (SessionMap::iterator itr = m_sessions.begin(), next; itr != m_sessions.end(); itr = next)
2415  {
2416  next = itr;
2417  ++next;
2418 
2419  if (!itr->second)
2420  continue;
2421 
2422  // and remove not active sessions from the list
2423  if (!itr->second->Update(diff)) // As interval = 0
2424  {
2425  if (!RemoveQueuedPlayer(itr->second) && itr->second && getConfig(CONFIG_INTERVAL_DISCONNECT_TOLERANCE))
2426  m_disconnects[itr->second->GetAccountId()] = time(NULL);
2427  delete itr->second;
2428  m_sessions.erase(itr);
2429  }
2430  }
2431 }
2432 
2433 // This handles the issued and queued CLI commands
2435 {
2436  CliCommandHolder::Print* zprint = NULL;
2437  void* callbackArg = NULL;
2438  CliCommandHolder* command;
2439  while (cliCmdQueue.next(command))
2440  {
2441  sLog.outDebug("CLI command under processing...");
2442  zprint = command->m_print;
2443  callbackArg = command->m_callbackArg;
2444  CliHandler handler(callbackArg, zprint);
2445  handler.ParseCommands(command->m_command);
2446 
2447  if (command->m_commandFinished)
2448  command->m_commandFinished(callbackArg, !handler.HasSentErrorMessage());
2449 
2450  delete command;
2451  }
2452 }
2453 
2455 {
2456  if (m_Autobroadcasts.empty())
2457  return;
2458 
2459  std::string msg;
2460 
2461  std::list<std::string>::const_iterator itr = m_Autobroadcasts.begin();
2462  std::advance(itr, rand() % m_Autobroadcasts.size());
2463  msg = *itr;
2464 
2465  uint32 abcenter = sConfig.GetIntDefault("AutoBroadcast.Center", 0);
2466 
2467  if (abcenter == 0)
2468  sWorld.SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
2469 
2470  else if (abcenter == 1)
2471  {
2472  WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1));
2473  data << msg;
2474  sWorld.SendGlobalMessage(&data);
2475  }
2476 
2477  else if (abcenter == 2)
2478  {
2479  sWorld.SendWorldText(LANG_AUTO_BROADCAST, msg.c_str());
2480 
2481  WorldPacket data(SMSG_NOTIFICATION, (msg.size() + 1));
2482  data << msg;
2483  sWorld.SendGlobalMessage(&data);
2484  }
2485 
2486  sLog.outString("AutoBroadcast: '%s'", msg.c_str());
2487 }
2488 
2490 {
2493 }
2494 
2496 {
2497  m_resultQueue->Update();
2498 }
2499 
2501 {
2503  "SELECT COUNT(guid) FROM characters WHERE account = '%u'", accountId);
2504 }
2505 
2507 {
2508  if (resultCharCount)
2509  {
2510  Field* fields = resultCharCount->Fetch();
2511  uint32 charCount = fields[0].GetUInt32();
2512 
2513  LoginDatabase.PExecute("DELETE FROM realmcharacters WHERE acctid= '%d' AND realmid = '%d'", accountId, realmID);
2514  LoginDatabase.PExecute("INSERT INTO realmcharacters (numchars, acctid, realmid) VALUES (%u, %u, %u)", charCount, accountId, realmID);
2515  }
2516 }
2517 
2519 {
2520  time_t mostRecentQuestTime;
2521 
2522  QueryResult_AutoPtr result = CharacterDatabase.Query("SELECT MAX(time) FROM character_queststatus_daily");
2523  if (result)
2524  {
2525  Field* fields = result->Fetch();
2526  mostRecentQuestTime = (time_t)fields[0].GetUInt64();
2527  }
2528  else
2529  mostRecentQuestTime = 0;
2530 
2531  // client built-in time for reset is 6:00 AM
2532  // FIX ME: client not show day start time
2533  time_t curTime = time(NULL);
2534  tm localTm = *localtime(&curTime);
2535  localTm.tm_hour = 6;
2536  localTm.tm_min = 0;
2537  localTm.tm_sec = 0;
2538 
2539  // current day reset time
2540  time_t curDayResetTime = mktime(&localTm);
2541 
2542  // last reset time before current moment
2543  time_t resetTime = (curTime < curDayResetTime) ? curDayResetTime - DAY : curDayResetTime;
2544 
2545  // need reset (if we have quest time before last reset time (not processed by some reason)
2546  if (mostRecentQuestTime && mostRecentQuestTime <= resetTime)
2547  m_NextDailyQuestReset = mostRecentQuestTime;
2548  else
2549  {
2550  // plan next reset time
2551  m_NextDailyQuestReset = (curTime >= curDayResetTime) ? curDayResetTime + DAY : curDayResetTime;
2552  }
2553 }
2554 
2556 {
2557  QueryResult_AutoPtr result = LoginDatabase.PQuery("SELECT allowedSecurityLevel from realmlist WHERE id = '%d'", realmID);
2558  if (result)
2559  {
2560  m_allowedSecurityLevel = AccountTypes(result->Fetch()->GetUInt16());
2561  sLog.outDebug("Allowed Level: %u Result %u", m_allowedSecurityLevel, result->Fetch()->GetUInt16());
2562  }
2563 }
2564 
2566 {
2567  sLog.outDetail("Daily quests reset for all characters.");
2568  CharacterDatabase.Execute("DELETE FROM character_queststatus_daily");
2569  for (SessionMap::iterator itr = m_sessions.begin(); itr != m_sessions.end(); ++itr)
2570  if (itr->second->GetPlayer())
2571  itr->second->GetPlayer()->ResetDailyQuestStatus();
2572 
2573  // change available dailies
2574  sPoolMgr.ChangeDailyQuests();
2575 }
2576 
2577 void World::SetPlayerLimit(int32 limit, bool /*needUpdate*/)
2578 {
2579  m_playerLimit = limit;
2580 }
2581 
2583 {
2586 }
2587 
2589 {
2590  QueryResult_AutoPtr result = WorldDatabase.Query("SELECT db_version FROM version LIMIT 1");
2591  if (result)
2592  {
2593  Field* fields = result->Fetch();
2594 
2595  m_DBVersion = fields[0].GetString();
2596  }
2597  else
2598  m_DBVersion = "unknown world database";
2599 }
2600 
BanReturn BanAccount(BanMode mode, std::string nameOrIP, std::string duration, std::string reason, std::string author)
Definition: World.cpp:2207
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:2163
void SetNewCharString(std::string str)
Definition: World.h:551
void LoadOpcodeProtection()
Definition: World.cpp:1762
void UpdateMaxSessionCounters()
Definition: World.cpp:2582
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:2155
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:1799
#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:1975
bool SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self=0, uint32 team=0)
Definition: World.cpp:2132
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:46
void SendWorldText(int32 string_id,...)
Definition: World.cpp:2006
static void InitVisibleBits()
Definition: Player.cpp:3580
uint32 m_updateTimeCount
Definition: World.h:801
uint32 GetActiveAndQueuedSessionCount() const
Definition: World.h:472
#define auctionbot
uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
Definition: Timer.h:78
void _UpdateGameTime()
Definition: World.cpp:2293
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:1656
AccountTypes
Definition: Common.h:188
Definition: World.h:457
void UpdateAllowedSecurity()
Definition: World.cpp:2555
SqlResultQueue * m_resultQueue
Definition: World.h:837
Definition: Field.h:24
void SendGMText(int32 string_id,...)
Definition: World.cpp:2059
#define sConsole
Definition: Console.h:99
void LoadDBVersion()
Definition: World.cpp:2588
SessionMap m_sessions
Definition: World.h:807
void SendGlobalText(const char *text, WorldSession *self)
Definition: World.cpp:2114
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:1202
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:743
AccountTypes m_allowedSecurityLevel
Definition: World.h:818
void UpdateRealmCharCount(uint32 accid)
Definition: World.cpp:2500
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:257
BanMode
void ShutdownCancel()
Definition: World.cpp:2376
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:938
World()
Definition: World.cpp:87
static void SendExternalMails()
Definition: Mail.cpp:1065
void LoadAutobroadcasts()
Definition: World.cpp:1720
unsigned long status
Definition: Opcodes.h:1112
~World()
Definition: World.cpp:110
void LoadSkillExtraItemTable()
#define sObjectMgr
Definition: ObjectMgr.h:1317
void SendPacket(WorldPacket const *packet)
static void clear()
void UpdateSessions(time_t diff)
Definition: World.cpp:2406
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:1990
Queue m_QueuedPlayer
Definition: World.h:843
void Print(void *, const char *)
Definition: World.h:416
void InitDailyQuestResetTime()
Definition: World.cpp:2518
Definition: Common.h:179
IntervalTimer m_timers[WUPDATE_COUNT]
Definition: World.h:796
void SetInitialWorldSettings()
Definition: World.cpp:1165
void UpdateResultQueue()
Definition: World.cpp:2495
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:2351
const bool & IsInWorld() const
Definition: Object.h:150
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:226
#define DEFAULT_VISIBILITY_BGARENAS
Definition: Object.h:47
uint32 TimeStringToSecs(const std::string &timestring)
Definition: Util.cpp:132
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:2182
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:2577
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
void * dtCustomAlloc(size_t size, dtAllocHint)
Definition: MoveMap.h:29
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:4040
#define sInstanceSaveMgr
uint32 GetPlayerAmountLimit() const
Definition: World.h:500
ProtectedOpcodeProperties const & GetProtectedOpcodeProperties(uint32 opcode)
Definition: World.cpp:1793
float rate_values[MAX_RATES]
Definition: World.h:815
std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
Definition: Util.cpp:109
static float m_MaxVisibleDistanceInBGArenas
Definition: World.h:829
bool IsFFAPvPRealm()
Definition: World.h:678
bool RemoveBanAccount(BanMode mode, std::string nameOrIP)
Definition: World.cpp:2268
#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:680
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:2489
void SetMotd(std::string motd)
Definition: World.h:540
void SendServerMessage(ServerMessageType type, const char *text="", Player *player=NULL)
Definition: World.cpp:2393
static volatile bool m_stopEvent
Definition: World.h:786
void Init(bool reload=false)
void SendAutoBroadcast()
Definition: World.cpp:2454
#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:2506
uint32 m_ShutdownTimer
Definition: World.h:788
void RecordTimeDiff(const char *text,...)
Definition: World.cpp:1694
ServerMessageType
Definition: World.h:43
void ResetDailyQuests()
Definition: World.cpp:2565
#define NOMINAL_MELEE_RANGE
Definition: Object.h:52
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:2434
void AddQueuedPlayer(WorldSession *)
Definition: World.cpp:294
static IVMapManager * createOrGetVMapManager()
#define ASSERT
Definition: Errors.h:29
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:1947
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:2173
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:10711
Definition: Player.h:923
#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:1966
#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:1518
#define sSmartScriptMgr
#define DEFAULT_VISIBILITY_DISTANCE
Definition: Object.h:45
void LoadIp2nation()
Definition: World.cpp:1748
void ShutdownServ(uint32 time, uint32 options, uint8 exitcode)
Definition: World.cpp:2325