/* * Copyright (C) 2005-2008 MaNGOS * * Copyright (C) 2008 Trinity * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /// \addtogroup world The World /// @{ /// \file #ifndef __WORLD_H #define __WORLD_H #include "Common.h" #include "Timer.h" #include "Policies/Singleton.h" #include "SharedDefines.h" #include #include #include class Object; class WorldPacket; class WorldSession; class Player; class Weather; struct ScriptAction; struct ScriptInfo; class SqlResultQueue; class QueryResult; class WorldSocket; enum ShutdownMask { SHUTDOWN_MASK_RESTART = 1, SHUTDOWN_MASK_IDLE = 2, }; enum ShutdownExitCode { SHUTDOWN_EXIT_CODE = 0, ERROR_EXIT_CODE = 1, RESTART_EXIT_CODE = 2, }; /// Timers for different object refresh rates enum WorldTimers { WUPDATE_OBJECTS = 0, WUPDATE_SESSIONS = 1, WUPDATE_AUCTIONS = 2, WUPDATE_WEATHERS = 3, WUPDATE_UPTIME = 4, WUPDATE_CORPSES = 5, WUPDATE_EVENTS = 6, WUPDATE_COUNT = 7 }; /// Configuration elements enum WorldConfigs { CONFIG_COMPRESSION = 0, CONFIG_GRID_UNLOAD, CONFIG_INTERVAL_SAVE, CONFIG_INTERVAL_GRIDCLEAN, CONFIG_INTERVAL_MAPUPDATE, CONFIG_INTERVAL_CHANGEWEATHER, CONFIG_PORT_WORLD, CONFIG_SOCKET_SELECTTIME, CONFIG_GROUP_XP_DISTANCE, CONFIG_SIGHT_MONSTER, CONFIG_SIGHT_GUARDER, CONFIG_GAME_TYPE, CONFIG_REALM_ZONE, CONFIG_ALLOW_TWO_SIDE_ACCOUNTS, CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHAT, CONFIG_ALLOW_TWO_SIDE_INTERACTION_CHANNEL, CONFIG_ALLOW_TWO_SIDE_INTERACTION_GROUP, CONFIG_ALLOW_TWO_SIDE_INTERACTION_GUILD, CONFIG_ALLOW_TWO_SIDE_INTERACTION_AUCTION, CONFIG_ALLOW_TWO_SIDE_INTERACTION_MAIL, CONFIG_ALLOW_TWO_SIDE_WHO_LIST, CONFIG_ALLOW_TWO_SIDE_ADD_FRIEND, CONFIG_STRICT_PLAYER_NAMES, CONFIG_STRICT_CHARTER_NAMES, CONFIG_STRICT_PET_NAMES, CONFIG_CHARACTERS_CREATING_DISABLED, CONFIG_MAX_WHO, CONFIG_CHARACTERS_PER_ACCOUNT, CONFIG_CHARACTERS_PER_REALM, CONFIG_SKIP_CINEMATICS, CONFIG_MAX_PLAYER_LEVEL, CONFIG_START_PLAYER_LEVEL, CONFIG_MAX_HONOR_POINTS, CONFIG_MAX_ARENA_POINTS, CONFIG_INSTANCE_IGNORE_LEVEL, CONFIG_INSTANCE_IGNORE_RAID, CONFIG_BATTLEGROUND_CAST_DESERTER, CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_ENABLE, CONFIG_BATTLEGROUND_QUEUE_ANNOUNCER_PLAYERONLY, CONFIG_INSTANCE_RESET_TIME_HOUR, CONFIG_INSTANCE_UNLOAD_DELAY, CONFIG_CAST_UNSTUCK, CONFIG_MAX_PRIMARY_TRADE_SKILL, CONFIG_MIN_PETITION_SIGNS, CONFIG_GM_LOGIN_STATE, CONFIG_GM_ACCEPT_TICKETS, CONFIG_GM_CHAT, CONFIG_GM_WISPERING_TO, CONFIG_GM_IN_GM_LIST, CONFIG_GM_IN_WHO_LIST, CONFIG_GM_LOG_TRADE, CONFIG_GROUP_VISIBILITY, CONFIG_MAIL_DELIVERY_DELAY, CONFIG_UPTIME_UPDATE, CONFIG_SKILL_CHANCE_ORANGE, CONFIG_SKILL_CHANCE_YELLOW, CONFIG_SKILL_CHANCE_GREEN, CONFIG_SKILL_CHANCE_GREY, CONFIG_SKILL_CHANCE_MINING_STEPS, CONFIG_SKILL_CHANCE_SKINNING_STEPS, CONFIG_SKILL_PROSPECTING, CONFIG_SKILL_GAIN_CRAFTING, CONFIG_SKILL_GAIN_DEFENSE, CONFIG_SKILL_GAIN_GATHERING, CONFIG_SKILL_GAIN_WEAPON, CONFIG_MAX_OVERSPEED_PINGS, CONFIG_SAVE_RESPAWN_TIME_IMMEDIATELY, CONFIG_WEATHER, CONFIG_EXPANSION, CONFIG_CHATFLOOD_MESSAGE_COUNT, CONFIG_CHATFLOOD_MESSAGE_DELAY, CONFIG_CHATFLOOD_MUTE_TIME, CONFIG_EVENT_ANNOUNCE, CONFIG_CREATURE_FAMILY_ASSISTEMCE_RADIUS, CONFIG_WORLD_BOSS_LEVEL_DIFF, CONFIG_QUEST_LOW_LEVEL_HIDE_DIFF, CONFIG_QUEST_HIGH_LEVEL_HIDE_DIFF, CONFIG_DETECT_POS_COLLISION, CONFIG_RESTRICTED_LFG_CHANNEL, CONFIG_SILENTLY_GM_JOIN_TO_CHANNEL, CONFIG_TALENTS_INSPECTING, CONFIG_CHAT_FAKE_MESSAGE_PREVENTING, CONFIG_CORPSE_DECAY_NORMAL, CONFIG_CORPSE_DECAY_RARE, CONFIG_CORPSE_DECAY_ELITE, CONFIG_CORPSE_DECAY_RAREELITE, CONFIG_CORPSE_DECAY_WORLDBOSS, CONFIG_ADDON_CHANNEL, CONFIG_DEATH_SICKNESS_LEVEL, CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVP, CONFIG_DEATH_CORPSE_RECLAIM_DELAY_PVE, CONFIG_PLAYER_START_GOLD, CONFIG_PLAYER_START_HONOR, CONFIG_PLAYER_START_ARENAPTS, CONFIG_GM_START_LEVEL, CONFIG_INSTANT_LOGOUT, CONFIG_BG_START_MUSIC, CONFIG_START_ALL_SPELLS, CONFIG_HONOR_AFTER_DUEL, CONFIG_START_ALL_EXPLORED, CONFIG_DISABLE_BREATHING, CONFIG_START_ALL_REP, CONFIG_ALWAYS_MAXSKILL, CONFIG_START_ALL_TAXI, CONFIG_PVP_TOKEN_ENABLE, CONFIG_PVP_TOKEN_MAP_TYPE, CONFIG_PVP_TOKEN_ID, CONFIG_PVP_TOKEN_COUNT, CONFIG_NO_RESET_TALENT_COST, CONFIG_THREAT_RADIUS, CONFIG_DECLINED_NAMES_USED, CONFIG_LISTEN_RANGE_SAY, CONFIG_LISTEN_RANGE_TEXTEMOTE, CONFIG_LISTEN_RANGE_YELL, CONFIG_ARENA_MAX_RATING_DIFFERENCE, CONFIG_ARENA_RATING_DISCARD_TIMER, CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS, CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS, CONFIG_BATTLEGROUND_PREMATURE_FINISH_TIMER, CONFIG_VALUE_COUNT }; /// Server rates enum Rates { RATE_HEALTH=0, RATE_POWER_MANA, RATE_POWER_RAGE_INCOME, RATE_POWER_RAGE_LOSS, RATE_POWER_FOCUS, RATE_SKILL_DISCOVERY, RATE_DROP_ITEM_POOR, RATE_DROP_ITEM_NORMAL, RATE_DROP_ITEM_UNCOMMON, RATE_DROP_ITEM_RARE, RATE_DROP_ITEM_EPIC, RATE_DROP_ITEM_LEGENDARY, RATE_DROP_ITEM_ARTIFACT, RATE_DROP_ITEM_REFERENCED, RATE_DROP_MONEY, RATE_XP_KILL, RATE_XP_QUEST, RATE_XP_EXPLORE, RATE_XP_PAST_70, RATE_REPUTATION_GAIN, RATE_CREATURE_NORMAL_HP, RATE_CREATURE_ELITE_ELITE_HP, RATE_CREATURE_ELITE_RAREELITE_HP, RATE_CREATURE_ELITE_WORLDBOSS_HP, RATE_CREATURE_ELITE_RARE_HP, RATE_CREATURE_NORMAL_DAMAGE, RATE_CREATURE_ELITE_ELITE_DAMAGE, RATE_CREATURE_ELITE_RAREELITE_DAMAGE, RATE_CREATURE_ELITE_WORLDBOSS_DAMAGE, RATE_CREATURE_ELITE_RARE_DAMAGE, RATE_CREATURE_NORMAL_SPELLDAMAGE, RATE_CREATURE_ELITE_ELITE_SPELLDAMAGE, RATE_CREATURE_ELITE_RAREELITE_SPELLDAMAGE, RATE_CREATURE_ELITE_WORLDBOSS_SPELLDAMAGE, RATE_CREATURE_ELITE_RARE_SPELLDAMAGE, RATE_CREATURE_AGGRO, RATE_REST_INGAME, RATE_REST_OFFLINE_IN_TAVERN_OR_CITY, RATE_REST_OFFLINE_IN_WILDERNESS, RATE_DAMAGE_FALL, RATE_AUCTION_TIME, RATE_AUCTION_DEPOSIT, RATE_AUCTION_CUT, RATE_HONOR, RATE_MINING_AMOUNT, RATE_MINING_NEXT, RATE_TALENT, RATE_LOYALTY, RATE_CORPSE_DECAY_LOOTED, RATE_INSTANCE_RESET_TIME, RATE_TARGET_POS_RECALCULATION_RANGE, RATE_DURABILITY_LOSS_DAMAGE, RATE_DURABILITY_LOSS_PARRY, RATE_DURABILITY_LOSS_ABSORB, RATE_DURABILITY_LOSS_BLOCK, MAX_RATES }; /// Type of server enum RealmType { REALM_TYPE_NORMAL = 0, REALM_TYPE_PVP = 1, REALM_TYPE_NORMAL2 = 4, REALM_TYPE_RP = 6, REALM_TYPE_RPPVP = 8, REALM_TYPE_FFA_PVP = 16 // custom, free for all pvp mode like arena PvP in all zones except rest activated places and sanctuaries // replaced by REALM_PVP in realm list }; enum RealmZone { REALM_ZONE_UNKNOWN = 0, // any language REALM_ZONE_DEVELOPMENT = 1, // any language REALM_ZONE_UNITED_STATES = 2, // extended-Latin REALM_ZONE_OCEANIC = 3, // extended-Latin REALM_ZONE_LATIN_AMERICA = 4, // extended-Latin REALM_ZONE_TOURNAMENT_5 = 5, // basic-Latin at create, any at login REALM_ZONE_KOREA = 6, // East-Asian REALM_ZONE_TOURNAMENT_7 = 7, // basic-Latin at create, any at login REALM_ZONE_ENGLISH = 8, // extended-Latin REALM_ZONE_GERMAN = 9, // extended-Latin REALM_ZONE_FRENCH = 10, // extended-Latin REALM_ZONE_SPANISH = 11, // extended-Latin REALM_ZONE_RUSSIAN = 12, // Cyrillic REALM_ZONE_TOURNAMENT_13 = 13, // basic-Latin at create, any at login REALM_ZONE_TAIWAN = 14, // East-Asian REALM_ZONE_TOURNAMENT_15 = 15, // basic-Latin at create, any at login REALM_ZONE_CHINA = 16, // East-Asian REALM_ZONE_CN1 = 17, // basic-Latin at create, any at login REALM_ZONE_CN2 = 18, // basic-Latin at create, any at login REALM_ZONE_CN3 = 19, // basic-Latin at create, any at login REALM_ZONE_CN4 = 20, // basic-Latin at create, any at login REALM_ZONE_CN5 = 21, // basic-Latin at create, any at login REALM_ZONE_CN6 = 22, // basic-Latin at create, any at login REALM_ZONE_CN7 = 23, // basic-Latin at create, any at login REALM_ZONE_CN8 = 24, // basic-Latin at create, any at login REALM_ZONE_TOURNAMENT_25 = 25, // basic-Latin at create, any at login REALM_ZONE_TEST_SERVER = 26, // any language REALM_ZONE_TOURNAMENT_27 = 27, // basic-Latin at create, any at login REALM_ZONE_QA_SERVER = 28, // any language REALM_ZONE_CN9 = 29 // basic-Latin at create, any at login }; // DB scripting commands #define SCRIPT_COMMAND_TALK 0 // source = unit, target=any, datalong ( 0=say, 1=whisper, 2=yell, 3=emote text) #define SCRIPT_COMMAND_EMOTE 1 // source = unit, datalong = anim_id #define SCRIPT_COMMAND_FIELD_SET 2 // source = any, datalong = field_id, datalog2 = value #define SCRIPT_COMMAND_MOVE_TO 3 // source = Creature, datalog2 = time, x/y/z #define SCRIPT_COMMAND_FLAG_SET 4 // source = any, datalong = field_id, datalog2 = bitmask #define SCRIPT_COMMAND_FLAG_REMOVE 5 // source = any, datalong = field_id, datalog2 = bitmask #define SCRIPT_COMMAND_TELEPORT_TO 6 // source or target with Player, datalong = map_id, x/y/z #define SCRIPT_COMMAND_QUEST_EXPLORED 7 // one from source or target must be Player, another GO/Creature, datalong=quest_id, datalong2=distance or 0 #define SCRIPT_COMMAND_RESPAWN_GAMEOBJECT 9 // source = any (summoner), datalong=db_guid, datalong2=despawn_delay #define SCRIPT_COMMAND_TEMP_SUMMON_CREATURE 10 // source = any (summoner), datalong=creature entry, datalong2=despawn_delay #define SCRIPT_COMMAND_OPEN_DOOR 11 // source = unit, datalong=db_guid, datalong2=reset_delay #define SCRIPT_COMMAND_CLOSE_DOOR 12 // source = unit, datalong=db_guid, datalong2=reset_delay #define SCRIPT_COMMAND_ACTIVATE_OBJECT 13 // source = unit, target=GO #define SCRIPT_COMMAND_REMOVE_AURA 14 // source (datalong2!=0) or target (datalong==0) unit, datalong = spell_id #define SCRIPT_COMMAND_CAST_SPELL 15 // source (datalong2!=0) or target (datalong==0) unit, datalong = spell_id /// Storage class for commands issued for delayed execution struct CliCommandHolder { typedef void Print(const char*); char *m_command; Print* m_print; CliCommandHolder(const char *command, Print* zprint) : m_print(zprint) { size_t len = strlen(command)+1; m_command = new char[len]; memcpy(m_command, command, len); } ~CliCommandHolder() { delete[] m_command; } }; /// The World class World { public: static volatile uint32 m_worldLoopCounter; World(); ~World(); WorldSession* FindSession(uint32 id) const; void AddSession(WorldSession *s); bool RemoveSession(uint32 id); /// Get the number of current active sessions void UpdateMaxSessionCounters(); uint32 GetActiveAndQueuedSessionCount() const { return m_sessions.size(); } uint32 GetActiveSessionCount() const { return m_sessions.size() - m_QueuedPlayer.size(); } uint32 GetQueuedSessionCount() const { return m_QueuedPlayer.size(); } /// Get the maximum number of parallel sessions on the server since last reboot uint32 GetMaxQueuedSessionCount() const { return m_maxQueuedSessionCount; } uint32 GetMaxActiveSessionCount() const { return m_maxActiveSessionCount; } Player* FindPlayerInZone(uint32 zone); Weather* FindWeather(uint32 id) const; Weather* AddWeather(uint32 zone_id); void RemoveWeather(uint32 zone_id); /// Get the active session server limit (or security level limitations) uint32 GetPlayerAmountLimit() const { return m_playerLimit >= 0 ? m_playerLimit : 0; } AccountTypes GetPlayerSecurityLimit() const { return m_playerLimit <= 0 ? AccountTypes(-m_playerLimit) : SEC_PLAYER; } /// Set the active session server limit (or security level limitation) void SetPlayerLimit(int32 limit, bool needUpdate = false); //player Queue typedef std::list Queue; void AddQueuedPlayer(WorldSession*); void RemoveQueuedPlayer(WorldSession*); int32 GetQueuePos(WorldSession*); uint32 GetQueueSize() const { return m_QueuedPlayer.size(); } /// \todo Actions on m_allowMovement still to be implemented /// Is movement allowed? bool getAllowMovement() const { return m_allowMovement; } /// Allow/Disallow object movements void SetAllowMovement(bool allow) { m_allowMovement = allow; } /// Set a new Message of the Day void SetMotd(std::string motd) { m_motd = motd; } /// Get the current Message of the Day const char* GetMotd() const { return m_motd.c_str(); } uint32 GetDefaultDbcLocale() const { return m_defaultDbcLocale; } /// Get the path where data (dbc, maps) are stored on disk std::string GetDataPath() const { return m_dataPath; } /// When server started? time_t const& GetStartTime() const { return m_startTime; } /// What time is it? time_t const& GetGameTime() const { return m_gameTime; } /// Uptime (in secs) uint32 GetUptime() const { return uint32(m_gameTime - m_startTime); } /// Get the maximum skill level a player can reach uint16 GetConfigMaxSkillValue() const { uint32 lvl = getConfig(CONFIG_MAX_PLAYER_LEVEL); return lvl > 60 ? 300 + ((lvl - 60) * 75) / 10 : lvl*5; } void SetInitialWorldSettings(); void LoadConfigSettings(bool reload = false); void SendWorldText(int32 string_id, ...); void SendGlobalMessage(WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); void SendZoneMessage(uint32 zone, WorldPacket *packet, WorldSession *self = 0, uint32 team = 0); void SendZoneText(uint32 zone, const char *text, WorldSession *self = 0, uint32 team = 0); void SendServerMessage(uint32 type, const char *text = "", Player* player = NULL); /// Are we in the middle of a shutdown? bool IsShutdowning() const { return m_ShutdownTimer > 0; } void ShutdownServ(uint32 time, uint32 options, uint8 exitcode); void ShutdownCancel(); void ShutdownMsg(bool show = false, Player* player = NULL); static uint8 GetExitCode() { return m_ExitCode; } static void StopNow(uint8 exitcode) { m_stopEvent = true; m_ExitCode = exitcode; } static bool IsStopped() { return m_stopEvent; } void Update(time_t diff); void UpdateSessions( time_t diff ); /// Set a server rate (see #Rates) void setRate(Rates rate,float value) { rate_values[rate]=value; } /// Get a server rate (see #Rates) float getRate(Rates rate) const { return rate_values[rate]; } /// Set a server configuration element (see #WorldConfigs) void setConfig(uint32 index,uint32 value) { if(index > const& scripts, uint32 id, Object* source, Object* target); void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target); bool IsScriptScheduled() const { return !m_scriptSchedule.empty(); } bool IsAllowedMap(uint32 mapid) { return m_forbiddenMapIds.count(mapid) == 0 ;} // for max speed access static float GetMaxVisibleDistanceForCreature() { return m_MaxVisibleDistanceForCreature; } static float GetMaxVisibleDistanceForPlayer() { return m_MaxVisibleDistanceForPlayer; } static float GetMaxVisibleDistanceForObject() { return m_MaxVisibleDistanceForObject; } static float GetMaxVisibleDistanceInFlight() { return m_MaxVisibleDistanceInFlight; } static float GetVisibleUnitGreyDistance() { return m_VisibleUnitGreyDistance; } static float GetVisibleObjectGreyDistance() { return m_VisibleObjectGreyDistance; } void ProcessCliCommands(); void QueueCliCommand( CliCommandHolder::Print* zprintf, char const* input ) { cliCmdQueue.add(new CliCommandHolder(input, zprintf)); } void UpdateResultQueue(); void InitResultQueue(); void ForceGameEventUpdate(); void UpdateRealmCharCount(uint32 accid); LocaleConstant GetAvailableDbcLocale(LocaleConstant locale) const { if(m_availableDbcLocaleMask & (1 << locale)) return locale; else return m_defaultDbcLocale; } //used World DB version void LoadDBVersion(); char const* GetDBVersion() { return m_DBVersion.c_str(); } //used Script version void SetScriptsVersion(char const* version) { m_ScriptsVersion = version ? version : "unknown scripting library"; } char const* GetScriptsVersion() { return m_ScriptsVersion.c_str(); } protected: void _UpdateGameTime(); void ScriptsProcess(); // callback for UpdateRealmCharacters void _UpdateRealmCharCount(QueryResult *resultCharCount, uint32 accountId); void InitDailyQuestResetTime(); void ResetDailyQuests(); private: static volatile bool m_stopEvent; static uint8 m_ExitCode; uint32 m_ShutdownTimer; uint32 m_ShutdownMask; time_t m_startTime; time_t m_gameTime; IntervalTimer m_timers[WUPDATE_COUNT]; uint32 mail_timer; uint32 mail_timer_expires; typedef UNORDERED_MAP WeatherMap; WeatherMap m_weathers; typedef UNORDERED_MAP SessionMap; SessionMap m_sessions; std::set m_kicked_sessions; uint32 m_maxActiveSessionCount; uint32 m_maxQueuedSessionCount; std::multimap m_scriptSchedule; float rate_values[MAX_RATES]; uint32 m_configs[CONFIG_VALUE_COUNT]; int32 m_playerLimit; LocaleConstant m_defaultDbcLocale; // from config for one from loaded DBC locales uint32 m_availableDbcLocaleMask; // by loaded DBC void DetectDBCLang(); bool m_allowMovement; std::string m_motd; std::string m_dataPath; std::set m_forbiddenMapIds; // for max speed access static float m_MaxVisibleDistanceForCreature; static float m_MaxVisibleDistanceForPlayer; static float m_MaxVisibleDistanceForObject; static float m_MaxVisibleDistanceInFlight; static float m_VisibleUnitGreyDistance; static float m_VisibleObjectGreyDistance; // CLI command holder to be thread safe ZThread::LockedQueue cliCmdQueue; SqlResultQueue *m_resultQueue; // next daily quests reset time time_t m_NextDailyQuestReset; //Player Queue Queue m_QueuedPlayer; //sessions that are added async void AddSession_(WorldSession* s); ZThread::LockedQueue addSessQueue; //used versions std::string m_DBVersion; std::string m_ScriptsVersion; }; extern uint32 realmID; #define sWorld Trinity::Singleton::Instance() #endif /// @}