aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml7
-rw-r--r--CMakeLists.txt3
-rw-r--r--cmake/compiler/clang/settings.cmake13
-rw-r--r--cmake/compiler/gcc/settings.cmake12
-rw-r--r--cmake/compiler/msvc/settings.cmake21
-rw-r--r--cmake/options.cmake1
-rw-r--r--cmake/showoptions.cmake12
-rw-r--r--dep/CMakeLists.txt1
-rw-r--r--dep/PackageList.txt4
-rw-r--r--dep/efsw/.hg_archival.txt5
-rw-r--r--dep/efsw/CMakeLists.txt85
-rw-r--r--dep/efsw/LICENSE22
-rw-r--r--dep/efsw/README.md138
-rw-r--r--dep/efsw/include/efsw/efsw.h151
-rw-r--r--dep/efsw/include/efsw/efsw.hpp197
-rw-r--r--dep/efsw/src/efsw/Debug.cpp85
-rw-r--r--dep/efsw/src/efsw/Debug.hpp50
-rw-r--r--dep/efsw/src/efsw/DirWatcherGeneric.cpp451
-rw-r--r--dep/efsw/src/efsw/DirWatcherGeneric.hpp55
-rw-r--r--dep/efsw/src/efsw/DirectorySnapshot.cpp261
-rw-r--r--dep/efsw/src/efsw/DirectorySnapshot.hpp46
-rw-r--r--dep/efsw/src/efsw/DirectorySnapshotDiff.cpp29
-rw-r--r--dep/efsw/src/efsw/DirectorySnapshotDiff.hpp35
-rw-r--r--dep/efsw/src/efsw/FileInfo.cpp274
-rw-r--r--dep/efsw/src/efsw/FileInfo.hpp66
-rw-r--r--dep/efsw/src/efsw/FileSystem.cpp124
-rw-r--r--dep/efsw/src/efsw/FileSystem.hpp40
-rw-r--r--dep/efsw/src/efsw/FileWatcher.cpp145
-rw-r--r--dep/efsw/src/efsw/FileWatcherCWrapper.cpp132
-rw-r--r--dep/efsw/src/efsw/FileWatcherFSEvents.cpp278
-rw-r--r--dep/efsw/src/efsw/FileWatcherFSEvents.hpp107
-rw-r--r--dep/efsw/src/efsw/FileWatcherGeneric.cpp197
-rw-r--r--dep/efsw/src/efsw/FileWatcherGeneric.hpp59
-rw-r--r--dep/efsw/src/efsw/FileWatcherImpl.cpp29
-rw-r--r--dep/efsw/src/efsw/FileWatcherImpl.hpp54
-rw-r--r--dep/efsw/src/efsw/FileWatcherInotify.cpp531
-rw-r--r--dep/efsw/src/efsw/FileWatcherInotify.hpp73
-rw-r--r--dep/efsw/src/efsw/FileWatcherKqueue.cpp274
-rw-r--r--dep/efsw/src/efsw/FileWatcherKqueue.hpp78
-rw-r--r--dep/efsw/src/efsw/FileWatcherWin32.cpp291
-rw-r--r--dep/efsw/src/efsw/FileWatcherWin32.hpp69
-rw-r--r--dep/efsw/src/efsw/Log.cpp27
-rw-r--r--dep/efsw/src/efsw/Mutex.cpp26
-rw-r--r--dep/efsw/src/efsw/Mutex.hpp28
-rw-r--r--dep/efsw/src/efsw/String.cpp813
-rw-r--r--dep/efsw/src/efsw/String.hpp629
-rw-r--r--dep/efsw/src/efsw/System.cpp26
-rw-r--r--dep/efsw/src/efsw/System.hpp26
-rw-r--r--dep/efsw/src/efsw/Thread.cpp51
-rw-r--r--dep/efsw/src/efsw/Thread.hpp111
-rw-r--r--dep/efsw/src/efsw/Utf.hpp748
-rw-r--r--dep/efsw/src/efsw/Utf.inl671
-rw-r--r--dep/efsw/src/efsw/Watcher.cpp21
-rw-r--r--dep/efsw/src/efsw/Watcher.hpp30
-rw-r--r--dep/efsw/src/efsw/WatcherFSEvents.cpp264
-rw-r--r--dep/efsw/src/efsw/WatcherFSEvents.hpp70
-rw-r--r--dep/efsw/src/efsw/WatcherGeneric.cpp40
-rw-r--r--dep/efsw/src/efsw/WatcherGeneric.hpp30
-rw-r--r--dep/efsw/src/efsw/WatcherInotify.cpp35
-rw-r--r--dep/efsw/src/efsw/WatcherInotify.hpp25
-rw-r--r--dep/efsw/src/efsw/WatcherKqueue.cpp667
-rw-r--r--dep/efsw/src/efsw/WatcherKqueue.hpp94
-rw-r--r--dep/efsw/src/efsw/WatcherWin32.cpp150
-rw-r--r--dep/efsw/src/efsw/WatcherWin32.hpp77
-rw-r--r--dep/efsw/src/efsw/base.hpp110
-rw-r--r--dep/efsw/src/efsw/inotify-nosys.h159
-rw-r--r--dep/efsw/src/efsw/platform/platformimpl.hpp20
-rw-r--r--dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp144
-rw-r--r--dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp27
-rw-r--r--dep/efsw/src/efsw/platform/posix/MutexImpl.cpp32
-rw-r--r--dep/efsw/src/efsw/platform/posix/MutexImpl.hpp31
-rw-r--r--dep/efsw/src/efsw/platform/posix/SystemImpl.cpp180
-rw-r--r--dep/efsw/src/efsw/platform/posix/SystemImpl.hpp26
-rw-r--r--dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp68
-rw-r--r--dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp35
-rw-r--r--dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp89
-rw-r--r--dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp28
-rw-r--r--dep/efsw/src/efsw/platform/win/MutexImpl.cpp29
-rw-r--r--dep/efsw/src/efsw/platform/win/MutexImpl.hpp34
-rw-r--r--dep/efsw/src/efsw/platform/win/SystemImpl.cpp50
-rw-r--r--dep/efsw/src/efsw/platform/win/SystemImpl.hpp26
-rw-r--r--dep/efsw/src/efsw/platform/win/ThreadImpl.cpp56
-rw-r--r--dep/efsw/src/efsw/platform/win/ThreadImpl.hpp39
-rw-r--r--dep/efsw/src/efsw/sophist.h147
-rw-r--r--dep/efsw/src/test/efsw-test.cpp151
-rw-r--r--sql/updates/world/2016_03_24_00_world_335.sql9
-rw-r--r--sql/updates/world/2016_03_24_01_world_335.sql9
-rw-r--r--sql/updates/world/2016_03_24_02_world.sql4
-rw-r--r--sql/updates/world/2016_03_26_00_world.sql516
-rw-r--r--sql/updates/world/2016_03_27_00_world.sql3
-rw-r--r--sql/updates/world/2016_03_28_00_world.sql2
-rw-r--r--sql/updates/world/2016_03_28_01_world.sql1
-rw-r--r--sql/updates/world/2016_03_29_00_world_335.sql11
-rw-r--r--src/common/CMakeLists.txt14
-rw-r--r--src/common/Collision/BoundingIntervalHierarchy.h2
-rw-r--r--src/common/Collision/DynamicTree.h2
-rw-r--r--src/common/Collision/Management/IVMapManager.h2
-rw-r--r--src/common/Collision/Management/MMapFactory.h2
-rw-r--r--src/common/Collision/Management/MMapManager.h2
-rw-r--r--src/common/Collision/Management/VMapFactory.h2
-rw-r--r--src/common/Collision/Management/VMapManager2.h4
-rw-r--r--src/common/Collision/Maps/MapTree.h6
-rw-r--r--src/common/Collision/Maps/TileAssembler.h10
-rw-r--r--src/common/Collision/Models/GameObjectModel.h6
-rw-r--r--src/common/Collision/Models/ModelInstance.h4
-rw-r--r--src/common/Collision/Models/WorldModel.h8
-rw-r--r--src/common/Collision/RegularGrid.h2
-rw-r--r--src/common/Common.h4
-rw-r--r--src/common/Configuration/BuiltInConfig.h9
-rw-r--r--src/common/Configuration/Config.cpp44
-rw-r--r--src/common/Configuration/Config.h4
-rw-r--r--src/common/Cryptography/ARC4.h2
-rw-r--r--src/common/Cryptography/Authentication/AuthCrypt.h2
-rw-r--r--src/common/Cryptography/BigNumber.h2
-rw-r--r--src/common/Cryptography/HMACSHA1.h2
-rw-r--r--src/common/Cryptography/OpenSSLCrypto.h8
-rw-r--r--src/common/Cryptography/SHA1.h2
-rw-r--r--src/common/Debugging/Errors.h14
-rw-r--r--src/common/Define.h39
-rw-r--r--src/common/GitRevision.cpp1
-rw-r--r--src/common/GitRevision.h27
-rw-r--r--src/common/Logging/Appender.h6
-rw-r--r--src/common/Logging/AppenderConsole.h2
-rw-r--r--src/common/Logging/AppenderFile.h2
-rw-r--r--src/common/Logging/Log.h2
-rw-r--r--src/common/Logging/LogOperation.h3
-rw-r--r--src/common/Logging/Logger.h2
-rw-r--r--src/common/Utilities/Containers.h1
-rw-r--r--src/common/Utilities/EventMap.h2
-rw-r--r--src/common/Utilities/EventProcessor.h4
-rw-r--r--src/common/Utilities/Random.h18
-rw-r--r--src/common/Utilities/TaskScheduler.h6
-rw-r--r--src/common/Utilities/Util.h48
-rw-r--r--src/server/authserver/Server/AuthSocketMgr.h4
-rw-r--r--src/server/database/CMakeLists.txt14
-rw-r--r--src/server/database/Database/AdhocStatement.h2
-rw-r--r--src/server/database/Database/DatabaseEnv.h6
-rw-r--r--src/server/database/Database/DatabaseLoader.cpp12
-rw-r--r--src/server/database/Database/DatabaseLoader.h2
-rw-r--r--src/server/database/Database/DatabaseWorker.h2
-rw-r--r--src/server/database/Database/DatabaseWorkerPool.cpp6
-rw-r--r--src/server/database/Database/Field.h2
-rw-r--r--src/server/database/Database/Implementation/CharacterDatabase.h2
-rw-r--r--src/server/database/Database/Implementation/LoginDatabase.h2
-rw-r--r--src/server/database/Database/Implementation/WorldDatabase.h2
-rw-r--r--src/server/database/Database/MySQLConnection.h4
-rw-r--r--src/server/database/Database/MySQLThreading.h2
-rw-r--r--src/server/database/Database/PreparedStatement.h6
-rw-r--r--src/server/database/Database/QueryHolder.h4
-rw-r--r--src/server/database/Database/QueryResult.h4
-rw-r--r--src/server/database/Database/SQLOperation.h2
-rw-r--r--src/server/database/Database/Transaction.h4
-rw-r--r--src/server/database/Logging/AppenderDB.h2
-rw-r--r--src/server/database/Updater/DBUpdater.cpp6
-rw-r--r--src/server/database/Updater/DBUpdater.h6
-rw-r--r--src/server/database/Updater/UpdateFetcher.h2
-rw-r--r--src/server/game/AI/CoreAI/CombatAI.h12
-rw-r--r--src/server/game/AI/CoreAI/GameObjectAI.h4
-rw-r--r--src/server/game/AI/CoreAI/GuardAI.h2
-rw-r--r--src/server/game/AI/CoreAI/PassiveAI.h10
-rw-r--r--src/server/game/AI/CoreAI/PetAI.h2
-rw-r--r--src/server/game/AI/CoreAI/ReactorAI.h2
-rw-r--r--src/server/game/AI/CoreAI/TotemAI.h2
-rw-r--r--src/server/game/AI/CoreAI/UnitAI.h8
-rw-r--r--src/server/game/AI/CreatureAI.h6
-rw-r--r--src/server/game/AI/CreatureAISelector.h6
-rw-r--r--src/server/game/AI/PlayerAI/PlayerAI.h2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.cpp10
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedCreature.h22
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedEscortAI.h2
-rw-r--r--src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartAI.h4
-rw-r--r--src/server/game/AI/SmartScripts/SmartScript.h2
-rw-r--r--src/server/game/AI/SmartScripts/SmartScriptMgr.h4
-rw-r--r--src/server/game/Accounts/AccountMgr.h2
-rw-r--r--src/server/game/Accounts/RBAC.h4
-rw-r--r--src/server/game/Achievements/AchievementMgr.h6
-rw-r--r--src/server/game/AuctionHouse/AuctionHouseMgr.h6
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBot.h4
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h2
-rw-r--r--src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h2
-rw-r--r--src/server/game/Battlefield/Battlefield.h6
-rw-r--r--src/server/game/Battlefield/BattlefieldMgr.h2
-rw-r--r--src/server/game/Battlefield/Zones/BattlefieldWG.h6
-rw-r--r--src/server/game/Battlegrounds/Arena.h2
-rw-r--r--src/server/game/Battlegrounds/ArenaScore.h4
-rw-r--r--src/server/game/Battlegrounds/ArenaTeam.h4
-rw-r--r--src/server/game/Battlegrounds/ArenaTeamMgr.h2
-rw-r--r--src/server/game/Battlegrounds/Battleground.h2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundMgr.h2
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.cpp10
-rw-r--r--src/server/game/Battlegrounds/BattlegroundQueue.h6
-rw-r--r--src/server/game/CMakeLists.txt18
-rw-r--r--src/server/game/Calendar/CalendarMgr.h6
-rw-r--r--src/server/game/Chat/Channels/Channel.h2
-rw-r--r--src/server/game/Chat/Channels/ChannelMgr.h2
-rw-r--r--src/server/game/Chat/Chat.h6
-rw-r--r--src/server/game/Chat/ChatLink.h20
-rw-r--r--src/server/game/Combat/HostileRefManager.h2
-rw-r--r--src/server/game/Combat/ThreatManager.h8
-rw-r--r--src/server/game/Combat/UnitEvents.h2
-rw-r--r--src/server/game/Conditions/ConditionMgr.h6
-rw-r--r--src/server/game/Conditions/DisableMgr.h10
-rw-r--r--src/server/game/DataStores/DBCStores.h288
-rw-r--r--src/server/game/DungeonFinding/LFG.h6
-rw-r--r--src/server/game/DungeonFinding/LFGGroupData.h2
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.h2
-rw-r--r--src/server/game/DungeonFinding/LFGPlayerData.h2
-rw-r--r--src/server/game/DungeonFinding/LFGQueue.h2
-rw-r--r--src/server/game/DungeonFinding/LFGScripts.h4
-rw-r--r--src/server/game/Entities/Corpse/Corpse.h2
-rw-r--r--src/server/game/Entities/Creature/Creature.h12
-rw-r--r--src/server/game/Entities/Creature/CreatureGroups.h4
-rw-r--r--src/server/game/Entities/Creature/GossipDef.h6
-rw-r--r--src/server/game/Entities/Creature/TemporarySummon.h10
-rw-r--r--src/server/game/Entities/DynamicObject/DynamicObject.h2
-rw-r--r--src/server/game/Entities/GameObject/GameObject.h2
-rw-r--r--src/server/game/Entities/Item/Container/Bag.h2
-rw-r--r--src/server/game/Entities/Item/Item.h2
-rw-r--r--src/server/game/Entities/Item/ItemEnchantmentMgr.cpp6
-rw-r--r--src/server/game/Entities/Item/ItemEnchantmentMgr.h7
-rw-r--r--src/server/game/Entities/Object/Object.h6
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.cpp17
-rw-r--r--src/server/game/Entities/Object/ObjectGuid.h19
-rw-r--r--src/server/game/Entities/Object/ObjectPosSelector.h2
-rw-r--r--src/server/game/Entities/Object/Position.h14
-rw-r--r--src/server/game/Entities/Object/Updates/UpdateFieldFlags.h10
-rw-r--r--src/server/game/Entities/Pet/Pet.h2
-rw-r--r--src/server/game/Entities/Player/KillRewarder.h2
-rw-r--r--src/server/game/Entities/Player/Player.h10
-rw-r--r--src/server/game/Entities/Player/SocialMgr.h2
-rw-r--r--src/server/game/Entities/Player/TradeData.h2
-rw-r--r--src/server/game/Entities/Totem/Totem.h2
-rw-r--r--src/server/game/Entities/Transport/Transport.h2
-rw-r--r--src/server/game/Entities/Unit/Unit.h14
-rw-r--r--src/server/game/Entities/Vehicle/Vehicle.h4
-rw-r--r--src/server/game/Events/GameEventMgr.h6
-rw-r--r--src/server/game/Globals/ObjectAccessor.cpp63
-rw-r--r--src/server/game/Globals/ObjectAccessor.h83
-rw-r--r--src/server/game/Globals/ObjectMgr.h14
-rw-r--r--src/server/game/Grids/GridStates.h10
-rw-r--r--src/server/game/Grids/Notifiers/GridNotifiers.h16
-rw-r--r--src/server/game/Grids/ObjectGridLoader.h6
-rw-r--r--src/server/game/Groups/Group.h2
-rw-r--r--src/server/game/Groups/GroupMgr.h2
-rw-r--r--src/server/game/Groups/GroupReference.h2
-rw-r--r--src/server/game/Guilds/Guild.h4
-rw-r--r--src/server/game/Guilds/GuildMgr.h2
-rw-r--r--src/server/game/Instances/InstanceSaveMgr.h4
-rw-r--r--src/server/game/Instances/InstanceScript.h4
-rw-r--r--src/server/game/Loot/LootMgr.cpp17
-rw-r--r--src/server/game/Loot/LootMgr.h81
-rw-r--r--src/server/game/Mails/Mail.h8
-rw-r--r--src/server/game/Maps/AreaBoundary.h14
-rw-r--r--src/server/game/Maps/Map.cpp18
-rw-r--r--src/server/game/Maps/Map.h12
-rw-r--r--src/server/game/Maps/MapInstanced.h2
-rw-r--r--src/server/game/Maps/MapManager.h2
-rw-r--r--src/server/game/Maps/MapUpdater.h2
-rw-r--r--src/server/game/Maps/TransportMgr.h6
-rw-r--r--src/server/game/Movement/MotionMaster.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerator.h2
-rwxr-xr-xsrc/server/game/Movement/MovementGenerators/IdleMovementGenerator.h2
-rw-r--r--src/server/game/Movement/PathGenerator.h2
-rw-r--r--src/server/game/Movement/Spline/MoveSpline.h2
-rw-r--r--src/server/game/Movement/Spline/MoveSplineInit.h4
-rw-r--r--src/server/game/Movement/Spline/MovementTypedefs.h4
-rw-r--r--src/server/game/Movement/Waypoints/WaypointManager.h2
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvP.h4
-rw-r--r--src/server/game/OutdoorPvP/OutdoorPvPMgr.h2
-rw-r--r--src/server/game/Pools/PoolMgr.cpp5
-rw-r--r--src/server/game/Pools/PoolMgr.h6
-rw-r--r--src/server/game/Quests/QuestDef.h2
-rw-r--r--src/server/game/Reputation/ReputationMgr.h2
-rw-r--r--src/server/game/Scripting/ScriptMgr.cpp52
-rw-r--r--src/server/game/Scripting/ScriptMgr.h58
-rw-r--r--src/server/game/Scripting/ScriptSystem.cpp2
-rw-r--r--src/server/game/Scripting/ScriptSystem.h2
-rw-r--r--src/server/game/Server/Protocol/Opcodes.h2
-rw-r--r--src/server/game/Server/Protocol/PacketLog.h2
-rw-r--r--src/server/game/Server/WorldSession.h2
-rw-r--r--src/server/game/Server/WorldSocket.h2
-rw-r--r--src/server/game/Server/WorldSocketMgr.cpp4
-rw-r--r--src/server/game/Server/WorldSocketMgr.h4
-rw-r--r--src/server/game/Skills/SkillDiscovery.h9
-rw-r--r--src/server/game/Skills/SkillExtraItems.h10
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.h2
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h10
-rw-r--r--src/server/game/Spells/Spell.h18
-rw-r--r--src/server/game/Spells/SpellHistory.h2
-rw-r--r--src/server/game/Spells/SpellInfo.h6
-rw-r--r--src/server/game/Spells/SpellMgr.cpp2
-rw-r--r--src/server/game/Spells/SpellMgr.h16
-rw-r--r--src/server/game/Spells/SpellScript.h60
-rw-r--r--src/server/game/Texts/CreatureTextMgr.h2
-rw-r--r--src/server/game/Tickets/TicketMgr.h4
-rw-r--r--src/server/game/Tools/CharacterDatabaseCleaner.h22
-rw-r--r--src/server/game/Tools/PlayerDump.cpp6
-rw-r--r--src/server/game/Tools/PlayerDump.h6
-rw-r--r--src/server/game/Warden/Warden.h2
-rw-r--r--src/server/game/Warden/WardenCheckMgr.h2
-rw-r--r--src/server/game/Warden/WardenMac.h2
-rw-r--r--src/server/game/Warden/WardenWin.h2
-rw-r--r--src/server/game/Weather/Weather.h2
-rw-r--r--src/server/game/Weather/WeatherMgr.h12
-rw-r--r--src/server/game/World/World.cpp20
-rw-r--r--src/server/game/World/World.h5
-rw-r--r--src/server/scripts/CMakeLists.txt2
-rw-r--r--src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp11
-rw-r--r--src/server/scripts/Pet/pet_generic.cpp65
-rw-r--r--src/server/scripts/Spells/spell_generic.cpp35
-rw-r--r--src/server/shared/CMakeLists.txt14
-rw-r--r--src/server/shared/DataStores/DBCFileLoader.h2
-rw-r--r--src/server/shared/Networking/SocketMgr.h12
-rw-r--r--src/server/shared/Packets/ByteBuffer.h8
-rw-r--r--src/server/worldserver/Main.cpp10
-rw-r--r--src/server/worldserver/worldserver.conf.dist23
317 files changed, 12381 insertions, 919 deletions
diff --git a/.travis.yml b/.travis.yml
index 7ed50ef0ec4..894fedf4da6 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -21,7 +21,7 @@ install:
- mysql -uroot -e 'create database test_mysql;'
- mkdir bin
- cd bin
- - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror"
+ - cmake ../ -DWITH_WARNINGS=1 -DWITH_COREDEBUG=0 -DUSE_COREPCH=1 -DUSE_SCRIPTPCH=1 -DTOOLS=1 -DSCRIPTS=1 -DSERVERS=1 -DNOJEM=1 -DWITH_DYNAMIC_LINKING=1 -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-Werror" -DCMAKE_CXX_FLAGS="-Werror" -DCMAKE_INSTALL_PREFIX=check_install
- cd ..
- sudo chmod +x contrib/check_updates.sh
@@ -36,4 +36,7 @@ script:
- cat sql/updates/world/*.sql | mysql -utrinity -ptrinity world
- mysql -uroot < sql/create/drop_mysql.sql
- cd bin
- - make -j 10 -k
+ - make -j 8 -k && make install
+ - cd check_install/bin
+ - ./authserver --version
+ - ./worldserver --version
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 17d4e1f051d..dda8f242feb 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -24,9 +24,6 @@ endif(POLICY CMP0043)
set(CMAKE_DISABLE_SOURCE_CHANGES ON)
set(CMAKE_DISABLE_IN_SOURCE_BUILD ON)
-# build static libraries
-set(BUILD_SHARED_LIBS OFF)
-
# Set RPATH-handing (CMake parameters)
set(CMAKE_SKIP_BUILD_RPATH 0)
set(CMAKE_BUILD_WITH_INSTALL_RPATH 0)
diff --git a/cmake/compiler/clang/settings.cmake b/cmake/compiler/clang/settings.cmake
index 261a55b285f..9a8cb85275e 100644
--- a/cmake/compiler/clang/settings.cmake
+++ b/cmake/compiler/clang/settings.cmake
@@ -18,3 +18,16 @@ endif()
# -Wno-deprecated-register is needed to suppress 185 gsoap warnings on Unix systems.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1")
+
+if (WITH_DYNAMIC_LINKING)
+ # -fPIC is needed to allow static linking in shared libs.
+ # -fvisibility=hidden sets the default visibility to hidden to prevent exporting of all symbols.
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden")
+
+ # --no-undefined to throw errors when there are undefined symbols
+ # (caused through missing TRINITY_*_API macros).
+ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --no-undefined")
+
+ message(STATUS "Clang: Disallow undefined symbols")
+endif()
diff --git a/cmake/compiler/gcc/settings.cmake b/cmake/compiler/gcc/settings.cmake
index acd71e82fd9..d9eda767b8e 100644
--- a/cmake/compiler/gcc/settings.cmake
+++ b/cmake/compiler/gcc/settings.cmake
@@ -34,3 +34,15 @@ if( WITH_COREDEBUG )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g3")
message(STATUS "GCC: Debug-flags set (-g3)")
endif()
+
+if (WITH_DYNAMIC_LINKING)
+ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -fvisibility=hidden -Wno-attributes")
+
+ # Should break the build when there are TRINITY_*_API macros missing
+ # but it complains about missing references in precompiled headers.
+ # set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wl,--no-undefined")
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--no-undefined")
+
+ message(STATUS "GCC: Enabled shared linking")
+endif()
diff --git a/cmake/compiler/msvc/settings.cmake b/cmake/compiler/msvc/settings.cmake
index 8af8033d809..c2eda80512b 100644
--- a/cmake/compiler/msvc/settings.cmake
+++ b/cmake/compiler/msvc/settings.cmake
@@ -18,11 +18,6 @@ if(PLATFORM EQUAL 64)
add_definitions("-D_WIN64")
message(STATUS "MSVC: 64-bit platform, enforced -D_WIN64 parameter")
- if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0)
- #Enable extended object support for debug compiles on X64 (not required on X86)
- set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /bigobj")
- message(STATUS "MSVC: Enabled increased number of sections in object files")
- endif()
else()
# mark 32 bit executables large address aware so they can use > 2GB address space
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /LARGEADDRESSAWARE")
@@ -41,15 +36,20 @@ add_definitions(-D_BUILD_DIRECTIVE=\\"$(ConfigurationName)\\")
# multithreaded compiling on VS
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
+if((PLATFORM EQUAL 64) OR (NOT CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0) OR WITH_DYNAMIC_LINKING)
+ # Enable extended object support
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /bigobj")
+ message(STATUS "MSVC: Enabled increased number of sections in object files")
+endif()
+
# /Zc:throwingNew.
# When you specify Zc:throwingNew on the command line, it instructs the compiler to assume
# that the program will eventually be linked with a conforming operator new implementation,
# and can omit all of these extra null checks from your program.
# http://blogs.msdn.com/b/vcblog/archive/2015/08/06/new-in-vs-2015-zc-throwingnew.aspx
if(NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 19.0.23026.0))
- # also enable /bigobj for ALL builds under visual studio 2015, increased number of templates in standard library
# makes this flag a requirement to build TC at all
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew /bigobj")
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:throwingNew")
endif()
# Define _CRT_SECURE_CPP_OVERLOAD_STANDARD_NAMES - eliminates the warning by changing the strcpy call to strcpy_s, which prevents buffer overruns
@@ -74,6 +74,13 @@ if(NOT WITH_WARNINGS)
message(STATUS "MSVC: Disabled generic compiletime warnings")
endif()
+if (WITH_DYNAMIC_LINKING)
+ # C4251: needs to have dll-interface to be used by clients of class '...'
+ # C4275: non dll-interface class ...' used as base for dll-interface class '...'
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4251 /wd4275")
+ message(STATUS "MSVC: Enabled shared linking")
+endif()
+
# Specify the maximum PreCompiled Header memory allocation limit
# Fixes a compiler-problem when using PCH - the /Ym flag is adjusted by the compiler in MSVC2012, hence we need to set an upper limit with /Zm to avoid discrepancies)
# (And yes, this is a verified , unresolved bug with MSVC... *sigh*)
diff --git a/cmake/options.cmake b/cmake/options.cmake
index d49393ed745..62810b2d3f2 100644
--- a/cmake/options.cmake
+++ b/cmake/options.cmake
@@ -13,6 +13,7 @@ option(SCRIPTS "Build core with scripts included"
option(TOOLS "Build map/vmap/mmap extraction/assembler tools" 0)
option(USE_SCRIPTPCH "Use precompiled headers when compiling scripts" 1)
option(USE_COREPCH "Use precompiled headers when compiling servers" 1)
+option(WITH_DYNAMIC_LINKING "Enable dynamic library linking." 0)
option(WITH_WARNINGS "Show all warnings during compile" 0)
option(WITH_COREDEBUG "Include additional debug-code in core" 0)
set(WITH_SOURCE_TREE "hierarchical" CACHE STRING "Build the source tree for IDE's.")
diff --git a/cmake/showoptions.cmake b/cmake/showoptions.cmake
index 537544ba10e..e6d709207b3 100644
--- a/cmake/showoptions.cmake
+++ b/cmake/showoptions.cmake
@@ -113,5 +113,15 @@ if ( HELGRIND )
add_definitions(-DHELGRIND)
endif()
-message("")
+if (WITH_DYNAMIC_LINKING)
+ message("")
+ message(" *** WITH_DYNAMIC_LINKING - INFO!")
+ message(" *** Will link against shared libraries!")
+ message(" *** Please note that this is an experimental feature!")
+ add_definitions(-DTRINITY_API_USE_DYNAMIC_LINKING)
+ set(BUILD_SHARED_LIBS ON)
+else()
+ set(BUILD_SHARED_LIBS OFF)
+endif()
+message("")
diff --git a/dep/CMakeLists.txt b/dep/CMakeLists.txt
index aeffd5b8469..0932c7d4058 100644
--- a/dep/CMakeLists.txt
+++ b/dep/CMakeLists.txt
@@ -34,6 +34,7 @@ if(SERVERS)
add_subdirectory(readline)
add_subdirectory(gsoap)
add_subdirectory(process)
+ add_subdirectory(efsw)
endif()
if(TOOLS)
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index f855e8d493d..66421127162 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -16,6 +16,10 @@ cppformat (type safe format library)
https://github.com/cppformat/cppformat
Version: 5174b8ca281426af604b85fdf53be8a748b33f56
+efws (Entropia File System Watcher - crossplatform file system watcher)
+ https://bitbucket.org/SpartanJ/efsw
+ ff0b69daeca1edf7785a8a580518e462be5a6f3d
+
G3D (a commercial-grade C++ 3D engine available as Open Source (BSD License)
http://g3d.sourceforge.net/
Version: 9.0-Release r4036
diff --git a/dep/efsw/.hg_archival.txt b/dep/efsw/.hg_archival.txt
new file mode 100644
index 00000000000..19565afb668
--- /dev/null
+++ b/dep/efsw/.hg_archival.txt
@@ -0,0 +1,5 @@
+repo: 78c2ea8c48b213ee0078d6326a1dd719d0844764
+node: ff0b69daeca1edf7785a8a580518e462be5a6f3d
+branch: default
+latesttag: null
+latesttagdistance: 144
diff --git a/dep/efsw/CMakeLists.txt b/dep/efsw/CMakeLists.txt
new file mode 100644
index 00000000000..81a1d20b204
--- /dev/null
+++ b/dep/efsw/CMakeLists.txt
@@ -0,0 +1,85 @@
+if (WITH_DYNAMIC_LINKING)
+ set(SRCS
+ src/efsw/DirectorySnapshot.cpp
+ src/efsw/DirectorySnapshotDiff.cpp
+ src/efsw/DirWatcherGeneric.cpp
+ src/efsw/FileInfo.cpp
+ src/efsw/FileSystem.cpp
+ src/efsw/FileWatcher.cpp
+ src/efsw/FileWatcherCWrapper.cpp
+ src/efsw/FileWatcherGeneric.cpp
+ src/efsw/FileWatcherImpl.cpp
+ src/efsw/Log.cpp
+ src/efsw/Mutex.cpp
+ src/efsw/String.cpp
+ src/efsw/System.cpp
+ src/efsw/Thread.cpp
+ src/efsw/Watcher.cpp
+ src/efsw/WatcherGeneric.cpp)
+
+ if(WIN32)
+ list(APPEND SRCS
+ src/efsw/platform/win/FileSystemImpl.cpp
+ src/efsw/platform/win/MutexImpl.cpp
+ src/efsw/platform/win/SystemImpl.cpp
+ src/efsw/platform/win/ThreadImpl.cpp)
+ else()
+ list(APPEND SRCS
+ src/efsw/platform/posix/FileSystemImpl.cpp
+ src/efsw/platform/posix/MutexImpl.cpp
+ src/efsw/platform/posix/SystemImpl.cpp
+ src/efsw/platform/posix/ThreadImpl.cpp)
+ endif()
+
+ if (WIN32)
+ list(APPEND SRCS
+ src/efsw/WatcherWin32.cpp
+ src/efsw/FileWatcherWin32.cpp)
+ elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
+ list(APPEND SRCS
+ src/efsw/FileWatcherInotify.cpp
+ src/efsw/WatcherInotify.cpp)
+
+ if (NOT EXISTS "/usr/include/sys/inotify.h" AND NOT EXISTS "/usr/local/include/sys/inotify.h")
+ add_definitions(-DEFSW_INOTIFY_NOSYS)
+ endif()
+ elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" OR APPLE)
+ list(APPEND SRCS
+ src/efsw/FileWatcherKqueue.cpp
+ src/efsw/WatcherKqueue.cpp)
+
+ if (APPLE)
+ list(APPEND SRCS
+ src/efsw/FileWatcherFSEvents.cpp
+ src/efsw/WatcherFSEvents.cpp)
+
+ exec_program(uname ARGS -v OUTPUT_VARIABLE OSX_VERSION)
+ string(REGEX MATCH "[0-9]+" OSX_VERSION ${OSX_VERSION})
+ if (NOT OSX_VERSION GREATER 9)
+ add_definitions(-DEFSW_FSEVENTS_NOT_SUPPORTED)
+ endif()
+
+ set(OPTIONAL_MAC_LINK_LIBRARIES "-framework CoreFoundation" "-framework CoreServices")
+ endif()
+ endif()
+
+ add_library(efsw STATIC ${SRCS})
+
+ target_include_directories(efsw
+ PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/include
+ PRIVATE
+ ${CMAKE_CURRENT_SOURCE_DIR}/src)
+
+ target_link_libraries(efsw
+ PUBLIC
+ threads
+ ${OPTIONAL_MAC_LINK_LIBRARIES})
+
+ set_target_properties(efsw
+ PROPERTIES
+ FOLDER
+ "dep")
+else()
+ add_library(efsw INTERFACE)
+endif()
diff --git a/dep/efsw/LICENSE b/dep/efsw/LICENSE
new file mode 100644
index 00000000000..ac8ac28988d
--- /dev/null
+++ b/dep/efsw/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012 Martín Lucas Golini
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com)
+http://code.google.com/p/simplefilewatcher/ also MIT licensed. \ No newline at end of file
diff --git a/dep/efsw/README.md b/dep/efsw/README.md
new file mode 100644
index 00000000000..fda0bb599aa
--- /dev/null
+++ b/dep/efsw/README.md
@@ -0,0 +1,138 @@
+Entropia File System Watcher
+============================
+**efsw** is a C++ cross-platform file system watcher and notifier.
+
+**efsw** monitors the file system asynchronously for changes to files and directories by watching a list of specified paths, and raises events when a directory or file change.
+
+**efsw** supports recursive directories watch, tracking the entire sub directory tree.
+
+**efsw** currently supports the following platforms:
+
+* Linux via [inotify](http://en.wikipedia.org/wiki/Inotify)
+
+* Windows via [I/O Completion Ports](http://en.wikipedia.org/wiki/IOCP)
+
+* Mac OS X via [FSEvents](http://en.wikipedia.org/wiki/FSEvents) or [kqueue](http://en.wikipedia.org/wiki/Kqueue)
+
+* FreeBSD/BSD via [kqueue](http://en.wikipedia.org/wiki/Kqueue)
+
+* OS-independent generic watcher
+(polling the disk for directory snapshots and comparing them periodically)
+
+If any of the backend fails to start by any reason, it will fallback to the OS-independent implementation.
+This should never happen, except for the Kqueue implementation, see `Platform limitations and clarifications`.
+
+**Code License**
+--------------
+[MIT License](http://www.opensource.org/licenses/mit-license.php)
+
+**Some example code:**
+--------------------
+
+ :::c++
+ // Inherits from the abstract listener class, and implements the the file action handler
+ class UpdateListener : public efsw::FileWatchListener
+ {
+ public:
+ UpdateListener() {}
+
+ void handleFileAction( efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "" )
+ {
+ switch( action )
+ {
+ case efsw::Actions::Add:
+ std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Added" << std::endl;
+ break;
+ case efsw::Actions::Delete:
+ std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Delete" << std::endl;
+ break;
+ case efsw::Actions::Modified:
+ std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Modified" << std::endl;
+ break;
+ case efsw::Actions::Moved:
+ std::cout << "DIR (" << dir << ") FILE (" << filename << ") has event Moved from (" << oldFilename << ")" << std::endl;
+ break;
+ default:
+ std::cout << "Should never happen!" << std::endl;
+ }
+ }
+ };
+
+ // Create the file system watcher instance
+ // efsw::FileWatcher allow a first boolean parameter that indicates if it should start with the generic file watcher instead of the platform specific backend
+ efsw::FileWatcher * fileWatcher = new efsw::FileWatcher();
+
+ // Create the instance of your efsw::FileWatcherListener implementation
+ UpdateListener * listener = new UpdateListener();
+
+ // Add a folder to watch, and get the efsw::WatchID
+ // It will watch the /tmp folder recursively ( the third parameter indicates that is recursive )
+ // Reporting the files and directories changes to the instance of the listener
+ efsw::WatchID watchID = fileWatcher->addWatch( "/tmp", listener, true );
+
+ // Adds another directory to watch. This time as non-recursive.
+ efsw::WatchID watchID2 = fileWatcher->addWatch( "/usr", listener, false );
+
+ // Start watching asynchronously the directories
+ fileWatcher.watch();
+
+ // Remove the second watcher added
+ // You can also call removeWatch by passing the watch path ( it must end with an slash or backslash in windows, since that's how internally it's saved )
+ fileWatcher->removeWatch( watchID2 );
+
+**Dependencies**
+--------------
+None :)
+
+**Compiling**
+------------
+To generate project files you will need to [download and install](http://industriousone.com/premake/download) [Premake](http://industriousone.com/what-premake)
+
+Then you can generate the project for your platform just going to the project directory where the premake4.lua file is located and then execute:
+
+`premake4 gmake` to generate project Makefiles, then `cd make/*YOURPLATFORM*/`, and finally `make` or `make config=release` ( it will generate the static lib, the shared lib and the test application ).
+
+or
+
+`premake4 vs2010` to generate Visual Studio 2010 project.
+
+or
+
+`premake4 xcode4` to generate Xcode 4 project.
+
+There is also a cmake file that i don't oficially support but it works just fine, provided by [Mohammed Nafees](https://bitbucket.org/binaryking).
+
+**Platform limitations and clarifications**
+-------------------------------------------
+
+Directory paths are expected to be encoded as UTF-8 strings in all platforms.
+
+handleFileAction returns UTF-8 strings in all platforms.
+
+Windows and FSEvents Mac OS X implementation can't follow symlinks ( it will ignore followSymlinks() and allowOutOfScopeLinks() ).
+
+Kqueue implementation is limited by the maximun number of file descriptors allowed per process by the OS, in the case of reaching the file descriptors limit ( in BSD around 18000 and in OS X around 10240 ) it will fallback to the generic file watcher.
+
+OS X will only use Kqueue if OS X version is below to 10.5, and this implementation needs to be compiled separately from the OS X >= 10.5 implementation. Since there's no way to compile FSEvents backend in OS X below 10.5.
+
+FSEvents for OS X Lion and beyond in some cases will generate more actions that in reality ocurred, since fine-grained implementation of FSEvents doesn't give the order of the actions retrieved, in some cases i need to guess/aproximate the order of them.
+
+Generic watcher relies on the inode information to detect file and directories renames/move. Since Windows has no concept of inodes as Unix platforms do, there is no current reliable way of determining file/directory movement on Windows without help from the Windows API ( this is replaced with Add/Delete events ).
+
+Linux versions below 2.6.13 are not supported, since inotify wasn't implemented yet. I'm not interested in support older kernels, since i don't see the point. If someone needs this open an issue in the issue tracker and i may consider implenent a dnotify backend.
+
+OS-independent watcher, Kqueue and FSEvents for OS X below 10.5 keep cache of the directories structures, to be able to detect changes in the directories. This means that there's a memory overhead for this backends.
+
+**Useful information**
+--------------------
+The project also comes with a C API wrapper, contributed by [Sepul Sepehr Taghdisian](https://bitbucket.org/sepul).
+
+There's a string manipulation class not exposed in the efsw header ( efsw::String ) that can be used to make string encoding conversion.
+
+
+**Clarifications**
+----------------
+
+This software started as a fork of the [simplefilewatcher](http://code.google.com/p/simplefilewatcher/) by James Wynn (james[at]jameswynn.com), [MIT licensed](http://www.opensource.org/licenses/mit-license.html).
+
+The icon used for the project is part of the [Haiku®'s Icons](http://www.haiku-inc.org/haiku-icons.html), [MIT licensed](http://www.opensource.org/licenses/mit-license.html).
diff --git a/dep/efsw/include/efsw/efsw.h b/dep/efsw/include/efsw/efsw.h
new file mode 100644
index 00000000000..28e63e2139e
--- /dev/null
+++ b/dep/efsw/include/efsw/efsw.h
@@ -0,0 +1,151 @@
+/**
+ @author Sepul Sepehr Taghdisian
+
+ Copyright (c) 2013 Martin Lucas Golini
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com)
+ http://code.google.com/p/simplefilewatcher/ also MIT licensed.
+*/
+/** This is the C API wrapper of EFSW */
+#ifndef ESFW_H
+#define ESFW_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_WIN32)
+ #ifdef EFSW_DYNAMIC
+ // Windows platforms
+ #ifdef EFSW_EXPORTS
+ // From DLL side, we must export
+ #define EFSW_API __declspec(dllexport)
+ #else
+ // From client application side, we must import
+ #define EFSW_API __declspec(dllimport)
+ #endif
+ #else
+ // No specific directive needed for static build
+ #ifndef EFSW_API
+ #define EFSW_API
+ #endif
+ #endif
+#else
+ #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS )
+ #define EFSW_API __attribute__ ((visibility("default")))
+ #endif
+
+ // Other platforms don't need to define anything
+ #ifndef EFSW_API
+ #define EFSW_API
+ #endif
+#endif
+
+/// Type for a watch id
+typedef long efsw_watchid;
+
+/// Type for watcher
+typedef void* efsw_watcher;
+
+enum efsw_action
+{
+ EFSW_ADD = 1, /// Sent when a file is created or renamed
+ EFSW_DELETE = 2, /// Sent when a file is deleted or renamed
+ EFSW_MODIFIED = 3, /// Sent when a file is modified
+ EFSW_MOVED = 4 /// Sent when a file is moved
+};
+
+enum efsw_error
+{
+ EFSW_NOTFOUND = -1,
+ EFSW_REPEATED = -2,
+ EFSW_OUTOFSCOPE = -3,
+ EFSW_NOTREADABLE = -4,
+ EFSW_REMOTE = -5,
+ EFSW_UNSPECIFIED = -6
+};
+
+/// Basic interface for listening for file events.
+typedef void (*efsw_pfn_fileaction_callback) (
+ efsw_watcher watcher,
+ efsw_watchid watchid,
+ const char* dir,
+ const char* filename,
+ enum efsw_action action,
+ const char* old_filename,
+ void* param
+);
+
+/**
+ * Creates a new file-watcher
+ * @param generic_mode Force the use of the Generic file watcher
+ */
+efsw_watcher EFSW_API efsw_create(int generic_mode);
+
+/// Release the file-watcher and unwatch any directories
+void EFSW_API efsw_release(efsw_watcher watcher);
+
+/// Retreive last error occured by file-watcher
+EFSW_API const char* efsw_getlasterror();
+
+/// Add a directory watch. Same as the other addWatch, but doesn't have recursive option.
+/// For backwards compatibility.
+/// On error returns WatchID with Error type.
+efsw_watchid EFSW_API efsw_addwatch(efsw_watcher watcher, const char* directory,
+ efsw_pfn_fileaction_callback callback_fn, int recursive, void* param);
+
+/// Remove a directory watch. This is a brute force search O(nlogn).
+void EFSW_API efsw_removewatch(efsw_watcher watcher, const char* directory);
+
+/// Remove a directory watch. This is a map lookup O(logn).
+void EFSW_API efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid);
+
+/// Starts watching ( in other thread )
+void EFSW_API efsw_watch(efsw_watcher watcher);
+
+/**
+ * Allow recursive watchers to follow symbolic links to other directories
+ * followSymlinks is disabled by default
+ */
+void EFSW_API efsw_follow_symlinks(efsw_watcher watcher, int enable);
+
+/** @return If can follow symbolic links to directorioes */
+int EFSW_API efsw_follow_symlinks_isenabled(efsw_watcher watcher);
+
+/**
+ * When enable this it will allow symlinks to watch recursively out of the pointed directory.
+ * follorSymlinks must be enabled to this work.
+ * For example, added symlink to /home/folder, and the symlink points to /, this by default is not allowed,
+ * it's only allowed to symlink anything from /home/ and deeper. This is to avoid great levels of recursion.
+ * Enabling this could lead in infinite recursion, and crash the watcher ( it will try not to avoid this ).
+ * Buy enabling out of scope links, it will allow this behavior.
+ * allowOutOfScopeLinks are disabled by default.
+ */
+void EFSW_API efsw_allow_outofscopelinks(efsw_watcher watcher, int allow);
+
+/// @return Returns if out of scope links are allowed
+int EFSW_API efsw_outofscopelinks_isallowed(efsw_watcher watcher);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/dep/efsw/include/efsw/efsw.hpp b/dep/efsw/include/efsw/efsw.hpp
new file mode 100644
index 00000000000..0693bb296f0
--- /dev/null
+++ b/dep/efsw/include/efsw/efsw.hpp
@@ -0,0 +1,197 @@
+/**
+ @author Martín Lucas Golini
+
+ Copyright (c) 2013 Martín Lucas Golini
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+
+ This software is a fork of the "simplefilewatcher" by James Wynn (james@jameswynn.com)
+ http://code.google.com/p/simplefilewatcher/ also MIT licensed.
+*/
+
+#ifndef ESFW_HPP
+#define ESFW_HPP
+
+#include <string>
+#include <list>
+
+#if defined(_WIN32)
+ #ifdef EFSW_DYNAMIC
+ // Windows platforms
+ #ifdef EFSW_EXPORTS
+ // From DLL side, we must export
+ #define EFSW_API __declspec(dllexport)
+ #else
+ // From client application side, we must import
+ #define EFSW_API __declspec(dllimport)
+ #endif
+ #else
+ // No specific directive needed for static build
+ #ifndef EFSW_API
+ #define EFSW_API
+ #endif
+ #endif
+#else
+ #if ( __GNUC__ >= 4 ) && defined( EFSW_EXPORTS )
+ #define EFSW_API __attribute__ ((visibility("default")))
+ #endif
+
+ // Other platforms don't need to define anything
+ #ifndef EFSW_API
+ #define EFSW_API
+ #endif
+#endif
+
+namespace efsw {
+
+/// Type for a watch id
+typedef long WatchID;
+
+// forward declarations
+class FileWatcherImpl;
+class FileWatchListener;
+
+/// Actions to listen for. Rename will send two events, one for
+/// the deletion of the old file, and one for the creation of the
+/// new file.
+namespace Actions {
+ enum Action
+ {
+ /// Sent when a file is created or renamed
+ Add = 1,
+ /// Sent when a file is deleted or renamed
+ Delete = 2,
+ /// Sent when a file is modified
+ Modified = 3,
+ /// Sent when a file is moved
+ Moved = 4
+ };
+}
+typedef Actions::Action Action;
+
+/// Errors log namespace
+namespace Errors {
+
+enum Error
+{
+ FileNotFound = -1,
+ FileRepeated = -2,
+ FileOutOfScope = -3,
+ FileNotReadable = -4,
+ FileRemote = -5, /** Directory in remote file system ( create a generic FileWatcher instance to watch this directory ). */
+ Unspecified = -6
+};
+
+class EFSW_API Log
+{
+ public:
+ /// @return The last error logged
+ static std::string getLastErrorLog();
+
+ /// Creates an error of the type specified
+ static Error createLastError( Error err, std::string log );
+};
+
+}
+typedef Errors::Error Error;
+
+/// Listens to files and directories and dispatches events
+/// to notify the listener of files and directories changes.
+/// @class FileWatcher
+class EFSW_API FileWatcher
+{
+ public:
+ /// Default constructor, will use the default platform file watcher
+ FileWatcher();
+
+ /// Constructor that lets you force the use of the Generic File Watcher
+ FileWatcher( bool useGenericFileWatcher );
+
+ virtual ~FileWatcher();
+
+ /// Add a directory watch. Same as the other addWatch, but doesn't have recursive option.
+ /// For backwards compatibility.
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher);
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive);
+
+ /// Remove a directory watch. This is a brute force search O(nlogn).
+ void removeWatch(const std::string& directory);
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ void removeWatch(WatchID watchid);
+
+ /// Starts watching ( in other thread )
+ void watch();
+
+ /// @return Returns a list of the directories that are being watched
+ std::list<std::string> directories();
+
+ /** Allow recursive watchers to follow symbolic links to other directories
+ * followSymlinks is disabled by default
+ */
+ void followSymlinks( bool follow );
+
+ /** @return If can follow symbolic links to directorioes */
+ const bool& followSymlinks() const;
+
+ /** When enable this it will allow symlinks to watch recursively out of the pointed directory.
+ * follorSymlinks must be enabled to this work.
+ * For example, added symlink to /home/folder, and the symlink points to /, this by default is not allowed,
+ * it's only allowed to symlink anything from /home/ and deeper. This is to avoid great levels of recursion.
+ * Enabling this could lead in infinite recursion, and crash the watcher ( it will try not to avoid this ).
+ * Buy enabling out of scope links, it will allow this behavior.
+ * allowOutOfScopeLinks are disabled by default.
+ */
+ void allowOutOfScopeLinks( bool allow );
+
+ /// @return Returns if out of scope links are allowed
+ const bool& allowOutOfScopeLinks() const;
+ private:
+ /// The implementation
+ FileWatcherImpl * mImpl;
+ bool mFollowSymlinks;
+ bool mOutOfScopeLinks;
+};
+
+/// Basic interface for listening for file events.
+/// @class FileWatchListener
+class FileWatchListener
+{
+ public:
+ FileWatchListener() {}
+
+ virtual ~FileWatchListener() {}
+
+ /// Handles the action file action
+ /// @param watchid The watch id for the directory
+ /// @param dir The directory
+ /// @param filename The filename that was accessed (not full path)
+ /// @param action Action that was performed
+ /// @param oldFilename The name of the file or directory moved
+ virtual void handleFileAction(WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename = "" ) = 0;
+
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/Debug.cpp b/dep/efsw/src/efsw/Debug.cpp
new file mode 100644
index 00000000000..9c4ee02e5b6
--- /dev/null
+++ b/dep/efsw/src/efsw/Debug.cpp
@@ -0,0 +1,85 @@
+#include <efsw/Debug.hpp>
+#include <iostream>
+
+#ifdef EFSW_COMPILER_MSVC
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#include <crtdbg.h>
+#endif
+
+#include <cassert>
+#include <cstdio>
+#include <cstdarg>
+
+namespace efsw {
+
+#ifdef DEBUG
+
+void efREPORT_ASSERT( const char * File, int Line, const char * Exp )
+{
+ #ifdef EFSW_COMPILER_MSVC
+ _CrtDbgReport( _CRT_ASSERT, File, Line, "", Exp);
+
+ DebugBreak();
+ #else
+ std::cout << "ASSERT: " << Exp << " file: " << File << " line: " << Line << std::endl;
+
+ #if defined(EFSW_COMPILER_GCC) && defined(EFSW_32BIT) && !defined(EFSW_ARM)
+ asm("int3");
+ #else
+ assert( false );
+ #endif
+ #endif
+}
+
+void efPRINT( const char * format, ... )
+{
+ char buf[2048];
+ va_list args;
+
+ va_start( args, format );
+
+ #ifdef EFSW_COMPILER_MSVC
+ _vsnprintf_s( buf, sizeof( buf ), sizeof( buf ) / sizeof( buf[0]), format, args );
+ #else
+ vsnprintf( buf, sizeof( buf ) / sizeof( buf[0]), format, args );
+ #endif
+
+ va_end( args );
+
+ #ifdef EFSW_COMPILER_MSVC
+ OutputDebugStringA( buf );
+ #else
+ std::cout << buf;
+ #endif
+}
+
+void efPRINTC( unsigned int cond, const char * format, ...)
+{
+ if ( 0 == cond )
+ return;
+
+ char buf[2048];
+ va_list args;
+
+ va_start( args, format );
+
+ #ifdef EFSW_COMPILER_MSVC
+ _vsnprintf_s( buf, efARRAY_SIZE( buf ), efARRAY_SIZE( buf ), format, args );
+ #else
+ vsnprintf( buf, sizeof( buf ) / sizeof( buf[0]), format, args );
+ #endif
+
+ va_end( args );
+
+ #ifdef EFSW_COMPILER_MSVC
+ OutputDebugStringA( buf );
+ #else
+ std::cout << buf;
+ #endif
+}
+
+#endif
+
+}
+
diff --git a/dep/efsw/src/efsw/Debug.hpp b/dep/efsw/src/efsw/Debug.hpp
new file mode 100644
index 00000000000..75d6dce0466
--- /dev/null
+++ b/dep/efsw/src/efsw/Debug.hpp
@@ -0,0 +1,50 @@
+#ifndef EFSW_DEBUG_HPP
+#define EFSW_DEBUG_HPP
+
+#include <efsw/base.hpp>
+
+namespace efsw {
+
+#ifdef DEBUG
+
+void efREPORT_ASSERT( const char * File, const int Line, const char * Exp );
+
+#define efASSERT( expr ) if ( !(expr) ) { efREPORT_ASSERT( __FILE__, __LINE__, #expr ); }
+#define efASSERTM( expr, msg ) if ( !(expr) ) { efREPORT_ASSERT( __FILE__, __LINE__, #msg ); }
+
+void efPRINT ( const char * format, ... );
+void efPRINTC ( unsigned int cond, const char * format, ... );
+
+#else
+
+#define efASSERT( expr )
+#define efASSERTM( expr, msg )
+
+#ifndef EFSW_COMPILER_MSVC
+ #define efPRINT( format, args... ) {}
+ #define efPRINTC( cond, format, args... ) {}
+#else
+ #define efPRINT
+ #define efPRINTC
+#endif
+
+#endif
+
+#ifdef EFSW_VERBOSE
+ #define efDEBUG efPRINT
+ #define efDEBUGC efPRINTC
+#else
+
+ #ifndef EFSW_COMPILER_MSVC
+ #define efDEBUG( format, args... ) {}
+ #define efDEBUGC( cond, format, args... ) {}
+ #else
+ #define efDEBUG
+ #define efDEBUGC
+ #endif
+
+#endif
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.cpp b/dep/efsw/src/efsw/DirWatcherGeneric.cpp
new file mode 100644
index 00000000000..b80c14d24ce
--- /dev/null
+++ b/dep/efsw/src/efsw/DirWatcherGeneric.cpp
@@ -0,0 +1,451 @@
+#include <efsw/DirWatcherGeneric.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/Debug.hpp>
+#include <efsw/String.hpp>
+
+namespace efsw {
+
+DirWatcherGeneric::DirWatcherGeneric( DirWatcherGeneric * parent, WatcherGeneric * ws, const std::string& directory, bool recursive, bool reportNewFiles ) :
+ Parent( parent ),
+ Watch( ws ),
+ Recursive( recursive ),
+ Deleted( false )
+{
+ resetDirectory( directory );
+
+ if ( !reportNewFiles )
+ {
+ DirSnap.scan();
+ }
+ else
+ {
+ DirectorySnapshotDiff Diff = DirSnap.scan();
+
+ if ( Diff.changed() )
+ {
+ FileInfoList::iterator it;
+
+ DiffIterator( FilesCreated )
+ {
+ handleAction( ( *it ).Filepath, Actions::Add );
+ }
+ }
+ }
+}
+
+DirWatcherGeneric::~DirWatcherGeneric()
+{
+ /// If the directory was deleted mark the files as deleted
+ if ( Deleted )
+ {
+ DirectorySnapshotDiff Diff = DirSnap.scan();
+
+ if ( !DirSnap.exists() )
+ {
+ FileInfoList::iterator it;
+
+ DiffIterator( FilesDeleted )
+ {
+ handleAction( (*it).Filepath, Actions::Delete );
+ }
+
+ DiffIterator( DirsDeleted )
+ {
+ handleAction( (*it).Filepath, Actions::Delete );
+ }
+ }
+ }
+
+ DirWatchMap::iterator it = Directories.begin();
+
+ for ( ; it != Directories.end(); it++ )
+ {
+ if ( Deleted )
+ {
+ /// If the directory was deleted, mark the flag for file deletion
+ it->second->Deleted = true;
+ }
+
+ efSAFE_DELETE( it->second );
+ }
+}
+
+void DirWatcherGeneric::resetDirectory( std::string directory )
+{
+ std::string dir( directory );
+
+ /// Is this a recursive watch?
+ if ( Watch->Directory != directory )
+ {
+ if ( !( directory.size() && ( directory.at(0) == FileSystem::getOSSlash() || directory.at( directory.size() - 1 ) == FileSystem::getOSSlash() ) ) )
+ {
+ /// Get the real directory
+ if ( NULL != Parent )
+ {
+ FileSystem::dirAddSlashAtEnd(directory);
+
+ dir = Parent->DirSnap.DirectoryInfo.Filepath + directory;
+ }
+ else
+ {
+ efDEBUG( "resetDirectory(): Parent is NULL. Fatal error." );
+ }
+ }
+ }
+
+ DirSnap.setDirectoryInfo( dir );
+}
+
+void DirWatcherGeneric::handleAction( const std::string &filename, unsigned long action, std::string oldFilename)
+{
+ Watch->Listener->handleFileAction( Watch->ID, DirSnap.DirectoryInfo.Filepath, FileSystem::fileNameFromPath( filename ), (Action)action, oldFilename );
+}
+
+void DirWatcherGeneric::addChilds( bool reportNewFiles )
+{
+ if ( Recursive )
+ {
+ /// Create the subdirectories watchers
+ std::string dir;
+
+ for ( FileInfoMap::iterator it = DirSnap.Files.begin(); it != DirSnap.Files.end(); it++ )
+ {
+ if ( it->second.isDirectory() && it->second.isReadable() && !FileSystem::isRemoteFS( it->second.Filepath ) )
+ {
+ /// Check if the directory is a symbolic link
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( it->second.Filepath, curPath ) );
+
+ dir = it->first;
+
+ if ( "" != link )
+ {
+ /// Avoid adding symlinks directories if it's now enabled
+ if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() )
+ {
+ continue;
+ }
+
+ /// If it's a symlink check if the realpath exists as a watcher, or
+ /// if the path is outside the current dir
+ if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || !Watch->WatcherImpl->linkAllowed( curPath, link ) )
+ {
+ continue;
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+ else
+ {
+ if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) )
+ {
+ continue;
+ }
+ }
+
+ if ( reportNewFiles )
+ {
+ handleAction( dir, Actions::Add );
+ }
+
+ Directories[dir] = new DirWatcherGeneric( this, Watch, dir, Recursive, reportNewFiles );
+
+ Directories[dir]->addChilds( reportNewFiles );
+ }
+ }
+ }
+}
+
+void DirWatcherGeneric::watch( bool reportOwnChange )
+{
+ DirectorySnapshotDiff Diff = DirSnap.scan();
+
+ if ( reportOwnChange && Diff.DirChanged && NULL != Parent )
+ {
+ Watch->Listener->handleFileAction( Watch->ID, FileSystem::pathRemoveFileName( DirSnap.DirectoryInfo.Filepath ), FileSystem::fileNameFromPath( DirSnap.DirectoryInfo.Filepath ), Actions::Modified );
+ }
+
+ if ( Diff.changed() )
+ {
+ FileInfoList::iterator it;
+ MovedList::iterator mit;
+
+ /// Files
+ DiffIterator( FilesCreated )
+ {
+ handleAction( (*it).Filepath, Actions::Add );
+ }
+
+ DiffIterator( FilesModified )
+ {
+ handleAction( (*it).Filepath, Actions::Modified );
+ }
+
+ DiffIterator( FilesDeleted )
+ {
+ handleAction( (*it).Filepath, Actions::Delete );
+ }
+
+ DiffMovedIterator( FilesMoved )
+ {
+ handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first );
+ }
+
+ /// Directories
+ DiffIterator( DirsCreated )
+ {
+ createDirectory( (*it).Filepath );
+ }
+
+ DiffIterator( DirsModified )
+ {
+ handleAction( (*it).Filepath, Actions::Modified );
+ }
+
+ DiffIterator( DirsDeleted )
+ {
+ handleAction( (*it).Filepath, Actions::Delete );
+ removeDirectory( (*it).Filepath );
+ }
+
+ DiffMovedIterator( DirsMoved )
+ {
+ handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first );
+ moveDirectory( (*mit).first, (*mit).second.Filepath );
+ }
+ }
+
+ /// Process the subdirectories looking for changes
+ for ( DirWatchMap::iterator dit = Directories.begin(); dit != Directories.end(); dit++ )
+ {
+ /// Just watch
+ dit->second->watch();
+ }
+}
+
+void DirWatcherGeneric::watchDir( std::string &dir )
+{
+ DirWatcherGeneric * watcher = Watch->WatcherImpl->mFileWatcher->allowOutOfScopeLinks() ?
+ findDirWatcher( dir ) :
+ findDirWatcherFast( dir );
+
+ if ( NULL != watcher )
+ {
+ watcher->watch( true );
+ }
+}
+
+DirWatcherGeneric * DirWatcherGeneric::findDirWatcherFast( std::string dir )
+{
+ // remove the common base ( dir should always start with the same base as the watcher )
+ efASSERT( !dir.empty() );
+ efASSERT( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() );
+ efASSERT( DirSnap.DirectoryInfo.Filepath == dir.substr( 0, DirSnap.DirectoryInfo.Filepath.size() ) );
+
+ if ( dir.size() >= DirSnap.DirectoryInfo.Filepath.size() )
+ {
+ dir = dir.substr( DirSnap.DirectoryInfo.Filepath.size() - 1 );
+ }
+
+ if ( dir.size() == 1 )
+ {
+ efASSERT( dir[0] == FileSystem::getOSSlash() );
+ return this;
+ }
+
+ size_t level = 0;
+ std::vector<std::string> dirv = String::split( dir, FileSystem::getOSSlash(), false );
+
+ DirWatcherGeneric * watcher = this;
+
+ while ( level < dirv.size() )
+ {
+ // search the dir level in the current watcher
+ DirWatchMap::iterator it = watcher->Directories.find( dirv[ level ] );
+
+ // found? continue with the next level
+ if ( it != watcher->Directories.end() )
+ {
+ watcher = it->second;
+
+ level++;
+ }
+ else
+ {
+ // couldn't found the folder level?
+ // directory not watched
+ return NULL;
+ }
+ }
+
+ return watcher;
+}
+
+DirWatcherGeneric * DirWatcherGeneric::findDirWatcher( std::string dir )
+{
+ if ( DirSnap.DirectoryInfo.Filepath == dir )
+ {
+ return this;
+ }
+ else
+ {
+ DirWatcherGeneric * watcher = NULL;
+
+ for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); it++ )
+ {
+ watcher = it->second->findDirWatcher( dir );
+
+ if ( NULL != watcher )
+ {
+ return watcher;
+ }
+ }
+ }
+
+ return NULL;
+}
+
+DirWatcherGeneric * DirWatcherGeneric::createDirectory( std::string newdir )
+{
+ FileSystem::dirRemoveSlashAtEnd( newdir );
+ newdir = FileSystem::fileNameFromPath( newdir );
+
+ DirWatcherGeneric * dw = NULL;
+
+ /// Check if the directory is a symbolic link
+ std::string dir( DirSnap.DirectoryInfo.Filepath + newdir );
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ FileInfo fi( dir );
+
+ if ( !fi.isDirectory() || !fi.isReadable() || FileSystem::isRemoteFS( dir ) )
+ {
+ return NULL;
+ }
+
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
+ bool skip = false;
+
+ if ( "" != link )
+ {
+ /// Avoid adding symlinks directories if it's now enabled
+ if ( !Watch->WatcherImpl->mFileWatcher->followSymlinks() )
+ {
+ skip = true;
+ }
+
+ /// If it's a symlink check if the realpath exists as a watcher, or
+ /// if the path is outside the current dir
+ if ( Watch->WatcherImpl->pathInWatches( link ) || Watch->pathInWatches( link ) || !Watch->WatcherImpl->linkAllowed( curPath, link ) )
+ {
+ skip = true;
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+ else
+ {
+ if ( Watch->pathInWatches( dir ) || Watch->WatcherImpl->pathInWatches( dir ) )
+ {
+ skip = true;
+ }
+ }
+
+ if ( !skip )
+ {
+ handleAction( newdir, Actions::Add );
+
+ /// Creates the new directory watcher of the subfolder and check for new files
+ dw = new DirWatcherGeneric( this, Watch, dir, Recursive );
+
+ dw->addChilds();
+
+ dw->watch();
+
+ /// Add it to the list of directories
+ Directories[ newdir ] = dw;
+ }
+
+ return dw;
+}
+
+void DirWatcherGeneric::removeDirectory( std::string dir )
+{
+ FileSystem::dirRemoveSlashAtEnd( dir );
+ dir = FileSystem::fileNameFromPath( dir );
+
+ DirWatcherGeneric * dw = NULL;
+ DirWatchMap::iterator dit;
+
+ /// Folder deleted
+
+ /// Search the folder, it should exists
+ dit = Directories.find( dir );
+
+ if ( dit != Directories.end() )
+ {
+ dw = dit->second;
+
+ /// Flag it as deleted so it fire the event for every file inside deleted
+ dw->Deleted = true;
+
+ /// Delete the DirWatcherGeneric
+ efSAFE_DELETE( dw );
+
+ /// Remove the directory from the map
+ Directories.erase( dit->first );
+ }
+}
+
+void DirWatcherGeneric::moveDirectory( std::string oldDir, std::string newDir )
+{
+ FileSystem::dirRemoveSlashAtEnd( oldDir );
+ oldDir = FileSystem::fileNameFromPath( oldDir );
+
+ FileSystem::dirRemoveSlashAtEnd( newDir );
+ newDir = FileSystem::fileNameFromPath( newDir );
+
+ DirWatcherGeneric * dw = NULL;
+ DirWatchMap::iterator dit;
+
+ /// Directory existed?
+ dit = Directories.find( oldDir );
+
+ if ( dit != Directories.end() )
+ {
+ dw = dit->second;
+
+ /// Remove the directory from the map
+ Directories.erase( dit->first );
+
+ Directories[ newDir ] = dw;
+
+ dw->resetDirectory( newDir );
+ }
+}
+
+bool DirWatcherGeneric::pathInWatches( std::string path )
+{
+ if ( DirSnap.DirectoryInfo.Filepath == path )
+ {
+ return true;
+ }
+
+ for ( DirWatchMap::iterator it = Directories.begin(); it != Directories.end(); it++ )
+ {
+ if ( it->second->pathInWatches( path ) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+}
diff --git a/dep/efsw/src/efsw/DirWatcherGeneric.hpp b/dep/efsw/src/efsw/DirWatcherGeneric.hpp
new file mode 100644
index 00000000000..a7581904422
--- /dev/null
+++ b/dep/efsw/src/efsw/DirWatcherGeneric.hpp
@@ -0,0 +1,55 @@
+#ifndef EFSW_DIRWATCHERGENERIC_HPP
+#define EFSW_DIRWATCHERGENERIC_HPP
+
+#include <efsw/WatcherGeneric.hpp>
+#include <efsw/FileInfo.hpp>
+#include <efsw/DirectorySnapshot.hpp>
+#include <map>
+
+namespace efsw {
+
+class DirWatcherGeneric
+{
+ public:
+ typedef std::map<std::string, DirWatcherGeneric*> DirWatchMap;
+
+ DirWatcherGeneric * Parent;
+ WatcherGeneric * Watch;
+ DirectorySnapshot DirSnap;
+ DirWatchMap Directories;
+ bool Recursive;
+
+ DirWatcherGeneric( DirWatcherGeneric * parent, WatcherGeneric * ws, const std::string& directory, bool recursive, bool reportNewFiles = false );
+
+ ~DirWatcherGeneric();
+
+ void watch( bool reportOwnChange = false );
+
+ void watchDir( std::string& dir );
+
+ static bool isDir( const std::string& directory );
+
+ bool pathInWatches( std::string path );
+
+ void addChilds( bool reportNewFiles = true );
+
+ DirWatcherGeneric * findDirWatcher( std::string dir );
+
+ DirWatcherGeneric * findDirWatcherFast( std::string dir );
+ protected:
+ bool Deleted;
+
+ DirWatcherGeneric * createDirectory( std::string newdir );
+
+ void removeDirectory( std::string dir );
+
+ void moveDirectory( std::string oldDir, std::string newDir );
+
+ void resetDirectory( std::string directory );
+
+ void handleAction( const std::string& filename, unsigned long action, std::string oldFilename = "");
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/DirectorySnapshot.cpp b/dep/efsw/src/efsw/DirectorySnapshot.cpp
new file mode 100644
index 00000000000..c0ef747548a
--- /dev/null
+++ b/dep/efsw/src/efsw/DirectorySnapshot.cpp
@@ -0,0 +1,261 @@
+#include <efsw/DirectorySnapshot.hpp>
+#include <efsw/FileSystem.hpp>
+
+namespace efsw {
+
+DirectorySnapshot::DirectorySnapshot()
+{
+}
+
+DirectorySnapshot::DirectorySnapshot( std::string directory )
+{
+ init( directory );
+}
+
+DirectorySnapshot::~DirectorySnapshot()
+{
+}
+
+void DirectorySnapshot::init( std::string directory )
+{
+ setDirectoryInfo( directory );
+ initFiles();
+}
+
+bool DirectorySnapshot::exists()
+{
+ return DirectoryInfo.exists();
+}
+
+void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff )
+{
+ FileInfo fi;
+
+ for ( FileInfoMap::iterator it = Files.begin(); it != Files.end(); it++ )
+ {
+ fi = it->second;
+
+ if ( fi.isDirectory() )
+ {
+ Diff.DirsDeleted.push_back( fi );
+ }
+ else
+ {
+ Diff.FilesDeleted.push_back( fi );
+ }
+ }
+}
+
+void DirectorySnapshot::setDirectoryInfo( std::string directory )
+{
+ DirectoryInfo = FileInfo( directory );
+}
+
+void DirectorySnapshot::initFiles()
+{
+ Files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath );
+
+ FileInfoMap::iterator it = Files.begin();
+ std::list<std::string> eraseFiles;
+
+ /// Remove all non regular files and non directories
+ for ( ; it != Files.end(); it++ )
+ {
+ if ( !it->second.isRegularFile() && !it->second.isDirectory() )
+ {
+ eraseFiles.push_back( it->first );
+ }
+ }
+
+ for ( std::list<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); eit++ )
+ {
+ Files.erase( *eit );
+ }
+}
+
+DirectorySnapshotDiff DirectorySnapshot::scan()
+{
+ DirectorySnapshotDiff Diff;
+
+ Diff.clear();
+
+ FileInfo curFI( DirectoryInfo.Filepath );
+
+ Diff.DirChanged = DirectoryInfo != curFI;
+
+ if ( Diff.DirChanged )
+ {
+ DirectoryInfo = curFI;
+ }
+
+ /// If the directory was erased, create the events for files and directories deletion
+ if ( !curFI.exists() )
+ {
+ deleteAll( Diff );
+
+ return Diff;
+ }
+
+ FileInfoMap files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath );
+
+ if ( files.empty() && Files.empty() )
+ {
+ return Diff;
+ }
+
+ FileInfo fi;
+ FileInfoMap FilesCpy;
+ FileInfoMap::iterator it;
+ FileInfoMap::iterator fiIt;
+
+ if ( Diff.DirChanged )
+ {
+ FilesCpy = Files;
+ }
+
+ for ( it = files.begin(); it != files.end(); it++ )
+ {
+ fi = it->second;
+
+ /// File existed before?
+ fiIt = Files.find( it->first );
+
+ if ( fiIt != Files.end() )
+ {
+ /// Erase from the file list copy
+ FilesCpy.erase( it->first );
+
+ /// File changed?
+ if ( (*fiIt).second != fi )
+ {
+ /// Update the new file info
+ Files[ it->first ] = fi;
+
+ /// handle modified event
+ if ( fi.isDirectory() )
+ {
+ Diff.DirsModified.push_back( fi );
+ }
+ else
+ {
+ Diff.FilesModified.push_back( fi );
+ }
+ }
+ }
+ /// Only add regular files or directories
+ else if ( fi.isRegularFile() || fi.isDirectory() )
+ {
+ /// New file found
+ Files[ it->first ] = fi;
+
+ FileInfoMap::iterator fit;
+ std::string oldFile = "";
+
+ /// Check if the same inode already existed
+ if ( ( fit = nodeInFiles( fi ) ) != Files.end() )
+ {
+ oldFile = fit->first;
+
+ /// Avoid firing a Delete event
+ FilesCpy.erase( fit->first );
+
+ /// Delete the old file name
+ Files.erase( fit->first );
+
+ if ( fi.isDirectory() )
+ {
+ Diff.DirsMoved.push_back( std::make_pair( oldFile, fi ) );
+ }
+ else
+ {
+ Diff.FilesMoved.push_back( std::make_pair( oldFile, fi ) );
+ }
+ }
+ else
+ {
+ if ( fi.isDirectory() )
+ {
+ Diff.DirsCreated.push_back( fi );
+ }
+ else
+ {
+ Diff.FilesCreated.push_back( fi );
+ }
+ }
+ }
+ }
+
+ if ( !Diff.DirChanged )
+ {
+ return Diff;
+ }
+
+ /// The files or directories that remains were deleted
+ for ( it = FilesCpy.begin(); it != FilesCpy.end(); it++ )
+ {
+ fi = it->second;
+
+ if ( fi.isDirectory() )
+ {
+ Diff.DirsDeleted.push_back( fi );
+ }
+ else
+ {
+ Diff.FilesDeleted.push_back( fi );
+ }
+
+ /// Remove the file or directory from the list of files
+ Files.erase( it->first );
+ }
+
+ return Diff;
+}
+
+FileInfoMap::iterator DirectorySnapshot::nodeInFiles( FileInfo& fi )
+{
+ FileInfoMap::iterator it;
+
+ if ( FileInfo::inodeSupported() )
+ {
+ for ( it = Files.begin(); it != Files.end(); it++ )
+ {
+ if ( it->second.sameInode( fi ) && it->second.Filepath != fi.Filepath )
+ {
+ return it;
+ }
+ }
+ }
+
+ return Files.end();
+}
+
+void DirectorySnapshot::addFile( std::string path )
+{
+ std::string name( FileSystem::fileNameFromPath( path ) );
+ Files[ name ] = FileInfo( path );
+}
+
+void DirectorySnapshot::removeFile( std::string path )
+{
+ std::string name( FileSystem::fileNameFromPath( path ) );
+
+ FileInfoMap::iterator it = Files.find( name );
+
+ if ( Files.end() != it )
+ {
+ Files.erase( it );
+ }
+}
+
+void DirectorySnapshot::moveFile( std::string oldPath, std::string newPath )
+{
+ removeFile( oldPath );
+ addFile( newPath );
+}
+
+void DirectorySnapshot::updateFile(std::string path)
+{
+ addFile( path );
+}
+
+}
diff --git a/dep/efsw/src/efsw/DirectorySnapshot.hpp b/dep/efsw/src/efsw/DirectorySnapshot.hpp
new file mode 100644
index 00000000000..1ada66fe980
--- /dev/null
+++ b/dep/efsw/src/efsw/DirectorySnapshot.hpp
@@ -0,0 +1,46 @@
+#ifndef EFSW_DIRECTORYSNAPSHOT_HPP
+#define EFSW_DIRECTORYSNAPSHOT_HPP
+
+#include <efsw/DirectorySnapshotDiff.hpp>
+
+namespace efsw {
+
+class DirectorySnapshot
+{
+ public:
+ FileInfo DirectoryInfo;
+ FileInfoMap Files;
+
+ void setDirectoryInfo( std::string directory );
+
+ DirectorySnapshot();
+
+ DirectorySnapshot( std::string directory );
+
+ ~DirectorySnapshot();
+
+ void init( std::string directory );
+
+ bool exists();
+
+ DirectorySnapshotDiff scan();
+
+ FileInfoMap::iterator nodeInFiles( FileInfo& fi );
+
+ void addFile( std::string path );
+
+ void removeFile( std::string path );
+
+ void moveFile( std::string oldPath, std::string newPath );
+
+ void updateFile( std::string path );
+ protected:
+ void initFiles();
+
+ void deleteAll( DirectorySnapshotDiff &Diff );
+};
+
+}
+
+#endif
+
diff --git a/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp b/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp
new file mode 100644
index 00000000000..eabc6fdbda1
--- /dev/null
+++ b/dep/efsw/src/efsw/DirectorySnapshotDiff.cpp
@@ -0,0 +1,29 @@
+#include <efsw/DirectorySnapshotDiff.hpp>
+
+namespace efsw {
+
+void DirectorySnapshotDiff::clear()
+{
+ FilesCreated.clear();
+ FilesModified.clear();
+ FilesMoved.clear();
+ FilesDeleted.clear();
+ DirsCreated.clear();
+ DirsModified.clear();
+ DirsMoved.clear();
+ DirsDeleted.clear();
+}
+
+bool DirectorySnapshotDiff::changed()
+{
+ return !FilesCreated.empty() ||
+ !FilesModified.empty() ||
+ !FilesMoved.empty() ||
+ !FilesDeleted.empty() ||
+ !DirsCreated.empty() ||
+ !DirsModified.empty() ||
+ !DirsMoved.empty() ||
+ !DirsDeleted.empty();
+}
+
+}
diff --git a/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp b/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp
new file mode 100644
index 00000000000..042de9ce02c
--- /dev/null
+++ b/dep/efsw/src/efsw/DirectorySnapshotDiff.hpp
@@ -0,0 +1,35 @@
+#ifndef EFSW_DIRECTORYSNAPSHOTDIFF_HPP
+#define EFSW_DIRECTORYSNAPSHOTDIFF_HPP
+
+#include <efsw/FileInfo.hpp>
+
+namespace efsw {
+
+class DirectorySnapshotDiff
+{
+ public:
+ FileInfoList FilesDeleted;
+ FileInfoList FilesCreated;
+ FileInfoList FilesModified;
+ MovedList FilesMoved;
+ FileInfoList DirsDeleted;
+ FileInfoList DirsCreated;
+ FileInfoList DirsModified;
+ MovedList DirsMoved;
+ bool DirChanged;
+
+ void clear();
+
+ bool changed();
+};
+
+#define DiffIterator( FileInfoListName ) it = Diff.FileInfoListName.begin(); \
+ for ( ; it != Diff.FileInfoListName.end(); it++ )
+
+#define DiffMovedIterator( MovedListName ) mit = Diff.MovedListName.begin(); \
+ for ( ; mit != Diff.MovedListName.end(); mit++ )
+
+}
+
+#endif
+
diff --git a/dep/efsw/src/efsw/FileInfo.cpp b/dep/efsw/src/efsw/FileInfo.cpp
new file mode 100644
index 00000000000..7003afc2a15
--- /dev/null
+++ b/dep/efsw/src/efsw/FileInfo.cpp
@@ -0,0 +1,274 @@
+#include <efsw/FileInfo.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/String.hpp>
+
+#ifndef _DARWIN_FEATURE_64_BIT_INODE
+#define _DARWIN_FEATURE_64_BIT_INODE
+#endif
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <sys/stat.h>
+
+#include <limits.h>
+#include <stdlib.h>
+
+#ifdef EFSW_COMPILER_MSVC
+ #ifndef S_ISDIR
+ #define S_ISDIR(f) ((f)&_S_IFDIR)
+ #endif
+
+ #ifndef S_ISREG
+ #define S_ISREG(f) ((f)&_S_IFREG)
+ #endif
+
+ #ifndef S_ISRDBL
+ #define S_ISRDBL(f) ((f)&_S_IREAD)
+ #endif
+#else
+ #include <unistd.h>
+
+ #ifndef S_ISRDBL
+ #define S_ISRDBL(f) ((f)&S_IRUSR)
+ #endif
+#endif
+
+namespace efsw {
+
+bool FileInfo::exists( const std::string& filePath )
+{
+ FileInfo fi( filePath );
+ return fi.exists();
+}
+
+bool FileInfo::isLink( const std::string& filePath )
+{
+ FileInfo fi( filePath, true );
+ return fi.isLink();
+}
+
+bool FileInfo::inodeSupported()
+{
+ #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ return true;
+ #else
+ return false;
+ #endif
+}
+
+FileInfo::FileInfo() :
+ ModificationTime(0),
+ OwnerId(0),
+ GroupId(0),
+ Permissions(0),
+ Inode(0)
+{}
+
+FileInfo::FileInfo( const std::string& filepath ) :
+ Filepath( filepath ),
+ ModificationTime(0),
+ OwnerId(0),
+ GroupId(0),
+ Permissions(0),
+ Inode(0)
+{
+ getInfo();
+}
+
+FileInfo::FileInfo( const std::string& filepath, bool linkInfo ) :
+ Filepath( filepath ),
+ ModificationTime(0),
+ OwnerId(0),
+ GroupId(0),
+ Permissions(0),
+ Inode(0)
+{
+ if ( linkInfo )
+ {
+ getRealInfo();
+ }
+ else
+ {
+ getInfo();
+ }
+}
+
+void FileInfo::getInfo()
+{
+ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+ if ( Filepath.size() == 3 && Filepath[1] == ':' && Filepath[2] == FileSystem::getOSSlash() )
+ {
+ Filepath += FileSystem::getOSSlash();
+ }
+ #endif
+
+ /// Why i'm doing this? stat in mingw32 doesn't work for directories if the dir path ends with a path slash
+ bool slashAtEnd = FileSystem::slashAtEnd( Filepath );
+
+ if ( slashAtEnd )
+ {
+ FileSystem::dirRemoveSlashAtEnd( Filepath );
+ }
+
+ #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ struct stat st;
+ int res = stat( Filepath.c_str(), &st );
+ #else
+ struct _stat st;
+ int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st );
+ #endif
+
+ if ( 0 == res )
+ {
+ ModificationTime = st.st_mtime;
+ Size = st.st_size;
+ OwnerId = st.st_uid;
+ GroupId = st.st_gid;
+ Permissions = st.st_mode;
+ Inode = st.st_ino;
+ }
+
+ if ( slashAtEnd )
+ {
+ FileSystem::dirAddSlashAtEnd( Filepath );
+ }
+}
+
+void FileInfo::getRealInfo()
+{
+ bool slashAtEnd = FileSystem::slashAtEnd( Filepath );
+
+ if ( slashAtEnd )
+ {
+ FileSystem::dirRemoveSlashAtEnd( Filepath );
+ }
+
+ #if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ struct stat st;
+ int res = lstat( Filepath.c_str(), &st );
+ #else
+ struct _stat st;
+ int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st );
+ #endif
+
+ if ( 0 == res )
+ {
+ ModificationTime = st.st_mtime;
+ Size = st.st_size;
+ OwnerId = st.st_uid;
+ GroupId = st.st_gid;
+ Permissions = st.st_mode;
+ Inode = st.st_ino;
+ }
+
+ if ( slashAtEnd )
+ {
+ FileSystem::dirAddSlashAtEnd( Filepath );
+ }
+}
+
+bool FileInfo::operator==( const FileInfo& Other ) const
+{
+ return ( ModificationTime == Other.ModificationTime &&
+ Size == Other.Size &&
+ OwnerId == Other.OwnerId &&
+ GroupId == Other.GroupId &&
+ Permissions == Other.Permissions &&
+ Inode == Other.Inode
+ );
+}
+
+bool FileInfo::isDirectory()
+{
+ return 0 != S_ISDIR(Permissions);
+}
+
+bool FileInfo::isRegularFile()
+{
+ return 0 != S_ISREG(Permissions);
+}
+
+bool FileInfo::isReadable()
+{
+ return 0 != S_ISRDBL(Permissions);
+}
+
+bool FileInfo::isLink()
+{
+#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ return S_ISLNK(Permissions);
+#else
+ return false;
+#endif
+}
+
+std::string FileInfo::linksTo()
+{
+#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ if ( isLink() )
+ {
+ char * ch = realpath( Filepath.c_str(), NULL);
+
+ if ( NULL != ch )
+ {
+ std::string tstr( ch );
+
+ free( ch );
+
+ return tstr;
+ }
+ }
+#endif
+ return std::string("");
+}
+
+bool FileInfo::exists()
+{
+ bool slashAtEnd = FileSystem::slashAtEnd( Filepath );
+
+ if ( slashAtEnd )
+ {
+ FileSystem::dirRemoveSlashAtEnd(Filepath);
+ }
+
+#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ struct stat st;
+ int res = stat( Filepath.c_str(), &st );
+#else
+ struct _stat st;
+ int res = _wstat( String::fromUtf8( Filepath ).toWideString().c_str(), &st );
+#endif
+
+ if (slashAtEnd)
+ {
+ FileSystem::dirAddSlashAtEnd(Filepath);
+ }
+
+ return 0 == res;
+}
+
+FileInfo& FileInfo::operator=( const FileInfo& Other )
+{
+ this->Filepath = Other.Filepath;
+ this->Size = Other.Size;
+ this->ModificationTime = Other.ModificationTime;
+ this->GroupId = Other.GroupId;
+ this->OwnerId = Other.OwnerId;
+ this->Permissions = Other.Permissions;
+ this->Inode = Other.Inode;
+ return *this;
+}
+
+bool FileInfo::sameInode( const FileInfo& Other ) const
+{
+ return inodeSupported() && Inode == Other.Inode;
+}
+
+bool FileInfo::operator!=( const FileInfo& Other ) const
+{
+ return !(*this == Other);
+}
+
+}
diff --git a/dep/efsw/src/efsw/FileInfo.hpp b/dep/efsw/src/efsw/FileInfo.hpp
new file mode 100644
index 00000000000..45cca6a7953
--- /dev/null
+++ b/dep/efsw/src/efsw/FileInfo.hpp
@@ -0,0 +1,66 @@
+#ifndef EFSW_FILEINFO_HPP
+#define EFSW_FILEINFO_HPP
+
+#include <efsw/base.hpp>
+#include <string>
+#include <map>
+#include <list>
+
+namespace efsw {
+
+class FileInfo
+{
+ public:
+ static bool exists( const std::string& filePath );
+
+ static bool isLink( const std::string& filePath );
+
+ static bool inodeSupported();
+
+ FileInfo();
+
+ FileInfo( const std::string& filepath );
+
+ FileInfo( const std::string& filepath, bool linkInfo );
+
+ bool operator==( const FileInfo& Other ) const;
+
+ bool operator!=( const FileInfo& Other ) const;
+
+ FileInfo& operator=( const FileInfo& Other );
+
+ bool isDirectory();
+
+ bool isRegularFile();
+
+ bool isReadable();
+
+ bool sameInode( const FileInfo& Other ) const;
+
+ bool isLink();
+
+ std::string linksTo();
+
+ bool exists();
+
+ void getInfo();
+
+ void getRealInfo();
+
+ std::string Filepath;
+ Uint64 ModificationTime;
+ Uint64 Size;
+ Uint32 OwnerId;
+ Uint32 GroupId;
+ Uint32 Permissions;
+ Uint64 Inode;
+};
+
+typedef std::map<std::string, FileInfo> FileInfoMap;
+typedef std::list<FileInfo> FileInfoList;
+typedef std::list< std::pair< std::string, FileInfo> > MovedList;
+
+}
+
+#endif
+
diff --git a/dep/efsw/src/efsw/FileSystem.cpp b/dep/efsw/src/efsw/FileSystem.cpp
new file mode 100644
index 00000000000..e3afa0b4046
--- /dev/null
+++ b/dep/efsw/src/efsw/FileSystem.cpp
@@ -0,0 +1,124 @@
+#include <efsw/FileSystem.hpp>
+#include <efsw/platform/platformimpl.hpp>
+
+#if EFSW_OS == EFSW_OS_MACOSX
+#include <CoreFoundation/CoreFoundation.h>
+#endif
+
+namespace efsw {
+
+bool FileSystem::isDirectory( const std::string& path )
+{
+ return Platform::FileSystem::isDirectory( path );
+}
+
+FileInfoMap FileSystem::filesInfoFromPath( std::string path ) {
+ dirAddSlashAtEnd( path );
+
+ return Platform::FileSystem::filesInfoFromPath( path );
+}
+
+char FileSystem::getOSSlash()
+{
+ return Platform::FileSystem::getOSSlash();
+}
+
+bool FileSystem::slashAtEnd( std::string &dir )
+{
+ return ( dir.size() && dir[ dir.size() - 1 ] == getOSSlash() );
+}
+
+void FileSystem::dirAddSlashAtEnd( std::string& dir )
+{
+ if ( dir.size() > 1 && dir[ dir.size() - 1 ] != getOSSlash() )
+ {
+ dir.push_back( getOSSlash() );
+ }
+}
+
+void FileSystem::dirRemoveSlashAtEnd( std::string& dir )
+{
+ if ( dir.size() > 1 && dir[ dir.size() - 1 ] == getOSSlash() )
+ {
+ dir.erase( dir.size() - 1 );
+ }
+}
+
+std::string FileSystem::fileNameFromPath( std::string filepath )
+{
+ dirRemoveSlashAtEnd( filepath );
+
+ size_t pos = filepath.find_last_of( getOSSlash() );
+
+ if ( pos != std::string::npos )
+ {
+ return filepath.substr( pos + 1 );
+ }
+
+ return filepath;
+}
+
+std::string FileSystem::pathRemoveFileName( std::string filepath )
+{
+ dirRemoveSlashAtEnd( filepath );
+
+ size_t pos = filepath.find_last_of( getOSSlash() );
+
+ if ( pos != std::string::npos )
+ {
+ return filepath.substr( 0, pos + 1 );
+ }
+
+ return filepath;
+}
+
+std::string FileSystem::getLinkRealPath( std::string dir, std::string& curPath )
+{
+ FileSystem::dirRemoveSlashAtEnd( dir );
+ FileInfo fi( dir, true );
+
+ /// Check with lstat and see if it's a link
+ if ( fi.isLink() )
+ {
+ /// get the real path of the link
+ std::string link( fi.linksTo() );
+
+ /// get the current path of the directory without the link dir path
+ curPath = FileSystem::pathRemoveFileName( dir );
+
+ /// ensure that ends with the os directory slash
+ FileSystem::dirAddSlashAtEnd( link );
+
+ return link;
+ }
+
+ /// if it's not a link return nothing
+ return "";
+}
+
+std::string FileSystem::precomposeFileName( const std::string& name )
+{
+#if EFSW_OS == EFSW_OS_MACOSX
+ CFStringRef cfStringRef = CFStringCreateWithCString(kCFAllocatorDefault, name.c_str(), kCFStringEncodingUTF8);
+ CFMutableStringRef cfMutable = CFStringCreateMutableCopy(NULL, 0, cfStringRef);
+
+ CFStringNormalize(cfMutable,kCFStringNormalizationFormC);
+
+ char c_str[255 + 1];
+ CFStringGetCString(cfMutable, c_str, sizeof(c_str)-1, kCFStringEncodingUTF8);
+
+ CFRelease(cfStringRef);
+ CFRelease(cfMutable);
+
+ return std::string(c_str);
+#else
+ return name;
+#endif
+}
+
+bool FileSystem::isRemoteFS( const std::string& directory )
+{
+ return Platform::FileSystem::isRemoteFS( directory );
+}
+
+}
diff --git a/dep/efsw/src/efsw/FileSystem.hpp b/dep/efsw/src/efsw/FileSystem.hpp
new file mode 100644
index 00000000000..4e2e1aeb7cd
--- /dev/null
+++ b/dep/efsw/src/efsw/FileSystem.hpp
@@ -0,0 +1,40 @@
+#ifndef EFSW_FILESYSTEM_HPP
+#define EFSW_FILESYSTEM_HPP
+
+#include <efsw/base.hpp>
+#include <efsw/FileInfo.hpp>
+#include <map>
+
+namespace efsw {
+
+class FileSystem
+{
+ public:
+ static bool isDirectory( const std::string& path );
+
+ static FileInfoMap filesInfoFromPath( std::string path );
+
+ static char getOSSlash();
+
+ static bool slashAtEnd( std::string& dir );
+
+ static void dirAddSlashAtEnd( std::string& dir );
+
+ static void dirRemoveSlashAtEnd( std::string& dir );
+
+ static std::string fileNameFromPath( std::string filepath );
+
+ static std::string pathRemoveFileName( std::string filepath );
+
+ static void realPath( std::string curdir, std::string& path );
+
+ static std::string getLinkRealPath( std::string dir, std::string& curPath );
+
+ static std::string precomposeFileName(const std::string& name);
+
+ static bool isRemoteFS( const std::string& directory );
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcher.cpp b/dep/efsw/src/efsw/FileWatcher.cpp
new file mode 100644
index 00000000000..e33d5ec46fb
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcher.cpp
@@ -0,0 +1,145 @@
+#include <efsw/efsw.hpp>
+#include <efsw/FileWatcherImpl.hpp>
+#include <efsw/FileWatcherGeneric.hpp>
+#include <efsw/FileSystem.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+# include <efsw/FileWatcherWin32.hpp>
+# define FILEWATCHER_IMPL FileWatcherWin32
+# define BACKEND_NAME "Win32"
+#elif EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY
+# include <efsw/FileWatcherInotify.hpp>
+# define FILEWATCHER_IMPL FileWatcherInotify
+# define BACKEND_NAME "Inotify"
+#elif EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE
+# include <efsw/FileWatcherKqueue.hpp>
+# define FILEWATCHER_IMPL FileWatcherKqueue
+# define BACKEND_NAME "Kqueue"
+#elif EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+# include <efsw/FileWatcherFSEvents.hpp>
+# define FILEWATCHER_IMPL FileWatcherFSEvents
+# define BACKEND_NAME "FSEvents"
+#else
+# define FILEWATCHER_IMPL FileWatcherGeneric
+# define BACKEND_NAME "Generic"
+#endif
+
+#include <efsw/Debug.hpp>
+
+namespace efsw {
+
+FileWatcher::FileWatcher() :
+ mFollowSymlinks(false),
+ mOutOfScopeLinks(false)
+{
+ efDEBUG( "Using backend: %s\n", BACKEND_NAME );
+
+ mImpl = new FILEWATCHER_IMPL( this );
+
+ if ( !mImpl->initOK() )
+ {
+ efSAFE_DELETE( mImpl );
+
+ efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME );
+
+ mImpl = new FileWatcherGeneric( this );
+ }
+}
+
+FileWatcher::FileWatcher( bool useGenericFileWatcher ) :
+ mFollowSymlinks(false),
+ mOutOfScopeLinks(false)
+{
+ if ( useGenericFileWatcher )
+ {
+ efDEBUG( "Using backend: Generic\n" );
+
+ mImpl = new FileWatcherGeneric( this );
+ }
+ else
+ {
+ efDEBUG( "Using backend: %s\n", BACKEND_NAME );
+
+ mImpl = new FILEWATCHER_IMPL( this );
+
+ if ( !mImpl->initOK() )
+ {
+ efSAFE_DELETE( mImpl );
+
+ efDEBUG( "Falled back to backend: %s\n", BACKEND_NAME );
+
+ mImpl = new FileWatcherGeneric( this );
+ }
+ }
+}
+
+FileWatcher::~FileWatcher()
+{
+ efSAFE_DELETE( mImpl );
+}
+
+WatchID FileWatcher::addWatch(const std::string& directory, FileWatchListener* watcher)
+{
+ if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) )
+ {
+ return mImpl->addWatch(directory, watcher, false);
+ }
+ else
+ {
+ return Errors::Log::createLastError( Errors::FileRemote, directory );
+ }
+}
+
+WatchID FileWatcher::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive)
+{
+ if ( mImpl->mIsGeneric || !FileSystem::isRemoteFS( directory ) )
+ {
+ return mImpl->addWatch(directory, watcher, recursive);
+ }
+ else
+ {
+ return Errors::Log::createLastError( Errors::FileRemote, directory );
+ }
+}
+
+void FileWatcher::removeWatch(const std::string& directory)
+{
+ mImpl->removeWatch(directory);
+}
+
+void FileWatcher::removeWatch(WatchID watchid)
+{
+ mImpl->removeWatch(watchid);
+}
+
+void FileWatcher::watch()
+{
+ mImpl->watch();
+}
+
+std::list<std::string> FileWatcher::directories()
+{
+ return mImpl->directories();
+}
+
+void FileWatcher::followSymlinks( bool follow )
+{
+ mFollowSymlinks = follow;
+}
+
+const bool& FileWatcher::followSymlinks() const
+{
+ return mFollowSymlinks;
+}
+
+void FileWatcher::allowOutOfScopeLinks( bool allow )
+{
+ mOutOfScopeLinks = allow;
+}
+
+const bool& FileWatcher::allowOutOfScopeLinks() const
+{
+ return mOutOfScopeLinks;
+}
+
+}
diff --git a/dep/efsw/src/efsw/FileWatcherCWrapper.cpp b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp
new file mode 100644
index 00000000000..2739e756bb2
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherCWrapper.cpp
@@ -0,0 +1,132 @@
+#include <efsw/efsw.h>
+#include <efsw/efsw.hpp>
+#include <vector>
+
+#define TOBOOL(i) ((i) == 0 ? false : true)
+
+/*************************************************************************************************/
+class Watcher_CAPI : public efsw::FileWatchListener
+{
+public:
+ efsw_watcher mWatcher;
+ efsw_pfn_fileaction_callback mFn;
+ void* mParam;
+public:
+ Watcher_CAPI(efsw_watcher watcher, efsw_pfn_fileaction_callback fn, void* param)
+ {
+ mWatcher = watcher;
+ mFn = fn;
+ mParam = param;
+ }
+
+ void handleFileAction(efsw::WatchID watchid, const std::string& dir, const std::string& filename,
+ efsw::Action action, std::string oldFilename = "")
+ {
+ mFn(mWatcher, watchid, dir.c_str(), filename.c_str(), (enum efsw_action)action,
+ oldFilename.c_str(), mParam );
+ }
+};
+
+/*************************************************************************************************
+ * globals
+ */
+static std::vector<Watcher_CAPI*> g_callbacks;
+
+Watcher_CAPI* find_callback(efsw_watcher watcher, efsw_pfn_fileaction_callback fn)
+{
+ for (std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin(); i != g_callbacks.end(); i++ )
+ {
+ Watcher_CAPI* callback = *i;
+
+ if (callback->mFn == fn && callback->mWatcher == watcher)
+ return *i;
+ }
+
+ return NULL;
+}
+
+Watcher_CAPI* remove_callback(efsw_watcher watcher)
+{
+ std::vector<Watcher_CAPI*>::iterator i = g_callbacks.begin();
+
+ while (i != g_callbacks.end()) {
+ Watcher_CAPI* callback = *i;
+
+ if (callback->mWatcher == watcher)
+ i = g_callbacks.erase(i);
+ else
+ i++;
+ }
+
+ return NULL;
+}
+
+
+/*************************************************************************************************/
+efsw_watcher efsw_create(int generic_mode)
+{
+ return (efsw_watcher)new efsw::FileWatcher(TOBOOL(generic_mode));
+}
+
+void efsw_release(efsw_watcher watcher)
+{
+ remove_callback(watcher);
+ delete (efsw::FileWatcher*)watcher;
+}
+
+const char* efsw_getlasterror()
+{
+ static std::string log_str;
+ log_str = efsw::Errors::Log::getLastErrorLog();
+ return log_str.c_str();
+}
+
+efsw_watchid efsw_addwatch(efsw_watcher watcher, const char* directory,
+ efsw_pfn_fileaction_callback callback_fn, int recursive, void * param)
+{
+ Watcher_CAPI* callback = find_callback(watcher, callback_fn);
+
+ if (callback == NULL) {
+ callback = new Watcher_CAPI(watcher, callback_fn, param);
+ g_callbacks.push_back(callback);
+ }
+
+ return ((efsw::FileWatcher*)watcher)->addWatch(std::string(directory), callback,
+ TOBOOL(recursive));
+}
+
+void efsw_removewatch(efsw_watcher watcher, const char* directory)
+{
+ ((efsw::FileWatcher*)watcher)->removeWatch(std::string(directory));
+}
+
+void efsw_removewatch_byid(efsw_watcher watcher, efsw_watchid watchid)
+{
+ ((efsw::FileWatcher*)watcher)->removeWatch(watchid);
+}
+
+void efsw_watch(efsw_watcher watcher)
+{
+ ((efsw::FileWatcher*)watcher)->watch();
+}
+
+void efsw_follow_symlinks(efsw_watcher watcher, int enable)
+{
+ ((efsw::FileWatcher*)watcher)->followSymlinks(TOBOOL(enable));
+}
+
+int efsw_follow_symlinks_isenabled(efsw_watcher watcher)
+{
+ return (int)((efsw::FileWatcher*)watcher)->followSymlinks();
+}
+
+void efsw_allow_outofscopelinks(efsw_watcher watcher, int allow)
+{
+ ((efsw::FileWatcher*)watcher)->allowOutOfScopeLinks(TOBOOL(allow));
+}
+
+int efsw_outofscopelinks_isallowed(efsw_watcher watcher)
+{
+ return (int)((efsw::FileWatcher*)watcher)->allowOutOfScopeLinks();
+}
+
diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.cpp b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp
new file mode 100644
index 00000000000..40156674132
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherFSEvents.cpp
@@ -0,0 +1,278 @@
+#include <efsw/FileWatcherFSEvents.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/System.hpp>
+#include <efsw/Debug.hpp>
+#include <efsw/String.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <sys/utsname.h>
+
+namespace efsw
+{
+
+int getOSXReleaseNumber()
+{
+ static int osxR = -1;
+
+ if ( -1 == osxR )
+ {
+ struct utsname os;
+
+ if ( -1 != uname( &os ) ) {
+ std::string release( os.release );
+
+ size_t pos = release.find_first_of( '.' );
+
+ if ( pos != std::string::npos )
+ {
+ release = release.substr( 0, pos );
+ }
+
+ int rel = 0;
+
+ if ( String::fromString<int>( rel, release ) )
+ {
+ osxR = rel;
+ }
+ }
+ }
+
+ return osxR;
+}
+
+bool FileWatcherFSEvents::isGranular()
+{
+ return getOSXReleaseNumber() >= 11;
+}
+
+void FileWatcherFSEvents::FSEventCallback( ConstFSEventStreamRef streamRef,
+ void *userData,
+ size_t numEvents,
+ void *eventPaths,
+ const FSEventStreamEventFlags eventFlags[],
+ const FSEventStreamEventId eventIds[] )
+{
+ WatcherFSEvents * watcher = static_cast<WatcherFSEvents*>( userData );
+
+ std::vector<FSEvent> events;
+ events.reserve( numEvents );
+
+ for ( size_t i = 0; i < numEvents; i++ )
+ {
+ events.push_back( FSEvent( std::string( ((char**)eventPaths)[i] ), (long)eventFlags[i], (Uint64)eventIds[i] ) );
+ }
+
+ watcher->handleActions( events );
+
+ watcher->process();
+
+ efDEBUG( "\n" );
+}
+
+FileWatcherFSEvents::FileWatcherFSEvents( FileWatcher * parent ) :
+ FileWatcherImpl( parent ),
+ mRunLoopRef( NULL ),
+ mLastWatchID(0),
+ mThread( NULL )
+{
+ mInitOK = true;
+
+ watch();
+}
+
+FileWatcherFSEvents::~FileWatcherFSEvents()
+{
+ WatchMap::iterator iter = mWatches.begin();
+
+ for( ; iter != mWatches.end(); ++iter )
+ {
+ WatcherFSEvents * watch = iter->second;
+
+ efSAFE_DELETE( watch );
+ }
+
+ mWatches.clear();
+
+ mInitOK = false;
+
+ if ( NULL != mRunLoopRef )
+ {
+ CFRunLoopStop( mRunLoopRef );
+ }
+
+ efSAFE_DELETE( mThread );
+}
+
+WatchID FileWatcherFSEvents::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive )
+{
+ /// Wait to the RunLoopRef to be ready
+ while ( NULL == mRunLoopRef )
+ {
+ System::sleep( 1 );
+ }
+
+ std::string dir( directory );
+
+ FileInfo fi( dir );
+
+ if ( !fi.isDirectory() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else if ( !fi.isReadable() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotReadable, dir );
+ }
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ if ( pathInWatches( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+
+ /// Check if the directory is a symbolic link
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
+
+ if ( "" != link )
+ {
+ /// If it's a symlink check if the realpath exists as a watcher, or
+ /// if the path is outside the current dir
+ if ( pathInWatches( link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+ else if ( !linkAllowed( curPath, link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+
+ mLastWatchID++;
+
+ WatcherFSEvents * pWatch = new WatcherFSEvents();
+ pWatch->Listener = watcher;
+ pWatch->ID = mLastWatchID;
+ pWatch->Directory = dir;
+ pWatch->Recursive = recursive;
+ pWatch->FWatcher = this;
+
+ pWatch->init();
+
+ mWatchesLock.lock();
+ mWatches.insert(std::make_pair(mLastWatchID, pWatch));
+ mWatchesLock.unlock();
+
+ return pWatch->ID;
+}
+
+void FileWatcherFSEvents::removeWatch(const std::string& directory)
+{
+ mWatchesLock.lock();
+
+ WatchMap::iterator iter = mWatches.begin();
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ if( directory == iter->second->Directory )
+ {
+ removeWatch( iter->second->ID );
+ return;
+ }
+ }
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherFSEvents::removeWatch(WatchID watchid)
+{
+ mWatchesLock.lock();
+
+ WatchMap::iterator iter = mWatches.find( watchid );
+
+ if( iter == mWatches.end() )
+ return;
+
+ WatcherFSEvents * watch = iter->second;
+
+ mWatches.erase( iter );
+
+ efDEBUG( "Removed watch %s\n", watch->Directory.c_str() );
+
+ efSAFE_DELETE( watch );
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherFSEvents::watch()
+{
+ if ( NULL == mThread )
+ {
+ mThread = new Thread( &FileWatcherFSEvents::run, this );
+ mThread->launch();
+ }
+}
+
+void FileWatcherFSEvents::run()
+{
+ mRunLoopRef = CFRunLoopGetCurrent();
+
+ while ( mInitOK )
+ {
+ if ( !mNeedInit.empty() )
+ {
+ for ( std::list<WatcherFSEvents*>::iterator it = mNeedInit.begin(); it != mNeedInit.end(); it++ )
+ {
+ (*it)->initAsync();
+ }
+
+ mNeedInit.clear();
+ }
+
+ CFRunLoopRunInMode( kCFRunLoopDefaultMode, 0.5, kCFRunLoopRunTimedOut );
+ }
+}
+
+void FileWatcherFSEvents::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename)
+{
+ /// Not used
+}
+
+std::list<std::string> FileWatcherFSEvents::directories()
+{
+ std::list<std::string> dirs;
+
+ mWatchesLock.lock();
+
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ dirs.push_back( std::string( it->second->Directory ) );
+ }
+
+ mWatchesLock.unlock();
+
+ return dirs;
+}
+
+bool FileWatcherFSEvents::pathInWatches( const std::string& path )
+{
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ if ( it->second->Directory == path )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherFSEvents.hpp b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp
new file mode 100644
index 00000000000..6aafbc0b5ea
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherFSEvents.hpp
@@ -0,0 +1,107 @@
+#ifndef EFSW_FILEWATCHERFSEVENTS_HPP
+#define EFSW_FILEWATCHERFSEVENTS_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+#include <efsw/WatcherFSEvents.hpp>
+#include <map>
+#include <list>
+#include <vector>
+
+namespace efsw
+{
+
+/* OSX < 10.7 has no file events */
+/* So i declare the events constants */
+enum FSEventEvents
+{
+ efswFSEventStreamCreateFlagFileEvents = 0x00000010,
+ efswFSEventStreamEventFlagItemCreated = 0x00000100,
+ efswFSEventStreamEventFlagItemRemoved = 0x00000200,
+ efswFSEventStreamEventFlagItemInodeMetaMod = 0x00000400,
+ efswFSEventStreamEventFlagItemRenamed = 0x00000800,
+ efswFSEventStreamEventFlagItemModified = 0x00001000,
+ efswFSEventStreamEventFlagItemFinderInfoMod = 0x00002000,
+ efswFSEventStreamEventFlagItemChangeOwner = 0x00004000,
+ efswFSEventStreamEventFlagItemXattrMod = 0x00008000,
+ efswFSEventStreamEventFlagItemIsFile = 0x00010000,
+ efswFSEventStreamEventFlagItemIsDir = 0x00020000,
+ efswFSEventStreamEventFlagItemIsSymlink = 0x00040000,
+ efswFSEventsModified = efswFSEventStreamEventFlagItemFinderInfoMod |
+ efswFSEventStreamEventFlagItemModified |
+ efswFSEventStreamEventFlagItemInodeMetaMod |
+ efswFSEventStreamEventFlagItemChangeOwner |
+ efswFSEventStreamEventFlagItemXattrMod
+};
+
+/// Implementation for Win32 based on ReadDirectoryChangesW.
+/// @class FileWatcherFSEvents
+class FileWatcherFSEvents : public FileWatcherImpl
+{
+ friend class WatcherFSEvents;
+ public:
+ /// @return If FSEvents supports file-level notifications ( true if OS X >= 10.7 )
+ static bool isGranular();
+
+ /// type for a map from WatchID to WatcherWin32 pointer
+ typedef std::map<WatchID, WatcherFSEvents*> WatchMap;
+
+ FileWatcherFSEvents( FileWatcher * parent );
+
+ virtual ~FileWatcherFSEvents();
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive);
+
+ /// Remove a directory watch. This is a brute force lazy search O(nlogn).
+ void removeWatch(const std::string& directory);
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ void removeWatch(WatchID watchid);
+
+ /// Updates the watcher. Must be called often.
+ void watch();
+
+ /// Handles the action
+ void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = "");
+
+ /// @return Returns a list of the directories that are being watched
+ std::list<std::string> directories();
+ protected:
+ static void FSEventCallback( ConstFSEventStreamRef streamRef,
+ void *userData,
+ size_t numEvents,
+ void *eventPaths,
+ const FSEventStreamEventFlags eventFlags[],
+ const FSEventStreamEventId eventIds[]
+ );
+
+ CFRunLoopRef mRunLoopRef;
+
+ /// Vector of WatcherWin32 pointers
+ WatchMap mWatches;
+
+ /// The last watchid
+ WatchID mLastWatchID;
+
+ Thread * mThread;
+
+ Mutex mWatchesLock;
+
+ bool pathInWatches( const std::string& path );
+
+ std::list<WatcherFSEvents*> mNeedInit;
+ private:
+ void run();
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.cpp b/dep/efsw/src/efsw/FileWatcherGeneric.cpp
new file mode 100644
index 00000000000..1534b6a9279
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherGeneric.cpp
@@ -0,0 +1,197 @@
+#include <efsw/FileWatcherGeneric.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/System.hpp>
+
+namespace efsw
+{
+
+FileWatcherGeneric::FileWatcherGeneric( FileWatcher * parent ) :
+ FileWatcherImpl( parent ),
+ mThread( NULL ),
+ mLastWatchID( 0 )
+{
+ mInitOK = true;
+ mIsGeneric = true;
+}
+
+FileWatcherGeneric::~FileWatcherGeneric()
+{
+ mInitOK = false;
+
+ mThread->wait();
+
+ efSAFE_DELETE( mThread );
+
+ /// Delete the watches
+ WatchList::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ efSAFE_DELETE( (*it) );
+ }
+}
+
+WatchID FileWatcherGeneric::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive)
+{
+ std::string dir( directory );
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ FileInfo fi( dir );
+
+ if ( !fi.isDirectory() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else if ( !fi.isReadable() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotReadable, dir );
+ }
+ else if ( pathInWatches( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, dir );
+ }
+
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
+
+ if ( "" != link )
+ {
+ if ( pathInWatches( link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, dir );
+ }
+ else if ( !linkAllowed( curPath, link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+
+ mLastWatchID++;
+
+ WatcherGeneric * pWatch = new WatcherGeneric( mLastWatchID, dir, watcher, this, recursive );
+
+ mWatchesLock.lock();
+ mWatches.push_back(pWatch);
+ mWatchesLock.unlock();
+
+ return pWatch->ID;
+}
+
+void FileWatcherGeneric::removeWatch( const std::string& directory )
+{
+ WatchList::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ if ( (*it)->Directory == directory )
+ {
+ WatcherGeneric * watch = (*it);
+
+ mWatchesLock.lock();
+
+ mWatches.erase( it );
+
+ efSAFE_DELETE( watch ) ;
+
+ mWatchesLock.unlock();
+
+ return;
+ }
+ }
+}
+
+void FileWatcherGeneric::removeWatch(WatchID watchid)
+{
+ WatchList::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ if ( (*it)->ID == watchid )
+ {
+ WatcherGeneric * watch = (*it);
+
+ mWatchesLock.lock();
+
+ mWatches.erase( it );
+
+ efSAFE_DELETE( watch ) ;
+
+ mWatchesLock.unlock();
+
+ return;
+ }
+ }
+}
+
+void FileWatcherGeneric::watch()
+{
+ if ( NULL == mThread )
+ {
+ mThread = new Thread( &FileWatcherGeneric::run, this );
+ mThread->launch();
+ }
+}
+
+void FileWatcherGeneric::run()
+{
+ do
+ {
+ mWatchesLock.lock();
+
+ WatchList::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ (*it)->watch();
+ }
+
+ mWatchesLock.unlock();
+
+ if ( mInitOK ) System::sleep( 1000 );
+ } while ( mInitOK );
+}
+
+void FileWatcherGeneric::handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename)
+{
+ /// Not used
+}
+
+std::list<std::string> FileWatcherGeneric::directories()
+{
+ std::list<std::string> dirs;
+
+ mWatchesLock.lock();
+
+ WatchList::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ dirs.push_back( (*it)->Directory );
+ }
+
+ mWatchesLock.unlock();
+
+ return dirs;
+}
+
+bool FileWatcherGeneric::pathInWatches( const std::string& path )
+{
+ WatchList::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ if ( (*it)->Directory == path || (*it)->pathInWatches( path ) )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+}
diff --git a/dep/efsw/src/efsw/FileWatcherGeneric.hpp b/dep/efsw/src/efsw/FileWatcherGeneric.hpp
new file mode 100644
index 00000000000..fc9826580ab
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherGeneric.hpp
@@ -0,0 +1,59 @@
+#ifndef EFSW_FILEWATCHERGENERIC_HPP
+#define EFSW_FILEWATCHERGENERIC_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+#include <efsw/WatcherGeneric.hpp>
+#include <efsw/DirWatcherGeneric.hpp>
+#include <list>
+
+namespace efsw
+{
+
+/// Implementation for Generic File Watcher.
+/// @class FileWatcherGeneric
+class FileWatcherGeneric : public FileWatcherImpl
+{
+ public:
+ typedef std::list<WatcherGeneric*> WatchList;
+
+ FileWatcherGeneric( FileWatcher * parent );
+
+ virtual ~FileWatcherGeneric();
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive);
+
+ /// Remove a directory watch. This is a brute force lazy search O(nlogn).
+ void removeWatch(const std::string& directory);
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ void removeWatch(WatchID watchid);
+
+ /// Updates the watcher. Must be called often.
+ void watch();
+
+ /// Handles the action
+ void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = "");
+
+ /// @return Returns a list of the directories that are being watched
+ std::list<std::string> directories();
+ protected:
+ Thread * mThread;
+
+ /// The last watchid
+ WatchID mLastWatchID;
+
+ /// Map of WatchID to WatchStruct pointers
+ WatchList mWatches;
+
+ Mutex mWatchesLock;
+
+ bool pathInWatches( const std::string& path );
+ private:
+ void run();
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherImpl.cpp b/dep/efsw/src/efsw/FileWatcherImpl.cpp
new file mode 100644
index 00000000000..e6e0fc72a13
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherImpl.cpp
@@ -0,0 +1,29 @@
+#include <efsw/FileWatcherImpl.hpp>
+#include <efsw/String.hpp>
+#include <efsw/System.hpp>
+
+namespace efsw {
+
+FileWatcherImpl::FileWatcherImpl( FileWatcher * parent ) :
+ mFileWatcher( parent ),
+ mInitOK( false ),
+ mIsGeneric( false )
+{
+ System::maxFD();
+}
+
+FileWatcherImpl::~FileWatcherImpl()
+{
+}
+
+bool FileWatcherImpl::initOK()
+{
+ return mInitOK;
+}
+
+bool FileWatcherImpl::linkAllowed( const std::string& curPath, const std::string& link )
+{
+ return ( mFileWatcher->followSymlinks() && mFileWatcher->allowOutOfScopeLinks() ) || -1 != String::strStartsWith( curPath, link );
+}
+
+}
diff --git a/dep/efsw/src/efsw/FileWatcherImpl.hpp b/dep/efsw/src/efsw/FileWatcherImpl.hpp
new file mode 100644
index 00000000000..8f472bf56c5
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherImpl.hpp
@@ -0,0 +1,54 @@
+#ifndef EFSW_FILEWATCHERIMPL_HPP
+#define EFSW_FILEWATCHERIMPL_HPP
+
+#include <efsw/base.hpp>
+#include <efsw/efsw.hpp>
+#include <efsw/Watcher.hpp>
+#include <efsw/Thread.hpp>
+#include <efsw/Mutex.hpp>
+
+namespace efsw {
+
+class FileWatcherImpl
+{
+ public:
+ FileWatcherImpl( FileWatcher * parent );
+
+ virtual ~FileWatcherImpl();
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ virtual WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive) = 0;
+
+ /// Remove a directory watch. This is a brute force lazy search O(nlogn).
+ virtual void removeWatch(const std::string& directory) = 0;
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ virtual void removeWatch(WatchID watchid) = 0;
+
+ /// Updates the watcher. Must be called often.
+ virtual void watch() = 0;
+
+ /// Handles the action
+ virtual void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = "") = 0;
+
+ /// @return Returns a list of the directories that are being watched
+ virtual std::list<std::string> directories() = 0;
+
+ /// @return true if the backend init successfully
+ virtual bool initOK();
+
+ /// @return If the link is allowed according to the current path and the state of out scope links
+ virtual bool linkAllowed( const std::string& curPath, const std::string& link );
+
+ /// Search if a directory already exists in the watches
+ virtual bool pathInWatches( const std::string& path ) = 0;
+
+ FileWatcher * mFileWatcher;
+ bool mInitOK;
+ bool mIsGeneric;
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherInotify.cpp b/dep/efsw/src/efsw/FileWatcherInotify.cpp
new file mode 100644
index 00000000000..19c20761663
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherInotify.cpp
@@ -0,0 +1,531 @@
+#include <efsw/FileWatcherInotify.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY
+
+#include <unistd.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifdef EFSW_INOTIFY_NOSYS
+#include <efsw/inotify-nosys.h>
+#else
+#include <sys/inotify.h>
+#endif
+
+#include <efsw/FileSystem.hpp>
+#include <efsw/System.hpp>
+#include <efsw/Debug.hpp>
+
+#define BUFF_SIZE ((sizeof(struct inotify_event)+FILENAME_MAX)*1024)
+
+namespace efsw
+{
+
+FileWatcherInotify::FileWatcherInotify( FileWatcher * parent ) :
+ FileWatcherImpl( parent ),
+ mFD(-1),
+ mThread(NULL)
+{
+ mFD = inotify_init();
+
+ if (mFD < 0)
+ {
+ efDEBUG( "Error: %s\n", strerror(errno) );
+ }
+ else
+ {
+ mInitOK = true;
+ }
+}
+
+FileWatcherInotify::~FileWatcherInotify()
+{
+ mInitOK = false;
+
+ efSAFE_DELETE( mThread );
+
+ WatchMap::iterator iter = mWatches.begin();
+ WatchMap::iterator end = mWatches.end();
+
+ for(; iter != end; ++iter)
+ {
+ efSAFE_DELETE( iter->second );
+ }
+
+ mWatches.clear();
+
+ if ( mFD != -1 )
+ {
+ close(mFD);
+ mFD = -1;
+ }
+}
+
+WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive )
+{
+ return addWatch( directory, watcher, recursive, NULL );
+}
+
+WatchID FileWatcherInotify::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherInotify * parent )
+{
+ std::string dir( directory );
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ FileInfo fi( dir );
+
+ if ( !fi.isDirectory() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else if ( !fi.isReadable() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotReadable, dir );
+ }
+ else if ( pathInWatches( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+ else if ( NULL != parent && FileSystem::isRemoteFS( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRemote, dir );
+ }
+
+ /// Check if the directory is a symbolic link
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
+
+ if ( "" != link )
+ {
+ /// Avoid adding symlinks directories if it's now enabled
+ if ( NULL != parent && !mFileWatcher->followSymlinks() )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
+ }
+
+ /// If it's a symlink check if the realpath exists as a watcher, or
+ /// if the path is outside the current dir
+ if ( pathInWatches( link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+ else if ( !linkAllowed( curPath, link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+
+ int wd = inotify_add_watch (mFD, dir.c_str(), IN_CLOSE_WRITE | IN_MOVED_TO | IN_CREATE | IN_MOVED_FROM | IN_DELETE | IN_MODIFY);
+
+ if ( wd < 0 )
+ {
+ if( errno == ENOENT )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else
+ {
+ return Errors::Log::createLastError( Errors::Unspecified, std::string(strerror(errno)) );
+ }
+ }
+
+ efDEBUG( "Added watch %s with id: %d\n", dir.c_str(), wd );
+
+ WatcherInotify * pWatch = new WatcherInotify();
+ pWatch->Listener = watcher;
+ pWatch->ID = wd;
+ pWatch->Directory = dir;
+ pWatch->Recursive = recursive;
+ pWatch->Parent = parent;
+
+ mWatchesLock.lock();
+ mWatches.insert(std::make_pair(wd, pWatch));
+ mWatchesLock.unlock();
+
+ if ( NULL == pWatch->Parent )
+ {
+ mRealWatches[ pWatch->ID ] = pWatch;
+ }
+
+ if ( pWatch->Recursive )
+ {
+ std::map<std::string, FileInfo> files = FileSystem::filesInfoFromPath( pWatch->Directory );
+ std::map<std::string, FileInfo>::iterator it = files.begin();
+
+ for ( ; it != files.end(); it++ )
+ {
+ FileInfo fi = it->second;
+
+ if ( fi.isDirectory() && fi.isReadable() )
+ {
+ addWatch( fi.Filepath, watcher, recursive, pWatch );
+ }
+ }
+ }
+
+ return wd;
+}
+
+void FileWatcherInotify::removeWatchLocked(WatchID watchid)
+{
+ WatchMap::iterator iter = mWatches.find( watchid );
+
+ WatcherInotify * watch = iter->second;
+
+ if ( watch->Recursive )
+ {
+ WatchMap::iterator it = mWatches.begin();
+ std::list<WatchID> eraseWatches;
+
+ for(; it != mWatches.end(); ++it)
+ {
+ if ( it->second != watch &&
+ it->second->inParentTree( watch )
+ )
+ {
+ eraseWatches.push_back( it->second->ID );
+ }
+ }
+
+ for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ )
+ {
+ removeWatch( *eit );
+ }
+ }
+
+ mWatches.erase( iter );
+
+ if ( NULL == watch->Parent )
+ {
+ WatchMap::iterator eraseit = mRealWatches.find( watch->ID );
+
+ if ( eraseit != mRealWatches.end() )
+ {
+ mRealWatches.erase( eraseit );
+ }
+ }
+
+ int err = inotify_rm_watch(mFD, watchid);
+
+ if ( err < 0 )
+ {
+ efDEBUG( "Error removing watch %d: %s\n", watchid, strerror(errno) );
+ }
+ else
+ {
+ efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), watchid );
+ }
+
+ efSAFE_DELETE( watch );
+}
+
+void FileWatcherInotify::removeWatch(const std::string& directory)
+{
+ mWatchesLock.lock();
+
+ WatchMap::iterator iter = mWatches.begin();
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ if( directory == iter->second->Directory )
+ {
+ WatcherInotify * watch = iter->second;
+
+ if ( watch->Recursive )
+ {
+ WatchMap::iterator it = mWatches.begin();
+ std::list<WatchID> eraseWatches;
+
+ for(; it != mWatches.end(); ++it)
+ {
+ if ( it->second->inParentTree( watch ) )
+ {
+ eraseWatches.push_back( it->second->ID );
+ }
+ }
+
+ for ( std::list<WatchID>::iterator eit = eraseWatches.begin(); eit != eraseWatches.end(); eit++ )
+ {
+ removeWatchLocked( *eit );
+ }
+ }
+
+ mWatches.erase( iter );
+
+ if ( NULL == watch->Parent )
+ {
+ WatchMap::iterator eraseit = mRealWatches.find( watch->ID );
+
+ if ( eraseit != mRealWatches.end() )
+ {
+ mRealWatches.erase( eraseit );
+ }
+ }
+
+ int err = inotify_rm_watch(mFD, watch->ID);
+
+ if ( err < 0 )
+ {
+ efDEBUG( "Error removing watch %d: %s\n", watch->ID, strerror(errno) );
+ }
+ else
+ {
+ efDEBUG( "Removed watch %s with id: %d\n", watch->Directory.c_str(), watch->ID );
+ }
+
+ efSAFE_DELETE( watch );
+
+ break;
+ }
+ }
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherInotify::removeWatch( WatchID watchid )
+{
+ mWatchesLock.lock();
+
+ WatchMap::iterator iter = mWatches.find( watchid );
+
+ if( iter == mWatches.end() )
+ {
+ mWatchesLock.unlock();
+
+ return;
+ }
+
+ removeWatchLocked( watchid );
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherInotify::watch()
+{
+ if ( NULL == mThread )
+ {
+ mThread = new Thread( &FileWatcherInotify::run, this );
+ mThread->launch();
+ }
+}
+
+void FileWatcherInotify::run()
+{
+ static char buff[BUFF_SIZE] = {0};
+ WatchMap::iterator wit;
+ std::list<WatcherInotify*> movedOutsideWatches;
+
+ do
+ {
+ fd_set rfds;
+ FD_ZERO (&rfds);
+ FD_SET (mFD, &rfds);
+ timeval timeout;
+ timeout.tv_sec=0;
+ timeout.tv_usec=100000;
+
+ if( select (FD_SETSIZE, &rfds, NULL, NULL, &timeout) > 0 )
+ {
+ ssize_t len, i = 0;
+
+ len = read (mFD, buff, BUFF_SIZE);
+
+ if (len != -1)
+ {
+ while (i < len)
+ {
+ struct inotify_event *pevent = (struct inotify_event *)&buff[i];
+
+ mWatchesLock.lock();
+
+ wit = mWatches.find( pevent->wd );
+
+ if ( wit != mWatches.end() )
+ {
+ handleAction(wit->second, pevent->name, pevent->mask);
+
+ /// Keep track of the IN_MOVED_FROM events to known if the IN_MOVED_TO event is also fired
+ if ( !wit->second->OldFileName.empty() )
+ {
+ movedOutsideWatches.push_back( wit->second );
+ }
+ }
+
+ mWatchesLock.unlock();
+
+ i += sizeof(struct inotify_event) + pevent->len;
+ }
+
+ if ( !movedOutsideWatches.empty() )
+ {
+ /// In case that the IN_MOVED_TO is never fired means that the file was moved to other folder
+ for ( std::list<WatcherInotify*>::iterator it = movedOutsideWatches.begin(); it != movedOutsideWatches.end(); it++ )
+ {
+ if ( !(*it)->OldFileName.empty() )
+ {
+ /// So we send a IN_DELETE event for files that where moved outside of our scope
+ handleAction( *it, (*it)->OldFileName, IN_DELETE );
+
+ /// Remove the OldFileName
+ (*it)->OldFileName = "";
+ }
+ }
+
+ movedOutsideWatches.clear();
+ }
+ }
+ }
+ } while( mInitOK );
+}
+
+void FileWatcherInotify::checkForNewWatcher( Watcher* watch, std::string fpath )
+{
+ FileSystem::dirAddSlashAtEnd( fpath );
+
+ /// If the watcher is recursive, checks if the new file is a folder, and creates a watcher
+ if ( watch->Recursive && FileSystem::isDirectory( fpath ) )
+ {
+ bool found = false;
+
+ /// First check if exists
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ if ( it->second->Directory == fpath )
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if ( !found )
+ {
+ addWatch( fpath, watch->Listener, watch->Recursive, static_cast<WatcherInotify*>( watch ) );
+ }
+ }
+}
+
+void FileWatcherInotify::handleAction( Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename )
+{
+ if ( !watch || !watch->Listener )
+ {
+ return;
+ }
+
+ std::string fpath( watch->Directory + filename );
+
+ if ( ( IN_CLOSE_WRITE & action ) || ( IN_MODIFY & action ) )
+ {
+ watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified );
+ }
+ else if( IN_MOVED_TO & action )
+ {
+ /// If OldFileName doesn't exist means that the file has been moved from other folder, so we just send the Add event
+ if ( watch->OldFileName.empty() )
+ {
+ watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Add );
+
+ watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Modified );
+
+ checkForNewWatcher( watch, fpath );
+ }
+ else
+ {
+ watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Moved, watch->OldFileName );
+ }
+
+ if ( watch->Recursive && FileSystem::isDirectory( fpath ) )
+ {
+ /// Update the new directory path
+ std::string opath( watch->Directory + watch->OldFileName );
+ FileSystem::dirAddSlashAtEnd( opath );
+ FileSystem::dirAddSlashAtEnd( fpath );
+
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ if ( it->second->Directory == opath && it->second->DirInfo.Inode == FileInfo( opath ).Inode )
+ {
+ it->second->Directory = fpath;
+ it->second->DirInfo = FileInfo( fpath );
+
+ break;
+ }
+ }
+ }
+
+ watch->OldFileName = "";
+ }
+ else if( IN_CREATE & action )
+ {
+ watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Add );
+
+ checkForNewWatcher( watch, fpath );
+ }
+ else if ( IN_MOVED_FROM & action )
+ {
+ watch->OldFileName = filename;
+ }
+ else if( IN_DELETE & action )
+ {
+ watch->Listener->handleFileAction( watch->ID, watch->Directory, filename, Actions::Delete );
+
+ FileSystem::dirAddSlashAtEnd( fpath );
+
+ /// If the file erased is a directory and recursive is enabled, removes the directory erased
+ if ( watch->Recursive )
+ {
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ if ( it->second->Directory == fpath )
+ {
+ removeWatch( it->second->ID );
+ break;
+ }
+ }
+ }
+ }
+}
+
+std::list<std::string> FileWatcherInotify::directories()
+{
+ std::list<std::string> dirs;
+
+ mWatchesLock.lock();
+
+ WatchMap::iterator it = mRealWatches.begin();
+
+ for ( ; it != mRealWatches.end(); it++ )
+ {
+ dirs.push_back( it->second->Directory );
+ }
+
+ mWatchesLock.unlock();
+
+ return dirs;
+}
+
+bool FileWatcherInotify::pathInWatches( const std::string& path )
+{
+ /// Search in the real watches, since it must allow adding a watch already watched as a subdir
+ WatchMap::iterator it = mRealWatches.begin();
+
+ for ( ; it != mRealWatches.end(); it++ )
+ {
+ if ( it->second->Directory == path )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherInotify.hpp b/dep/efsw/src/efsw/FileWatcherInotify.hpp
new file mode 100644
index 00000000000..43ee9ca6afc
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherInotify.hpp
@@ -0,0 +1,73 @@
+#ifndef EFSW_FILEWATCHERLINUX_HPP
+#define EFSW_FILEWATCHERLINUX_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_INOTIFY
+
+#include <efsw/WatcherInotify.hpp>
+#include <map>
+
+namespace efsw
+{
+
+/// Implementation for Linux based on inotify.
+/// @class FileWatcherInotify
+class FileWatcherInotify : public FileWatcherImpl
+{
+ public:
+ /// type for a map from WatchID to WatchStruct pointer
+ typedef std::map<WatchID, WatcherInotify*> WatchMap;
+
+ FileWatcherInotify( FileWatcher * parent );
+
+ virtual ~FileWatcherInotify();
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive);
+
+ /// Remove a directory watch. This is a brute force lazy search O(nlogn).
+ void removeWatch(const std::string& directory);
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ void removeWatch(WatchID watchid);
+
+ /// Updates the watcher. Must be called often.
+ void watch();
+
+ /// Handles the action
+ void handleAction(Watcher * watch, const std::string& filename, unsigned long action, std::string oldFilename = "");
+
+ /// @return Returns a list of the directories that are being watched
+ std::list<std::string> directories();
+ protected:
+ /// Map of WatchID to WatchStruct pointers
+ WatchMap mWatches;
+
+ /// User added watches
+ WatchMap mRealWatches;
+
+ /// inotify file descriptor
+ int mFD;
+
+ Thread * mThread;
+
+ Mutex mWatchesLock;
+
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherInotify * parent = NULL );
+
+ bool pathInWatches( const std::string& path );
+ private:
+ void run();
+
+ void removeWatchLocked(WatchID watchid);
+
+ void checkForNewWatcher( Watcher* watch, std::string fpath );
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.cpp b/dep/efsw/src/efsw/FileWatcherKqueue.cpp
new file mode 100644
index 00000000000..600fd085b35
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherKqueue.cpp
@@ -0,0 +1,274 @@
+#include <efsw/FileWatcherKqueue.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <string.h>
+#include <efsw/FileSystem.hpp>
+#include <efsw/System.hpp>
+#include <efsw/Debug.hpp>
+#include <efsw/WatcherGeneric.hpp>
+
+namespace efsw
+{
+
+FileWatcherKqueue::FileWatcherKqueue( FileWatcher * parent ) :
+ FileWatcherImpl( parent ),
+ mLastWatchID(0),
+ mThread( NULL ),
+ mFileDescriptorCount( 1 ),
+ mAddingWatcher( false )
+{
+ mTimeOut.tv_sec = 0;
+ mTimeOut.tv_nsec = 0;
+ mInitOK = true;
+}
+
+FileWatcherKqueue::~FileWatcherKqueue()
+{
+ WatchMap::iterator iter = mWatches.begin();
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ efSAFE_DELETE( iter->second );
+ }
+
+ mWatches.clear();
+
+ mInitOK = false;
+
+ mThread->wait();
+
+ efSAFE_DELETE( mThread );
+}
+
+WatchID FileWatcherKqueue::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive)
+{
+ static bool s_ug = false;
+
+ std::string dir( directory );
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ FileInfo fi( dir );
+
+ if ( !fi.isDirectory() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else if ( !fi.isReadable() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotReadable, dir );
+ }
+ else if ( pathInWatches( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
+
+ if ( "" != link )
+ {
+ if ( pathInWatches( link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+ else if ( !linkAllowed( curPath, link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+
+ /// Check first if are enough file descriptors available to create another kqueue watcher, otherwise it creates a generic watcher
+ if ( availablesFD() )
+ {
+ mAddingWatcher = true;
+
+ WatcherKqueue * watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, this );
+
+ mWatchesLock.lock();
+ mWatches.insert(std::make_pair(mLastWatchID, watch));
+ mWatchesLock.unlock();
+
+ watch->addAll();
+
+ // if failed to open the directory... erase the watcher
+ if ( !watch->initOK() )
+ {
+ int le = watch->lastErrno();
+
+ mWatches.erase( watch->ID );
+
+ efSAFE_DELETE( watch );
+
+ mLastWatchID--;
+
+ // Probably the folder has too many files, create a generic watcher
+ if ( EACCES != le )
+ {
+ WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive );
+
+ mWatchesLock.lock();
+ mWatches.insert(std::make_pair(mLastWatchID, watch));
+ mWatchesLock.unlock();
+ }
+ else
+ {
+ return Errors::Log::createLastError( Errors::Unspecified, link );
+ }
+ }
+
+ mAddingWatcher = false;
+ }
+ else
+ {
+ if ( !s_ug )
+ {
+ efDEBUG( "Started using generic watcher, file descriptor limit reached: %ld\n", mFileDescriptorCount );
+ s_ug = true;
+ }
+
+ WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, this, recursive );
+
+ mWatchesLock.lock();
+ mWatches.insert(std::make_pair(mLastWatchID, watch));
+ mWatchesLock.unlock();
+ }
+
+ return mLastWatchID;
+}
+
+void FileWatcherKqueue::removeWatch(const std::string& directory)
+{
+ mWatchesLock.lock();
+
+ WatchMap::iterator iter = mWatches.begin();
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ if(directory == iter->second->Directory)
+ {
+ removeWatch(iter->first);
+ return;
+ }
+ }
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherKqueue::removeWatch(WatchID watchid)
+{
+ mWatchesLock.lock();
+
+ WatchMap::iterator iter = mWatches.find(watchid);
+
+ if(iter == mWatches.end())
+ return;
+
+ Watcher* watch = iter->second;
+
+ mWatches.erase(iter);
+
+ efSAFE_DELETE( watch );
+
+ mWatchesLock.unlock();
+}
+
+bool FileWatcherKqueue::isAddingWatcher() const
+{
+ return mAddingWatcher;
+}
+
+void FileWatcherKqueue::watch()
+{
+ if ( NULL == mThread )
+ {
+ mThread = new Thread( &FileWatcherKqueue::run, this );
+ mThread->launch();
+ }
+}
+
+void FileWatcherKqueue::run()
+{
+ do
+ {
+ mWatchesLock.lock();
+
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it )
+ {
+ it->second->watch();
+ }
+
+ mWatchesLock.unlock();
+
+ System::sleep( 500 );
+ } while( mInitOK );
+}
+
+void FileWatcherKqueue::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename)
+{
+}
+
+std::list<std::string> FileWatcherKqueue::directories()
+{
+ std::list<std::string> dirs;
+
+ mWatchesLock.lock();
+
+ WatchMap::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ dirs.push_back( it->second->Directory );
+ }
+
+ mWatchesLock.unlock();
+
+ return dirs;
+}
+
+bool FileWatcherKqueue::pathInWatches( const std::string& path )
+{
+ WatchMap::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ if ( it->second->Directory == path )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void FileWatcherKqueue::addFD()
+{
+ mFileDescriptorCount++;
+}
+
+void FileWatcherKqueue::removeFD()
+{
+ mFileDescriptorCount--;
+}
+
+bool FileWatcherKqueue::availablesFD()
+{
+ return mFileDescriptorCount <= (Int64)System::getMaxFD() - 500;
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherKqueue.hpp b/dep/efsw/src/efsw/FileWatcherKqueue.hpp
new file mode 100644
index 00000000000..0a2431e3777
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherKqueue.hpp
@@ -0,0 +1,78 @@
+#ifndef EFSW_FILEWATCHEROSX_HPP
+#define EFSW_FILEWATCHEROSX_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <efsw/WatcherKqueue.hpp>
+
+namespace efsw
+{
+
+/// Implementation for OSX based on kqueue.
+/// @class FileWatcherKqueue
+class FileWatcherKqueue : public FileWatcherImpl
+{
+ friend class WatcherKqueue;
+ public:
+ FileWatcherKqueue( FileWatcher * parent );
+
+ virtual ~FileWatcherKqueue();
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive);
+
+ /// Remove a directory watch. This is a brute force lazy search O(nlogn).
+ void removeWatch(const std::string& directory);
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ void removeWatch(WatchID watchid);
+
+ /// Updates the watcher. Must be called often.
+ void watch();
+
+ /// Handles the action
+ void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = "");
+
+ /// @return Returns a list of the directories that are being watched
+ std::list<std::string> directories();
+ protected:
+ /// Map of WatchID to WatchStruct pointers
+ WatchMap mWatches;
+
+ /// time out data
+ struct timespec mTimeOut;
+
+ /// WatchID allocator
+ int mLastWatchID;
+
+ Thread * mThread;
+
+ Mutex mWatchesLock;
+
+ std::list<WatchID> mRemoveList;
+
+ long mFileDescriptorCount;
+
+ bool mAddingWatcher;
+
+ bool isAddingWatcher() const;
+
+ bool pathInWatches( const std::string& path );
+
+ void addFD();
+
+ void removeFD();
+
+ bool availablesFD();
+ private:
+ void run();
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherWin32.cpp b/dep/efsw/src/efsw/FileWatcherWin32.cpp
new file mode 100644
index 00000000000..fe78dd122cf
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherWin32.cpp
@@ -0,0 +1,291 @@
+#include <efsw/FileWatcherWin32.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/System.hpp>
+#include <efsw/String.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+namespace efsw
+{
+
+FileWatcherWin32::FileWatcherWin32( FileWatcher * parent ) :
+ FileWatcherImpl( parent ),
+ mLastWatchID(0),
+ mThread( NULL )
+{
+ mInitOK = true;
+}
+
+FileWatcherWin32::~FileWatcherWin32()
+{
+ WatchVector::iterator iter = mWatches.begin();
+
+ mWatchesLock.lock();
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ DestroyWatch((*iter));
+ }
+
+ mHandles.clear();
+ mWatches.clear();
+
+ mInitOK = false;
+
+ mWatchesLock.unlock();
+
+ efSAFE_DELETE( mThread );
+}
+
+WatchID FileWatcherWin32::addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive)
+{
+ std::string dir( directory );
+
+ FileInfo fi( dir );
+
+ if ( !fi.isDirectory() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else if ( !fi.isReadable() )
+ {
+ return Errors::Log::createLastError( Errors::FileNotReadable, dir );
+ }
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ WatchID watchid = ++mLastWatchID;
+
+ mWatchesLock.lock();
+
+ WatcherStructWin32 * watch = CreateWatch( String::fromUtf8( dir ).toWideString().c_str(), recursive, FILE_NOTIFY_CHANGE_CREATION |
+ FILE_NOTIFY_CHANGE_LAST_WRITE |
+ FILE_NOTIFY_CHANGE_FILE_NAME |
+ FILE_NOTIFY_CHANGE_DIR_NAME |
+ FILE_NOTIFY_CHANGE_SIZE
+ );
+
+ if( NULL == watch )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+
+ if ( pathInWatches( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, dir );
+ }
+
+ // Add the handle to the handles vector
+ watch->Watch->ID = watchid;
+ watch->Watch->Watch = this;
+ watch->Watch->Listener = watcher;
+ watch->Watch->DirName = new char[dir.length()+1];
+ strcpy(watch->Watch->DirName, dir.c_str());
+
+ mHandles.push_back( watch->Watch->DirHandle );
+ mWatches.push_back( watch );
+ mWatchesLock.unlock();
+
+ return watchid;
+}
+
+void FileWatcherWin32::removeWatch(const std::string& directory)
+{
+ mWatchesLock.lock();
+
+ WatchVector::iterator iter = mWatches.begin();
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ if(directory == (*iter)->Watch->DirName)
+ {
+ removeWatch((*iter)->Watch->ID);
+ return;
+ }
+ }
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherWin32::removeWatch(WatchID watchid)
+{
+ mWatchesLock.lock();
+
+ WatchVector::iterator iter = mWatches.begin();
+
+ WatcherStructWin32* watch = NULL;
+
+ for(; iter != mWatches.end(); ++iter)
+ {
+ // Find the watch ID
+ if ( (*iter)->Watch->ID == watchid )
+ {
+ watch = (*iter);
+
+ mWatches.erase( iter );
+
+ // Remove handle from the handle vector
+ HandleVector::iterator it = mHandles.begin();
+
+ for ( ; it != mHandles.end(); it++ )
+ {
+ if ( watch->Watch->DirHandle == (*it) )
+ {
+ mHandles.erase( it );
+ break;
+ }
+ }
+
+ DestroyWatch(watch);
+
+ break;
+ }
+ }
+
+ mWatchesLock.unlock();
+}
+
+void FileWatcherWin32::watch()
+{
+ if ( NULL == mThread )
+ {
+ mThread = new Thread( &FileWatcherWin32::run, this );
+ mThread->launch();
+ }
+}
+
+void FileWatcherWin32::run()
+{
+ if ( mHandles.empty() )
+ {
+ return;
+ }
+
+ do
+ {
+ if ( !mHandles.empty() )
+ {
+ mWatchesLock.lock();
+
+ for ( std::size_t i = 0; i < mWatches.size(); i++ )
+ {
+ WatcherStructWin32 * watch = mWatches[ i ];
+
+ // If the overlapped struct was cancelled ( because the creator thread doesn't exists anymore ),
+ // we recreate the overlapped in the current thread and refresh the watch
+ if ( /*STATUS_CANCELED*/0xC0000120 == watch->Overlapped.Internal )
+ {
+ watch->Overlapped = OVERLAPPED();
+ RefreshWatch(watch);
+ }
+
+ // First ensure that the handle is the same, this means that the watch was not removed.
+ if ( HasOverlappedIoCompleted( &watch->Overlapped ) && mHandles[ i ] == watch->Watch->DirHandle )
+ {
+ DWORD bytes;
+
+ if ( GetOverlappedResult( watch->Watch->DirHandle, &watch->Overlapped, &bytes, FALSE ) )
+ {
+ WatchCallback( ERROR_SUCCESS, bytes, &watch->Overlapped );
+ }
+ }
+ }
+
+ mWatchesLock.unlock();
+
+ if ( mInitOK )
+ {
+ System::sleep( 10 );
+ }
+ }
+ else
+ {
+ // Wait for a new handle to be added
+ System::sleep( 10 );
+ }
+ } while ( mInitOK );
+}
+
+void FileWatcherWin32::handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename)
+{
+ Action fwAction;
+
+ switch(action)
+ {
+ case FILE_ACTION_RENAMED_OLD_NAME:
+ watch->OldFileName = filename;
+ return;
+ case FILE_ACTION_ADDED:
+ fwAction = Actions::Add;
+ break;
+ case FILE_ACTION_RENAMED_NEW_NAME:
+ {
+ fwAction = Actions::Moved;
+
+ std::string fpath( watch->Directory + filename );
+
+ // Update the directory path
+ if ( watch->Recursive && FileSystem::isDirectory( fpath ) )
+ {
+ // Update the new directory path
+ std::string opath( watch->Directory + watch->OldFileName );
+ FileSystem::dirAddSlashAtEnd( opath );
+ FileSystem::dirAddSlashAtEnd( fpath );
+
+ for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ if ( (*it)->Watch->Directory == opath )
+ {
+ (*it)->Watch->Directory = fpath;
+
+ break;
+ }
+ }
+ }
+
+ watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction, watch->OldFileName);
+ return;
+ }
+ case FILE_ACTION_REMOVED:
+ fwAction = Actions::Delete;
+ break;
+ case FILE_ACTION_MODIFIED:
+ fwAction = Actions::Modified;
+ break;
+ };
+
+ watch->Listener->handleFileAction(watch->ID, static_cast<WatcherWin32*>( watch )->DirName, filename, fwAction);
+}
+
+std::list<std::string> FileWatcherWin32::directories()
+{
+ std::list<std::string> dirs;
+
+ mWatchesLock.lock();
+
+ for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ dirs.push_back( std::string( (*it)->Watch->DirName ) );
+ }
+
+ mWatchesLock.unlock();
+
+ return dirs;
+}
+
+bool FileWatcherWin32::pathInWatches( const std::string& path )
+{
+ for ( WatchVector::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ if ( (*it)->Watch->DirName == path )
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/FileWatcherWin32.hpp b/dep/efsw/src/efsw/FileWatcherWin32.hpp
new file mode 100644
index 00000000000..505cd772b82
--- /dev/null
+++ b/dep/efsw/src/efsw/FileWatcherWin32.hpp
@@ -0,0 +1,69 @@
+#ifndef EFSW_FILEWATCHERWIN32_HPP
+#define EFSW_FILEWATCHERWIN32_HPP
+
+#include <efsw/base.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#include <efsw/WatcherWin32.hpp>
+#include <vector>
+#include <map>
+
+namespace efsw
+{
+
+/// Implementation for Win32 based on ReadDirectoryChangesW.
+/// @class FileWatcherWin32
+class FileWatcherWin32 : public FileWatcherImpl
+{
+ public:
+ /// type for a map from WatchID to WatcherWin32 pointer
+ typedef std::vector<WatcherStructWin32*> WatchVector;
+ typedef std::vector<HANDLE> HandleVector;
+
+ FileWatcherWin32( FileWatcher * parent );
+
+ virtual ~FileWatcherWin32();
+
+ /// Add a directory watch
+ /// On error returns WatchID with Error type.
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive);
+
+ /// Remove a directory watch. This is a brute force lazy search O(nlogn).
+ void removeWatch(const std::string& directory);
+
+ /// Remove a directory watch. This is a map lookup O(logn).
+ void removeWatch(WatchID watchid);
+
+ /// Updates the watcher. Must be called often.
+ void watch();
+
+ /// Handles the action
+ void handleAction(Watcher* watch, const std::string& filename, unsigned long action, std::string oldFilename = "");
+
+ /// @return Returns a list of the directories that are being watched
+ std::list<std::string> directories();
+ protected:
+ /// Vector of WatcherWin32 pointers
+ WatchVector mWatches;
+
+ /// Keeps an updated handles vector
+ HandleVector mHandles;
+
+ /// The last watchid
+ WatchID mLastWatchID;
+
+ Thread * mThread;
+
+ Mutex mWatchesLock;
+
+ bool pathInWatches( const std::string& path );
+ private:
+ void run();
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/Log.cpp b/dep/efsw/src/efsw/Log.cpp
new file mode 100644
index 00000000000..8e2860ac099
--- /dev/null
+++ b/dep/efsw/src/efsw/Log.cpp
@@ -0,0 +1,27 @@
+#include <efsw/efsw.hpp>
+
+namespace efsw { namespace Errors {
+
+static std::string LastError;
+
+std::string Log::getLastErrorLog()
+{
+ return LastError;
+}
+
+Error Log::createLastError( Error err, std::string log )
+{
+ switch ( err )
+ {
+ case FileNotFound: LastError = "File not found ( " + log + " )"; break;
+ case FileRepeated: LastError = "File reapeated in watches ( " + log + " )"; break;
+ case FileOutOfScope: LastError = "Symlink file out of scope ( " + log + " )"; break;
+ case FileRemote: LastError = "File is located in a remote file system, use a generic watcher. ( " + log + " )"; break;
+ case Unspecified:
+ default: LastError = log;
+ }
+
+ return err;
+}
+
+}}
diff --git a/dep/efsw/src/efsw/Mutex.cpp b/dep/efsw/src/efsw/Mutex.cpp
new file mode 100644
index 00000000000..b34ba066ee9
--- /dev/null
+++ b/dep/efsw/src/efsw/Mutex.cpp
@@ -0,0 +1,26 @@
+#include <efsw/Mutex.hpp>
+#include <efsw/platform/platformimpl.hpp>
+
+namespace efsw {
+
+Mutex::Mutex() :
+ mMutexImpl( new Platform::MutexImpl() )
+{
+}
+
+Mutex::~Mutex()
+{
+ efSAFE_DELETE( mMutexImpl );
+}
+
+void Mutex::lock()
+{
+ mMutexImpl->lock();
+}
+
+void Mutex::unlock()
+{
+ mMutexImpl->unlock();
+}
+
+}
diff --git a/dep/efsw/src/efsw/Mutex.hpp b/dep/efsw/src/efsw/Mutex.hpp
new file mode 100644
index 00000000000..e6e89def175
--- /dev/null
+++ b/dep/efsw/src/efsw/Mutex.hpp
@@ -0,0 +1,28 @@
+#ifndef EFSW_MUTEX_HPP
+#define EFSW_MUTEX_HPP
+
+#include <efsw/base.hpp>
+
+namespace efsw {
+
+namespace Platform { class MutexImpl; }
+
+/** Simple mutex class */
+class Mutex {
+ public:
+ Mutex();
+
+ ~Mutex();
+
+ /** Lock the mutex */
+ void lock();
+
+ /** Unlock the mutex */
+ void unlock();
+ private:
+ Platform::MutexImpl * mMutexImpl;
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/String.cpp b/dep/efsw/src/efsw/String.cpp
new file mode 100644
index 00000000000..f703d25cb35
--- /dev/null
+++ b/dep/efsw/src/efsw/String.cpp
@@ -0,0 +1,813 @@
+#include <iterator>
+#include <efsw/String.hpp>
+#include <efsw/Utf.hpp>
+
+namespace efsw {
+
+const std::size_t String::InvalidPos = StringType::npos;
+
+std::vector < std::string > String::split ( const std::string& str, const char& splitchar, const bool& pushEmptyString )
+{
+ std::vector < std::string > tmp;
+ std::string tmpstr;
+
+ for ( size_t i = 0; i < str.size(); i++ )
+ {
+ if ( str[i] == splitchar )
+ {
+ if ( pushEmptyString || tmpstr.size() )
+ {
+ tmp.push_back(tmpstr);
+ tmpstr = "";
+ }
+ }
+ else
+ {
+ tmpstr += str[i];
+ }
+ }
+
+ if ( tmpstr.size() )
+ {
+ tmp.push_back( tmpstr );
+ }
+
+ return tmp;
+}
+
+std::vector < String > String::split ( const String& str, const Uint32& splitchar, const bool& pushEmptyString )
+{
+ std::vector < String > tmp;
+ String tmpstr;
+
+ for ( size_t i = 0; i < str.size(); i++ )
+ {
+ if ( str[i] == splitchar )
+ {
+ if ( pushEmptyString || tmpstr.size() )
+ {
+ tmp.push_back(tmpstr);
+ tmpstr = "";
+ }
+ }
+ else
+ {
+ tmpstr += str[i];
+ }
+ }
+
+ if ( tmpstr.size() )
+ {
+ tmp.push_back( tmpstr );
+ }
+
+ return tmp;
+}
+
+int String::strStartsWith( const std::string& start, const std::string& str )
+{
+ int pos = -1;
+ size_t size = start.size();
+
+ if ( str.size() >= size )
+ {
+ for ( std::size_t i = 0; i < size; i++ )
+ {
+ if ( start[i] == str[i] )
+ {
+ pos = (int)i;
+ }
+ else
+ {
+ pos = -1;
+ break;
+ }
+ }
+ }
+
+ return pos;
+}
+
+int String::strStartsWith( const String& start, const String& str )
+{
+ int pos = -1;
+ size_t size = start.size();
+
+ if ( str.size() >= size )
+ {
+ for ( std::size_t i = 0; i < size; i++ )
+ {
+ if ( start[i] == str[i] )
+ {
+ pos = (int)i;
+ }
+ else
+ {
+ pos = -1;
+ break;
+ }
+ }
+ }
+
+ return pos;
+}
+
+String::String()
+{
+}
+
+String::String(char ansiChar, const std::locale& locale)
+{
+ mString += Utf32::DecodeAnsi(ansiChar, locale);
+}
+
+#ifndef EFSW_NO_WIDECHAR
+String::String(wchar_t wideChar)
+{
+ mString += Utf32::DecodeWide(wideChar);
+}
+#endif
+
+String::String(StringBaseType utf32Char)
+{
+ mString += utf32Char;
+}
+
+String::String( const char* uf8String ) {
+ if (uf8String)
+ {
+ std::size_t length = strlen(uf8String);
+
+ if (length > 0)
+ {
+ mString.reserve(length + 1);
+
+ Utf8::ToUtf32(uf8String, uf8String + length, std::back_inserter(mString));
+ }
+ }
+}
+
+String::String( const std::string& utf8String ) {
+ mString.reserve( utf8String.length() + 1 );
+
+ Utf8::ToUtf32( utf8String.begin(), utf8String.end(), std::back_inserter( mString ) );
+}
+
+String::String(const char* ansiString, const std::locale& locale)
+{
+ if (ansiString)
+ {
+ std::size_t length = strlen(ansiString);
+ if (length > 0)
+ {
+ mString.reserve(length + 1);
+ Utf32::FromAnsi(ansiString, ansiString + length, std::back_inserter(mString), locale);
+ }
+ }
+}
+
+String::String(const std::string& ansiString, const std::locale& locale)
+{
+ mString.reserve(ansiString.length() + 1);
+ Utf32::FromAnsi(ansiString.begin(), ansiString.end(), std::back_inserter(mString), locale);
+}
+
+#ifndef EFSW_NO_WIDECHAR
+String::String(const wchar_t* wideString)
+{
+ if (wideString)
+ {
+ std::size_t length = std::wcslen(wideString);
+ if (length > 0)
+ {
+ mString.reserve(length + 1);
+ Utf32::FromWide(wideString, wideString + length, std::back_inserter(mString));
+ }
+ }
+}
+
+String::String(const std::wstring& wideString)
+{
+ mString.reserve(wideString.length() + 1);
+ Utf32::FromWide(wideString.begin(), wideString.end(), std::back_inserter(mString));
+}
+#endif
+
+String::String(const StringBaseType* utf32String)
+{
+ if (utf32String)
+ mString = utf32String;
+}
+
+String::String(const StringType& utf32String) :
+mString(utf32String)
+{
+}
+
+String::String(const String& str) :
+mString(str.mString)
+{
+}
+
+String String::fromUtf8( const std::string& utf8String )
+{
+ String::StringType utf32;
+
+ utf32.reserve( utf8String.length() + 1 );
+
+ Utf8::ToUtf32( utf8String.begin(), utf8String.end(), std::back_inserter( utf32 ) );
+
+ return String( utf32 );
+}
+
+String::operator std::string() const
+{
+ return toAnsiString();
+}
+
+std::string String::toAnsiString(const std::locale& locale) const
+{
+ // Prepare the output string
+ std::string output;
+ output.reserve(mString.length() + 1);
+
+ // Convert
+ Utf32::ToAnsi(mString.begin(), mString.end(), std::back_inserter(output), 0, locale);
+
+ return output;
+}
+
+#ifndef EFSW_NO_WIDECHAR
+std::wstring String::toWideString() const
+{
+ // Prepare the output string
+ std::wstring output;
+ output.reserve(mString.length() + 1);
+
+ // Convert
+ Utf32::ToWide(mString.begin(), mString.end(), std::back_inserter(output), 0);
+
+ return output;
+}
+#endif
+
+std::string String::toUtf8() const {
+ // Prepare the output string
+ std::string output;
+ output.reserve(mString.length() + 1);
+
+ // Convert
+ Utf32::toUtf8(mString.begin(), mString.end(), std::back_inserter(output) );
+
+ return output;
+}
+
+String& String::operator =(const String& right)
+{
+ mString = right.mString;
+ return *this;
+}
+
+String& String::operator =( const StringBaseType& right )
+{
+ mString = right;
+ return *this;
+}
+
+String& String::operator +=(const String& right)
+{
+ mString += right.mString;
+ return *this;
+}
+
+String& String::operator +=( const StringBaseType& right )
+{
+ mString += right;
+ return *this;
+}
+
+
+String::StringBaseType String::operator [](std::size_t index) const
+{
+ return mString[index];
+}
+
+String::StringBaseType& String::operator [](std::size_t index)
+{
+ return mString[index];
+}
+
+String::StringBaseType String::at( std::size_t index ) const
+{
+ return mString.at( index );
+}
+
+void String::push_back( StringBaseType c )
+{
+ mString.push_back( c );
+}
+
+void String::swap ( String& str )
+{
+ mString.swap( str.mString );
+}
+
+void String::clear()
+{
+ mString.clear();
+}
+
+std::size_t String::size() const
+{
+ return mString.size();
+}
+
+std::size_t String::length() const
+{
+ return mString.length();
+}
+
+bool String::empty() const
+{
+ return mString.empty();
+}
+
+void String::erase(std::size_t position, std::size_t count)
+{
+ mString.erase(position, count);
+}
+
+String& String::insert(std::size_t position, const String& str)
+{
+ mString.insert(position, str.mString);
+ return *this;
+}
+
+String& String::insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n )
+{
+ mString.insert( pos1, str.mString, pos2, n );
+ return *this;
+}
+
+String& String::insert ( size_t pos1, const char* s, size_t n )
+{
+ String tmp( s );
+
+ mString.insert( pos1, tmp.data(), n );
+
+ return *this;
+}
+
+String& String::insert ( size_t pos1, size_t n, char c )
+{
+ mString.insert( pos1, n, c );
+ return *this;
+}
+
+String& String::insert ( size_t pos1, const char* s )
+{
+ String tmp( s );
+
+ mString.insert( pos1, tmp.data() );
+
+ return *this;
+}
+
+String::Iterator String::insert ( Iterator p, char c )
+{
+ return mString.insert( p, c );
+}
+
+void String::insert ( Iterator p, size_t n, char c )
+{
+ mString.insert( p, n, c );
+}
+
+const String::StringBaseType* String::c_str() const
+{
+ return mString.c_str();
+}
+
+const String::StringBaseType* String::data() const
+{
+ return mString.data();
+}
+
+String::Iterator String::begin()
+{
+ return mString.begin();
+}
+
+String::ConstIterator String::begin() const
+{
+ return mString.begin();
+}
+
+String::Iterator String::end()
+{
+ return mString.end();
+}
+
+String::ConstIterator String::end() const
+{
+ return mString.end();
+}
+
+String::ReverseIterator String::rbegin()
+{
+ return mString.rbegin();
+}
+
+String::ConstReverseIterator String::rbegin() const
+{
+ return mString.rbegin();
+}
+
+String::ReverseIterator String::rend()
+{
+ return mString.rend();
+}
+
+String::ConstReverseIterator String::rend() const
+{
+ return mString.rend();
+}
+
+void String::resize( std::size_t n, StringBaseType c )
+{
+ mString.resize( n, c );
+}
+
+void String::resize( std::size_t n )
+{
+ mString.resize( n );
+}
+
+std::size_t String::max_size() const
+{
+ return mString.max_size();
+}
+
+void String::reserve( size_t res_arg )
+{
+ mString.reserve( res_arg );
+}
+
+std::size_t String::capacity() const
+{
+ return mString.capacity();
+}
+
+String& String::assign ( const String& str )
+{
+ mString.assign( str.mString );
+ return *this;
+}
+
+String& String::assign ( const String& str, size_t pos, size_t n )
+{
+ mString.assign( str.mString, pos, n );
+ return *this;
+}
+
+String& String::assign ( const char* s, size_t n )
+{
+ String tmp( s );
+
+ mString.assign( tmp.mString );
+
+ return *this;
+}
+
+String& String::assign ( const char* s )
+{
+ String tmp( s );
+
+ mString.assign( tmp.mString );
+
+ return *this;
+}
+
+String& String::assign ( size_t n, char c )
+{
+ mString.assign( n, c );
+
+ return *this;
+}
+
+String& String::append ( const String& str )
+{
+ mString.append( str.mString );
+
+ return *this;
+}
+
+String& String::append ( const String& str, size_t pos, size_t n )
+{
+ mString.append( str.mString, pos, n );
+
+ return *this;
+}
+
+String& String::append ( const char* s, size_t n )
+{
+ String tmp( s );
+
+ mString.append( tmp.mString );
+
+ return *this;
+}
+
+String& String::append ( const char* s )
+{
+ String tmp( s );
+
+ mString.append( tmp.mString );
+
+ return *this;
+}
+
+String& String::append ( size_t n, char c )
+{
+ mString.append( n, c );
+
+ return *this;
+}
+
+String& String::append ( std::size_t n, StringBaseType c )
+{
+ mString.append( n, c );
+
+ return *this;
+}
+
+String& String::replace ( size_t pos1, size_t n1, const String& str )
+{
+ mString.replace( pos1, n1, str.mString );
+
+ return *this;
+}
+
+String& String::replace ( Iterator i1, Iterator i2, const String& str )
+{
+ mString.replace( i1, i2, str.mString );
+
+ return *this;
+}
+
+String& String::replace ( size_t pos1, size_t n1, const String& str, size_t pos2, size_t n2 )
+{
+ mString.replace( pos1, n1, str.mString, pos2, n2 );
+
+ return *this;
+}
+
+String& String::replace ( size_t pos1, size_t n1, const char* s, size_t n2 )
+{
+ String tmp( s );
+
+ mString.replace( pos1, n1, tmp.data(), n2 );
+
+ return *this;
+}
+
+String& String::replace ( Iterator i1, Iterator i2, const char* s, size_t n2 )
+{
+ String tmp( s );
+
+ mString.replace( i1, i2, tmp.data(), n2 );
+
+ return *this;
+}
+
+String& String::replace ( size_t pos1, size_t n1, const char* s )
+{
+ String tmp( s );
+
+ mString.replace( pos1, n1, tmp.mString );
+
+ return *this;
+}
+
+String& String::replace ( Iterator i1, Iterator i2, const char* s )
+{
+ String tmp( s );
+
+ mString.replace( i1, i2, tmp.mString );
+
+ return *this;
+}
+
+String& String::replace ( size_t pos1, size_t n1, size_t n2, char c )
+{
+ mString.replace( pos1, n1, n2, (StringBaseType)c );
+
+ return *this;
+}
+
+String& String::replace ( Iterator i1, Iterator i2, size_t n2, char c )
+{
+ mString.replace( i1, i2, n2, (StringBaseType)c );
+
+ return *this;
+}
+
+std::size_t String::find( const String& str, std::size_t start ) const
+{
+ return mString.find( str.mString, start );
+}
+
+std::size_t String::find ( const char* s, std::size_t pos, std::size_t n ) const
+{
+ return find( String( s ), pos );
+}
+
+std::size_t String::find ( const char* s, std::size_t pos ) const
+{
+ return find( String( s ), pos );
+}
+
+size_t String::find ( char c, std::size_t pos ) const
+{
+ return mString.find( (StringBaseType)c, pos );
+}
+
+std::size_t String::rfind ( const String& str, std::size_t pos ) const
+{
+ return mString.rfind( str.mString, pos );
+}
+
+std::size_t String::rfind ( const char* s, std::size_t pos, std::size_t n ) const
+{
+ return rfind( String( s ), pos );
+}
+
+std::size_t String::rfind ( const char* s, std::size_t pos ) const
+{
+ return rfind( String( s ), pos );
+}
+
+std::size_t String::rfind ( char c, std::size_t pos ) const
+{
+ return mString.rfind( c, pos );
+}
+
+std::size_t String::copy ( StringBaseType* s, std::size_t n, std::size_t pos ) const
+{
+ return mString.copy( s, n, pos );
+}
+
+String String::substr ( std::size_t pos, std::size_t n ) const
+{
+ return String( mString.substr( pos, n ) );
+}
+
+int String::compare ( const String& str ) const
+{
+ return mString.compare( str.mString );
+}
+
+int String::compare ( const char* s ) const
+{
+ return compare( String( s ) );
+}
+
+int String::compare ( std::size_t pos1, std::size_t n1, const String& str ) const
+{
+ return mString.compare( pos1, n1, str.mString );
+}
+
+int String::compare ( std::size_t pos1, std::size_t n1, const char* s) const
+{
+ return compare( pos1, n1, String( s ) );
+}
+
+int String::compare ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ) const
+{
+ return mString.compare( pos1, n1, str.mString, pos2, n2 );
+}
+
+int String::compare ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2) const
+{
+ return compare( pos1, n1, String( s ), 0, n2 );
+}
+
+std::size_t String::find_first_of ( const String& str, std::size_t pos ) const
+{
+ return mString.find_first_of( str.mString, pos );
+}
+
+std::size_t String::find_first_of ( const char* s, std::size_t pos, std::size_t n ) const
+{
+ return find_first_of( String( s ), pos );
+}
+
+std::size_t String::find_first_of ( const char* s, std::size_t pos ) const
+{
+ return find_first_of( String( s ), pos );
+}
+
+std::size_t String::find_first_of ( StringBaseType c, std::size_t pos ) const
+{
+ return mString.find_first_of( c, pos );
+}
+
+std::size_t String::find_last_of ( const String& str, std::size_t pos ) const
+{
+ return mString.find_last_of( str.mString, pos );
+}
+
+std::size_t String::find_last_of ( const char* s, std::size_t pos, std::size_t n ) const
+{
+ return find_last_of( String( s ), pos );
+}
+
+std::size_t String::find_last_of ( const char* s, std::size_t pos ) const
+{
+ return find_last_of( String( s ), pos );
+}
+
+std::size_t String::find_last_of ( StringBaseType c, std::size_t pos) const
+{
+ return mString.find_last_of( c, pos );
+}
+
+std::size_t String::find_first_not_of ( const String& str, std::size_t pos ) const
+{
+ return mString.find_first_not_of( str.mString, pos );
+}
+
+std::size_t String::find_first_not_of ( const char* s, std::size_t pos, std::size_t n ) const
+{
+ return find_first_not_of( String( s ), pos );
+}
+
+std::size_t String::find_first_not_of ( const char* s, std::size_t pos ) const
+{
+ return find_first_not_of( String( s ), pos );
+}
+
+std::size_t String::find_first_not_of ( StringBaseType c, std::size_t pos ) const
+{
+ return mString.find_first_not_of( c, pos );
+}
+
+std::size_t String::find_last_not_of ( const String& str, std::size_t pos ) const
+{
+ return mString.find_last_not_of( str.mString, pos );
+}
+
+std::size_t String::find_last_not_of ( const char* s, std::size_t pos, std::size_t n ) const
+{
+ return find_last_not_of( String( s ), pos );
+}
+
+std::size_t String::find_last_not_of ( const char* s, std::size_t pos ) const
+{
+ return find_last_not_of( String( s ), pos );
+}
+
+std::size_t String::find_last_not_of ( StringBaseType c, std::size_t pos ) const
+{
+ return mString.find_last_not_of( c, pos );
+}
+
+bool operator ==(const String& left, const String& right)
+{
+ return left.mString == right.mString;
+}
+
+bool operator !=(const String& left, const String& right)
+{
+ return !(left == right);
+}
+
+bool operator <(const String& left, const String& right)
+{
+ return left.mString < right.mString;
+}
+
+bool operator >(const String& left, const String& right)
+{
+ return right < left;
+}
+
+bool operator <=(const String& left, const String& right)
+{
+ return !(right < left);
+}
+
+bool operator >=(const String& left, const String& right)
+{
+ return !(left < right);
+}
+
+String operator +(const String& left, const String& right)
+{
+ String string = left;
+ string += right;
+
+ return string;
+}
+
+}
diff --git a/dep/efsw/src/efsw/String.hpp b/dep/efsw/src/efsw/String.hpp
new file mode 100644
index 00000000000..ce7e3b75f89
--- /dev/null
+++ b/dep/efsw/src/efsw/String.hpp
@@ -0,0 +1,629 @@
+/** NOTE:
+* This code is based on the Utf implementation from SFML2. License zlib/png ( http://www.sfml-dev.org/license.php )
+* The class was modified to fit efsw own needs. This is not the original implementation from SFML2.
+* Functions and methods are the same that in std::string to facilitate portability.
+**/
+
+#ifndef EFSW_STRING_HPP
+#define EFSW_STRING_HPP
+
+#include <efsw/base.hpp>
+#include <locale>
+#include <string>
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+#include <fstream>
+#include <sstream>
+#include <vector>
+
+namespace efsw {
+
+/** @brief Utility string class that automatically handles conversions between types and encodings **/
+class String
+{
+ public :
+ typedef Uint32 StringBaseType;
+ typedef std::basic_string<StringBaseType> StringType;
+ typedef StringType::iterator Iterator; //! Iterator type
+ typedef StringType::const_iterator ConstIterator; //! Constant iterator type
+ typedef StringType::reverse_iterator ReverseIterator; //! Reverse Iterator type
+ typedef StringType::const_reverse_iterator ConstReverseIterator; //! Constant iterator type
+
+ static const std::size_t InvalidPos; ///< Represents an invalid position in the string
+
+ template <class T>
+ static std::string toStr(const T& i) {
+ std::ostringstream ss;
+ ss << i;
+ return ss.str();
+ }
+
+ /** Converts from a string to type */
+ template <class T>
+ static bool fromString(T& t, const std::string& s, std::ios_base& (*f)(std::ios_base&) = std::dec ) {
+ std::istringstream iss(s);
+ return !(iss >> f >> t).fail();
+ }
+
+ /** Converts from a String to type */
+ template <class T>
+ static bool fromString(T& t, const String& s, std::ios_base& (*f)(std::ios_base&) = std::dec ) {
+ std::istringstream iss( s.toUtf8() );
+ return !(iss >> f >> t).fail();
+ }
+
+ /** Split a string and hold it on a vector */
+ static std::vector < std::string > split( const std::string& str, const char& splitchar, const bool& pushEmptyString = false );
+
+ /** Split a string and hold it on a vector */
+ static std::vector < String > split( const String& str, const Uint32& splitchar, const bool& pushEmptyString = false );
+
+ /** Determine if a string starts with the string passed
+ ** @param start The substring expected to start
+ ** @param str The string to compare
+ ** @return -1 if the substring is no in str, otherwise the size of the substring
+ */
+ static int strStartsWith( const std::string& start, const std::string& str );
+
+ static int strStartsWith( const String& start, const String& str );
+
+ /** @brief Construct from an UTF-8 string to UTF-32 according
+ ** @param uf8String UTF-8 string to convert
+ **/
+ static String fromUtf8( const std::string& utf8String );
+
+ /** @brief Default constructor
+ ** This constructor creates an empty string.
+ **/
+ String();
+
+ /** @brief Construct from a single ANSI character and a locale
+ ** The source character is converted to UTF-32 according
+ ** to the given locale. If you want to use the current global
+ ** locale, rather use the other constructor.
+ ** @param ansiChar ANSI character to convert
+ ** @param locale Locale to use for conversion
+ **/
+ String( char ansiChar, const std::locale& locale = std::locale() );
+
+#ifndef EFSW_NO_WIDECHAR
+ /** @brief Construct from single wide character
+ ** @param wideChar Wide character to convert
+ **/
+ String( wchar_t wideChar );
+#endif
+
+ /** @brief Construct from single UTF-32 character
+ ** @param utf32Char UTF-32 character to convert
+ **/
+ String( StringBaseType utf32Char );
+
+ /** @brief Construct from an from a null-terminated C-style UTF-8 string to UTF-32
+ ** @param uf8String UTF-8 string to convert
+ **/
+ String( const char* uf8String );
+
+ /** @brief Construct from an UTF-8 string to UTF-32 according
+ ** @param uf8String UTF-8 string to convert
+ **/
+ String( const std::string& utf8String );
+
+ /** @brief Construct from a null-terminated C-style ANSI string and a locale
+ ** The source string is converted to UTF-32 according
+ ** to the given locale. If you want to use the current global
+ ** locale, rather use the other constructor.
+ ** @param ansiString ANSI string to convert
+ ** @param locale Locale to use for conversion
+ **/
+ String( const char* ansiString, const std::locale& locale );
+
+ /** @brief Construct from an ANSI string and a locale
+ ** The source string is converted to UTF-32 according
+ ** to the given locale. If you want to use the current global
+ ** locale, rather use the other constructor.
+ ** @param ansiString ANSI string to convert
+ ** @param locale Locale to use for conversion
+ **/
+ String( const std::string& ansiString, const std::locale& locale );
+
+#ifndef EFSW_NO_WIDECHAR
+ /** @brief Construct from null-terminated C-style wide string
+ ** @param wideString Wide string to convert
+ **/
+ String( const wchar_t* wideString );
+
+ /** @brief Construct from a wide string
+ ** @param wideString Wide string to convert
+ **/
+ String( const std::wstring& wideString );
+#endif
+
+ /** @brief Construct from a null-terminated C-style UTF-32 string
+ ** @param utf32String UTF-32 string to assign
+ **/
+ String( const StringBaseType* utf32String );
+
+ /** @brief Construct from an UTF-32 string
+ ** @param utf32String UTF-32 string to assign
+ **/
+ String( const StringType& utf32String );
+
+
+ /** @brief Copy constructor
+ ** @param str Instance to copy
+ **/
+ String( const String& str );
+
+ /** @brief Implicit cast operator to std::string (ANSI string)
+ ** The current global locale is used for conversion. If you
+ ** want to explicitely specify a locale, see toAnsiString.
+ ** Characters that do not fit in the target encoding are
+ ** discarded from the returned string.
+ ** This operator is defined for convenience, and is equivalent
+ ** to calling toAnsiString().
+ ** @return Converted ANSI string
+ ** @see toAnsiString, operator String
+ **/
+ operator std::string() const;
+
+ /** @brief Convert the unicode string to an ANSI string
+ ** The UTF-32 string is converted to an ANSI string in
+ ** the encoding defined by \a locale. If you want to use
+ ** the current global locale, see the other overload
+ ** of toAnsiString.
+ ** Characters that do not fit in the target encoding are
+ ** discarded from the returned string.
+ ** @param locale Locale to use for conversion
+ ** @return Converted ANSI string
+ ** @see toWideString, operator std::string
+ **/
+ std::string toAnsiString( const std::locale& locale = std::locale() ) const;
+
+#ifndef EFSW_NO_WIDECHAR
+ /** @brief Convert the unicode string to a wide string
+ ** Characters that do not fit in the target encoding are
+ ** discarded from the returned string.
+ ** @return Converted wide string
+ ** @see toAnsiString, operator String
+ **/
+ std::wstring toWideString() const;
+#endif
+
+ std::string toUtf8() const;
+
+ /** @brief Overload of assignment operator
+ ** @param right Instance to assign
+ ** @return Reference to self
+ **/
+ String& operator =(const String& right);
+
+ String& operator =( const StringBaseType& right );
+
+ /** @brief Overload of += operator to append an UTF-32 string
+ ** @param right String to append
+ ** @return Reference to self
+ **/
+ String& operator +=(const String& right);
+
+ String& operator +=( const StringBaseType& right );
+
+ /** @brief Overload of [] operator to access a character by its position
+ ** This function provides read-only access to characters.
+ ** Note: this function doesn't throw if \a index is out of range.
+ ** @param index Index of the character to get
+ ** @return Character at position \a index
+ **/
+ StringBaseType operator [](std::size_t index) const;
+
+ /** @brief Overload of [] operator to access a character by its position
+ ** This function provides read and write access to characters.
+ ** Note: this function doesn't throw if \a index is out of range.
+ ** @param index Index of the character to get
+ ** @return Reference to the character at position \a index
+ **/
+
+ StringBaseType& operator [](std::size_t index);
+
+ /** @brief Get character in string
+ ** Performs a range check, throwing an exception of type out_of_range in case that pos is not an actual position in the string.
+ ** @return The character at position pos in the string.
+ */
+ StringBaseType at( std::size_t index ) const;
+
+ /** @brief clear the string
+ ** This function removes all the characters from the string.
+ ** @see empty, erase
+ **/
+ void clear();
+
+ /** @brief Get the size of the string
+ ** @return Number of characters in the string
+ ** @see empty
+ **/
+ std::size_t size() const;
+
+ /** @see size() */
+ std::size_t length() const;
+
+ /** @brief Check whether the string is empty or not
+ ** @return True if the string is empty (i.e. contains no character)
+ ** @see clear, size
+ **/
+ bool empty() const;
+
+ /** @brief Erase one or more characters from the string
+ ** This function removes a sequence of \a count characters
+ ** starting from \a position.
+ ** @param position Position of the first character to erase
+ ** @param count Number of characters to erase
+ **/
+ void erase(std::size_t position, std::size_t count = 1);
+
+
+ /** @brief Insert one or more characters into the string
+ ** This function inserts the characters of \a str
+ ** into the string, starting from \a position.
+ ** @param position Position of insertion
+ ** @param str Characters to insert
+ **/
+ String& insert(std::size_t position, const String& str);
+
+ String& insert( std::size_t pos1, const String& str, std::size_t pos2, std::size_t n );
+
+ String& insert ( std::size_t pos1, const char* s, std::size_t n );
+
+ String& insert ( std::size_t pos1, const char* s );
+
+ String& insert ( std::size_t pos1, size_t n, char c );
+
+ Iterator insert ( Iterator p, char c );
+
+ void insert ( Iterator p, std::size_t n, char c );
+
+ template<class InputIterator>
+ void insert ( Iterator p, InputIterator first, InputIterator last )
+ {
+ mString.insert( p, first, last );
+ }
+
+ /** @brief Find a sequence of one or more characters in the string
+ ** This function searches for the characters of \a str
+ ** into the string, starting from \a start.
+ ** @param str Characters to find
+ ** @param start Where to begin searching
+ ** @return Position of \a str in the string, or String::InvalidPos if not found
+ **/
+ std::size_t find( const String& str, std::size_t start = 0 ) const;
+
+ std::size_t find ( const char* s, std::size_t pos, std::size_t n ) const;
+
+ std::size_t find ( const char* s, std::size_t pos = 0 ) const;
+
+ std::size_t find ( char c, std::size_t pos = 0 ) const;
+
+ /** @brief Get a pointer to the C-style array of characters
+ ** This functions provides a read-only access to a
+ ** null-terminated C-style representation of the string.
+ ** The returned pointer is temporary and is meant only for
+ ** immediate use, thus it is not recommended to store it.
+ ** @return Read-only pointer to the array of characters
+ **/
+ const StringBaseType* c_str() const;
+
+ /** @brief Get string data
+ ** Notice that no terminating null character is appended (see member c_str for such a functionality).
+ ** The returned array points to an internal location which should not be modified directly in the program.
+ ** Its contents are guaranteed to remain unchanged only until the next call to a non-constant member function of the string object.
+ ** @return Pointer to an internal array containing the same content as the string.
+ **/
+ const StringBaseType* data() const;
+
+ /** @brief Return an iterator to the beginning of the string
+ ** @return Read-write iterator to the beginning of the string characters
+ ** @see end
+ **/
+ Iterator begin();
+
+ /** @brief Return an iterator to the beginning of the string
+ ** @return Read-only iterator to the beginning of the string characters
+ ** @see end
+ **/
+ ConstIterator begin() const;
+
+ /** @brief Return an iterator to the beginning of the string
+ ** The end iterator refers to 1 position past the last character;
+ ** thus it represents an invalid character and should never be
+ ** accessed.
+ ** @return Read-write iterator to the end of the string characters
+ ** @see begin
+ **/
+ Iterator end();
+
+ /** @brief Return an iterator to the beginning of the string
+ ** The end iterator refers to 1 position past the last character;
+ ** thus it represents an invalid character and should never be
+ ** accessed.
+ ** @return Read-only iterator to the end of the string characters
+ ** @see begin
+ **/
+ ConstIterator end() const;
+
+ /** @brief Return an reverse iterator to the beginning of the string
+ ** @return Read-write reverse iterator to the beginning of the string characters
+ ** @see end
+ **/
+ ReverseIterator rbegin();
+
+ /** @brief Return an reverse iterator to the beginning of the string
+ ** @return Read-only reverse iterator to the beginning of the string characters
+ ** @see end
+ **/
+ ConstReverseIterator rbegin() const;
+
+ /** @brief Return an reverse iterator to the beginning of the string
+ ** The end reverse iterator refers to 1 position past the last character;
+ ** thus it represents an invalid character and should never be
+ ** accessed.
+ ** @return Read-write reverse iterator to the end of the string characters
+ ** @see begin
+ **/
+ ReverseIterator rend();
+
+
+ /** @brief Return an reverse iterator to the beginning of the string
+ ** The end reverse iterator refers to 1 position past the last character;
+ ** thus it represents an invalid character and should never be
+ ** accessed.
+ ** @return Read-only reverse iterator to the end of the string characters
+ ** @see begin
+ **/
+ ConstReverseIterator rend() const;
+
+ /** @brief Resize String */
+ void resize ( std::size_t n, StringBaseType c );
+
+ /** @brief Resize String */
+ void resize ( std::size_t n );
+
+ /** @return Maximum size of string */
+ std::size_t max_size() const;
+
+ /** @brief Request a change in capacity */
+ void reserve ( size_t res_arg=0 );
+
+ /** @return Size of allocated storage */
+ std::size_t capacity() const;
+
+ /** @brief Append character to string */
+ void push_back( StringBaseType c );
+
+ /** @brief Swap contents with another string */
+ void swap ( String& str );
+
+ String& assign ( const String& str );
+
+ String& assign ( const String& str, std::size_t pos, std::size_t n );
+
+ String& assign ( const char* s, std::size_t n );
+
+ String& assign ( const char* s );
+
+ String& assign ( std::size_t n, char c );
+
+ template <class InputIterator>
+ String& assign ( InputIterator first, InputIterator last )
+ {
+ mString.assign( first, last );
+ return *this;
+ }
+
+ String& append ( const String& str );
+
+ String& append ( const String& str, std::size_t pos, std::size_t n );
+
+ String& append ( const char* s, std::size_t n );
+
+ String& append ( const char* s );
+
+ String& append ( std::size_t n, char c );
+
+ String& append ( std::size_t n, StringBaseType c );
+
+ template <class InputIterator>
+ String& append ( InputIterator first, InputIterator last )
+ {
+ mString.append( first, last );
+ return *this;
+ }
+
+ String& replace ( std::size_t pos1, std::size_t n1, const String& str );
+
+ String& replace ( Iterator i1, Iterator i2, const String& str );
+
+ String& replace ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 );
+
+ String& replace ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2 );
+
+ String& replace ( Iterator i1, Iterator i2, const char* s, std::size_t n2 );
+
+ String& replace ( std::size_t pos1, std::size_t n1, const char* s );
+
+ String& replace ( Iterator i1, Iterator i2, const char* s );
+
+ String& replace ( std::size_t pos1, std::size_t n1, std::size_t n2, char c );
+
+ String& replace ( Iterator i1, Iterator i2, std::size_t n2, char c );
+
+ template<class InputIterator>
+ String& replace ( Iterator i1, Iterator i2, InputIterator j1, InputIterator j2 )
+ {
+ mString.replace( i1, i2, j1, j2 );
+ return *this;
+ }
+
+ std::size_t rfind ( const String& str, std::size_t pos = StringType::npos ) const;
+
+ std::size_t rfind ( const char* s, std::size_t pos, std::size_t n ) const;
+
+ std::size_t rfind ( const char* s, std::size_t pos = StringType::npos ) const;
+
+ std::size_t rfind ( char c, std::size_t pos = StringType::npos ) const;
+
+ String substr ( std::size_t pos = 0, std::size_t n = StringType::npos ) const;
+
+ std::size_t copy ( StringBaseType* s, std::size_t n, std::size_t pos = 0 ) const;
+
+ int compare ( const String& str ) const;
+
+ int compare ( const char* s ) const;
+
+ int compare ( std::size_t pos1, std::size_t n1, const String& str ) const;
+
+ int compare ( std::size_t pos1, std::size_t n1, const char* s) const;
+
+ int compare ( std::size_t pos1, std::size_t n1, const String& str, std::size_t pos2, std::size_t n2 ) const;
+
+ int compare ( std::size_t pos1, std::size_t n1, const char* s, std::size_t n2) const;
+
+ std::size_t find_first_of ( const String& str, std::size_t pos = 0 ) const;
+
+ std::size_t find_first_of ( const char* s, std::size_t pos, std::size_t n ) const;
+
+ std::size_t find_first_of ( const char* s, std::size_t pos = 0 ) const;
+
+ std::size_t find_first_of ( StringBaseType c, std::size_t pos = 0 ) const;
+
+ std::size_t find_last_of ( const String& str, std::size_t pos = StringType::npos ) const;
+
+ std::size_t find_last_of ( const char* s, std::size_t pos, std::size_t n ) const;
+
+ std::size_t find_last_of ( const char* s, std::size_t pos = StringType::npos ) const;
+
+ std::size_t find_last_of ( StringBaseType c, std::size_t pos = StringType::npos ) const;
+
+ std::size_t find_first_not_of ( const String& str, std::size_t pos = 0 ) const;
+
+ std::size_t find_first_not_of ( const char* s, std::size_t pos, std::size_t n ) const;
+
+ std::size_t find_first_not_of ( const char* s, std::size_t pos = 0 ) const;
+
+ std::size_t find_first_not_of ( StringBaseType c, std::size_t pos = 0 ) const;
+
+ std::size_t find_last_not_of ( const String& str, std::size_t pos = StringType::npos ) const;
+
+ std::size_t find_last_not_of ( const char* s, std::size_t pos, std::size_t n ) const;
+
+ std::size_t find_last_not_of ( const char* s, std::size_t pos = StringType::npos ) const;
+
+ std::size_t find_last_not_of ( StringBaseType c, std::size_t pos = StringType::npos ) const;
+private :
+ friend bool operator ==(const String& left, const String& right);
+ friend bool operator <(const String& left, const String& right);
+
+ StringType mString; ///< Internal string of UTF-32 characters
+};
+
+/** @relates String
+** @brief Overload of == operator to compare two UTF-32 strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return True if both strings are equal
+**/
+ bool operator ==(const String& left, const String& right);
+
+/** @relates String
+** @brief Overload of != operator to compare two UTF-32 strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return True if both strings are different
+**/
+ bool operator !=(const String& left, const String& right);
+
+/** @relates String
+** @brief Overload of < operator to compare two UTF-32 strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return True if \a left is alphabetically lesser than \a right
+**/
+ bool operator <(const String& left, const String& right);
+
+/** @relates String
+** @brief Overload of > operator to compare two UTF-32 strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return True if \a left is alphabetically greater than \a right
+**/
+ bool operator >(const String& left, const String& right);
+
+/** @relates String
+** @brief Overload of <= operator to compare two UTF-32 strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return True if \a left is alphabetically lesser or equal than \a right
+**/
+ bool operator <=(const String& left, const String& right);
+
+/** @relates String
+** @brief Overload of >= operator to compare two UTF-32 strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return True if \a left is alphabetically greater or equal than \a right
+**/
+ bool operator >=(const String& left, const String& right);
+
+/** @relates String
+** @brief Overload of binary + operator to concatenate two strings
+** @param left Left operand (a string)
+** @param right Right operand (a string)
+** @return Concatenated string
+**/
+ String operator +( const String& left, const String& right );
+
+}
+
+#endif
+
+/** @class efsw::String
+** @ingroup system
+** efsw::String is a utility string class defined mainly for
+** convenience. It is a Unicode string (implemented using
+** UTF-32), thus it can store any character in the world
+** (european, chinese, arabic, hebrew, etc.).
+** It automatically handles conversions from/to ANSI and
+** wide strings, so that you can work with standard string
+** classes and still be compatible with functions taking a
+** efsw::String.
+** @code
+** efsw::String s;
+** std::string s1 = s; // automatically converted to ANSI string
+** String s2 = s; // automatically converted to wide string
+** s = "hello"; // automatically converted from ANSI string
+** s = L"hello"; // automatically converted from wide string
+** s += 'a'; // automatically converted from ANSI string
+** s += L'a'; // automatically converted from wide string
+** @endcode
+** Conversions involving ANSI strings use the default user locale. However
+** it is possible to use a custom locale if necessary:
+** @code
+** std::locale locale;
+** efsw::String s;
+** ...
+** std::string s1 = s.toAnsiString(locale);
+** s = efsw::String("hello", locale);
+** @endcode
+**
+** efsw::String defines the most important functions of the
+** standard std::string class: removing, random access, iterating,
+** appending, comparing, etc. However it is a simple class
+** provided for convenience, and you may have to consider using
+** a more optimized class if your program requires complex string
+** handling. The automatic conversion functions will then take
+** care of converting your string to efsw::String whenever EE
+** requires it.
+**
+** Please note that EE also defines a low-level, generic
+** interface for Unicode handling, see the efsw::Utf classes.
+**
+** All credits to Laurent Gomila, i just modified and expanded a little bit the implementation.
+**/
diff --git a/dep/efsw/src/efsw/System.cpp b/dep/efsw/src/efsw/System.cpp
new file mode 100644
index 00000000000..f8767cbc58f
--- /dev/null
+++ b/dep/efsw/src/efsw/System.cpp
@@ -0,0 +1,26 @@
+#include <efsw/System.hpp>
+#include <efsw/platform/platformimpl.hpp>
+
+namespace efsw {
+
+void System::sleep( const unsigned long& ms )
+{
+ Platform::System::sleep( ms );
+}
+
+std::string System::getProcessPath()
+{
+ return Platform::System::getProcessPath();
+}
+
+void System::maxFD()
+{
+ Platform::System::maxFD();
+}
+
+Uint64 System::getMaxFD()
+{
+ return Platform::System::getMaxFD();
+}
+
+}
diff --git a/dep/efsw/src/efsw/System.hpp b/dep/efsw/src/efsw/System.hpp
new file mode 100644
index 00000000000..1d6f4a70f91
--- /dev/null
+++ b/dep/efsw/src/efsw/System.hpp
@@ -0,0 +1,26 @@
+#ifndef EFSW_SYSTEM_HPP
+#define EFSW_SYSTEM_HPP
+
+#include <efsw/base.hpp>
+
+namespace efsw {
+
+class System
+{
+ public:
+ /// Sleep for x milliseconds
+ static void sleep( const unsigned long& ms );
+
+ /// @return The process binary path
+ static std::string getProcessPath();
+
+ /// Maximize the number of file descriptors allowed per process in the current OS
+ static void maxFD();
+
+ /// @return The number of supported file descriptors for the process
+ static Uint64 getMaxFD();
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/Thread.cpp b/dep/efsw/src/efsw/Thread.cpp
new file mode 100644
index 00000000000..fff41517dc1
--- /dev/null
+++ b/dep/efsw/src/efsw/Thread.cpp
@@ -0,0 +1,51 @@
+#include <efsw/Thread.hpp>
+#include <efsw/platform/platformimpl.hpp>
+
+namespace efsw {
+
+Thread::Thread() :
+ mThreadImpl(NULL),
+ mEntryPoint(NULL)
+{
+}
+
+Thread::~Thread()
+{
+ wait();
+
+ efSAFE_DELETE( mEntryPoint );
+}
+
+void Thread::launch()
+{
+ wait();
+
+ mThreadImpl = new Platform::ThreadImpl( this );
+}
+
+void Thread::wait()
+{
+ if ( mThreadImpl )
+ {
+ mThreadImpl->wait();
+
+ efSAFE_DELETE( mThreadImpl );
+ }
+}
+
+void Thread::terminate()
+{
+ if ( mThreadImpl )
+ {
+ mThreadImpl->terminate();
+
+ efSAFE_DELETE( mThreadImpl );
+ }
+}
+
+void Thread::run()
+{
+ mEntryPoint->run();
+}
+
+}
diff --git a/dep/efsw/src/efsw/Thread.hpp b/dep/efsw/src/efsw/Thread.hpp
new file mode 100644
index 00000000000..c7da9e8b33c
--- /dev/null
+++ b/dep/efsw/src/efsw/Thread.hpp
@@ -0,0 +1,111 @@
+#ifndef EFSW_THREAD_HPP
+#define EFSW_THREAD_HPP
+
+#include <efsw/base.hpp>
+
+namespace efsw {
+
+namespace Platform { class ThreadImpl; }
+namespace Private { struct ThreadFunc; }
+
+/** @brief Thread manager class */
+class Thread {
+ public:
+ typedef void (*FuncType)(void*);
+
+ template <typename F>
+ Thread( F function );
+
+ template <typename F, typename A>
+ Thread( F function, A argument );
+
+ template <typename C>
+ Thread( void(C::*function)(), C* object );
+
+ virtual ~Thread();
+
+ /** Launch the thread */
+ virtual void launch();
+
+ /** Wait the thread until end */
+ void wait();
+
+ /** Terminate the thread */
+ void terminate();
+ protected:
+ Thread();
+ private:
+ friend class Platform::ThreadImpl;
+
+ /** The virtual function to run in the thread */
+ virtual void run();
+
+ Platform::ThreadImpl * mThreadImpl; ///< OS-specific implementation of the thread
+ Private::ThreadFunc * mEntryPoint; ///< Abstraction of the function to run
+};
+
+//! NOTE: Taken from SFML2 threads
+namespace Private {
+
+// Base class for abstract thread functions
+struct ThreadFunc
+{
+ virtual ~ThreadFunc() {}
+ virtual void run() = 0;
+};
+
+// Specialization using a functor (including free functions) with no argument
+template <typename T>
+struct ThreadFunctor : ThreadFunc
+{
+ ThreadFunctor(T functor) : m_functor(functor) {}
+ virtual void run() {m_functor();}
+ T m_functor;
+};
+
+// Specialization using a functor (including free functions) with one argument
+template <typename F, typename A>
+struct ThreadFunctorWithArg : ThreadFunc
+{
+ ThreadFunctorWithArg(F function, A arg) : m_function(function), m_arg(arg) {}
+ virtual void run() {m_function(m_arg);}
+ F m_function;
+ A m_arg;
+};
+
+// Specialization using a member function
+template <typename C>
+struct ThreadMemberFunc : ThreadFunc
+{
+ ThreadMemberFunc(void(C::*function)(), C* object) : m_function(function), m_object(object) {}
+ virtual void run() {(m_object->*m_function)();}
+ void(C::*m_function)();
+ C* m_object;
+};
+
+}
+
+template <typename F>
+Thread::Thread(F functor) :
+ mThreadImpl (NULL),
+ mEntryPoint( new Private::ThreadFunctor<F>(functor) )
+{
+}
+
+template <typename F, typename A>
+Thread::Thread(F function, A argument) :
+ mThreadImpl(NULL),
+ mEntryPoint( new Private::ThreadFunctorWithArg<F efCOMMA A>(function, argument) )
+{
+}
+
+template <typename C>
+Thread::Thread(void(C::*function)(), C* object) :
+ mThreadImpl(NULL),
+ mEntryPoint( new Private::ThreadMemberFunc<C>(function, object) )
+{
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/Utf.hpp b/dep/efsw/src/efsw/Utf.hpp
new file mode 100644
index 00000000000..925a7cc149b
--- /dev/null
+++ b/dep/efsw/src/efsw/Utf.hpp
@@ -0,0 +1,748 @@
+/** NOTE:
+* This code is based on the Utf implementation from SFML2. License zlib/png ( http://www.sfml-dev.org/license.php )
+* The class was modified to fit efsw own needs. This is not the original implementation from SFML2.
+* */
+
+#ifndef EFSW_UTF_HPP
+#define EFSW_UTF_HPP
+
+////////////////////////////////////////////////////////////
+// Headers
+////////////////////////////////////////////////////////////
+#include <locale>
+#include <string>
+#include <cstdlib>
+#include <efsw/base.hpp>
+
+namespace efsw {
+
+template <unsigned int N>
+class Utf;
+
+////////////////////////////////////////////////////////////
+/// \brief Specialization of the Utf template for UTF-8
+///
+////////////////////////////////////////////////////////////
+template <>
+class Utf<8> {
+public :
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-8 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-8 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-8 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-8.
+ ///
+ /// \param input Codepoint to encode as UTF-8
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-8 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint8 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-8 character
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-8 sequence
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element, thus the
+ /// total size can be different from (begin - end).
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-8
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+#ifndef EFSW_NO_WIDECHAR
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+#endif
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-8 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-8
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the efsw::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out toUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-8 characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+};
+
+////////////////////////////////////////////////////////////
+/// \brief Specialization of the Utf template for UTF-16
+///
+////////////////////////////////////////////////////////////
+template <>
+class Utf<16>
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-16 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-16 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-16 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-16.
+ ///
+ /// \param input Codepoint to encode as UTF-16
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-16 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint16 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-16 character
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-16 sequence
+ ///
+ /// This function is necessary for multi-elements encodings, as
+ /// a single character may use more than 1 storage element, thus the
+ /// total size can be different from (begin - end).
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-16
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+#ifndef EFSW_NO_WIDECHAR
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+#endif
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out toUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-16
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the efsw::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-16 characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+};
+
+////////////////////////////////////////////////////////////
+/// \brief Specialization of the Utf template for UTF-32
+///
+////////////////////////////////////////////////////////////
+template <>
+class Utf<32>
+{
+public :
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single UTF-32 character
+ ///
+ /// Decoding a character means finding its unique 32-bits
+ /// code (called the codepoint) in the Unicode standard.
+ /// For UTF-32, the character value is the same as the codepoint.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Codepoint of the decoded UTF-32 character
+ /// \param replacement Replacement character to use in case the UTF-8 sequence is invalid
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Decode(In begin, In end, Uint32& output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character
+ ///
+ /// Encoding a character means converting a unique 32-bits
+ /// code (called the codepoint) in the target encoding, UTF-32.
+ /// For UTF-32, the codepoint is the same as the character value.
+ ///
+ /// \param input Codepoint to encode as UTF-32
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to UTF-32 (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out Encode(Uint32 input, Out output, Uint32 replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Advance to the next UTF-32 character
+ ///
+ /// This function is trivial for UTF-32, which can store
+ /// every character in a single storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static In Next(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Count the number of characters of a UTF-32 sequence
+ ///
+ /// This function is trivial for UTF-32, which can store
+ /// every character in a single storage element.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ ///
+ /// \return Iterator pointing to one past the last read element of the input sequence
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static std::size_t Count(In begin, In end);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an ANSI characters range to UTF-32
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromAnsi(In begin, In end, Out output, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a wide characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromWide(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a latin-1 (ISO-5589-1) characters range to UTF-32
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out FromLatin1(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-32 characters range to ANSI characters
+ ///
+ /// The current global locale will be used by default, unless you
+ /// pass a custom one in the \a locale parameter.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to ANSI (use 0 to skip them)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToAnsi(In begin, In end, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+#ifndef EFSW_NO_WIDECHAR
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-32 characters range to wide characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToWide(In begin, In end, Out output, wchar_t replacement = 0);
+#endif
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert an UTF-16 characters range to latin-1 (ISO-5589-1) characters
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement for characters not convertible to wide (use 0 to skip them)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToLatin1(In begin, In end, Out output, char replacement = 0);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-8
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out toUtf8(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-16
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf16(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Convert a UTF-32 characters range to UTF-32
+ ///
+ /// This functions does nothing more than a direct copy;
+ /// it is defined only to provide the same interface as other
+ /// specializations of the efsw::Utf<> template, and allow
+ /// generic code to be written on top of it.
+ ///
+ /// \param begin Iterator pointing to the beginning of the input sequence
+ /// \param end Iterator pointing to the end of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In, typename Out>
+ static Out ToUtf32(In begin, In end, Out output);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single ANSI character to UTF-32
+ ///
+ /// This function does not exist in other specializations
+ /// of efsw::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param input Input ANSI character
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Converted character
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static Uint32 DecodeAnsi(In input, const std::locale& locale = std::locale());
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Decode a single wide character to UTF-32
+ ///
+ /// This function does not exist in other specializations
+ /// of efsw::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param input Input wide character
+ ///
+ /// \return Converted character
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename In>
+ static Uint32 DecodeWide(In input);
+
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character to ANSI
+ ///
+ /// This function does not exist in other specializations
+ /// of efsw::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param codepoint Iterator pointing to the beginning of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement if the input character is not convertible to ANSI (use 0 to skip it)
+ /// \param locale Locale to use for conversion
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out EncodeAnsi(Uint32 codepoint, Out output, char replacement = 0, const std::locale& locale = std::locale());
+
+#ifndef EFSW_NO_WIDECHAR
+ ////////////////////////////////////////////////////////////
+ /// \brief Encode a single UTF-32 character to wide
+ ///
+ /// This function does not exist in other specializations
+ /// of efsw::Utf<>, it is defined for convenience (it is used by
+ /// several other conversion functions).
+ ///
+ /// \param codepoint Iterator pointing to the beginning of the input sequence
+ /// \param output Iterator pointing to the beginning of the output sequence
+ /// \param replacement Replacement if the input character is not convertible to wide (use 0 to skip it)
+ ///
+ /// \return Iterator to the end of the output sequence which has been written
+ ///
+ ////////////////////////////////////////////////////////////
+ template <typename Out>
+ static Out EncodeWide(Uint32 codepoint, Out output, wchar_t replacement = 0);
+#endif
+};
+
+#include "Utf.inl"
+
+// Make typedefs to get rid of the template syntax
+typedef Utf<8> Utf8;
+typedef Utf<16> Utf16;
+typedef Utf<32> Utf32;
+
+}
+#endif
+
+////////////////////////////////////////////////////////////
+/// \class efsw::Utf
+/// \ingroup system
+///
+/// Utility class providing generic functions for UTF conversions.
+///
+/// efsw::Utf is a low-level, generic interface for counting, iterating,
+/// encoding and decoding Unicode characters and strings. It is able
+/// to handle ANSI, wide, UTF-8, UTF-16 and UTF-32 encodings.
+///
+/// efsw::Utf<X> functions are all static, these classes are not meant to
+/// be instanciated. All the functions are template, so that you
+/// can use any character / string type for a given encoding.
+///
+/// It has 3 specializations:
+/// \li efsw::Utf<8> (typedef'd to efsw::Utf8)
+/// \li efsw::Utf<16> (typedef'd to efsw::Utf16)
+/// \li efsw::Utf<32> (typedef'd to efsw::Utf32)
+///
+////////////////////////////////////////////////////////////
diff --git a/dep/efsw/src/efsw/Utf.inl b/dep/efsw/src/efsw/Utf.inl
new file mode 100644
index 00000000000..db8fd5d61ee
--- /dev/null
+++ b/dep/efsw/src/efsw/Utf.inl
@@ -0,0 +1,671 @@
+// References :
+// http://www.unicode.org/
+// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.c
+// http://www.unicode.org/Public/PROGRAMS/CVTUTF/ConvertUTF.h
+// http://people.w3.org/rishida/scripts/uniview/conversion
+////////////////////////////////////////////////////////////
+
+template <typename In>
+In Utf<8>::Decode(In begin, In end, Uint32& output, Uint32 replacement)
+{
+ // Some useful precomputed data
+ static const int trailing[256] =
+ {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5
+ };
+ static const Uint32 offsets[6] =
+ {
+ 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080
+ };
+
+ // Decode the character
+ int trailingBytes = trailing[static_cast<Uint8>(*begin)];
+ if (begin + trailingBytes < end)
+ {
+ output = 0;
+ switch (trailingBytes)
+ {
+ case 5 : output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 4 : output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 3 : output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 2 : output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 1 : output += static_cast<Uint8>(*begin++); output <<= 6;
+ case 0 : output += static_cast<Uint8>(*begin++);
+ }
+ output -= offsets[trailingBytes];
+ }
+ else
+ {
+ // Incomplete character
+ begin = end;
+ output = replacement;
+ }
+
+ return begin;
+}
+
+template <typename Out>
+Out Utf<8>::Encode(Uint32 input, Out output, Uint8 replacement)
+{
+ // Some useful precomputed data
+ static const Uint8 firstBytes[7] =
+ {
+ 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
+ };
+
+ // Encode the character
+ if ((input > 0x0010FFFF) || ((input >= 0xD800) && (input <= 0xDBFF)))
+ {
+ // Invalid character
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // Valid character
+
+ // Get the number of bytes to write
+ int bytesToWrite = 1;
+ if (input < 0x80) bytesToWrite = 1;
+ else if (input < 0x800) bytesToWrite = 2;
+ else if (input < 0x10000) bytesToWrite = 3;
+ else if (input <= 0x0010FFFF) bytesToWrite = 4;
+
+ // Extract the bytes to write
+ Uint8 bytes[4];
+ switch (bytesToWrite)
+ {
+ case 4 : bytes[3] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 3 : bytes[2] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 2 : bytes[1] = static_cast<Uint8>((input | 0x80) & 0xBF); input >>= 6;
+ case 1 : bytes[0] = static_cast<Uint8> (input | firstBytes[bytesToWrite]);
+ }
+
+ // Add them to the output
+ const Uint8* currentByte = bytes;
+ switch (bytesToWrite)
+ {
+ case 4 : *output++ = *currentByte++;
+ case 3 : *output++ = *currentByte++;
+ case 2 : *output++ = *currentByte++;
+ case 1 : *output++ = *currentByte++;
+ }
+ }
+
+ return output;
+}
+
+template <typename In>
+In Utf<8>::Next(In begin, In end)
+{
+ Uint32 codepoint;
+ return Decode(begin, end, codepoint);
+}
+
+template <typename In>
+std::size_t Utf<8>::Count(In begin, In end)
+{
+ std::size_t length = 0;
+ while (begin < end)
+ {
+ begin = Next(begin, end);
+ ++length;
+ }
+
+ return length;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeWide(*begin++);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ output = Encode(*begin++, output);
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale);
+ }
+
+ return output;
+}
+
+#ifndef EFSW_NO_WIDECHAR
+template <typename In, typename Out>
+Out Utf<8>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeWide(codepoint, output, replacement);
+ }
+
+ return output;
+}
+#endif
+
+template <typename In, typename Out>
+Out Utf<8>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint < 256 ? static_cast<char>(codepoint) : replacement;
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::toUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ *output++ = *begin++;
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<16>::Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<8>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint;
+ }
+
+ return output;
+}
+
+template <typename In>
+In Utf<16>::Decode(In begin, In end, Uint32& output, Uint32 replacement)
+{
+ Uint16 first = *begin++;
+
+ // If it's a surrogate pair, first convert to a single UTF-32 character
+ if ((first >= 0xD800) && (first <= 0xDBFF))
+ {
+ if (begin < end)
+ {
+ Uint32 second = *begin++;
+ if ((second >= 0xDC00) && (second <= 0xDFFF))
+ {
+ // The second element is valid: convert the two elements to a UTF-32 character
+ output = static_cast<Uint32>(((first - 0xD800) << 10) + (second - 0xDC00) + 0x0010000);
+ }
+ else
+ {
+ // Invalid character
+ output = replacement;
+ }
+ }
+ else
+ {
+ // Invalid character
+ begin = end;
+ output = replacement;
+ }
+ }
+ else
+ {
+ // We can make a direct copy
+ output = first;
+ }
+
+ return begin;
+}
+
+template <typename Out>
+Out Utf<16>::Encode(Uint32 input, Out output, Uint16 replacement)
+{
+ if (input < 0xFFFF)
+ {
+ // The character can be copied directly, we just need to check if it's in the valid range
+ if ((input >= 0xD800) && (input <= 0xDFFF))
+ {
+ // Invalid character (this range is reserved)
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // Valid character directly convertible to a single UTF-16 character
+ *output++ = static_cast<Uint16>(input);
+ }
+ }
+ else if (input > 0x0010FFFF)
+ {
+ // Invalid character (greater than the maximum unicode value)
+ if (replacement)
+ *output++ = replacement;
+ }
+ else
+ {
+ // The input character will be converted to two UTF-16 elements
+ input -= 0x0010000;
+ *output++ = static_cast<Uint16>((input >> 10) + 0xD800);
+ *output++ = static_cast<Uint16>((input & 0x3FFUL) + 0xDC00);
+ }
+
+ return output;
+}
+
+template <typename In>
+In Utf<16>::Next(In begin, In end)
+{
+ Uint32 codepoint;
+ return Decode(begin, end, codepoint);
+}
+
+template <typename In>
+std::size_t Utf<16>::Count(In begin, In end)
+{
+ std::size_t length = 0;
+ while (begin < end)
+ {
+ begin = Next(begin, end);
+ ++length;
+ }
+
+ return length;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeAnsi(*begin++, locale);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint = Utf<32>::DecodeWide(*begin++);
+ output = Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ *output++ = *begin++;
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeAnsi(codepoint, output, replacement, locale);
+ }
+
+ return output;
+}
+
+#ifndef EFSW_NO_WIDECHAR
+template <typename In, typename Out>
+Out Utf<16>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<32>::EncodeWide(codepoint, output, replacement);
+ }
+
+ return output;
+}
+#endif
+
+template <typename In, typename Out>
+Out Utf<16>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
+ begin++;
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::toUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ output = Utf<8>::Encode(codepoint, output);
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ *output++ = *begin++;
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<16>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ {
+ Uint32 codepoint;
+ begin = Decode(begin, end, codepoint);
+ *output++ = codepoint;
+ }
+
+ return output;
+}
+
+template <typename In>
+In Utf<32>::Decode(In begin, In end, Uint32& output, Uint32)
+{
+ output = *begin++;
+ return begin;
+}
+
+template <typename Out>
+Out Utf<32>::Encode(Uint32 input, Out output, Uint32 replacement)
+{
+ *output++ = input;
+ return output;
+}
+
+template <typename In>
+In Utf<32>::Next(In begin, In end)
+{
+ return ++begin;
+}
+
+template <typename In>
+std::size_t Utf<32>::Count(In begin, In end)
+{
+ return begin - end;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::FromAnsi(In begin, In end, Out output, const std::locale& locale)
+{
+ while (begin < end)
+ *output++ = DecodeAnsi(*begin++, locale);
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::FromWide(In begin, In end, Out output)
+{
+ while (begin < end)
+ *output++ = DecodeWide(*begin++);
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::FromLatin1(In begin, In end, Out output)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ *output++ = *begin++;
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::ToAnsi(In begin, In end, Out output, char replacement, const std::locale& locale)
+{
+ while (begin < end)
+ output = EncodeAnsi(*begin++, output, replacement, locale);
+
+ return output;
+}
+
+#ifndef EFSW_NO_WIDECHAR
+template <typename In, typename Out>
+Out Utf<32>::ToWide(In begin, In end, Out output, wchar_t replacement)
+{
+ while (begin < end)
+ output = EncodeWide(*begin++, output, replacement);
+
+ return output;
+}
+#endif
+
+template <typename In, typename Out>
+Out Utf<32>::ToLatin1(In begin, In end, Out output, char replacement)
+{
+ // Latin-1 is directly compatible with Unicode encodings,
+ // and can thus be treated as (a sub-range of) UTF-32
+ while (begin < end)
+ {
+ *output++ = *begin < 256 ? static_cast<char>(*begin) : replacement;
+ begin++;
+ }
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::toUtf8(In begin, In end, Out output)
+{
+ while (begin < end)
+ output = Utf<8>::Encode(*begin++, output);
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::ToUtf16(In begin, In end, Out output)
+{
+ while (begin < end)
+ output = Utf<16>::Encode(*begin++, output);
+
+ return output;
+}
+
+template <typename In, typename Out>
+Out Utf<32>::ToUtf32(In begin, In end, Out output)
+{
+ while (begin < end)
+ *output++ = *begin++;
+
+ return output;
+}
+
+template <typename In>
+Uint32 Utf<32>::DecodeAnsi(In input, const std::locale& locale)
+{
+ // On Windows, gcc's standard library (glibc++) has almost
+ // no support for Unicode stuff. As a consequence, in this
+ // context we can only use the default locale and ignore
+ // the one passed as parameter.
+
+ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \
+ (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
+ !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
+
+ wchar_t character = 0;
+ mbtowc(&character, &input, 1);
+ return static_cast<Uint32>(character);
+
+ #else
+ // Get the facet of the locale which deals with character conversion
+ #ifndef EFSW_NO_WIDECHAR
+ const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
+ #else
+ const std::ctype<char>& facet = std::use_facet< std::ctype<char> >(locale);
+ #endif
+
+ // Use the facet to convert each character of the input string
+ return static_cast<Uint32>(facet.widen(input));
+
+ #endif
+}
+
+template <typename In>
+Uint32 Utf<32>::DecodeWide(In input)
+{
+ // The encoding of wide characters is not well defined and is left to the system;
+ // however we can safely assume that it is UCS-2 on Windows and
+ // UCS-4 on Unix systems.
+ // In both cases, a simple copy is enough (UCS-2 is a subset of UCS-4,
+ // and UCS-4 *is* UTF-32).
+
+ return input;
+}
+
+template <typename Out>
+Out Utf<32>::EncodeAnsi(Uint32 codepoint, Out output, char replacement, const std::locale& locale)
+{
+ // On Windows, gcc's standard library (glibc++) has almost
+ // no support for Unicode stuff. As a consequence, in this
+ // context we can only use the default locale and ignore
+ // the one passed as parameter.
+
+ #if EFSW_PLATFORM == EFSW_PLATFORM_WIN && /* if Windows ... */ \
+ (defined(__GLIBCPP__) || defined (__GLIBCXX__)) && /* ... and standard library is glibc++ ... */ \
+ !(defined(__SGI_STL_PORT) || defined(_STLPORT_VERSION)) /* ... and STLPort is not used on top of it */
+
+ char character = 0;
+ if (wctomb(&character, static_cast<wchar_t>(codepoint)) >= 0)
+ *output++ = character;
+ else if (replacement)
+ *output++ = replacement;
+
+ return output;
+
+ #else
+ // Get the facet of the locale which deals with character conversion
+ #ifndef EFSW_NO_WIDECHAR
+ const std::ctype<wchar_t>& facet = std::use_facet< std::ctype<wchar_t> >(locale);
+ #else
+ const std::ctype<char>& facet = std::use_facet< std::ctype<char> >(locale);
+ #endif
+
+ // Use the facet to convert each character of the input string
+ *output++ = facet.narrow(static_cast<wchar_t>(codepoint), replacement);
+
+ return output;
+
+ #endif
+}
+
+#ifndef EFSW_NO_WIDECHAR
+template <typename Out>
+Out Utf<32>::EncodeWide(Uint32 codepoint, Out output, wchar_t replacement)
+{
+ // The encoding of wide characters is not well defined and is left to the system;
+ // however we can safely assume that it is UCS-2 on Windows and
+ // UCS-4 on Unix systems.
+ // For UCS-2 we need to check if the source characters fits in (UCS-2 is a subset of UCS-4).
+ // For UCS-4 we can do a direct copy (UCS-4 *is* UTF-32).
+
+ switch (sizeof(wchar_t))
+ {
+ case 4:
+ {
+ *output++ = static_cast<wchar_t>(codepoint);
+ break;
+ }
+
+ default:
+ {
+ if ((codepoint <= 0xFFFF) && ((codepoint < 0xD800) || (codepoint > 0xDFFF)))
+ {
+ *output++ = static_cast<wchar_t>(codepoint);
+ }
+ else if (replacement)
+ {
+ *output++ = replacement;
+ }
+ break;
+ }
+ }
+
+ return output;
+}
+#endif
diff --git a/dep/efsw/src/efsw/Watcher.cpp b/dep/efsw/src/efsw/Watcher.cpp
new file mode 100644
index 00000000000..d81c84228ad
--- /dev/null
+++ b/dep/efsw/src/efsw/Watcher.cpp
@@ -0,0 +1,21 @@
+#include <efsw/Watcher.hpp>
+
+namespace efsw {
+
+Watcher::Watcher() :
+ ID(0),
+ Directory(""),
+ Listener(NULL),
+ Recursive(false)
+{
+}
+
+Watcher::Watcher( WatchID id, std::string directory, FileWatchListener * listener, bool recursive ) :
+ ID( id ),
+ Directory( directory ),
+ Listener( listener ),
+ Recursive( recursive )
+{
+}
+
+}
diff --git a/dep/efsw/src/efsw/Watcher.hpp b/dep/efsw/src/efsw/Watcher.hpp
new file mode 100644
index 00000000000..5a35cb9a2ac
--- /dev/null
+++ b/dep/efsw/src/efsw/Watcher.hpp
@@ -0,0 +1,30 @@
+#ifndef EFSW_WATCHERIMPL_HPP
+#define EFSW_WATCHERIMPL_HPP
+
+#include <efsw/base.hpp>
+#include <efsw/efsw.hpp>
+
+namespace efsw {
+
+/** @brief Base Watcher class */
+class Watcher
+{
+ public:
+ Watcher();
+
+ Watcher( WatchID id, std::string directory, FileWatchListener * listener, bool recursive );
+
+ virtual ~Watcher() {}
+
+ virtual void watch() {}
+
+ WatchID ID;
+ std::string Directory;
+ FileWatchListener * Listener;
+ bool Recursive;
+ std::string OldFileName;
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherFSEvents.cpp b/dep/efsw/src/efsw/WatcherFSEvents.cpp
new file mode 100644
index 00000000000..3a9700c77ec
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherFSEvents.cpp
@@ -0,0 +1,264 @@
+#include <efsw/WatcherFSEvents.hpp>
+#include <efsw/FileWatcherFSEvents.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/Debug.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+namespace efsw {
+
+WatcherFSEvents::WatcherFSEvents() :
+ Watcher(),
+ FWatcher( NULL ),
+ FSStream( NULL ),
+ WatcherGen( NULL ),
+ initializedAsync( false )
+{
+}
+
+WatcherFSEvents::WatcherFSEvents( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherFSEvents * parent ) :
+ Watcher( id, directory, listener, recursive ),
+ FWatcher( NULL ),
+ FSStream( NULL ),
+ WatcherGen( NULL ),
+ initializedAsync( false )
+{
+}
+
+WatcherFSEvents::~WatcherFSEvents()
+{
+ if ( initializedAsync )
+ {
+ FSEventStreamStop( FSStream );
+ FSEventStreamInvalidate( FSStream );
+ }
+
+ if ( NULL != FSStream )
+ {
+ FSEventStreamRelease( FSStream );
+ }
+
+ efSAFE_DELETE( WatcherGen );
+}
+
+void WatcherFSEvents::init()
+{
+ CFStringRef CFDirectory = CFStringCreateWithCString( NULL, Directory.c_str(), kCFStringEncodingUTF8 );
+ CFArrayRef CFDirectoryArray = CFArrayCreate( NULL, (const void **)&CFDirectory, 1, NULL );
+
+ Uint32 streamFlags = kFSEventStreamCreateFlagNone;
+
+ if ( FileWatcherFSEvents::isGranular() )
+ {
+ streamFlags = efswFSEventStreamCreateFlagFileEvents;
+ }
+ else
+ {
+ WatcherGen = new WatcherGeneric( ID, Directory, Listener, FWatcher, Recursive );
+ }
+
+ FSEventStreamContext ctx;
+ /* Initialize context */
+ ctx.version = 0;
+ ctx.info = this;
+ ctx.retain = NULL;
+ ctx.release = NULL;
+ ctx.copyDescription = NULL;
+
+ FSStream = FSEventStreamCreate( kCFAllocatorDefault, &FileWatcherFSEvents::FSEventCallback, &ctx, CFDirectoryArray, kFSEventStreamEventIdSinceNow, 0.25, streamFlags );
+
+ FWatcher->mNeedInit.push_back( this );
+
+ CFRelease( CFDirectoryArray );
+ CFRelease( CFDirectory );
+}
+
+void WatcherFSEvents::initAsync()
+{
+ FSEventStreamScheduleWithRunLoop( FSStream, FWatcher->mRunLoopRef, kCFRunLoopDefaultMode );
+ FSEventStreamStart( FSStream );
+ initializedAsync = true;
+}
+
+void WatcherFSEvents::sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename )
+{
+ Listener->handleFileAction( watchid, FileSystem::precomposeFileName( dir ), FileSystem::precomposeFileName( filename ), action, oldFilename );
+}
+
+void WatcherFSEvents::handleAddModDel( const Uint32& flags, const std::string& path, std::string& dirPath, std::string& filePath )
+{
+ if ( flags & efswFSEventStreamEventFlagItemCreated )
+ {
+ if ( FileInfo::exists( path ) )
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Add );
+ }
+ }
+
+ if ( flags & efswFSEventsModified )
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Modified );
+ }
+
+ if ( flags & efswFSEventStreamEventFlagItemRemoved )
+ {
+ // Since i don't know the order, at least i try to keep the data consistent with the real state
+ if ( !FileInfo::exists( path ) )
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Delete );
+ }
+ }
+}
+
+void WatcherFSEvents::handleActions( std::vector<FSEvent>& events )
+{
+ size_t esize = events.size();
+
+ for ( size_t i = 0; i < esize; i++ )
+ {
+ FSEvent& event = events[i];
+
+ if ( event.Flags & ( kFSEventStreamEventFlagUserDropped |
+ kFSEventStreamEventFlagKernelDropped |
+ kFSEventStreamEventFlagEventIdsWrapped |
+ kFSEventStreamEventFlagHistoryDone |
+ kFSEventStreamEventFlagMount |
+ kFSEventStreamEventFlagUnmount |
+ kFSEventStreamEventFlagRootChanged ) )
+ {
+ continue;
+ }
+
+ if ( !Recursive )
+ {
+ /** In case that is not recursive the watcher, ignore the events from subfolders */
+ if ( event.Path.find_last_of( FileSystem::getOSSlash() ) != Directory.size() - 1 )
+ {
+ continue;
+ }
+ }
+
+ if ( FileWatcherFSEvents::isGranular() )
+ {
+ std::string dirPath( FileSystem::pathRemoveFileName( event.Path ) );
+ std::string filePath( FileSystem::fileNameFromPath( event.Path ) );
+
+ if ( event.Flags & ( efswFSEventStreamEventFlagItemCreated |
+ efswFSEventStreamEventFlagItemRemoved |
+ efswFSEventStreamEventFlagItemRenamed )
+ )
+ {
+ if ( dirPath != Directory )
+ {
+ DirsChanged.insert( dirPath );
+ }
+ }
+
+ // This is a mess. But it's FSEvents faults, because shrinks events from the same file in one single event ( so there's no order for them )
+ // For example a file could have been added modified and erased, but i can't know if first was erased and then added and modified, or added, then modified and then erased.
+ // I don't know what they were thinking by doing this...
+ efDEBUG( "Event in: %s - flags: %ld\n", path.c_str(), event.Flags );
+
+ if ( event.Flags & efswFSEventStreamEventFlagItemRenamed )
+ {
+ if ( ( i + 1 < esize ) &&
+ ( events[ i + 1 ].Flags & efswFSEventStreamEventFlagItemRenamed ) &&
+ ( events[ i + 1 ].Id == event.Id + 1 )
+ )
+ {
+ FSEvent& nEvent = events[ i + 1 ];
+ std::string newDir( FileSystem::pathRemoveFileName( nEvent.Path ) );
+ std::string newFilepath( FileSystem::fileNameFromPath( nEvent.Path ) );
+
+ if ( event.Path != nEvent.Path )
+ {
+ if ( dirPath == newDir )
+ {
+ if ( !FileInfo::exists( event.Path ) )
+ {
+ sendFileAction( ID, dirPath, newFilepath, Actions::Moved, filePath );
+ }
+ else
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Moved, newFilepath );
+ }
+ }
+ else
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Delete );
+ sendFileAction( ID, newDir, newFilepath, Actions::Add );
+
+ if ( nEvent.Flags & efswFSEventsModified )
+ {
+ sendFileAction( ID, newDir, newFilepath, Actions::Modified );
+ }
+ }
+ }
+ else
+ {
+ handleAddModDel( nEvent.Flags, nEvent.Path, dirPath, filePath );
+ }
+
+ if ( nEvent.Flags & ( efswFSEventStreamEventFlagItemCreated |
+ efswFSEventStreamEventFlagItemRemoved |
+ efswFSEventStreamEventFlagItemRenamed )
+ )
+ {
+ if ( newDir != Directory )
+ {
+ DirsChanged.insert( newDir );
+ }
+ }
+
+ // Skip the renamed file
+ i++;
+ }
+ else if ( FileInfo::exists( event.Path ) )
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Add );
+
+ if ( event.Flags & efswFSEventsModified )
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Modified );
+ }
+ }
+ else
+ {
+ sendFileAction( ID, dirPath, filePath, Actions::Delete );
+ }
+ }
+ else
+ {
+ handleAddModDel( event.Flags, event.Path, dirPath, filePath );
+ }
+ }
+ else
+ {
+ efDEBUG( "Directory: %s changed\n", event.Path.c_str() );
+ DirsChanged.insert( event.Path );
+ }
+ }
+}
+
+void WatcherFSEvents::process()
+{
+ std::set<std::string>::iterator it = DirsChanged.begin();
+
+ for ( ; it != DirsChanged.end(); it++ )
+ {
+ if ( !FileWatcherFSEvents::isGranular() )
+ {
+ WatcherGen->watchDir( (*it) );
+ }
+ else
+ {
+ sendFileAction( ID, FileSystem::pathRemoveFileName( (*it) ), FileSystem::fileNameFromPath( (*it) ), Actions::Modified );
+ }
+ }
+
+ DirsChanged.clear();
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherFSEvents.hpp b/dep/efsw/src/efsw/WatcherFSEvents.hpp
new file mode 100644
index 00000000000..d4fc5c9a8d3
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherFSEvents.hpp
@@ -0,0 +1,70 @@
+#ifndef EFSW_WATCHERINOTIFY_HPP
+#define EFSW_WATCHERINOTIFY_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <efsw/WatcherGeneric.hpp>
+#include <efsw/FileInfo.hpp>
+#include <CoreFoundation/CoreFoundation.h>
+#include <CoreServices/CoreServices.h>
+#include <set>
+#include <vector>
+
+namespace efsw {
+
+class FileWatcherFSEvents;
+
+class FSEvent
+{
+ public:
+ FSEvent( std::string path, long flags, Uint64 id ) :
+ Path( path ),
+ Flags( flags ),
+ Id ( id )
+ {
+ }
+
+ std::string Path;
+ long Flags;
+ Uint64 Id;
+};
+
+class WatcherFSEvents : public Watcher
+{
+ public:
+ WatcherFSEvents();
+
+ WatcherFSEvents( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherFSEvents * parent = NULL );
+
+ ~WatcherFSEvents();
+
+ void init();
+
+ void initAsync();
+
+ void handleActions( std::vector<FSEvent> & events );
+
+ void process();
+
+ FileWatcherFSEvents * FWatcher;
+
+ FSEventStreamRef FSStream;
+ protected:
+ void handleAddModDel( const Uint32 &flags, const std::string &path, std::string &dirPath, std::string &filePath );
+
+ WatcherGeneric * WatcherGen;
+
+ bool initializedAsync;
+
+ std::set<std::string> DirsChanged;
+
+ void sendFileAction( WatchID watchid, const std::string& dir, const std::string& filename, Action action, std::string oldFilename = "" );
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherGeneric.cpp b/dep/efsw/src/efsw/WatcherGeneric.cpp
new file mode 100644
index 00000000000..94170d3ce87
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherGeneric.cpp
@@ -0,0 +1,40 @@
+#include <efsw/WatcherGeneric.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/DirWatcherGeneric.hpp>
+
+namespace efsw
+{
+
+WatcherGeneric::WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener * fwl, FileWatcherImpl * fw, bool recursive ) :
+ Watcher( id, directory, fwl, recursive ),
+ WatcherImpl( fw ),
+ DirWatch( NULL )
+{
+ FileSystem::dirAddSlashAtEnd( Directory );
+
+ DirWatch = new DirWatcherGeneric( NULL, this, directory, recursive, false );
+
+ DirWatch->addChilds( false );
+}
+
+WatcherGeneric::~WatcherGeneric()
+{
+ efSAFE_DELETE( DirWatch );
+}
+
+void WatcherGeneric::watch()
+{
+ DirWatch->watch();
+}
+
+void WatcherGeneric::watchDir( std::string dir )
+{
+ DirWatch->watchDir( dir );
+}
+
+bool WatcherGeneric::pathInWatches( std::string path )
+{
+ return DirWatch->pathInWatches( path );
+}
+
+}
diff --git a/dep/efsw/src/efsw/WatcherGeneric.hpp b/dep/efsw/src/efsw/WatcherGeneric.hpp
new file mode 100644
index 00000000000..8794e921b40
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherGeneric.hpp
@@ -0,0 +1,30 @@
+#ifndef EFSW_WATCHERGENERIC_HPP
+#define EFSW_WATCHERGENERIC_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+
+namespace efsw
+{
+
+class DirWatcherGeneric;
+
+class WatcherGeneric : public Watcher
+{
+ public:
+ FileWatcherImpl * WatcherImpl;
+ DirWatcherGeneric * DirWatch;
+
+ WatcherGeneric( WatchID id, const std::string& directory, FileWatchListener * fwl, FileWatcherImpl * fw, bool recursive );
+
+ ~WatcherGeneric();
+
+ void watch();
+
+ void watchDir( std::string dir );
+
+ bool pathInWatches( std::string path );
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherInotify.cpp b/dep/efsw/src/efsw/WatcherInotify.cpp
new file mode 100644
index 00000000000..741641bf43c
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherInotify.cpp
@@ -0,0 +1,35 @@
+#include <efsw/WatcherInotify.hpp>
+
+namespace efsw {
+
+WatcherInotify::WatcherInotify() :
+ Watcher(),
+ Parent( NULL )
+{
+}
+
+WatcherInotify::WatcherInotify( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherInotify * parent ) :
+ Watcher( id, directory, listener, recursive ),
+ Parent( parent ),
+ DirInfo( directory )
+{
+}
+
+bool WatcherInotify::inParentTree( WatcherInotify * parent )
+{
+ WatcherInotify * tNext = Parent;
+
+ while ( NULL != tNext )
+ {
+ if ( tNext == parent )
+ {
+ return true;
+ }
+
+ tNext = tNext->Parent;
+ }
+
+ return false;
+}
+
+}
diff --git a/dep/efsw/src/efsw/WatcherInotify.hpp b/dep/efsw/src/efsw/WatcherInotify.hpp
new file mode 100644
index 00000000000..1caf399679b
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherInotify.hpp
@@ -0,0 +1,25 @@
+#ifndef EFSW_WATCHERINOTIFY_HPP
+#define EFSW_WATCHERINOTIFY_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+#include <efsw/FileInfo.hpp>
+
+namespace efsw {
+
+class WatcherInotify : public Watcher
+{
+ public:
+ WatcherInotify();
+
+ WatcherInotify( WatchID id, std::string directory, FileWatchListener * listener, bool recursive, WatcherInotify * parent = NULL );
+
+ bool inParentTree( WatcherInotify * parent );
+
+ WatcherInotify * Parent;
+
+ FileInfo DirInfo;
+};
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherKqueue.cpp b/dep/efsw/src/efsw/WatcherKqueue.cpp
new file mode 100644
index 00000000000..8347fb53439
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherKqueue.cpp
@@ -0,0 +1,667 @@
+#include <efsw/WatcherKqueue.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <sys/stat.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <efsw/Debug.hpp>
+#include <efsw/String.hpp>
+#include <efsw/System.hpp>
+#include <efsw/FileSystem.hpp>
+#include <efsw/WatcherGeneric.hpp>
+#include <efsw/FileWatcherKqueue.hpp>
+
+#define KEVENT_RESERVE_VALUE (10)
+
+#ifndef O_EVTONLY
+#define O_EVTONLY (O_RDONLY | O_NONBLOCK)
+#endif
+
+namespace efsw {
+
+int comparator(const void* ke1, const void* ke2)
+{
+ const KEvent * kev1 = reinterpret_cast<const KEvent*>( ke1 );
+ const KEvent * kev2 = reinterpret_cast<const KEvent*>( ke2 );
+
+ if ( NULL != kev2->udata )
+ {
+ FileInfo * fi1 = reinterpret_cast<FileInfo*>( kev1->udata );
+ FileInfo * fi2 = reinterpret_cast<FileInfo*>( kev2->udata );
+
+ return strcmp( fi1->Filepath.c_str(), fi2->Filepath.c_str() );
+ }
+
+ return 1;
+}
+
+WatcherKqueue::WatcherKqueue(WatchID watchid, const std::string& dirname, FileWatchListener* listener, bool recursive, FileWatcherKqueue * watcher, WatcherKqueue * parent ) :
+ Watcher( watchid, dirname, listener, recursive ),
+ mLastWatchID(0),
+ mChangeListCount( 0 ),
+ mKqueue( kqueue() ),
+ mWatcher( watcher ),
+ mParent( parent ),
+ mInitOK( true ),
+ mErrno(0)
+{
+ if ( -1 == mKqueue )
+ {
+ efDEBUG( "kqueue() returned invalid descriptor for directory %s. File descriptors count: %ld\n", Directory.c_str(), mWatcher->mFileDescriptorCount );
+
+ mInitOK = false;
+ mErrno = errno;
+ }
+ else
+ {
+ mWatcher->addFD();
+ }
+}
+
+WatcherKqueue::~WatcherKqueue()
+{
+ // Remove the childs watchers ( sub-folders watches )
+ removeAll();
+
+ for ( size_t i = 0; i < mChangeListCount; i++ )
+ {
+ if ( NULL != mChangeList[i].udata )
+ {
+ FileInfo * fi = reinterpret_cast<FileInfo*>( mChangeList[i].udata );
+
+ efSAFE_DELETE( fi );
+ }
+ }
+
+ close( mKqueue );
+
+ mWatcher->removeFD();
+}
+
+void WatcherKqueue::addAll()
+{
+ if ( -1 == mKqueue )
+ {
+ return;
+ }
+
+ // scan directory and call addFile(name, false) on each file
+ FileSystem::dirAddSlashAtEnd( Directory );
+
+ efDEBUG( "addAll(): Added folder: %s\n", Directory.c_str());
+
+ // add base dir
+ int fd = open( Directory.c_str(), O_EVTONLY );
+
+ if ( -1 == fd )
+ {
+ efDEBUG( "addAll(): Couldn't open folder: %s\n", Directory.c_str() );
+
+ if ( EACCES != errno )
+ {
+ mInitOK = false;
+ }
+
+ mErrno = errno;
+
+ return;
+ }
+
+ mDirSnap.setDirectoryInfo( Directory );
+ mDirSnap.scan();
+
+ mChangeList.resize( KEVENT_RESERVE_VALUE );
+
+ // Creates the kevent for the folder
+ EV_SET(
+ &mChangeList[0],
+ fd,
+ EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_ONESHOT,
+ NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME,
+ 0,
+ 0
+ );
+
+ mWatcher->addFD();
+
+ // Get the files and directories from the directory
+ FileInfoMap files = FileSystem::filesInfoFromPath( Directory );
+
+ for ( FileInfoMap::iterator it = files.begin(); it != files.end(); it++ )
+ {
+ FileInfo& fi = it->second;
+
+ if ( fi.isRegularFile() )
+ {
+ // Add the regular files kevent
+ addFile( fi.Filepath , false );
+ }
+ else if ( Recursive && fi.isDirectory() && fi.isReadable() )
+ {
+ // Create another watcher for the subfolders ( if recursive )
+ WatchID id = addWatch( fi.Filepath, Listener, Recursive, this );
+
+ // If the watcher is not adding the watcher means that the directory was created
+ if ( id > 0 && !mWatcher->isAddingWatcher() )
+ {
+ handleFolderAction( fi.Filepath, Actions::Add );
+ }
+ }
+ }
+}
+
+void WatcherKqueue::removeAll()
+{
+ efDEBUG( "removeAll(): Removing all child watchers\n" );
+
+ std::list<WatchID> erase;
+
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); it++ )
+ {
+ efDEBUG( "removeAll(): Removed child watcher %s\n", it->second->Directory.c_str() );
+
+ erase.push_back( it->second->ID );
+ }
+
+ for ( std::list<WatchID>::iterator eit = erase.begin(); eit != erase.end(); eit++ )
+ {
+ removeWatch( *eit );
+ }
+}
+
+void WatcherKqueue::addFile(const std::string& name, bool emitEvents)
+{
+ efDEBUG( "addFile(): Added: %s\n", name.c_str() );
+
+ // Open the file to get the file descriptor
+ int fd = open( name.c_str(), O_EVTONLY );
+
+ if( fd == -1 )
+ {
+ efDEBUG( "addFile(): Could open file descriptor for %s. File descriptor count: %ld\n", name.c_str(), mWatcher->mFileDescriptorCount );
+
+ Errors::Log::createLastError( Errors::FileNotReadable, name );
+
+ if ( EACCES != errno )
+ {
+ mInitOK = false;
+ }
+
+ mErrno = errno;
+
+ return;
+ }
+
+ mWatcher->addFD();
+
+ // increase the file kevent file count
+ mChangeListCount++;
+
+ if ( mChangeListCount + KEVENT_RESERVE_VALUE > mChangeList.size() &&
+ mChangeListCount % KEVENT_RESERVE_VALUE == 0 )
+ {
+ size_t reserve_size = mChangeList.size() + KEVENT_RESERVE_VALUE;
+ mChangeList.resize( reserve_size );
+ efDEBUG( "addFile(): Reserverd more KEvents space for %s, space reserved %ld, list actual size %ld.\n", Directory.c_str(), reserve_size, mChangeListCount );
+ }
+
+ // create entry
+ FileInfo * entry = new FileInfo( name );
+
+ // set the event data at the end of the list
+ EV_SET(
+ &mChangeList[mChangeListCount],
+ fd,
+ EVFILT_VNODE,
+ EV_ADD | EV_ENABLE | EV_ONESHOT,
+ NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB | NOTE_RENAME,
+ 0,
+ (void*)entry
+ );
+
+ // qsort sort the list by name
+ qsort(&mChangeList[1], mChangeListCount, sizeof(KEvent), comparator);
+
+ // handle action
+ if( emitEvents )
+ {
+ handleAction(name, Actions::Add);
+ }
+}
+
+void WatcherKqueue::removeFile( const std::string& name, bool emitEvents )
+{
+ efDEBUG( "removeFile(): Trying to remove file: %s\n", name.c_str() );
+
+ // bsearch
+ KEvent target;
+
+ // Create a temporary file info to search the kevent ( searching the directory )
+ FileInfo tempEntry( name );
+
+ target.udata = &tempEntry;
+
+ // Search the kevent
+ KEvent * ke = (KEvent*)bsearch(&target, &mChangeList[0], mChangeListCount + 1, sizeof(KEvent), comparator);
+
+ // Trying to remove a non-existing file?
+ if( !ke )
+ {
+ Errors::Log::createLastError( Errors::FileNotFound, name );
+ efDEBUG( "File not removed\n" );
+ return;
+ }
+
+ efDEBUG( "File removed\n" );
+
+ // handle action
+ if ( emitEvents )
+ {
+ handleAction( name, Actions::Delete );
+ }
+
+ // Delete the user data ( FileInfo ) from the kevent closed
+ FileInfo * del = reinterpret_cast<FileInfo*>( ke->udata );
+
+ efSAFE_DELETE( del );
+
+ // close the file descriptor from the kevent
+ close( ke->ident );
+
+ mWatcher->removeFD();
+
+ memset(ke, 0, sizeof(KEvent));
+
+ // move end to current
+ memcpy(ke, &mChangeList[mChangeListCount], sizeof(KEvent));
+ memset(&mChangeList[mChangeListCount], 0, sizeof(KEvent));
+ --mChangeListCount;
+}
+
+void WatcherKqueue::rescan()
+{
+ efDEBUG( "rescan(): Rescanning: %s\n", Directory.c_str() );
+
+ DirectorySnapshotDiff Diff = mDirSnap.scan();
+
+ if ( Diff.DirChanged )
+ {
+ sendDirChanged();
+ }
+
+ if ( Diff.changed() )
+ {
+ FileInfoList::iterator it;
+ MovedList::iterator mit;
+
+ /// Files
+ DiffIterator( FilesCreated )
+ {
+ addFile( (*it).Filepath );
+ }
+
+ DiffIterator( FilesModified )
+ {
+ handleAction( (*it).Filepath, Actions::Modified );
+ }
+
+ DiffIterator( FilesDeleted )
+ {
+ removeFile( (*it).Filepath );
+ }
+
+ DiffMovedIterator( FilesMoved )
+ {
+ handleAction( (*mit).second.Filepath, Actions::Moved, (*mit).first );
+ removeFile( Directory + (*mit).first, false );
+ addFile( (*mit).second.Filepath, false );
+ }
+
+ /// Directories
+ DiffIterator( DirsCreated )
+ {
+ handleFolderAction( (*it).Filepath, Actions::Add );
+ addWatch( (*it).Filepath, Listener, Recursive, this );
+ }
+
+ DiffIterator( DirsModified )
+ {
+ handleFolderAction( (*it).Filepath, Actions::Modified );
+ }
+
+ DiffIterator( DirsDeleted )
+ {
+ handleFolderAction( (*it).Filepath, Actions::Delete );
+
+ Watcher * watch = findWatcher( (*it).Filepath );
+
+ if ( NULL != watch )
+ {
+ removeWatch( watch->ID );
+
+ }
+ }
+
+ DiffMovedIterator( DirsMoved )
+ {
+ moveDirectory( Directory + (*mit).first, (*mit).second.Filepath );
+ }
+ }
+}
+
+WatchID WatcherKqueue::watchingDirectory( std::string dir )
+{
+ Watcher * watch = findWatcher( dir );
+
+ if ( NULL != watch )
+ {
+ return watch->ID;
+ }
+
+ return Errors::FileNotFound;
+}
+
+void WatcherKqueue::handleAction( const std::string& filename, efsw::Action action, const std::string& oldFilename )
+{
+ Listener->handleFileAction( ID, Directory, FileSystem::fileNameFromPath( filename ), action, FileSystem::fileNameFromPath( oldFilename ) );
+}
+
+void WatcherKqueue::handleFolderAction( std::string filename, efsw::Action action , const std::string &oldFilename )
+{
+ FileSystem::dirRemoveSlashAtEnd( filename );
+
+ handleAction( filename, action, oldFilename );
+}
+
+void WatcherKqueue::sendDirChanged()
+{
+ if ( NULL != mParent )
+ {
+ Listener->handleFileAction( mParent->ID, mParent->Directory, FileSystem::fileNameFromPath( Directory ), Actions::Modified );
+ }
+}
+
+void WatcherKqueue::watch()
+{
+ if ( -1 == mKqueue )
+ {
+ return;
+ }
+
+ int nev = 0;
+ KEvent event;
+
+ // First iterate the childs, to get the events from the deepest folder, to the watcher childs
+ for ( WatchMap::iterator it = mWatches.begin(); it != mWatches.end(); ++it )
+ {
+ it->second->watch();
+ }
+
+ bool needScan = false;
+
+ // Then we get the the events of the current folder
+ while( ( nev = kevent( mKqueue, &mChangeList[0], mChangeListCount + 1, &event, 1, &mWatcher->mTimeOut ) ) != 0 )
+ {
+ // An error ocurred?
+ if( nev == -1 )
+ {
+ efDEBUG( "watch(): Error on directory %s\n", Directory.c_str() );
+ perror("kevent");
+ break;
+ }
+ else
+ {
+ FileInfo * entry = NULL;
+
+ // If udate == NULL means that it is the fisrt element of the change list, the folder.
+ // otherwise it is an event of some file inside the folder
+ if( ( entry = reinterpret_cast<FileInfo*> ( event.udata ) ) != NULL )
+ {
+ efDEBUG( "watch(): File: %s ", entry->Filepath.c_str() );
+
+ // If the event flag is delete... the file was deleted
+ if ( event.fflags & NOTE_DELETE )
+ {
+ efDEBUG( "deleted\n" );
+
+ mDirSnap.removeFile( entry->Filepath );
+
+ removeFile( entry->Filepath );
+ }
+ else if ( event.fflags & NOTE_EXTEND ||
+ event.fflags & NOTE_WRITE ||
+ event.fflags & NOTE_ATTRIB
+ )
+ {
+ // The file was modified
+ efDEBUG( "modified\n" );
+
+ FileInfo fi( entry->Filepath );
+
+ if ( fi != *entry )
+ {
+ *entry = fi;
+
+ mDirSnap.updateFile( entry->Filepath );
+
+ handleAction( entry->Filepath, efsw::Actions::Modified );
+ }
+ }
+ else if ( event.fflags & NOTE_RENAME )
+ {
+ efDEBUG( "moved\n" );
+
+ needScan = true;
+ }
+ }
+ else
+ {
+ needScan = true;
+ }
+ }
+ }
+
+ if ( needScan )
+ {
+ rescan();
+ }
+}
+
+Watcher * WatcherKqueue::findWatcher( const std::string path )
+{
+ WatchMap::iterator it = mWatches.begin();
+
+ for ( ; it != mWatches.end(); it++ )
+ {
+ if ( it->second->Directory == path )
+ {
+ return it->second;
+ }
+ }
+
+ return NULL;
+}
+
+void WatcherKqueue::moveDirectory( std::string oldPath, std::string newPath, bool emitEvents )
+{
+ // Update the directory path if it's a watcher
+ std::string opath2( oldPath );
+ FileSystem::dirAddSlashAtEnd( opath2 );
+
+ Watcher * watch = findWatcher( opath2 );
+
+ if ( NULL != watch )
+ {
+ watch->Directory = opath2;
+ }
+
+ if ( emitEvents )
+ {
+ handleFolderAction( newPath, efsw::Actions::Moved, oldPath );
+ }
+}
+
+WatchID WatcherKqueue::addWatch( const std::string& directory, FileWatchListener* watcher, bool recursive , WatcherKqueue *parent)
+{
+ static long s_fc = 0;
+ static bool s_ug = false;
+
+ std::string dir( directory );
+
+ FileSystem::dirAddSlashAtEnd( dir );
+
+ // This should never happen here
+ if( !FileSystem::isDirectory( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileNotFound, dir );
+ }
+ else if ( pathInWatches( dir ) || pathInParent( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, directory );
+ }
+ else if ( NULL != parent && FileSystem::isRemoteFS( dir ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRemote, dir );
+ }
+
+ std::string curPath;
+ std::string link( FileSystem::getLinkRealPath( dir, curPath ) );
+
+ if ( "" != link )
+ {
+ /// Avoid adding symlinks directories if it's now enabled
+ if ( NULL != parent && !mWatcher->mFileWatcher->followSymlinks() )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, dir );
+ }
+
+ if ( pathInWatches( link ) || pathInParent( link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileRepeated, link );
+ }
+ else if ( !mWatcher->linkAllowed( curPath, link ) )
+ {
+ return Errors::Log::createLastError( Errors::FileOutOfScope, link );
+ }
+ else
+ {
+ dir = link;
+ }
+ }
+
+ if ( mWatcher->availablesFD() )
+ {
+ WatcherKqueue* watch = new WatcherKqueue( ++mLastWatchID, dir, watcher, recursive, mWatcher, parent );
+
+ mWatches.insert(std::make_pair(mLastWatchID, watch));
+
+ watch->addAll();
+
+ s_fc++;
+
+ // if failed to open the directory... erase the watcher
+ if ( !watch->initOK() )
+ {
+ int le = watch->lastErrno();
+
+ mWatches.erase( watch->ID );
+
+ efSAFE_DELETE( watch );
+
+ mLastWatchID--;
+
+ // Probably the folder has too many files, create a generic watcher
+ if ( EACCES != le )
+ {
+ WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive );
+
+ mWatches.insert(std::make_pair(mLastWatchID, watch));
+ }
+ else
+ {
+ return Errors::Log::createLastError( Errors::Unspecified, link );
+ }
+ }
+ }
+ else
+ {
+ if ( !s_ug )
+ {
+ efDEBUG( "Started using WatcherGeneric, reached file descriptors limit: %ld. Folders added: %ld\n", mWatcher->mFileDescriptorCount, s_fc );
+ s_ug = true;
+ }
+
+ WatcherGeneric * watch = new WatcherGeneric( ++mLastWatchID, dir, watcher, mWatcher, recursive );
+
+ mWatches.insert(std::make_pair(mLastWatchID, watch));
+ }
+
+ return mLastWatchID;
+}
+
+bool WatcherKqueue::initOK()
+{
+ return mInitOK;
+}
+
+void WatcherKqueue::removeWatch( WatchID watchid )
+{
+ WatchMap::iterator iter = mWatches.find(watchid);
+
+ if(iter == mWatches.end())
+ return;
+
+ Watcher * watch = iter->second;
+
+ mWatches.erase(iter);
+
+ efSAFE_DELETE( watch );
+}
+
+bool WatcherKqueue::pathInWatches( const std::string& path )
+{
+ return NULL != findWatcher( path );
+}
+
+bool WatcherKqueue::pathInParent( const std::string &path )
+{
+ WatcherKqueue * pNext = mParent;
+
+ while ( NULL != pNext )
+ {
+ if ( pNext->pathInWatches( path ) )
+ {
+ return true;
+ }
+
+ pNext = pNext->mParent;
+ }
+
+ if ( mWatcher->pathInWatches( path ) )
+ {
+ return true;
+ }
+
+ if ( path == Directory )
+ {
+ return true;
+ }
+
+ return false;
+}
+
+int WatcherKqueue::lastErrno()
+{
+ return mErrno;
+}
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherKqueue.hpp b/dep/efsw/src/efsw/WatcherKqueue.hpp
new file mode 100644
index 00000000000..4babbe73354
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherKqueue.hpp
@@ -0,0 +1,94 @@
+#ifndef EFSW_WATCHEROSX_HPP
+#define EFSW_WATCHEROSX_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_KQUEUE || EFSW_PLATFORM == EFSW_PLATFORM_FSEVENTS
+
+#include <map>
+#include <vector>
+#include <sys/types.h>
+#include <sys/event.h>
+#include <efsw/DirectorySnapshot.hpp>
+
+namespace efsw
+{
+
+class FileWatcherKqueue;
+class WatcherKqueue;
+
+typedef struct kevent KEvent;
+
+/// type for a map from WatchID to WatcherKqueue pointer
+typedef std::map<WatchID, Watcher*> WatchMap;
+
+class WatcherKqueue : public Watcher
+{
+ public:
+ WatcherKqueue( WatchID watchid, const std::string& dirname, FileWatchListener* listener, bool recursive, FileWatcherKqueue * watcher, WatcherKqueue * parent = NULL );
+
+ virtual ~WatcherKqueue();
+
+ void addFile( const std::string& name, bool emitEvents = true );
+
+ void removeFile( const std::string& name, bool emitEvents = true );
+
+ // called when the directory is actually changed
+ // means a file has been added or removed
+ // rescans the watched directory adding/removing files and sending notices
+ void rescan();
+
+ void handleAction( const std::string& filename, efsw::Action action, const std::string& oldFilename = "" );
+
+ void handleFolderAction( std::string filename, efsw::Action action, const std::string& oldFilename = "" );
+
+ void addAll();
+
+ void removeAll();
+
+ WatchID watchingDirectory( std::string dir );
+
+ void watch();
+
+ WatchID addWatch(const std::string& directory, FileWatchListener* watcher, bool recursive, WatcherKqueue * parent);
+
+ void removeWatch (WatchID watchid );
+
+ bool initOK();
+
+ int lastErrno();
+ protected:
+ WatchMap mWatches;
+ int mLastWatchID;
+
+ // index 0 is always the directory
+ std::vector<KEvent> mChangeList;
+ size_t mChangeListCount;
+ DirectorySnapshot mDirSnap;
+
+ /// The descriptor for the kqueue
+ int mKqueue;
+
+ FileWatcherKqueue * mWatcher;
+
+ WatcherKqueue * mParent;
+
+ bool mInitOK;
+ int mErrno;
+
+ bool pathInWatches( const std::string& path );
+
+ bool pathInParent( const std::string& path );
+
+ Watcher * findWatcher( const std::string path );
+
+ void moveDirectory( std::string oldPath, std::string newPath, bool emitEvents = true );
+
+ void sendDirChanged();
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/WatcherWin32.cpp b/dep/efsw/src/efsw/WatcherWin32.cpp
new file mode 100644
index 00000000000..01d7b0fcd99
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherWin32.cpp
@@ -0,0 +1,150 @@
+#include <efsw/WatcherWin32.hpp>
+#include <efsw/String.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+namespace efsw
+{
+
+/// Unpacks events and passes them to a user defined callback.
+void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped)
+{
+ char szFile[MAX_PATH];
+ PFILE_NOTIFY_INFORMATION pNotify;
+ WatcherStructWin32 * tWatch = (WatcherStructWin32*) lpOverlapped;
+ WatcherWin32 * pWatch = tWatch->Watch;
+ size_t offset = 0;
+
+ if (dwNumberOfBytesTransfered == 0)
+ {
+ RefreshWatch(tWatch); // If dwNumberOfBytesTransfered == 0, it means the buffer overflowed (too many changes between GetOverlappedResults calls). Those events are lost, but at least we can refresh so subsequent changes are seen again.
+ return;
+ }
+
+ if (dwErrorCode == ERROR_SUCCESS)
+ {
+ do
+ {
+ bool skip = false;
+
+ pNotify = (PFILE_NOTIFY_INFORMATION) &pWatch->mBuffer[offset];
+ offset += pNotify->NextEntryOffset;
+
+ int count = WideCharToMultiByte(CP_UTF8, 0, pNotify->FileName,
+ pNotify->FileNameLength / sizeof(WCHAR),
+ szFile, MAX_PATH - 1, NULL, NULL);
+ szFile[count] = TEXT('\0');
+
+ std::string nfile( szFile );
+
+ if ( FILE_ACTION_MODIFIED == pNotify->Action )
+ {
+ FileInfo fifile( std::string( pWatch->DirName ) + nfile );
+
+ if ( pWatch->LastModifiedEvent.file.ModificationTime == fifile.ModificationTime && pWatch->LastModifiedEvent.file.Size == fifile.Size && pWatch->LastModifiedEvent.fileName == nfile )
+ {
+ skip = true;
+ }
+
+ pWatch->LastModifiedEvent.fileName = nfile;
+ pWatch->LastModifiedEvent.file = fifile;
+ }
+
+ if ( !skip )
+ {
+ pWatch->Watch->handleAction(pWatch, nfile, pNotify->Action);
+ }
+ } while (pNotify->NextEntryOffset != 0);
+ }
+
+ if (!pWatch->StopNow)
+ {
+ RefreshWatch(tWatch);
+ }
+}
+
+/// Refreshes the directory monitoring.
+bool RefreshWatch(WatcherStructWin32* pWatch)
+{
+ return ReadDirectoryChangesW(
+ pWatch->Watch->DirHandle,
+ pWatch->Watch->mBuffer,
+ sizeof(pWatch->Watch->mBuffer),
+ pWatch->Watch->Recursive,
+ pWatch->Watch->NotifyFilter,
+ NULL,
+ &pWatch->Overlapped,
+ NULL
+ ) != 0;
+}
+
+/// Stops monitoring a directory.
+void DestroyWatch(WatcherStructWin32* pWatch)
+{
+ if (pWatch)
+ {
+ WatcherWin32 * tWatch = pWatch->Watch;
+
+ tWatch->StopNow = true;
+
+ CancelIo(tWatch->DirHandle);
+
+ RefreshWatch(pWatch);
+
+ if (!HasOverlappedIoCompleted(&pWatch->Overlapped))
+ {
+ SleepEx(5, TRUE);
+ }
+
+ CloseHandle(pWatch->Overlapped.hEvent);
+ CloseHandle(pWatch->Watch->DirHandle);
+ efSAFE_DELETE_ARRAY( pWatch->Watch->DirName );
+ efSAFE_DELETE( pWatch->Watch );
+ HeapFree(GetProcessHeap(), 0, pWatch);
+ }
+}
+
+/// Starts monitoring a directory.
+WatcherStructWin32* CreateWatch(LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter)
+{
+ WatcherStructWin32 * tWatch;
+ size_t ptrsize = sizeof(*tWatch);
+ tWatch = static_cast<WatcherStructWin32*>(HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, ptrsize));
+
+ WatcherWin32 * pWatch = new WatcherWin32();
+ tWatch->Watch = pWatch;
+
+ pWatch->DirHandle = CreateFileW(
+ szDirectory,
+ GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED,
+ NULL
+ );
+
+ if (pWatch->DirHandle != INVALID_HANDLE_VALUE)
+ {
+ tWatch->Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ pWatch->NotifyFilter = NotifyFilter;
+ pWatch->Recursive = recursive;
+
+ if (RefreshWatch(tWatch))
+ {
+ return tWatch;
+ }
+ else
+ {
+ CloseHandle(tWatch->Overlapped.hEvent);
+ CloseHandle(pWatch->DirHandle);
+ }
+ }
+
+ HeapFree(GetProcessHeap(), 0, tWatch);
+ return NULL;
+}
+
+}
+
+ #endif
diff --git a/dep/efsw/src/efsw/WatcherWin32.hpp b/dep/efsw/src/efsw/WatcherWin32.hpp
new file mode 100644
index 00000000000..3c6d988fbf4
--- /dev/null
+++ b/dep/efsw/src/efsw/WatcherWin32.hpp
@@ -0,0 +1,77 @@
+#ifndef EFSW_WATCHERWIN32_HPP
+#define EFSW_WATCHERWIN32_HPP
+
+#include <efsw/FileWatcherImpl.hpp>
+#include <efsw/FileInfo.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#include <windows.h>
+
+#ifdef EFSW_COMPILER_MSVC
+ #pragma comment(lib, "comctl32.lib")
+ #pragma comment(lib, "user32.lib")
+ #pragma comment(lib, "ole32.lib")
+
+ // disable secure warnings
+ #pragma warning (disable: 4996)
+#endif
+
+namespace efsw
+{
+
+class WatcherWin32;
+
+/// Internal watch data
+struct WatcherStructWin32
+{
+ OVERLAPPED Overlapped;
+ WatcherWin32 * Watch;
+};
+
+class cLastModifiedEvent
+{
+ public:
+ cLastModifiedEvent() {}
+ FileInfo file;
+ std::string fileName;
+};
+
+bool RefreshWatch(WatcherStructWin32* pWatch);
+
+void CALLBACK WatchCallback(DWORD dwErrorCode, DWORD dwNumberOfBytesTransfered, LPOVERLAPPED lpOverlapped);
+
+void DestroyWatch(WatcherStructWin32* pWatch);
+
+WatcherStructWin32* CreateWatch(LPCWSTR szDirectory, bool recursive, DWORD NotifyFilter);
+
+class WatcherWin32 : public Watcher
+{
+ public:
+ WatcherWin32() :
+ Struct( NULL ),
+ DirHandle( NULL ),
+ lParam( 0 ),
+ NotifyFilter( 0 ),
+ StopNow( false ),
+ Watch( NULL ),
+ DirName( NULL )
+ {
+ }
+
+ WatcherStructWin32 * Struct;
+ HANDLE DirHandle;
+ BYTE mBuffer[63 * 1024]; // do NOT make this bigger than 64K because it will fail if the folder being watched is on the network! (see http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465(v=vs.85).aspx)
+ LPARAM lParam;
+ DWORD NotifyFilter;
+ bool StopNow;
+ FileWatcherImpl* Watch;
+ char* DirName;
+ cLastModifiedEvent LastModifiedEvent;
+};
+
+}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/base.hpp b/dep/efsw/src/efsw/base.hpp
new file mode 100644
index 00000000000..26108c76985
--- /dev/null
+++ b/dep/efsw/src/efsw/base.hpp
@@ -0,0 +1,110 @@
+#ifndef EFSW_BASE
+#define EFSW_BASE
+
+#include <efsw/sophist.h>
+#include <efsw/efsw.hpp>
+
+namespace efsw {
+
+typedef SOPHIST_int8 Int8;
+typedef SOPHIST_uint8 Uint8;
+typedef SOPHIST_int16 Int16;
+typedef SOPHIST_uint16 Uint16;
+typedef SOPHIST_int32 Int32;
+typedef SOPHIST_uint32 Uint32;
+typedef SOPHIST_int64 Int64;
+typedef SOPHIST_uint64 Uint64;
+
+#define EFSW_OS_WIN 1
+#define EFSW_OS_LINUX 2
+#define EFSW_OS_MACOSX 3
+#define EFSW_OS_BSD 4
+#define EFSW_OS_SOLARIS 5
+#define EFSW_OS_HAIKU 6
+#define EFSW_OS_ANDROID 7
+#define EFSW_OS_IOS 8
+
+#define EFSW_PLATFORM_WIN32 1
+#define EFSW_PLATFORM_INOTIFY 2
+#define EFSW_PLATFORM_KQUEUE 3
+#define EFSW_PLATFORM_FSEVENTS 4
+#define EFSW_PLATFORM_GENERIC 5
+
+#if defined(_WIN32)
+ /// Any Windows platform
+ #define EFSW_OS EFSW_OS_WIN
+ #define EFSW_PLATFORM EFSW_PLATFORM_WIN32
+
+ #if ( defined( _MSCVER ) || defined( _MSC_VER ) )
+ #define EFSW_COMPILER_MSVC
+ #endif
+
+#elif defined( __FreeBSD__ ) || defined(__OpenBSD__) || defined( __NetBSD__ ) || defined( __DragonFly__ )
+ #define EFSW_OS EFSW_OS_BSD
+ #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE
+
+#elif defined( __APPLE_CC__ ) || defined ( __APPLE__ )
+ #include <TargetConditionals.h>
+
+ #if defined( __IPHONE__ ) || ( defined( TARGET_OS_IPHONE ) && TARGET_OS_IPHONE ) || ( defined( TARGET_IPHONE_SIMULATOR ) && TARGET_IPHONE_SIMULATOR )
+ #define EFSW_OS EFSW_OS_IOS
+ #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE
+ #else
+ #define EFSW_OS EFSW_OS_MACOSX
+
+ #if defined(EFSW_FSEVENTS_NOT_SUPPORTED)
+ #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE
+ #else
+ #define EFSW_PLATFORM EFSW_PLATFORM_FSEVENTS
+ #endif
+ #endif
+
+#elif defined(__linux__)
+ /// This includes Linux and Android
+ #ifndef EFSW_KQUEUE
+ #define EFSW_PLATFORM EFSW_PLATFORM_INOTIFY
+ #else
+ /// This is for testing libkqueue, sadly it doesnt work
+ #define EFSW_PLATFORM EFSW_PLATFORM_KQUEUE
+ #endif
+
+ #if defined( __ANDROID__ ) || defined( ANDROID )
+ #define EFSW_OS EFSW_OS_ANDROID
+ #else
+ #define EFSW_OS EFSW_OS_LINUX
+ #endif
+
+#else
+ #if defined( __SVR4 )
+ #define EFSW_OS EFSW_OS_SOLARIS
+ #elif defined( __HAIKU__ ) || defined( __BEOS__ )
+ #define EFSW_OS EFSW_OS_HAIKU
+ #endif
+
+ /// Everything else
+ #define EFSW_PLATFORM EFSW_PLATFORM_GENERIC
+#endif
+
+#if EFSW_PLATFORM != EFSW_PLATFORM_WIN32
+ #define EFSW_PLATFORM_POSIX
+#endif
+
+#if 1 == SOPHIST_pointer64
+ #define EFSW_64BIT
+#else
+ #define EFSW_32BIT
+#endif
+
+#if defined(arm) || defined(__arm__)
+ #define EFSW_ARM
+#endif
+
+#define efCOMMA ,
+
+#define efSAFE_DELETE(p) { if(p) { delete (p); (p)=NULL; } }
+#define efSAFE_DELETE_ARRAY(p) { if(p) { delete [] (p); (p)=NULL; } }
+#define efARRAY_SIZE(__array) ( sizeof(__array) / sizeof(__array[0]) )
+
+}
+
+#endif
diff --git a/dep/efsw/src/efsw/inotify-nosys.h b/dep/efsw/src/efsw/inotify-nosys.h
new file mode 100644
index 00000000000..75df5d3ced3
--- /dev/null
+++ b/dep/efsw/src/efsw/inotify-nosys.h
@@ -0,0 +1,159 @@
+#ifndef _LINUX_INOTIFY_H
+#define _LINUX_INOTIFY_H
+
+#include <stdint.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+
+/*
+ * struct inotify_event - structure read from the inotify device for each event
+ *
+ * When you are watching a directory, you will receive the filename for events
+ * such as IN_CREATE, IN_DELETE, IN_OPEN, IN_CLOSE, ..., relative to the wd.
+ */
+struct inotify_event {
+ int wd; /* watch descriptor */
+ uint32_t mask; /* watch mask */
+ uint32_t cookie; /* cookie to synchronize two events */
+ uint32_t len; /* length (including nulls) of name */
+ char name __flexarr; /* stub for possible name */
+};
+
+/* the following are legal, implemented events that user-space can watch for */
+#define IN_ACCESS 0x00000001 /* File was accessed */
+#define IN_MODIFY 0x00000002 /* File was modified */
+#define IN_ATTRIB 0x00000004 /* Metadata changed */
+#define IN_CLOSE_WRITE 0x00000008 /* Writtable file was closed */
+#define IN_CLOSE_NOWRITE 0x00000010 /* Unwrittable file closed */
+#define IN_OPEN 0x00000020 /* File was opened */
+#define IN_MOVED_FROM 0x00000040 /* File was moved from X */
+#define IN_MOVED_TO 0x00000080 /* File was moved to Y */
+#define IN_CREATE 0x00000100 /* Subfile was created */
+#define IN_DELETE 0x00000200 /* Subfile was deleted */
+#define IN_DELETE_SELF 0x00000400 /* Self was deleted */
+#define IN_MOVE_SELF 0x00000800 /* Self was moved */
+
+/* the following are legal events. they are sent as needed to any watch */
+#define IN_UNMOUNT 0x00002000 /* Backing fs was unmounted */
+#define IN_Q_OVERFLOW 0x00004000 /* Event queued overflowed */
+#define IN_IGNORED 0x00008000 /* File was ignored */
+
+/* helper events */
+#define IN_CLOSE (IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) /* close */
+#define IN_MOVE (IN_MOVED_FROM | IN_MOVED_TO) /* moves */
+
+/* special flags */
+#define IN_ONLYDIR 0x01000000 /* only watch the path if it is a directory */
+#define IN_DONT_FOLLOW 0x02000000 /* don't follow a sym link */
+#define IN_MASK_ADD 0x20000000 /* add to the mask of an already existing watch */
+#define IN_ISDIR 0x40000000 /* event occurred against dir */
+#define IN_ONESHOT 0x80000000 /* only send event once */
+
+/*
+ * All of the events - we build the list by hand so that we can add flags in
+ * the future and not break backward compatibility. Apps will get only the
+ * events that they originally wanted. Be sure to add new events here!
+ */
+#define IN_ALL_EVENTS (IN_ACCESS | IN_MODIFY | IN_ATTRIB | IN_CLOSE_WRITE | \
+ IN_CLOSE_NOWRITE | IN_OPEN | IN_MOVED_FROM | \
+ IN_MOVED_TO | IN_DELETE | IN_CREATE | IN_DELETE_SELF | \
+ IN_MOVE_SELF)
+
+#if defined (__alpha__)
+# define __NR_inotify_init 444
+# define __NR_inotify_add_watch 445
+# define __NR_inotify_rm_watch 446
+
+#elif defined (__arm__)
+# define __NR_inotify_init (__NR_SYSCALL_BASE+316)
+# define __NR_inotify_add_watch (__NR_SYSCALL_BASE+317)
+# define __NR_inotify_rm_watch (__NR_SYSCALL_BASE+318)
+
+#elif defined (__frv__)
+# define __NR_inotify_init 291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch 293
+
+#elif defined(__i386__)
+# define __NR_inotify_init 291
+# define __NR_inotify_add_watch 292
+# define __NR_inotify_rm_watch 293
+
+#elif defined (__ia64__)
+# define __NR_inotify_init 1277
+# define __NR_inotify_add_watch 1278
+# define __NR_inotify_rm_watch 1279
+
+#elif defined (__mips__)
+# if _MIPS_SIM == _MIPS_SIM_ABI32
+# define __NR_inotify_init (__NR_Linux + 284)
+# define __NR_inotify_add_watch (__NR_Linux + 285)
+# define __NR_inotify_rm_watch (__NR_Linux + 286)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_ABI64
+# define __NR_inotify_init (__NR_Linux + 243)
+# define __NR_inotify_add_watch (__NR_Linux + 243)
+# define __NR_inotify_rm_watch (__NR_Linux + 243)
+# endif
+# if _MIPS_SIM == _MIPS_SIM_NABI32
+# define __NR_inotify_init (__NR_Linux + 247)
+# define __NR_inotify_add_watch (__NR_Linux + 248)
+# define __NR_inotify_rm_watch (__NR_Linux + 249)
+# endif
+
+#elif defined(__parisc__)
+# define __NR_inotify_init (__NR_Linux + 269)
+# define __NR_inotify_add_watch (__NR_Linux + 270)
+# define __NR_inotify_rm_watch (__NR_Linux + 271)
+
+#elif defined(__powerpc__) || defined(__powerpc64__)
+# define __NR_inotify_init 275
+# define __NR_inotify_add_watch 276
+# define __NR_inotify_rm_watch 277
+
+#elif defined (__s390__)
+# define __NR_inotify_init 284
+# define __NR_inotify_add_watch 285
+# define __NR_inotify_rm_watch 286
+
+#elif defined (__sh__)
+# define __NR_inotify_init 290
+# define __NR_inotify_add_watch 291
+# define __NR_inotify_rm_watch 292
+
+#elif defined (__sh64__)
+# define __NR_inotify_init 318
+# define __NR_inotify_add_watch 319
+# define __NR_inotify_rm_watch 320
+
+#elif defined (__sparc__) || defined (__sparc64__)
+# define __NR_inotify_init 151
+# define __NR_inotify_add_watch 152
+# define __NR_inotify_rm_watch 156
+
+#elif defined(__x86_64__)
+# define __NR_inotify_init 253
+# define __NR_inotify_add_watch 254
+# define __NR_inotify_rm_watch 255
+
+#else
+# error "Unsupported architecture!"
+#endif
+
+static inline int inotify_init (void)
+{
+ return syscall (__NR_inotify_init);
+}
+
+static inline int inotify_add_watch (int fd, const char *name, uint32_t mask)
+{
+ return syscall (__NR_inotify_add_watch, fd, name, mask);
+}
+
+static inline int inotify_rm_watch (int fd, uint32_t wd)
+{
+ return syscall (__NR_inotify_rm_watch, fd, wd);
+}
+
+
+#endif /* _LINUX_INOTIFY_H */
diff --git a/dep/efsw/src/efsw/platform/platformimpl.hpp b/dep/efsw/src/efsw/platform/platformimpl.hpp
new file mode 100644
index 00000000000..86a74eee0c8
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/platformimpl.hpp
@@ -0,0 +1,20 @@
+#ifndef EFSW_PLATFORMIMPL_HPP
+#define EFSW_PLATFORMIMPL_HPP
+
+#include <efsw/base.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+ #include <efsw/platform/posix/ThreadImpl.hpp>
+ #include <efsw/platform/posix/MutexImpl.hpp>
+ #include <efsw/platform/posix/SystemImpl.hpp>
+ #include <efsw/platform/posix/FileSystemImpl.hpp>
+#elif EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+ #include <efsw/platform/win/ThreadImpl.hpp>
+ #include <efsw/platform/win/MutexImpl.hpp>
+ #include <efsw/platform/win/SystemImpl.hpp>
+ #include <efsw/platform/win/FileSystemImpl.hpp>
+#else
+ #error Thread, Mutex, and System not implemented for this platform.
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp
new file mode 100644
index 00000000000..e061b25d56b
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.cpp
@@ -0,0 +1,144 @@
+#include <efsw/platform/posix/FileSystemImpl.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+#include <efsw/FileInfo.hpp>
+#include <efsw/FileSystem.hpp>
+#include <dirent.h>
+#include <cstring>
+
+#ifndef _DARWIN_FEATURE_64_BIT_INODE
+#define _DARWIN_FEATURE_64_BIT_INODE
+#endif
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#include <sys/stat.h>
+#include <cstdlib>
+
+#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID
+#include <sys/vfs.h>
+#elif EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_IOS
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+
+/** Remote file systems codes */
+#define S_MAGIC_AFS 0x5346414F
+#define S_MAGIC_AUFS 0x61756673
+#define S_MAGIC_CEPH 0x00C36400
+#define S_MAGIC_CIFS 0xFF534D42
+#define S_MAGIC_CODA 0x73757245
+#define S_MAGIC_FHGFS 0x19830326
+#define S_MAGIC_FUSEBLK 0x65735546
+#define S_MAGIC_FUSECTL 0x65735543
+#define S_MAGIC_GFS 0x01161970
+#define S_MAGIC_GPFS 0x47504653
+#define S_MAGIC_KAFS 0x6B414653
+#define S_MAGIC_LUSTRE 0x0BD00BD0
+#define S_MAGIC_NCP 0x564C
+#define S_MAGIC_NFS 0x6969
+#define S_MAGIC_NFSD 0x6E667364
+#define S_MAGIC_OCFS2 0x7461636F
+#define S_MAGIC_PANFS 0xAAD7AAEA
+#define S_MAGIC_PIPEFS 0x50495045
+#define S_MAGIC_SMB 0x517B
+#define S_MAGIC_SNFS 0xBEEFDEAD
+#define S_MAGIC_VMHGFS 0xBACBACBC
+#define S_MAGIC_VXFS 0xA501FCF5
+
+namespace efsw { namespace Platform {
+
+FileInfoMap FileSystem::filesInfoFromPath( const std::string& path )
+{
+ FileInfoMap files;
+
+ DIR *dp;
+ struct dirent *dirp;
+
+ if( ( dp = opendir( path.c_str() ) ) == NULL)
+ return files;
+
+ while ( ( dirp = readdir(dp) ) != NULL)
+ {
+ if ( strcmp( dirp->d_name, ".." ) != 0 && strcmp( dirp->d_name, "." ) != 0 )
+ {
+ std::string name( dirp->d_name );
+ std::string fpath( path + name );
+
+ files[ name ] = FileInfo( fpath );
+ }
+ }
+
+ closedir(dp);
+
+ return files;
+}
+
+char FileSystem::getOSSlash()
+{
+ return '/';
+}
+
+bool FileSystem::isDirectory( const std::string& path )
+{
+ struct stat st;
+ int res = stat( path.c_str(), &st );
+
+ if ( 0 == res )
+ {
+ return static_cast<bool>( S_ISDIR(st.st_mode) );
+ }
+
+ return false;
+}
+
+bool FileSystem::isRemoteFS( const std::string& directory )
+{
+#if EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_MACOSX || EFSW_OS == EFSW_OS_BSD || EFSW_OS == EFSW_OS_SOLARIS || EFSW_OS == EFSW_OS_ANDROID || EFSW_OS == EFSW_OS_IOS
+ struct statfs statfsbuf;
+
+ statfs( directory.c_str(), &statfsbuf );
+
+ switch ( statfsbuf.f_type | 0UL )
+ {
+ case S_MAGIC_AFS: /* 0x5346414F remote */
+ case S_MAGIC_AUFS: /* 0x61756673 remote */
+ case S_MAGIC_CEPH: /* 0x00C36400 remote */
+ case S_MAGIC_CIFS: /* 0xFF534D42 remote */
+ case S_MAGIC_CODA: /* 0x73757245 remote */
+ case S_MAGIC_FHGFS: /* 0x19830326 remote */
+ case S_MAGIC_FUSEBLK: /* 0x65735546 remote */
+ case S_MAGIC_FUSECTL: /* 0x65735543 remote */
+ case S_MAGIC_GFS: /* 0x01161970 remote */
+ case S_MAGIC_GPFS: /* 0x47504653 remote */
+ case S_MAGIC_KAFS: /* 0x6B414653 remote */
+ case S_MAGIC_LUSTRE: /* 0x0BD00BD0 remote */
+ case S_MAGIC_NCP: /* 0x564C remote */
+ case S_MAGIC_NFS: /* 0x6969 remote */
+ case S_MAGIC_NFSD: /* 0x6E667364 remote */
+ case S_MAGIC_OCFS2: /* 0x7461636F remote */
+ case S_MAGIC_PANFS: /* 0xAAD7AAEA remote */
+ case S_MAGIC_PIPEFS: /* 0x50495045 remote */
+ case S_MAGIC_SMB: /* 0x517B remote */
+ case S_MAGIC_SNFS: /* 0xBEEFDEAD remote */
+ case S_MAGIC_VMHGFS: /* 0xBACBACBC remote */
+ case S_MAGIC_VXFS: /* 0xA501FCF5 remote */
+ {
+ return true;
+ }
+ default:
+ {
+ return false;
+ }
+ }
+#endif
+
+ return false;
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp
new file mode 100644
index 00000000000..865b3f8dfdf
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/FileSystemImpl.hpp
@@ -0,0 +1,27 @@
+#ifndef EFSW_FILESYSTEMIMPLPOSIX_HPP
+#define EFSW_FILESYSTEMIMPLPOSIX_HPP
+
+#include <efsw/base.hpp>
+#include <efsw/FileInfo.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+namespace efsw { namespace Platform {
+
+class FileSystem
+{
+ public:
+ static FileInfoMap filesInfoFromPath( const std::string& path );
+
+ static char getOSSlash();
+
+ static bool isDirectory( const std::string& path );
+
+ static bool isRemoteFS( const std::string& directory );
+};
+
+}}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp
new file mode 100644
index 00000000000..6f2af5abc61
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/MutexImpl.cpp
@@ -0,0 +1,32 @@
+#include <efsw/platform/posix/MutexImpl.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+namespace efsw { namespace Platform {
+
+MutexImpl::MutexImpl()
+{
+ pthread_mutexattr_t attributes;
+ pthread_mutexattr_init(&attributes);
+ pthread_mutexattr_settype(&attributes, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&mMutex, &attributes);
+}
+
+MutexImpl::~MutexImpl()
+{
+ pthread_mutex_destroy(&mMutex);
+}
+
+void MutexImpl::lock()
+{
+ pthread_mutex_lock(&mMutex);
+}
+
+void MutexImpl::unlock()
+{
+ pthread_mutex_unlock(&mMutex);
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp
new file mode 100644
index 00000000000..d51eecb16aa
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/MutexImpl.hpp
@@ -0,0 +1,31 @@
+#ifndef EFSW_MUTEXIMPLPOSIX_HPP
+#define EFSW_MUTEXIMPLPOSIX_HPP
+
+#include <efsw/base.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+#include <pthread.h>
+
+namespace efsw { namespace Platform {
+
+class MutexImpl
+{
+ public:
+ MutexImpl();
+
+ ~MutexImpl();
+
+ void lock();
+
+ void unlock();
+ private:
+ pthread_mutex_t mMutex;
+};
+
+}}
+
+#endif
+
+#endif
+
diff --git a/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp b/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp
new file mode 100644
index 00000000000..22e37095afd
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/SystemImpl.cpp
@@ -0,0 +1,180 @@
+#include <efsw/platform/posix/SystemImpl.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+#include <cstdio>
+#include <pthread.h>
+#include <sys/time.h>
+#include <limits.h>
+#include <sys/resource.h>
+
+#include <efsw/FileSystem.hpp>
+#include <efsw/Debug.hpp>
+
+#if EFSW_OS == EFSW_OS_MACOSX
+ #include <CoreFoundation/CoreFoundation.h>
+#elif EFSW_OS == EFSW_OS_LINUX || EFSW_OS == EFSW_OS_ANDROID
+ #include <libgen.h>
+ #include <unistd.h>
+#elif EFSW_OS == EFSW_OS_HAIKU
+ #include <kernel/OS.h>
+ #include <kernel/image.h>
+#elif EFSW_OS == EFSW_OS_SOLARIS
+ #include <stdlib.h>
+#elif EFSW_OS == EFSW_OS_BSD
+ #include <sys/sysctl.h>
+#endif
+
+namespace efsw { namespace Platform {
+
+void System::sleep( const unsigned long& ms )
+{
+ // usleep( static_cast<unsigned long>( ms * 1000 ) );
+
+ // usleep is not reliable enough (it might block the
+ // whole process instead of just the current thread)
+ // so we must use pthread_cond_timedwait instead
+
+ // this implementation is inspired from Qt
+ // and taken from SFML
+
+ unsigned long long usecs = ms * 1000;
+
+ // get the current time
+ timeval tv;
+ gettimeofday(&tv, NULL);
+
+ // construct the time limit (current time + time to wait)
+ timespec ti;
+ ti.tv_nsec = (tv.tv_usec + (usecs % 1000000)) * 1000;
+ ti.tv_sec = tv.tv_sec + (usecs / 1000000) + (ti.tv_nsec / 1000000000);
+ ti.tv_nsec %= 1000000000;
+
+ // create a mutex and thread condition
+ pthread_mutex_t mutex;
+ pthread_mutex_init(&mutex, 0);
+ pthread_cond_t condition;
+ pthread_cond_init(&condition, 0);
+
+ // wait...
+ pthread_mutex_lock(&mutex);
+ pthread_cond_timedwait(&condition, &mutex, &ti);
+ pthread_mutex_unlock(&mutex);
+
+ // destroy the mutex and condition
+ pthread_cond_destroy(&condition);
+}
+
+std::string System::getProcessPath()
+{
+#if EFSW_OS == EFSW_OS_MACOSX
+ char exe_file[FILENAME_MAX + 1];
+
+ CFBundleRef mainBundle = CFBundleGetMainBundle();
+
+ if (mainBundle)
+ {
+ CFURLRef mainURL = CFBundleCopyBundleURL(mainBundle);
+
+ if (mainURL)
+ {
+ int ok = CFURLGetFileSystemRepresentation ( mainURL, (Boolean) true, (UInt8*)exe_file, FILENAME_MAX );
+
+ if (ok)
+ {
+ return std::string(exe_file) + "/";
+ }
+ }
+ }
+
+ return "./";
+#elif EFSW_OS == EFSW_OS_LINUX
+ char exe_file[FILENAME_MAX + 1];
+
+ int size;
+
+ size = readlink("/proc/self/exe", exe_file, FILENAME_MAX);
+
+ if (size < 0)
+ {
+ return std::string( "./" );
+ }
+ else
+ {
+ exe_file[size] = '\0';
+ return std::string( dirname( exe_file ) ) + "/";
+ }
+
+#elif EFSW_OS == EFSW_OS_BSD
+ int mib[4];
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_PROC;
+ mib[2] = KERN_PROC_PATHNAME;
+ mib[3] = -1;
+ char buf[1024];
+ size_t cb = sizeof(buf);
+ sysctl(mib, 4, buf, &cb, NULL, 0);
+
+ return FileSystem::pathRemoveFileName( std::string( buf ) );
+
+#elif EFSW_OS == EFSW_OS_SOLARIS
+ return FileSystem::pathRemoveFileName( std::string( getexecname() ) );
+
+#elif EFSW_OS == EFSW_OS_HAIKU
+ image_info info;
+ int32 cookie = 0;
+
+ while ( B_OK == get_next_image_info( 0, &cookie, &info ) )
+ {
+ if ( info.type == B_APP_IMAGE )
+ break;
+ }
+
+ return FileSystem::pathRemoveFileName( std::string( info.name ) );
+
+#elif EFSW_OS == EFSW_OS_ANDROID
+ return "/sdcard/";
+
+#else
+ #warning getProcessPath() not implemented on this platform. ( will return "./" )
+ return "./";
+
+#endif
+}
+
+void System::maxFD()
+{
+ static bool maxed = false;
+
+ if ( !maxed )
+ {
+ struct rlimit limit;
+ getrlimit( RLIMIT_NOFILE, &limit );
+ limit.rlim_cur = limit.rlim_max;
+ setrlimit( RLIMIT_NOFILE, &limit );
+
+ getrlimit( RLIMIT_NOFILE, &limit );
+
+ efDEBUG( "File descriptor limit %ld\n", limit.rlim_cur );
+
+ maxed = true;
+ }
+}
+
+Uint64 System::getMaxFD()
+{
+ static rlim_t max_fd = 0;
+
+ if ( max_fd == 0 )
+ {
+ struct rlimit limit;
+ getrlimit( RLIMIT_NOFILE, &limit );
+ max_fd = limit.rlim_cur;
+ }
+
+ return max_fd;
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp b/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp
new file mode 100644
index 00000000000..34734104467
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/SystemImpl.hpp
@@ -0,0 +1,26 @@
+#ifndef EFSW_SYSTEMIMPLPOSIX_HPP
+#define EFSW_SYSTEMIMPLPOSIX_HPP
+
+#include <efsw/base.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+namespace efsw { namespace Platform {
+
+class System
+{
+ public:
+ static void sleep( const unsigned long& ms );
+
+ static std::string getProcessPath();
+
+ static void maxFD();
+
+ static Uint64 getMaxFD();
+};
+
+}}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp
new file mode 100644
index 00000000000..2d3671db9b8
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/ThreadImpl.cpp
@@ -0,0 +1,68 @@
+#include <efsw/platform/posix/ThreadImpl.hpp>
+#include <efsw/Thread.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+#include <cassert>
+#include <iostream>
+#include <efsw/Debug.hpp>
+
+namespace efsw { namespace Platform {
+
+ThreadImpl::ThreadImpl( Thread * owner ) :
+ mIsActive(false)
+{
+ mIsActive = pthread_create( &mThread, NULL, &ThreadImpl::entryPoint, owner ) == 0;
+
+ if ( !mIsActive )
+ {
+ efDEBUG( "Failed to create thread\n" );
+ }
+}
+
+void ThreadImpl::wait()
+{
+ // Wait for the thread to finish, no timeout
+ if ( mIsActive )
+ {
+ assert( pthread_equal( pthread_self(), mThread ) == 0 );
+
+ pthread_join( mThread, NULL );
+
+ mIsActive = false; // Reset the thread state
+ }
+}
+
+void ThreadImpl::terminate()
+{
+ if ( mIsActive )
+ {
+ #if !defined( __ANDROID__ ) && !defined( ANDROID )
+ pthread_cancel( mThread );
+ #else
+ pthread_kill( mThread , SIGUSR1 );
+ #endif
+
+ mIsActive = false;
+ }
+}
+
+void * ThreadImpl::entryPoint( void * userData )
+{
+ // The Thread instance is stored in the user data
+ Thread * owner = static_cast<Thread*>( userData );
+
+ // Tell the thread to handle cancel requests immediatly
+ #ifdef PTHREAD_CANCEL_ASYNCHRONOUS
+ pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
+ #endif
+
+ // Forward to the owner
+ owner->run();
+
+ return NULL;
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp
new file mode 100644
index 00000000000..be6dc1b3e58
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/posix/ThreadImpl.hpp
@@ -0,0 +1,35 @@
+#ifndef EFSW_THREADIMPLPOSIX_HPP
+#define EFSW_THREADIMPLPOSIX_HPP
+
+#include <efsw/base.hpp>
+
+#if defined( EFSW_PLATFORM_POSIX )
+
+#include <pthread.h>
+
+namespace efsw {
+
+class Thread;
+
+namespace Platform {
+
+class ThreadImpl
+{
+ public:
+ ThreadImpl( Thread * owner );
+
+ void wait();
+
+ void terminate();
+ protected:
+ static void * entryPoint( void* userData );
+
+ pthread_t mThread;
+ bool mIsActive;
+};
+
+}}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp
new file mode 100644
index 00000000000..376a474e662
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.cpp
@@ -0,0 +1,89 @@
+#include <efsw/platform/win/FileSystemImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+#ifndef EFSW_COMPILER_MSVC
+#include <dirent.h>
+#endif
+
+namespace efsw { namespace Platform {
+
+FileInfoMap FileSystem::filesInfoFromPath( const std::string& path )
+{
+ FileInfoMap files;
+
+ String tpath( path );
+
+ if ( tpath[ tpath.size() - 1 ] == '/' || tpath[ tpath.size() - 1 ] == '\\' )
+ {
+ tpath += "*";
+ }
+ else
+ {
+ tpath += "\\*";
+ }
+
+ WIN32_FIND_DATAW findFileData;
+ HANDLE hFind = FindFirstFileW( (LPCWSTR)tpath.toWideString().c_str(), &findFileData );
+
+ if( hFind != INVALID_HANDLE_VALUE )
+ {
+ std::string name( String( findFileData.cFileName ).toUtf8() );
+ std::string fpath( path + name );
+
+ if ( name != "." && name != ".." )
+ {
+ files[ name ] = FileInfo( fpath );
+ }
+
+ while( FindNextFileW( hFind, &findFileData ) )
+ {
+ name = String( findFileData.cFileName ).toUtf8();
+ fpath = path + name;
+
+ if ( name != "." && name != ".." )
+ {
+ files[ name ] = FileInfo( fpath );
+ }
+ }
+
+ FindClose( hFind );
+ }
+
+ return files;
+}
+
+char FileSystem::getOSSlash()
+{
+ return '\\';
+}
+
+bool FileSystem::isDirectory( const std::string& path )
+{
+ return 0 != ( GetFileAttributesW( String( path ).toWideString().c_str() ) & FILE_ATTRIBUTE_DIRECTORY );
+}
+
+bool FileSystem::isRemoteFS( const std::string& directory )
+{
+ if ((directory[0] == '\\' || directory[0] == '/') &&
+ (directory[1] == '\\' || directory[1] == '/'))
+ {
+ return true;
+ }
+
+ if ( directory.size() >= 3 )
+ {
+ return 4 == GetDriveTypeA( directory.substr( 0, 3 ).c_str() );
+ }
+
+ return false;
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp
new file mode 100644
index 00000000000..597edc4a647
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/FileSystemImpl.hpp
@@ -0,0 +1,28 @@
+#ifndef EFSW_FILESYSTEMIMPLWIN_HPP
+#define EFSW_FILESYSTEMIMPLWIN_HPP
+
+#include <efsw/base.hpp>
+#include <efsw/String.hpp>
+#include <efsw/FileInfo.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+namespace efsw { namespace Platform {
+
+class FileSystem
+{
+ public:
+ static FileInfoMap filesInfoFromPath( const std::string& path );
+
+ static char getOSSlash();
+
+ static bool isDirectory( const std::string& path );
+
+ static bool isRemoteFS( const std::string& directory );
+};
+
+}}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.cpp b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp
new file mode 100644
index 00000000000..0c8c36d8b39
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/MutexImpl.cpp
@@ -0,0 +1,29 @@
+#include <efsw/platform/win/MutexImpl.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+namespace efsw { namespace Platform {
+
+MutexImpl::MutexImpl()
+{
+ InitializeCriticalSection(&mMutex);
+}
+
+MutexImpl::~MutexImpl()
+{
+ DeleteCriticalSection(&mMutex);
+}
+
+void MutexImpl::lock()
+{
+ EnterCriticalSection(&mMutex);
+}
+
+void MutexImpl::unlock()
+{
+ LeaveCriticalSection(&mMutex);
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/MutexImpl.hpp b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp
new file mode 100644
index 00000000000..da1e20c5fa9
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/MutexImpl.hpp
@@ -0,0 +1,34 @@
+#ifndef EFSW_MUTEXIMPLWIN_HPP
+#define EFSW_MUTEXIMPLWIN_HPP
+
+#include <efsw/base.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+
+namespace efsw { namespace Platform {
+
+class MutexImpl
+{
+ public:
+ MutexImpl();
+
+ ~MutexImpl();
+
+ void lock();
+
+ void unlock();
+ private:
+ CRITICAL_SECTION mMutex;
+};
+
+}}
+
+#endif
+
+#endif
+
diff --git a/dep/efsw/src/efsw/platform/win/SystemImpl.cpp b/dep/efsw/src/efsw/platform/win/SystemImpl.cpp
new file mode 100644
index 00000000000..ddbe1e5c45c
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/SystemImpl.cpp
@@ -0,0 +1,50 @@
+#include <efsw/platform/win/SystemImpl.hpp>
+#include <efsw/String.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <cstdlib>
+
+namespace efsw { namespace Platform {
+
+void System::sleep( const unsigned long& ms )
+{
+ ::Sleep( ms );
+}
+
+std::string System::getProcessPath()
+{
+ // Get path to executable:
+ WCHAR szDrive[_MAX_DRIVE];
+ WCHAR szDir[_MAX_DIR];
+ WCHAR szFilename[_MAX_DIR];
+ WCHAR szExt[_MAX_DIR];
+ std::wstring dllName( _MAX_DIR, 0 );
+
+ GetModuleFileNameW(0, &dllName[0], _MAX_PATH);
+
+ #ifdef EFSW_COMPILER_MSVC
+ _wsplitpath_s( dllName.c_str(), szDrive, _MAX_DRIVE, szDir, _MAX_DIR, szFilename, _MAX_DIR, szExt, _MAX_DIR );
+ #else
+ _wsplitpath( dllName.c_str(), szDrive, szDir, szFilename, szExt);
+ #endif
+
+ return String( szDrive ).toUtf8() + String( szDir ).toUtf8();
+}
+
+void System::maxFD()
+{
+}
+
+Uint64 System::getMaxFD()
+{ // Number of ReadDirectory per thread
+ return 60;
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/SystemImpl.hpp b/dep/efsw/src/efsw/platform/win/SystemImpl.hpp
new file mode 100644
index 00000000000..2f785e3565c
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/SystemImpl.hpp
@@ -0,0 +1,26 @@
+#ifndef EFSW_SYSTEMIMPLWIN_HPP
+#define EFSW_SYSTEMIMPLWIN_HPP
+
+#include <efsw/base.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+namespace efsw { namespace Platform {
+
+class System
+{
+ public:
+ static void sleep( const unsigned long& ms );
+
+ static std::string getProcessPath();
+
+ static void maxFD();
+
+ static Uint64 getMaxFD();
+};
+
+}}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp
new file mode 100644
index 00000000000..2fa30f30060
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.cpp
@@ -0,0 +1,56 @@
+#include <efsw/platform/win/ThreadImpl.hpp>
+#include <efsw/Thread.hpp>
+#include <assert.h>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#include <efsw/Debug.hpp>
+
+namespace efsw { namespace Platform {
+
+ThreadImpl::ThreadImpl( Thread *owner )
+{
+ mThread = reinterpret_cast<HANDLE>( _beginthreadex( NULL, 0, &ThreadImpl::entryPoint, owner, 0, &mThreadId ) );
+
+ if ( !mThread )
+ {
+ efDEBUG( "Failed to create thread\n" );
+ }
+}
+
+void ThreadImpl::wait()
+{
+ // Wait for the thread to finish, no timeout
+ if ( mThread )
+ {
+ assert( mThreadId != GetCurrentThreadId() ); // A thread cannot wait for itself!
+
+ WaitForSingleObject( mThread, INFINITE );
+ }
+}
+
+void ThreadImpl::terminate()
+{
+ if ( mThread )
+ {
+ TerminateThread( mThread, 0 );
+ }
+}
+
+unsigned int __stdcall ThreadImpl::entryPoint( void * userData )
+{
+ // The Thread instance is stored in the user data
+ Thread * owner = static_cast<Thread*>( userData );
+
+ // Forward to the owner
+ owner->run();
+
+ // Optional, but it is cleaner
+ _endthreadex(0);
+
+ return 0;
+}
+
+}}
+
+#endif
diff --git a/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp
new file mode 100644
index 00000000000..506c659c675
--- /dev/null
+++ b/dep/efsw/src/efsw/platform/win/ThreadImpl.hpp
@@ -0,0 +1,39 @@
+#ifndef EFSW_THREADIMPLWIN_HPP
+#define EFSW_THREADIMPLWIN_HPP
+
+#include <efsw/base.hpp>
+
+#if EFSW_PLATFORM == EFSW_PLATFORM_WIN32
+
+#ifndef WIN32_LEAN_AND_MEAN
+ #define WIN32_LEAN_AND_MEAN
+#endif
+#include <windows.h>
+#include <process.h>
+
+namespace efsw {
+
+class Thread;
+
+namespace Platform {
+
+class ThreadImpl
+{
+ public:
+ ThreadImpl( Thread * owner );
+
+ void wait();
+
+ void terminate();
+ protected:
+ static unsigned int __stdcall entryPoint(void* userData);
+
+ HANDLE mThread;
+ unsigned int mThreadId;
+};
+
+}}
+
+#endif
+
+#endif
diff --git a/dep/efsw/src/efsw/sophist.h b/dep/efsw/src/efsw/sophist.h
new file mode 100644
index 00000000000..3a645040e2f
--- /dev/null
+++ b/dep/efsw/src/efsw/sophist.h
@@ -0,0 +1,147 @@
+/* sophist.h - 0.3 - public domain - Sean Barrett 2010
+** Knowledge drawn from Brian Hook's posh.h and http://predef.sourceforge.net
+** Sophist provides portable types; you typedef/#define them to your own names
+**
+** defines:
+** - SOPHIST_endian - either SOPHIST_little_endian or SOPHIST_big_endian
+** - SOPHIST_has_64 - either 0 or 1; if 0, int64 types aren't defined
+** - SOPHIST_pointer64 - either 0 or 1; if 1, pointer is 64-bit
+**
+** - SOPHIST_intptr, SOPHIST_uintptr - integer same size as pointer
+** - SOPHIST_int8, SOPHIST_uint8, SOPHIST_int16, SOPHIST_uint16
+** - SOPHIST_int32, SOPHIST_uint32, SOPHIST_int64, SOPHIST_uint64
+** - SOPHIST_int64_constant(number) - macros for creating 64-bit
+** - SOPHIST_uint64_constant(number) integer constants
+** - SOPHIST_printf_format64 - string for printf format for int64
+*/
+
+#ifndef __INCLUDE_SOPHIST_H__
+#define __INCLUDE_SOPHIST_H__
+
+#define SOPHIST_compiletime_assert(name,val) \
+ typedef int SOPHIST__assert##name[(val) ? 1 : -1]
+
+/* define a couple synthetic rules to make code more readable */
+#if (defined(__sparc__) || defined(__sparc)) && \
+ (defined(__arch64__) || defined(__sparcv9) || defined(__sparc_v9__))
+ #define SOPHIST_sparc64
+#endif
+
+#if (defined(linux) || defined(__linux__)) && \
+ (defined(__alpha)||defined(__alpha__)||defined(__x86_64__)||defined(_M_X64))
+ #define SOPHIST_linux64
+#endif
+
+/* basic types */
+typedef signed char SOPHIST_int8;
+typedef unsigned char SOPHIST_uint8;
+
+typedef signed short SOPHIST_int16;
+typedef unsigned short SOPHIST_uint16;
+
+#ifdef __palmos__
+ typedef signed long SOPHIST_int32;
+ typedef unsigned long SOPHIST_uint32;
+#else
+ typedef signed int SOPHIST_int32;
+ typedef unsigned int SOPHIST_uint32;
+#endif
+
+#ifndef SOPHIST_NO_64
+ #if defined(_MSC_VER) || defined(__WATCOMC__) || defined(__BORLANDC__) \
+ || (defined(__alpha) && defined(__DECC))
+
+ typedef signed __int64 SOPHIST_int64;
+ typedef unsigned __int64 SOPHIST_uint64;
+ #define SOPHIST_has_64 1
+ #define SOPHIST_int64_constant(x) (x##i64)
+ #define SOPHIST_uint64_constant(x) (x##ui64)
+ #define SOPHIST_printf_format64 "I64"
+
+ #elif defined(__LP64__) || defined(__powerpc64__) || defined(SOPHIST_sparc64)
+
+ typedef signed long SOPHIST_int64;
+ typedef unsigned long SOPHIST_uint64;
+
+ #define SOPHIST_has_64 1
+ #define SOPHIST_int64_constant(x) ((SOPHIST_int64) x)
+ #define SOPHIST_uint64_constant(x) ((SOPHIST_uint64) x)
+ #define SOPHIST_printf_format64 "l"
+
+ #elif defined(_LONG_LONG) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) \
+ || defined(__GNUC__) || defined(__MWERKS__) || defined(__APPLE_CC__) \
+ || defined(sgi) || defined (__sgi) || defined(__sgi__) \
+ || defined(_CRAYC)
+
+ typedef signed long long SOPHIST_int64;
+ typedef unsigned long long SOPHIST_uint64;
+
+ #define SOPHIST_has_64 1
+ #define SOPHIST_int64_constant(x) (x##LL)
+ #define SOPHIST_uint64_constant(x) (x##ULL)
+ #define SOPHIST_printf_format64 "ll"
+ #endif
+#endif
+
+#ifndef SOPHIST_has_64
+#define SOPHIST_has_64 0
+#endif
+
+SOPHIST_compiletime_assert( int8 , sizeof(SOPHIST_int8 ) == 1);
+SOPHIST_compiletime_assert(uint16, sizeof(SOPHIST_int16) == 2);
+SOPHIST_compiletime_assert( int32, sizeof(SOPHIST_int32 ) == 4);
+SOPHIST_compiletime_assert(uint32, sizeof(SOPHIST_uint32) == 4);
+
+#if SOPHIST_has_64
+ SOPHIST_compiletime_assert( int64, sizeof(SOPHIST_int64 ) == 8);
+ SOPHIST_compiletime_assert(uint64, sizeof(SOPHIST_uint64) == 8);
+#endif
+
+/* determine whether pointers are 64-bit */
+
+#if defined(SOPHIST_linux64) || defined(SOPHIST_sparc64) \
+ || defined(__osf__) || (defined(_WIN64) && !defined(_XBOX)) \
+ || defined(__64BIT__) \
+ || defined(__LP64) || defined(__LP64__) || defined(_LP64) \
+ || defined(_ADDR64) || defined(_CRAYC) \
+
+ #define SOPHIST_pointer64 1
+
+ SOPHIST_compiletime_assert(pointer64, sizeof(void*) == 8);
+
+ typedef SOPHIST_int64 SOPHIST_intptr;
+ typedef SOPHIST_uint64 SOPHIST_uintptr;
+#else
+
+ #define SOPHIST_pointer64 0
+
+ SOPHIST_compiletime_assert(pointer64, sizeof(void*) <= 4);
+
+ /* do we care about pointers that are only 16-bit? */
+ typedef SOPHIST_int32 SOPHIST_intptr;
+ typedef SOPHIST_uint32 SOPHIST_uintptr;
+
+#endif
+
+SOPHIST_compiletime_assert(intptr, sizeof(SOPHIST_intptr) == sizeof(char *));
+
+/* enumerate known little endian cases; fallback to big-endian */
+
+#define SOPHIST_little_endian 1
+#define SOPHIST_big_endian 2
+
+#if defined(__386__) || defined(i386) || defined(__i386__) \
+ || defined(__X86) || defined(_M_IX86) \
+ || defined(_M_X64) || defined(__x86_64__) \
+ || defined(alpha) || defined(__alpha) || defined(__alpha__) \
+ || defined(_M_ALPHA) \
+ || defined(ARM) || defined(_ARM) || defined(__arm__) \
+ || defined(WIN32) || defined(_WIN32) || defined(__WIN32__) \
+ || defined(_WIN32_WCE) || defined(__NT__) \
+ || defined(__MIPSEL__)
+ #define SOPHIST_endian SOPHIST_little_endian
+#else
+ #define SOPHIST_endian SOPHIST_big_endian
+#endif
+
+#endif /* __INCLUDE_SOPHIST_H__ */
diff --git a/dep/efsw/src/test/efsw-test.cpp b/dep/efsw/src/test/efsw-test.cpp
new file mode 100644
index 00000000000..a49e3414fcc
--- /dev/null
+++ b/dep/efsw/src/test/efsw-test.cpp
@@ -0,0 +1,151 @@
+#include <efsw/efsw.hpp>
+#include <efsw/System.hpp>
+#include <efsw/FileSystem.hpp>
+#include <signal.h>
+#include <iostream>
+
+bool STOP = false;
+
+void sigend(int signal)
+{
+ std::cout << std::endl << "Bye bye" << std::endl;
+ STOP = true;
+}
+
+/// Processes a file action
+class UpdateListener : public efsw::FileWatchListener
+{
+ public:
+ UpdateListener() {}
+
+ std::string getActionName( efsw::Action action )
+ {
+ switch ( action )
+ {
+ case efsw::Actions::Add: return "Add";
+ case efsw::Actions::Modified: return "Modified";
+ case efsw::Actions::Delete: return "Delete";
+ case efsw::Actions::Moved: return "Moved";
+ default: return "Bad Action";
+ }
+ }
+
+ void handleFileAction( efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename = "" )
+ {
+ std::cout << "DIR (" << dir + ") FILE (" + ( oldFilename.empty() ? "" : "from file " + oldFilename + " to " ) + filename + ") has event " << getActionName( action ) << std::endl;
+ }
+};
+
+efsw::WatchID handleWatchID( efsw::WatchID watchid )
+{
+ switch ( watchid )
+ {
+ case efsw::Errors::FileNotFound:
+ case efsw::Errors::FileRepeated:
+ case efsw::Errors::FileOutOfScope:
+ case efsw::Errors::FileRemote:
+ case efsw::Errors::Unspecified:
+ {
+ std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl;
+ break;
+ }
+ default:
+ {
+ std::cout << "Added WatchID: " << watchid << std::endl;
+ }
+ }
+
+ return watchid;
+}
+
+int main(int argc, char **argv)
+{
+ signal( SIGABRT , sigend );
+ signal( SIGINT , sigend );
+ signal( SIGTERM , sigend );
+
+ std::cout << "Press ^C to exit demo" << std::endl;
+
+ bool commonTest = true;
+ bool useGeneric = false;
+ std::string path;
+
+ if ( argc >= 2 )
+ {
+ path = std::string( argv[1] );
+
+ if ( efsw::FileSystem::isDirectory( path ) )
+ {
+ commonTest = false;
+ }
+
+ if ( argc >= 3 )
+ {
+ if ( std::string( argv[2] ) == "true" )
+ {
+ useGeneric = true;
+ }
+ }
+ }
+
+ UpdateListener * ul = new UpdateListener();
+
+ /// create the file watcher object
+ efsw::FileWatcher fileWatcher( useGeneric );
+
+ fileWatcher.followSymlinks( false );
+ fileWatcher.allowOutOfScopeLinks( false );
+
+ if ( commonTest )
+ {
+ std::string CurPath( efsw::System::getProcessPath() );
+
+ std::cout << "CurPath: " << CurPath.c_str() << std::endl;
+
+ /// add a watch to the system
+ handleWatchID( fileWatcher.addWatch( CurPath + "test", ul, true ) );
+
+ /// starts watching
+ fileWatcher.watch();
+
+ /// adds another watch after started watching...
+ efsw::System::sleep( 100 );
+
+ efsw::WatchID watchID = handleWatchID( fileWatcher.addWatch( CurPath + "test2", ul, true ) );
+
+ /// delete the watch
+ if ( watchID > 0 )
+ {
+ efsw::System::sleep( 1000 );
+ fileWatcher.removeWatch( watchID );
+ }
+ }
+ else
+ {
+ efsw::WatchID err;
+
+ if ( ( err = fileWatcher.addWatch( path, ul, true ) ) > 0 )
+ {
+ fileWatcher.watch();
+
+ std::cout << "Watching directory: " << path.c_str() << std::endl;
+
+ if ( useGeneric )
+ {
+ std::cout << "Using generic backend watcher" << std::endl;
+ }
+ }
+ else
+ {
+ std::cout << "Error trying to watch directory: " << path.c_str() << std::endl;
+ std::cout << efsw::Errors::Log::getLastErrorLog().c_str() << std::endl;
+ }
+ }
+
+ while( !STOP )
+ {
+ efsw::System::sleep( 100 );
+ }
+
+ return 0;
+}
diff --git a/sql/updates/world/2016_03_24_00_world_335.sql b/sql/updates/world/2016_03_24_00_world_335.sql
new file mode 100644
index 00000000000..4d69d8fd3f2
--- /dev/null
+++ b/sql/updates/world/2016_03_24_00_world_335.sql
@@ -0,0 +1,9 @@
+--
+UPDATE `creature` SET `MovementType`=0 WHERE `guid` IN (46414, 46416);
+UPDATE `creature_addon` SET `path_id`=0 WHERE `guid` IN (46414, 46416);
+DELETE FROM `waypoint_data` WHERE `id` IN (464140, 464160);
+DELETE FROM `creature_formations` WHERE `leaderGUID`=46394;
+INSERT INTO `creature_formations` (`leaderGUID`, `memberGUID`, `dist`, `angle`, `groupAI`, `point_1`, `point_2`) VALUES
+(46394, 46394, 0, 0, 2, 0, 0),
+(46394, 46414, 4, 260, 2, 1, 5),
+(46394, 46416, 4, 100, 2, 1, 5);
diff --git a/sql/updates/world/2016_03_24_01_world_335.sql b/sql/updates/world/2016_03_24_01_world_335.sql
new file mode 100644
index 00000000000..01d7857519e
--- /dev/null
+++ b/sql/updates/world/2016_03_24_01_world_335.sql
@@ -0,0 +1,9 @@
+--
+UPDATE `quest_template_addon` SET `AllowableClasses`=1 WHERE `id`=8316;
+UPDATE `quest_template_addon` SET `AllowableClasses`=2 WHERE `id`=8376;
+UPDATE `quest_template_addon` SET `AllowableClasses`=4 WHERE `id`=8377;
+UPDATE `quest_template_addon` SET `AllowableClasses`=8 WHERE `id`=8378;
+UPDATE `quest_template_addon` SET `AllowableClasses`=16 WHERE `id`=8379;
+UPDATE `quest_template_addon` SET `AllowableClasses`=64 WHERE `id`=8380;
+UPDATE `quest_template_addon` SET `AllowableClasses`=384 WHERE `id`=8381;
+UPDATE `quest_template_addon` SET `AllowableClasses`=1024 WHERE `id`=8382;
diff --git a/sql/updates/world/2016_03_24_02_world.sql b/sql/updates/world/2016_03_24_02_world.sql
new file mode 100644
index 00000000000..199582eb4a0
--- /dev/null
+++ b/sql/updates/world/2016_03_24_02_world.sql
@@ -0,0 +1,4 @@
+UPDATE `creature` SET `unit_flags`=832 WHERE `guid`IN(57890,57891) AND `id`=16831;
+UPDATE `creature` SET `unit_flags`=33536 WHERE `guid`IN(57492) AND `id`=16580;
+UPDATE `creature` SET `unit_flags`=768 WHERE `guid`IN(57542,57543) AND `id`=16582;
+UPDATE `creature` SET `unit_flags`=768 WHERE `guid`IN(58137) AND `id`=16864;
diff --git a/sql/updates/world/2016_03_26_00_world.sql b/sql/updates/world/2016_03_26_00_world.sql
new file mode 100644
index 00000000000..58a42dc214d
--- /dev/null
+++ b/sql/updates/world/2016_03_26_00_world.sql
@@ -0,0 +1,516 @@
+-- Fix moving phantom guest who should be sitting.
+UPDATE `creature` SET `MovementType`=0 AND `spawndist`=0, `position_x`=-10997.400391, `position_y`=-1893.040039, `orientation`=3.572645 WHERE `guid`=135230;
+UPDATE `creature_addon` SET `bytes1`=1, `bytes2`=5 WHERE `guid`=135230;
+
+SET @NPC := 135151;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10988.13,`position_y`=-2019.135,`position_z`=80.22357 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10988.13,-2019.135,80.22357,0,0,0,0,100,0),
+(@PATH,2,-10987.89,-2011.348,80.22346,0,0,0,0,100,0),
+(@PATH,3,-10984.39,-2008.848,80.22346,0,0,0,0,100,0),
+(@PATH,4,-10981.26,-2006.71,80.22307,0,0,0,0,100,0),
+(@PATH,5,-10972.16,-2002.439,80.22302,0,0,0,0,100,0),
+(@PATH,6,-10979.17,-1997.218,80.22329,0,0,0,0,100,0),
+(@PATH,7,-10980.42,-1997.218,80.22329,0,0,0,0,100,0),
+(@PATH,8,-10981.42,-1997.218,80.22329,0,0,0,0,100,0),
+(@PATH,9,-10985.26,-1997.161,80.22356,0,0,0,0,100,0),
+(@PATH,10,-10984.12,-1987.489,80.22325,0,0,0,0,100,0),
+(@PATH,11,-10979.12,-1986.239,80.22325,0,0,0,0,100,0),
+(@PATH,12,-10973.73,-1984.487,80.22291,0,0,0,0,100,0),
+(@PATH,13,-10967.48,-1974.487,80.22291,0,0,0,0,100,0),
+(@PATH,14,-10966.55,-1973.238,80.22318,0,0,0,0,100,0),
+(@PATH,15,-10962.55,-1970.488,80.22318,0,0,0,0,100,0),
+(@PATH,16,-10957.55,-1966.988,80.22318,0,0,0,0,100,0),
+(@PATH,17,-10955.99,-1967.212,80.2233,0,0,0,0,100,0),
+(@PATH,18,-10952.45,-1968.359,80.22365,0,0,0,0,100,0),
+(@PATH,19,-10951.29,-1984.542,80.22362,0,0,0,0,100,0),
+(@PATH,20,-10953.64,-1990.575,80.22345,0,0,0,0,100,0),
+(@PATH,21,-10954.39,-1991.575,80.22345,0,0,0,0,100,0),
+(@PATH,22,-10956.89,-1995.075,80.22345,0,0,0,0,100,0),
+(@PATH,23,-10961.48,-2000.67,80.2235,0,0,0,0,100,0),
+(@PATH,24,-10961.23,-2004.42,80.2235,0,0,0,0,100,0),
+(@PATH,25,-10961.32,-2013.403,80.22313,0,0,0,0,100,0),
+(@PATH,26,-10964.57,-2015.653,80.22313,0,0,0,0,100,0),
+(@PATH,27,-10972.57,-2021.653,80.22313,0,0,0,0,100,0),
+(@PATH,28,-10974.32,-2022.653,80.22313,0,0,0,0,100,0),
+(@PATH,29,-10976.85,-2024.267,80.22278,0,0,0,0,100,0),
+(@PATH,30,-10984.28,-2022.546,80.22318,0,0,0,0,100,0),
+(@PATH,31,-10986.03,-2021.296,80.22318,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00021939B3 .go -10988.13 -2019.135 80.22357
+
+SET @NPC := 135153;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-11067.45,`position_y`=-1954.224,`position_z`=77.52905 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-11067.45,-1954.224,77.52905,0,0,0,0,100,0),
+(@PATH,2,-11066.2,-1960.974,77.52905,0,0,0,0,100,0),
+(@PATH,3,-11065.75,-1963.135,77.51662,0,0,0,0,100,0),
+(@PATH,4,-11065.75,-1967.135,77.51662,0,0,0,0,100,0),
+(@PATH,5,-11065.79,-1972.166,77.51814,0,0,0,0,100,0),
+(@PATH,6,-11066.38,-1980.533,77.51814,0,0,0,0,100,0),
+(@PATH,7,-11066.62,-1984.77,77.51814,0,0,0,0,100,0),
+(@PATH,8,-11069.65,-1987.687,77.51814,0,0,0,0,100,0),
+(@PATH,9,-11070.65,-1989.187,77.51814,0,0,0,0,100,0),
+(@PATH,10,-11071.15,-1989.937,77.51814,0,0,0,0,100,0),
+(@PATH,11,-11070.94,-1998.072,77.51814,0,0,0,0,100,0),
+(@PATH,12,-11070.44,-1998.822,77.51814,0,0,0,0,100,0),
+(@PATH,13,-11068.2,-2002.879,77.51814,0,0,0,0,100,0),
+(@PATH,14,-11065.7,-2003.629,77.51814,0,0,0,0,100,0),
+(@PATH,15,-11063.57,-2004.327,77.51814,0,0,0,0,100,0),
+(@PATH,16,-11061.32,-2005.077,77.51814,0,0,0,0,100,0),
+(@PATH,17,-11055.32,-2003.327,77.51814,0,0,0,0,100,0),
+(@PATH,18,-11054.66,-2002.821,77.55538,0,0,0,0,100,0),
+(@PATH,19,-11054.31,-1995.887,77.51814,0,0,0,0,100,0),
+(@PATH,20,-11055.06,-1993.137,77.51814,0,0,0,0,100,0),
+(@PATH,21,-11055.91,-1986.87,77.51814,0,0,0,0,100,0),
+(@PATH,22,-11054.91,-1981.87,77.51814,0,0,0,0,100,0),
+(@PATH,23,-11054.66,-1978.87,77.51814,0,0,0,0,100,0),
+(@PATH,24,-11054.28,-1978.515,77.51814,0,0,0,0,100,0),
+(@PATH,25,-11054.03,-1977.265,77.51814,0,0,0,0,100,0),
+(@PATH,26,-11053.78,-1974.765,77.51814,0,0,0,0,100,0),
+(@PATH,27,-11051.89,-1965.272,77.51814,0,0,0,0,100,0),
+(@PATH,28,-11048.71,-1950.098,77.51814,0,0,0,0,100,0),
+(@PATH,29,-11048.46,-1946.348,77.51814,0,0,0,0,100,0),
+(@PATH,30,-11047.88,-1941.905,77.51763,0,0,0,0,100,0),
+(@PATH,31,-11047.38,-1933.655,77.51763,0,0,0,0,100,0),
+(@PATH,32,-11047.21,-1931.985,77.51714,0,0,0,0,100,0),
+(@PATH,33,-11047.59,-1921.692,77.51558,0,0,0,0,100,0),
+(@PATH,34,-11057.2,-1924.383,77.51465,0,0,0,0,100,0),
+(@PATH,35,-11058.45,-1924.383,77.51465,0,0,0,0,100,0),
+(@PATH,36,-11063.45,-1924.133,77.51465,0,0,0,0,100,0),
+(@PATH,37,-11068.15,-1924.406,77.51405,0,0,0,0,100,0),
+(@PATH,38,-11067.4,-1927.406,77.51405,0,0,0,0,100,0),
+(@PATH,39,-11067.21,-1928.737,77.51527,0,0,0,0,100,0),
+(@PATH,40,-11066.71,-1930.737,77.51527,0,0,0,0,100,0),
+(@PATH,41,-11067.95,-1936.832,77.515,0,0,0,0,100,0),
+(@PATH,42,-11068.2,-1939.332,77.515,0,0,0,0,100,0),
+(@PATH,43,-11068.68,-1942.693,77.51746,0,0,0,0,100,0),
+(@PATH,44,-11068.93,-1945.193,77.51746,0,0,0,0,100,0),
+(@PATH,45,-11068.48,-1949.942,77.51735,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00029939B3 .go -11067.45 -1954.224 77.52905
+
+SET @NPC := 135160;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10901.4,`position_y`=-1937.891,`position_z`=92.465 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10901.4,-1937.891,92.465,0,0,0,0,100,0),
+(@PATH,2,-10900.29,-1929.272,92.4336,0,0,0,0,100,0),
+(@PATH,3,-10901.91,-1923.966,92.44674,0,0,0,0,100,0),
+(@PATH,4,-10929.68,-1920.51,94.00494,0,0,0,0,100,0),
+(@PATH,5,-10931.06,-1919.155,94.07338,0,0,0,0,100,0),
+(@PATH,6,-10943.3,-1903.568,94.07179,0,0,0,0,100,0),
+(@PATH,7,-10944.89,-1920.322,94.07281,0,0,0,0,100,0),
+(@PATH,8,-10942.7,-1925.781,94.07328,0,0,0,0,100,0),
+(@PATH,9,-10938.01,-1929.625,94.00285,0,0,0,0,100,0),
+(@PATH,10,-10916.58,-1931.924,92.45416,0,0,0,0,100,0),
+(@PATH,11,-10913.29,-1936.26,92.45316,0,0,0,0,100,0),
+(@PATH,12,-10914.17,-1940.8,92.45174,0,0,0,0,100,0),
+(@PATH,13,-10916.33,-1945.966,92.44943,0,0,0,0,100,0),
+(@PATH,14,-10918.42,-1951.383,92.44786,0,0,0,0,100,0),
+(@PATH,15,-10915.9,-1954.492,92.43726,0,0,0,0,100,0),
+(@PATH,16,-10918.41,-1959.593,92.43956,0,0,0,0,100,0),
+(@PATH,17,-10925.46,-1968.512,92.43243,0,0,0,0,100,0),
+(@PATH,18,-10929.36,-1971.48,92.43213,0,0,0,0,100,0),
+(@PATH,19,-10930.33,-1974.389,92.43208,0,0,0,0,100,0),
+(@PATH,20,-10921.77,-1991.525,92.43311,0,0,0,0,100,0),
+(@PATH,21,-10917.44,-1995.525,92.43374,0,0,0,0,100,0),
+(@PATH,22,-10909.94,-1997.982,92.43427,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00031939B3 .go -10901.4 -1937.891 92.465
+
+SET @NPC := 135165;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10939.02,`position_y`=-1978.883,`position_z`=93.82455 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10939.02,-1978.883,93.82455,0,0,0,0,100,0),
+(@PATH,2,-10937.05,-1980.987,94.02183,0,0,0,0,100,0),
+(@PATH,3,-10936.1,-1981.984,93.75357,0,0,0,0,100,0),
+(@PATH,4,-10935.1,-1982.984,93.00357,0,0,0,0,100,0),
+(@PATH,5,-10933.3,-1984.661,92.40492,0,0,0,0,100,0),
+(@PATH,6,-10931.4,-1988.728,92.43253,0,0,0,0,100,0),
+(@PATH,7,-10929.84,-1993.005,92.43249,0,0,0,0,100,0),
+(@PATH,8,-10929.33,-1998.021,92.43246,0,0,0,0,100,0),
+(@PATH,9,-10927.59,-1998.024,92.4326,0,0,0,0,100,0),
+(@PATH,10,-10926.84,-1997.024,92.4326,0,0,0,0,100,0),
+(@PATH,11,-10923.82,-1993.655,92.43284,0,0,0,0,100,0),
+(@PATH,12,-10920.28,-1992.615,92.43314,0,0,0,0,100,0),
+(@PATH,13,-10916.69,-1991.384,92.43354,0,0,0,0,100,0),
+(@PATH,14,-10912.31,-1989.809,92.43417,0,0,0,0,100,0),
+(@PATH,15,-10907.22,-1987.487,92.43446,0,0,0,0,100,0),
+(@PATH,16,-10907.61,-1983.417,92.43436,0,0,0,0,100,0),
+(@PATH,17,-10911.33,-1980.017,92.43408,0,0,0,0,100,0),
+(@PATH,18,-10913.89,-1977.515,92.43388,0,0,0,0,100,0),
+(@PATH,19,-10915.35,-1974.443,92.43365,0,0,0,0,100,0),
+(@PATH,20,-10917.08,-1969.858,92.43343,0,0,0,0,100,0),
+(@PATH,21,-10918.56,-1962.168,92.43033,0,0,0,0,100,0),
+(@PATH,22,-10917.81,-1960.168,92.43033,0,0,0,0,100,0),
+(@PATH,23,-10917.31,-1957.168,92.43033,0,0,0,0,100,0),
+(@PATH,24,-10916.8,-1956.043,92.44185,0,0,0,0,100,0),
+(@PATH,25,-10913.85,-1945.233,92.44743,0,0,0,0,100,0),
+(@PATH,26,-10913.63,-1940.582,92.45272,0,0,0,0,100,0),
+(@PATH,27,-10913.35,-1935.01,92.45383,0,0,0,0,100,0),
+(@PATH,28,-10917.51,-1933.436,92.45338,0,0,0,0,100,0),
+(@PATH,29,-10922.4,-1936.293,92.4428,0,0,0,0,100,0),
+(@PATH,30,-10925.65,-1937.793,92.4428,0,0,0,0,100,0),
+(@PATH,31,-10926.53,-1938.423,92.52744,0,0,0,0,100,0),
+(@PATH,32,-10929.78,-1939.673,92.52744,0,0,0,0,100,0),
+(@PATH,33,-10930.73,-1940.091,93.50311,0,0,0,0,100,0),
+(@PATH,34,-10930.98,-1938.091,93.75311,0,0,0,0,100,0),
+(@PATH,35,-10930.98,-1935.091,94.00311,0,0,0,0,100,0),
+(@PATH,36,-10932.33,-1925.829,94.07312,0,0,0,0,100,0),
+(@PATH,37,-10934.22,-1919.477,94.07236,0,0,0,0,100,0),
+(@PATH,38,-10936.83,-1914.139,94.07259,0,0,0,0,100,0),
+(@PATH,39,-10940.94,-1913.56,94.07243,0,0,0,0,100,0),
+(@PATH,40,-10943.83,-1916.909,94.07263,0,0,0,0,100,0),
+(@PATH,41,-10945.09,-1924.069,94.07304,0,0,0,0,100,0),
+(@PATH,42,-10945.81,-1929.354,94.07185,0,0,0,0,100,0),
+(@PATH,43,-10946.08,-1934.29,94.07332,0,0,0,0,100,0),
+(@PATH,44,-10945.36,-1938.052,94.06967,0,0,0,0,100,0),
+(@PATH,45,-10944.86,-1940.302,94.06967,0,0,0,0,100,0),
+(@PATH,46,-10943.61,-1941.302,94.06967,0,0,0,0,100,0),
+(@PATH,47,-10942.36,-1942.552,94.06967,0,0,0,0,100,0),
+(@PATH,48,-10941.18,-1943.745,94.07132,0,0,0,0,100,0),
+(@PATH,49,-10938.37,-1950.035,94.06915,0,0,0,0,100,0),
+(@PATH,50,-10938.62,-1951.785,94.06915,0,0,0,0,100,0),
+(@PATH,51,-10938.97,-1960.17,94.07024,0,0,0,0,100,0),
+(@PATH,52,-10939.53,-1967.704,94.07249,0,0,0,0,100,0),
+(@PATH,53,-10939.97,-1974.155,94.07382,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00039939B3 .go -10939.02 -1978.883 93.82455
+
+SET @NPC := 135162;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10946.03,`position_y`=-2018.407,`position_z`=80.01561 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10946.03,-2018.407,80.01561,0,0,0,0,100,0),
+(@PATH,2,-10938.18,-2019.209,80.42243,0,0,0,0,100,0),
+(@PATH,3,-10936.18,-2020.459,80.42243,0,0,0,0,100,0),
+(@PATH,4,-10937.69,-2035.067,86.25978,0,0,0,0,100,0),
+(@PATH,5,-10937,-2040.216,86.32371,0,0,0,0,100,0),
+(@PATH,6,-10933.3,-2043.247,86.32394,0,0,0,0,100,0),
+(@PATH,7,-10928.26,-2043.84,86.32447,0,0,0,0,100,0),
+(@PATH,8,-10923.09,-2042.638,86.32227,0,0,0,0,100,0),
+(@PATH,9,-10920.8,-2037.279,86.56629,0,0,0,0,100,0),
+(@PATH,10,-10916.75,-2002.508,92.43436,0,0,0,0,100,0),
+(@PATH,11,-10911.1,-2000.068,92.43423,0,0,0,0,100,0),
+(@PATH,12,-10907.79,-1994.801,92.43451,0,0,0,0,100,0),
+(@PATH,13,-10903.67,-1963.204,92.42834,0,0,0,0,100,0),
+(@PATH,14,-10888.27,-1964.728,92.42189,0,0,0,0,100,0),
+(@PATH,15,-10903.75,-1963.212,92.4287,0,0,0,0,100,0),
+(@PATH,16,-10907.83,-1994.959,92.43437,0,0,0,0,100,0),
+(@PATH,17,-10911.13,-1999.935,92.43394,0,0,0,0,100,0),
+(@PATH,18,-10916.75,-2002.692,92.43467,0,0,0,0,100,0),
+(@PATH,19,-10920.86,-2037.652,86.46838,0,0,0,0,100,0),
+(@PATH,20,-10923.34,-2042.72,86.32289,0,0,0,0,100,0),
+(@PATH,21,-10927.59,-2043.72,86.32289,0,0,0,0,100,0),
+(@PATH,22,-10933.56,-2043.322,86.32355,0,0,0,0,100,0),
+(@PATH,23,-10937.03,-2040.081,86.32348,0,0,0,0,100,0),
+(@PATH,24,-10937.61,-2035.351,86.17421,0,0,0,0,100,0),
+(@PATH,25,-10935.98,-2020.486,80.32269,0,0,0,0,100,0),
+(@PATH,26,-10938.22,-2019.048,80.224,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00041939B3 .go -10946.03 -2018.407 80.01561
+
+SET @NPC := 135163;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10955.42,`position_y`=-1963.914,`position_z`=80.2235 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10955.42,-1963.914,80.2235,0,0,0,0,100,0),
+(@PATH,2,-10954.92,-1963.914,80.2235,0,0,0,0,100,0),
+(@PATH,3,-10953.17,-1964.164,80.2235,0,0,0,0,100,0),
+(@PATH,4,-10951.67,-1964.164,80.2235,0,0,0,0,100,0),
+(@PATH,5,-10948.86,-1964.864,80.22345,0,0,0,0,100,0),
+(@PATH,6,-10950.26,-1979.561,80.22365,0,0,0,0,100,0),
+(@PATH,7,-10951.19,-1990.361,80.22372,0,0,0,0,100,0),
+(@PATH,8,-10951.69,-1996.111,80.22372,0,0,0,0,100,0),
+(@PATH,9,-10952.35,-2001.243,80.22384,0,0,0,0,100,0),
+(@PATH,10,-10952.85,-2007.493,80.22384,0,0,0,0,100,0),
+(@PATH,11,-10953.4,-2011.886,80.22395,0,0,0,0,100,0),
+(@PATH,12,-10954.68,-2022.679,80.224,0,0,0,0,100,0),
+(@PATH,13,-10954.93,-2024.179,80.224,0,0,0,0,100,0),
+(@PATH,14,-10955.48,-2028.294,80.22382,0,0,0,0,100,0),
+(@PATH,15,-10957.73,-2030.747,80.22321,0,0,0,0,100,0),
+(@PATH,16,-10962.98,-2030.497,80.22321,0,0,0,0,100,0),
+(@PATH,17,-10972.18,-2030.008,80.22282,0,0,0,0,100,0),
+(@PATH,18,-10983.17,-2027.766,80.22281,0,0,0,0,100,0),
+(@PATH,19,-10988.94,-2024.042,80.22321,0,0,0,0,100,0),
+(@PATH,20,-10988.37,-2013.056,80.22353,0,0,0,0,100,0),
+(@PATH,21,-10988.54,-2013.409,79.97359,0,0,0,0,100,0),
+(@PATH,22,-10988.46,-2013.481,80.22325,0,0,0,0,100,0),
+(@PATH,23,-10988.71,-2023.731,80.22325,0,0,0,0,100,0),
+(@PATH,24,-10988.75,-2023.836,80.22316,0,0,0,0,100,0),
+(@PATH,25,-10988.75,-2024.336,80.22316,0,0,0,0,100,0),
+(@PATH,26,-10982.8,-2028.037,80.22272,0,0,0,0,100,0),
+(@PATH,27,-10971.73,-2030.244,80.22316,0,0,0,0,100,0),
+(@PATH,28,-10962.98,-2030.494,80.22316,0,0,0,0,100,0),
+(@PATH,29,-10957.72,-2030.729,80.22354,0,0,0,0,100,0),
+(@PATH,30,-10955.97,-2028.979,80.22354,0,0,0,0,100,0),
+(@PATH,31,-10955.48,-2028.02,80.22393,0,0,0,0,100,0),
+(@PATH,32,-10954.98,-2024.27,80.22393,0,0,0,0,100,0),
+(@PATH,33,-10954.72,-2023.956,80.22394,0,0,0,0,100,0),
+(@PATH,34,-10954.47,-2022.456,80.22394,0,0,0,0,100,0),
+(@PATH,35,-10953.16,-2011.596,80.22389,0,0,0,0,100,0),
+(@PATH,36,-10953.16,-2007.846,80.22389,0,0,0,0,100,0),
+(@PATH,37,-10952.21,-2001.05,80.22374,0,0,0,0,100,0),
+(@PATH,38,-10951.96,-1996.3,80.22374,0,0,0,0,100,0),
+(@PATH,39,-10951.04,-1990.129,80.22367,0,0,0,0,100,0),
+(@PATH,40,-10949.86,-1979.275,80.22361,0,0,0,0,100,0),
+(@PATH,41,-10948.86,-1965.775,80.22361,0,0,0,0,100,0),
+(@PATH,42,-10948.85,-1965.412,80.22345,0,0,0,0,100,0),
+(@PATH,43,-10951.85,-1964.412,80.22345,0,0,0,0,100,0),
+(@PATH,44,-10953.1,-1964.162,80.22345,0,0,0,0,100,0),
+(@PATH,45,-10955.14,-1963.792,80.22339,0,0,0,0,100,0),
+(@PATH,46,-10960.14,-1963.292,80.22339,0,0,0,0,100,0),
+(@PATH,47,-10965.23,-1962.463,80.2235,0,0,0,0,100,0),
+(@PATH,48,-10965.14,-1962.785,79.97355,0,0,0,0,100,0),
+(@PATH,49,-10960.49,-1963.204,80.22346,0,0,0,0,100,0),
+(@PATH,50,-10955.74,-1963.704,80.22346,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00049939B3 .go -10955.42 -1963.914 80.2235
+
+SET @NPC := 135164;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10966.42,`position_y`=-1982.83,`position_z`=80.22289 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10966.42,-1982.83,80.22289,0,0,0,0,100,0),
+(@PATH,2,-10966.24,-1994.689,80.22308,0,0,0,0,100,0),
+(@PATH,3,-10964.49,-1996.189,80.22308,0,0,0,0,100,0),
+(@PATH,4,-10960.91,-2000.212,80.22343,0,0,0,0,100,0),
+(@PATH,5,-10960.91,-2004.462,80.22343,0,0,0,0,100,0),
+(@PATH,6,-10960.92,-2011.736,80.22325,0,0,0,0,100,0),
+(@PATH,7,-10964.42,-2015.986,80.22325,0,0,0,0,100,0),
+(@PATH,8,-10970.53,-2022.625,80.22308,0,0,0,0,100,0),
+(@PATH,9,-10972.53,-2020.375,80.22308,0,0,0,0,100,0),
+(@PATH,10,-10972.61,-2018.252,80.22304,0,0,0,0,100,0),
+(@PATH,11,-10977.02,-2015.768,80.22273,0,0,0,0,100,0),
+(@PATH,12,-10973.18,-2002.99,80.22287,0,0,0,0,100,0),
+(@PATH,13,-10975.69,-1994.738,80.22289,0,0,0,0,100,0),
+(@PATH,14,-10973.55,-1987.507,80.22292,0,0,0,0,100,0),
+(@PATH,15,-10973.07,-1975.399,80.22276,0,0,0,0,100,0),
+(@PATH,16,-10967.98,-1974.459,80.22279,0,0,0,0,100,0),
+(@PATH,17,-10967.48,-1973.709,80.22279,0,0,0,0,100,0),
+(@PATH,18,-10964.03,-1970.752,80.22292,0,0,0,0,100,0),
+(@PATH,19,-10959.04,-1970.99,80.22316,0,0,0,0,100,0),
+(@PATH,20,-10957.93,-1975.517,80.22319,0,0,0,0,100,0),
+(@PATH,21,-10959.64,-1979.725,80.22298,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00051939B3 .go -10966.42 -1982.83 80.22289
+
+SET @NPC := 135152;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10993.07,`position_y`=-2027.777,`position_z`=79.97364 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10993.07,-2027.777,79.97364,0,0,0,0,100,0),
+(@PATH,2,-10954.54,-2031.941,80.22369,0,0,0,0,100,0),
+(@PATH,3,-10945.95,-1963.57,80.2234,0,0,0,0,100,0),
+(@PATH,4,-10964.31,-1961.222,80.22327,0,0,0,0,100,0),
+(@PATH,5,-10945.95,-1963.57,80.2234,0,0,0,0,100,0),
+(@PATH,6,-10954.54,-2031.941,80.22369,0,0,0,0,100,0),
+(@PATH,7,-10993.07,-2027.777,79.97364,0,0,0,0,100,0),
+(@PATH,8,-10990.63,-2007.031,80.22373,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00059939B3 .go -10993.07 -2027.777 79.97364
+
+SET @NPC := 135161;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10940.92,`position_y`=-1998.817,`position_z`=93.95387 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10936.96,-1999.992,92.54521,0,0,0,0,100,0),
+(@PATH,2,-10940.92,-1998.817,93.95387,0,0,0,0,100,0),
+(@PATH,3,-10946.22,-2042.642,94.07538,0,0,0,0,100,0),
+(@PATH,4,-11002.46,-2037.389,94.07399,0,0,0,0,100,0),
+(@PATH,5,-10997.76,-1988.969,94.08043,0,0,0,0,100,0),
+(@PATH,6,-11001.04,-1986.668,94.07949,0,0,0,0,100,0),
+(@PATH,7,-11019.84,-1984.078,94.08058,0,0,0,0,100,0),
+(@PATH,8,-11021.94,-1979.799,94.07922,0,0,0,0,100,0),
+(@PATH,9,-11021.18,-1971.51,94.07477,0,0,0,0,100,0),
+(@PATH,10,-11021.94,-1979.799,94.07922,0,0,0,0,100,0),
+(@PATH,11,-11019.84,-1984.078,94.08058,0,0,0,0,100,0),
+(@PATH,12,-11001.04,-1986.668,94.07949,0,0,0,0,100,0),
+(@PATH,13,-10997.76,-1988.969,94.08043,0,0,0,0,100,0),
+(@PATH,14,-11002.46,-2037.389,94.07399,0,0,0,0,100,0),
+(@PATH,15,-10946.22,-2042.642,94.07538,0,0,0,0,100,0),
+(@PATH,16,-10940.92,-1998.817,93.95387,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00061939B3 .go -10936.96 -1999.992 92.54521
+
+SET @NPC := 135166;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-11018.67,`position_y`=-1948.95,`position_z`=94.11409 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-11018.67,-1948.95,94.11409,0,0,0,0,100,0),
+(@PATH,2,-11019.33,-1955.598,94.06949,0,0,0,0,100,0),
+(@PATH,3,-11017.58,-1958.348,94.06949,0,0,0,0,100,0),
+(@PATH,4,-11015.82,-1960.591,94.07437,0,0,0,0,100,0),
+(@PATH,5,-11010.95,-1961.954,94.07813,0,0,0,0,100,0),
+(@PATH,6,-11005.31,-1962.993,94.07982,0,0,0,0,100,0),
+(@PATH,7,-11000.51,-1962.511,94.08182,0,0,0,0,100,0),
+(@PATH,8,-10997.26,-1960.511,94.08182,0,0,0,0,100,0),
+(@PATH,9,-10997.06,-1960.231,94.07545,0,0,0,0,100,0),
+(@PATH,10,-10993.45,-1956.026,94.0743,0,0,0,0,100,0),
+(@PATH,11,-10992.71,-1952.289,94.06744,0,0,0,0,100,0),
+(@PATH,12,-10992.46,-1951.039,94.06744,0,0,0,0,100,0),
+(@PATH,13,-10989.33,-1951.245,94.06941,0,0,0,0,100,0),
+(@PATH,14,-10989.58,-1952.745,94.06941,0,0,0,0,100,0),
+(@PATH,15,-10990.44,-1956.788,94.07174,0,0,0,0,100,0),
+(@PATH,16,-10992.64,-1960.311,94.07793,0,0,0,0,100,0),
+(@PATH,17,-10999.8,-1964.796,94.08316,0,0,0,0,100,0),
+(@PATH,18,-11003.42,-1967.318,94.08348,0,0,0,0,100,0),
+(@PATH,19,-11005.92,-1969.318,94.08348,0,0,0,0,100,0),
+(@PATH,20,-11009.72,-1972.45,94.08435,0,0,0,0,100,0),
+(@PATH,21,-11006.94,-1976.569,94.08415,0,0,0,0,100,0),
+(@PATH,22,-11005.19,-1978.569,94.08415,0,0,0,0,100,0),
+(@PATH,23,-11002.7,-1981.706,94.08524,0,0,0,0,100,0),
+(@PATH,24,-10996.71,-1985.477,94.08297,0,0,0,0,100,0),
+(@PATH,25,-10993.34,-1986.766,94.08041,0,0,0,0,100,0),
+(@PATH,26,-10998.21,-2033.577,94.07561,0,0,0,0,100,0),
+(@PATH,27,-10949.22,-2039.019,94.07603,0,0,0,0,100,0),
+(@PATH,28,-10941.91,-1976.454,94.07447,0,0,0,0,100,0),
+(@PATH,29,-10941.03,-1973.073,94.07249,0,0,0,0,100,0),
+(@PATH,30,-10941.03,-1970.573,94.07249,0,0,0,0,100,0),
+(@PATH,31,-10938.04,-1944.34,94.0692,0,0,0,0,100,0),
+(@PATH,32,-10944.45,-1938.374,94.06937,0,0,0,0,100,0),
+(@PATH,33,-10945.51,-1937.203,94.07327,0,0,0,0,100,0),
+(@PATH,34,-10942.28,-1905.302,93.82167,0,0,0,0,100,0),
+(@PATH,35,-10945.63,-1937.244,94.0717,0,0,0,0,100,0),
+(@PATH,36,-10944.63,-1938.244,94.0717,0,0,0,0,100,0),
+(@PATH,37,-10938.18,-1944.174,94.06793,0,0,0,0,100,0),
+(@PATH,38,-10940.76,-1970.675,94.07205,0,0,0,0,100,0),
+(@PATH,39,-10941.05,-1973.169,94.07341,0,0,0,0,100,0),
+(@PATH,40,-10942.1,-1976.591,94.07454,0,0,0,0,100,0),
+(@PATH,41,-10949.38,-2038.871,94.07526,0,0,0,0,100,0),
+(@PATH,42,-10998.12,-2033.78,94.07454,0,0,0,0,100,0),
+(@PATH,43,-10993.17,-1986.922,94.08283,0,0,0,0,100,0),
+(@PATH,44,-10996.42,-1985.672,94.08283,0,0,0,0,100,0),
+(@PATH,45,-11002.46,-1981.708,94.08536,0,0,0,0,100,0),
+(@PATH,46,-11005.32,-1978.522,94.08371,0,0,0,0,100,0),
+(@PATH,47,-11007.07,-1976.272,94.08371,0,0,0,0,100,0),
+(@PATH,48,-11009.86,-1972.258,94.08409,0,0,0,0,100,0),
+(@PATH,49,-11006.01,-1968.957,94.08367,0,0,0,0,100,0),
+(@PATH,50,-11003.51,-1967.457,94.08367,0,0,0,0,100,0),
+(@PATH,51,-10999.68,-1964.603,94.08018,0,0,0,0,100,0),
+(@PATH,52,-10992.57,-1960.071,94.07755,0,0,0,0,100,0),
+(@PATH,53,-10990.57,-1957.071,94.07755,0,0,0,0,100,0),
+(@PATH,54,-10989.64,-1952.785,94.06929,0,0,0,0,100,0),
+(@PATH,55,-10989.41,-1951.198,94.06895,0,0,0,0,100,0),
+(@PATH,56,-10992.41,-1950.948,94.06895,0,0,0,0,100,0),
+(@PATH,57,-10992.66,-1952.448,94.06895,0,0,0,0,100,0),
+(@PATH,58,-10993.41,-1956.079,94.07048,0,0,0,0,100,0),
+(@PATH,59,-10997.04,-1960.266,94.07538,0,0,0,0,100,0),
+(@PATH,60,-11000.84,-1962.545,94.08139,0,0,0,0,100,0),
+(@PATH,61,-11005.54,-1962.94,94.07911,0,0,0,0,100,0),
+(@PATH,62,-11011.18,-1961.785,94.07573,0,0,0,0,100,0),
+(@PATH,63,-11015.9,-1960.729,94.07407,0,0,0,0,100,0),
+(@PATH,64,-11017.4,-1958.479,94.07407,0,0,0,0,100,0),
+(@PATH,65,-11019.35,-1955.508,94.06929,0,0,0,0,100,0);
+-- 0x1C310842801005C00053CE00069939B3 .go -11018.67 -1948.95 94.11409
+
+SET @NPC := 135308;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10979.41,`position_y`=-1917.581,`position_z`=79.1259 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10979.41,-1917.581,79.1259,0,0,0,0,100,0),
+(@PATH,2,-10998.85,-1915.525,79.12059,0,0,0,0,100,0),
+(@PATH,3,-11004.85,-1917.525,79.12059,0,0,0,0,100,0),
+(@PATH,4,-11006.42,-1919.255,79.13147,0,0,0,0,100,0),
+(@PATH,5,-11009.31,-1923.276,79.13788,0,0,0,0,100,0),
+(@PATH,6,-11014.77,-1924.695,79.11803,0,0,0,0,100,0),
+(@PATH,7,-11025.74,-1923.575,79.06779,0,0,0,0,100,0),
+(@PATH,8,-11039.73,-1922.107,77.51696,0,0,0,0,100,0),
+(@PATH,9,-11050.26,-1923.549,77.51479,0,0,0,0,100,0),
+(@PATH,10,-11062.01,-1926.049,77.51479,0,0,0,0,100,0),
+(@PATH,11,-11068.23,-1927.658,77.51482,0,0,0,0,100,0),
+(@PATH,12,-11050.19,-1925.471,77.51665,0,0,0,0,100,0),
+(@PATH,13,-11039.85,-1924.404,77.56751,0,0,0,0,100,0),
+(@PATH,14,-11025.49,-1925.841,79.11525,0,0,0,0,100,0),
+(@PATH,15,-11014.73,-1927.159,79.11803,0,0,0,0,100,0),
+(@PATH,16,-11010.48,-1927.909,79.11803,0,0,0,0,100,0),
+(@PATH,17,-11008.93,-1928.397,79.11803,0,0,0,0,100,0),
+(@PATH,18,-11007.43,-1929.897,79.11803,0,0,0,0,100,0),
+(@PATH,19,-11004.79,-1932.291,79.11801,0,0,0,0,100,0),
+(@PATH,20,-10995.54,-1934.041,79.11801,0,0,0,0,100,0),
+(@PATH,21,-10970.88,-1936.847,79.11803,0,0,0,0,100,0),
+(@PATH,22,-10965.63,-1935.597,79.11803,0,0,0,0,100,0),
+(@PATH,23,-10963.02,-1932.276,79.11803,0,0,0,0,100,0),
+(@PATH,24,-10960.78,-1928.736,79.11803,0,0,0,0,100,0),
+(@PATH,25,-10962.28,-1925.236,79.11803,0,0,0,0,100,0),
+(@PATH,26,-10963.28,-1922.127,79.1109,0,0,0,0,100,0),
+(@PATH,27,-10968.51,-1919.033,79.11447,0,0,0,0,100,0);
+-- 0x1C310842801007C00053CE00001939B3 .go -10979.41 -1917.581 79.1259
+
+SET @NPC := 135311;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-10967.35,`position_y`=-1910.074,`position_z`=79.13056 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-10967.35,-1910.074,79.13056,0,0,0,0,100,0),
+(@PATH,2,-10973.81,-1909.259,79.13441,0,0,0,0,100,0),
+(@PATH,3,-10978.96,-1902.012,79.11913,0,0,0,0,100,0),
+(@PATH,4,-10993.51,-1900.544,79.10841,0,0,0,0,100,0),
+(@PATH,5,-10998.31,-1904.632,79.0873,0,0,0,0,100,0),
+(@PATH,6,-11008.63,-1904.277,79.12164,0,0,0,0,100,0),
+(@PATH,7,-11016.06,-1902.035,79.11803,0,0,0,0,100,0),
+(@PATH,8,-11018.93,-1894.202,79.11803,0,0,0,0,100,0),
+(@PATH,9,-11013.55,-1888.369,79.11407,0,0,0,0,100,0),
+(@PATH,10,-11005.47,-1887.72,79.09593,0,0,0,0,100,0),
+(@PATH,11,-10997.97,-1889.47,79.09593,0,0,0,0,100,0),
+(@PATH,12,-10993.66,-1894.292,79.0679,0,0,0,0,100,0),
+(@PATH,13,-10993.11,-1896.752,79.08858,0,0,0,0,100,0),
+(@PATH,14,-10978.52,-1899.429,79.14062,0,0,0,0,100,0),
+(@PATH,15,-10971.52,-1891.436,79.14864,0,0,0,0,100,0),
+(@PATH,16,-10968.58,-1890.591,79.14295,0,0,0,0,100,0),
+(@PATH,17,-10964.36,-1890.848,79.12196,0,0,0,0,100,0),
+(@PATH,18,-10958.21,-1891.544,78.85779,0,0,0,0,100,0),
+(@PATH,19,-10953.68,-1895.616,79.11803,0,0,0,0,100,0),
+(@PATH,20,-10951.67,-1902.097,79.12449,0,0,0,0,100,0),
+(@PATH,21,-10954.11,-1907.472,79.1279,0,0,0,0,100,0),
+(@PATH,22,-10957.36,-1910.472,79.1279,0,0,0,0,100,0);
+-- 0x1C310842801007C00053CE00009939B3 .go -10967.35 -1910.074 79.13056
+
+SET @NPC := 135307;
+SET @PATH := @NPC * 10;
+UPDATE `creature` SET `spawndist`=0,`MovementType`=2,`position_x`=-11097.81,`position_y`=-1933.661,`position_z`=50.14211 WHERE `guid`=@NPC;
+DELETE FROM `creature_addon` WHERE `guid`=@NPC;
+INSERT INTO `creature_addon` (`guid`,`path_id`,`mount`,`bytes1`,`bytes2`,`emote`,`auras`) VALUES (@NPC,@PATH,0,0,1,0, '');
+DELETE FROM `waypoint_data` WHERE `id`=@PATH;
+INSERT INTO `waypoint_data` (`id`,`point`,`position_x`,`position_y`,`position_z`,`orientation`,`delay`,`move_type`,`action`,`action_chance`,`wpguid`) VALUES
+(@PATH,1,-11097.81,-1933.661,50.14211,0,0,0,0,100,0),
+(@PATH,2,-11102.14,-1941.538,50.13525,0,0,0,0,100,0),
+(@PATH,3,-11110.07,-1946.739,50.13507,0,0,0,0,100,0),
+(@PATH,4,-11116.22,-1949.221,50.13885,0,0,0,0,100,0),
+(@PATH,5,-11127.4,-1949.477,50.13752,0,0,0,0,100,0),
+(@PATH,6,-11137.96,-1945.1,50.13647,0,0,0,0,100,0),
+(@PATH,7,-11127.29,-1949.459,50.13817,0,0,0,0,100,0),
+(@PATH,8,-11116.23,-1949.254,50.13683,0,0,0,0,100,0),
+(@PATH,9,-11110.07,-1946.739,50.13507,0,0,0,0,100,0),
+(@PATH,10,-11102.14,-1941.538,50.13525,0,0,0,0,100,0);
+-- 0x1C310842800FC7C00053CE00001939B3 .go -11097.81 -1933.661 50.14211
diff --git a/sql/updates/world/2016_03_27_00_world.sql b/sql/updates/world/2016_03_27_00_world.sql
new file mode 100644
index 00000000000..9421881c88a
--- /dev/null
+++ b/sql/updates/world/2016_03_27_00_world.sql
@@ -0,0 +1,3 @@
+DELETE FROM `spell_script_names` WHERE `ScriptName` = 'spell_gen_clear_debuffs';
+INSERT INTO `spell_script_names` (`spell_id`, `ScriptName`) VALUES
+(34098, 'spell_gen_clear_debuffs');
diff --git a/sql/updates/world/2016_03_28_00_world.sql b/sql/updates/world/2016_03_28_00_world.sql
new file mode 100644
index 00000000000..b4a7e2d5a36
--- /dev/null
+++ b/sql/updates/world/2016_03_28_00_world.sql
@@ -0,0 +1,2 @@
+--
+UPDATE `creature` SET `spawndist`=0 WHERE `guid`=135230;
diff --git a/sql/updates/world/2016_03_28_01_world.sql b/sql/updates/world/2016_03_28_01_world.sql
new file mode 100644
index 00000000000..b4a24b011b3
--- /dev/null
+++ b/sql/updates/world/2016_03_28_01_world.sql
@@ -0,0 +1 @@
+UPDATE creature_template SET ScriptName = "npc_pet_gen_baby_blizzard_bear" WHERE entry = 32841;
diff --git a/sql/updates/world/2016_03_29_00_world_335.sql b/sql/updates/world/2016_03_29_00_world_335.sql
new file mode 100644
index 00000000000..e3851e59c8e
--- /dev/null
+++ b/sql/updates/world/2016_03_29_00_world_335.sql
@@ -0,0 +1,11 @@
+--
+UPDATE `game_event` SET `start_time`='2016-06-21 00:01:00' WHERE `eventEntry`=1;
+UPDATE `game_event` SET `start_time`='2016-12-15 06:00:00' WHERE `eventEntry`=2;
+UPDATE `game_event` SET `start_time`='2016-03-27 00:01:00' WHERE `eventEntry`=9;
+UPDATE `game_event` SET `start_time`='2016-05-02 00:01:00' WHERE `eventEntry`=10;
+UPDATE `game_event` SET `start_time`='2016-09-09 00:01:00' WHERE `eventEntry`=11;
+UPDATE `game_event` SET `start_time`='2016-10-18 01:00:00' WHERE `eventEntry`=12;
+UPDATE `game_event` SET `start_time`='2016-09-20 00:01:00' WHERE `eventEntry`=24;
+UPDATE `game_event` SET `start_time`='2016-11-21 01:00:00' WHERE `eventEntry`=26;
+UPDATE `game_event` SET `start_time`='2016-09-19 00:01:00' WHERE `eventEntry`=50;
+UPDATE `game_event` SET `start_time`='2016-11-01 01:00:00' WHERE `eventEntry`=51;
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 6f13dc821a9..4250df6d1f1 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -30,6 +30,8 @@ endif (USE_COREPCH)
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+add_definitions(-DTRINITY_API_EXPORT_COMMON)
+
add_library(common
${PRIVATE_SOURCES}
${PRIVATE_PCH_SOURCE}
@@ -78,6 +80,18 @@ set_target_properties(common
FOLDER
"server")
+if( BUILD_SHARED_LIBS )
+ if( UNIX )
+ install(TARGETS common
+ LIBRARY
+ DESTINATION lib)
+ elseif( WIN32 )
+ install(TARGETS common
+ RUNTIME
+ DESTINATION "${CMAKE_INSTALL_PREFIX}")
+ endif()
+endif()
+
# Generate precompiled header
if (USE_COREPCH)
add_cxx_pch(common ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
diff --git a/src/common/Collision/BoundingIntervalHierarchy.h b/src/common/Collision/BoundingIntervalHierarchy.h
index 0b15bd2d92f..eb0a102806f 100644
--- a/src/common/Collision/BoundingIntervalHierarchy.h
+++ b/src/common/Collision/BoundingIntervalHierarchy.h
@@ -67,7 +67,7 @@ struct AABound
Copyright (c) 2003-2007 Christopher Kulla
*/
-class BIH
+class TC_COMMON_API BIH
{
private:
void init_empty()
diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h
index 0f18bb265f8..85707efebd2 100644
--- a/src/common/Collision/DynamicTree.h
+++ b/src/common/Collision/DynamicTree.h
@@ -31,7 +31,7 @@ namespace G3D
class GameObjectModel;
struct DynTreeImpl;
-class DynamicMapTree
+class TC_COMMON_API DynamicMapTree
{
DynTreeImpl *impl;
diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h
index 1e64551956c..35437b7b816 100644
--- a/src/common/Collision/Management/IVMapManager.h
+++ b/src/common/Collision/Management/IVMapManager.h
@@ -42,7 +42,7 @@ namespace VMAP
#define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case
//===========================================================
- class IVMapManager
+ class TC_COMMON_API IVMapManager
{
private:
bool iEnableLineOfSightCalc;
diff --git a/src/common/Collision/Management/MMapFactory.h b/src/common/Collision/Management/MMapFactory.h
index edd074fc93d..6dda7a40a22 100644
--- a/src/common/Collision/Management/MMapFactory.h
+++ b/src/common/Collision/Management/MMapFactory.h
@@ -38,7 +38,7 @@ namespace MMAP
// static class
// holds all mmap global data
// access point to MMapManager singleton
- class MMapFactory
+ class TC_COMMON_API MMapFactory
{
public:
static MMapManager* createOrGetMMapManager();
diff --git a/src/common/Collision/Management/MMapManager.h b/src/common/Collision/Management/MMapManager.h
index 1a502a916dd..afb693553a4 100644
--- a/src/common/Collision/Management/MMapManager.h
+++ b/src/common/Collision/Management/MMapManager.h
@@ -58,7 +58,7 @@ namespace MMAP
// singleton class
// holds all all access to mmap loading unloading and meshes
- class MMapManager
+ class TC_COMMON_API MMapManager
{
public:
MMapManager() : loadedTiles(0), thread_safe_environment(true) {}
diff --git a/src/common/Collision/Management/VMapFactory.h b/src/common/Collision/Management/VMapFactory.h
index 1a45bd5094b..a730fa12ef2 100644
--- a/src/common/Collision/Management/VMapFactory.h
+++ b/src/common/Collision/Management/VMapFactory.h
@@ -29,7 +29,7 @@ namespace VMAP
{
//===========================================================
- class VMapFactory
+ class TC_COMMON_API VMapFactory
{
public:
static IVMapManager* createOrGetVMapManager();
diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h
index 722ac4935c6..61c5025e41f 100644
--- a/src/common/Collision/Management/VMapManager2.h
+++ b/src/common/Collision/Management/VMapManager2.h
@@ -51,7 +51,7 @@ namespace VMAP
class StaticMapTree;
class WorldModel;
- class ManagedModel
+ class TC_COMMON_API ManagedModel
{
public:
ManagedModel() : iModel(nullptr), iRefCount(0) { }
@@ -75,7 +75,7 @@ namespace VMAP
VMAP_DISABLE_LIQUIDSTATUS = 0x8
};
- class VMapManager2 : public IVMapManager
+ class TC_COMMON_API VMapManager2 : public IVMapManager
{
protected:
// Tree to check collision
diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h
index 63d542754c1..c6a283cac4d 100644
--- a/src/common/Collision/Maps/MapTree.h
+++ b/src/common/Collision/Maps/MapTree.h
@@ -29,7 +29,7 @@ namespace VMAP
class GroupModel;
class VMapManager2;
- struct LocationInfo
+ struct TC_COMMON_API LocationInfo
{
LocationInfo(): hitInstance(nullptr), hitModel(nullptr), ground_Z(-G3D::finf()) { }
const ModelInstance* hitInstance;
@@ -37,7 +37,7 @@ namespace VMAP
float ground_Z;
};
- class StaticMapTree
+ class TC_COMMON_API StaticMapTree
{
typedef std::unordered_map<uint32, bool> loadedTileMap;
typedef std::unordered_map<uint32, uint32> loadedSpawnMap;
@@ -87,7 +87,7 @@ namespace VMAP
StaticMapTree& operator=(StaticMapTree const& right) = delete;
};
- struct AreaInfo
+ struct TC_COMMON_API AreaInfo
{
AreaInfo(): result(false), ground_Z(-G3D::finf()), flags(0), adtId(0),
rootId(0), groupId(0) { }
diff --git a/src/common/Collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h
index 1e2dc1924f1..74111f69910 100644
--- a/src/common/Collision/Maps/TileAssembler.h
+++ b/src/common/Collision/Maps/TileAssembler.h
@@ -35,7 +35,7 @@ namespace VMAP
*/
//===============================================
- class ModelPosition
+ class TC_COMMON_API ModelPosition
{
private:
G3D::Matrix3 iRotation;
@@ -55,7 +55,7 @@ namespace VMAP
typedef std::map<uint32, ModelSpawn> UniqueEntryMap;
typedef std::multimap<uint32, uint32> TileMap;
- struct MapSpawns
+ struct TC_COMMON_API MapSpawns
{
UniqueEntryMap UniqueEntries;
TileMap TileEntries;
@@ -64,7 +64,7 @@ namespace VMAP
typedef std::map<uint32, MapSpawns*> MapData;
//===============================================
- struct GroupModel_Raw
+ struct TC_COMMON_API GroupModel_Raw
{
uint32 mogpflags;
uint32 GroupWMOID;
@@ -82,7 +82,7 @@ namespace VMAP
bool Read(FILE* f);
};
- struct WorldModel_Raw
+ struct TC_COMMON_API WorldModel_Raw
{
uint32 RootWMOID;
std::vector<GroupModel_Raw> groupsArray;
@@ -90,7 +90,7 @@ namespace VMAP
bool Read(const char * path);
};
- class TileAssembler
+ class TC_COMMON_API TileAssembler
{
private:
std::string iDestDir;
diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h
index 7834f53c63a..37f11af20ac 100644
--- a/src/common/Collision/Models/GameObjectModel.h
+++ b/src/common/Collision/Models/GameObjectModel.h
@@ -35,7 +35,7 @@ namespace VMAP
class GameObject;
struct GameObjectDisplayInfoEntry;
-class GameObjectModelOwnerBase
+class TC_COMMON_API GameObjectModelOwnerBase
{
public:
virtual bool IsSpawned() const { return false; }
@@ -47,7 +47,7 @@ public:
virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const { }
};
-class GameObjectModel /*, public Intersectable*/
+class TC_COMMON_API GameObjectModel /*, public Intersectable*/
{
GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { }
public:
@@ -84,6 +84,6 @@ private:
std::unique_ptr<GameObjectModelOwnerBase> owner;
};
-void LoadGameObjectModelList(std::string const& dataPath);
+TC_COMMON_API void LoadGameObjectModelList(std::string const& dataPath);
#endif // _GAMEOBJECT_MODEL_H
diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h
index d101630d1e9..84a41b15ce6 100644
--- a/src/common/Collision/Models/ModelInstance.h
+++ b/src/common/Collision/Models/ModelInstance.h
@@ -39,7 +39,7 @@ namespace VMAP
MOD_HAS_BOUND = 1<<2
};
- class ModelSpawn
+ class TC_COMMON_API ModelSpawn
{
public:
//mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
@@ -60,7 +60,7 @@ namespace VMAP
static bool writeToFile(FILE* rw, const ModelSpawn &spawn);
};
- class ModelInstance: public ModelSpawn
+ class TC_COMMON_API ModelInstance: public ModelSpawn
{
public:
ModelInstance(): iInvScale(0.0f), iModel(nullptr) { }
diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h
index 39787f6c664..bfc0367627f 100644
--- a/src/common/Collision/Models/WorldModel.h
+++ b/src/common/Collision/Models/WorldModel.h
@@ -33,7 +33,7 @@ namespace VMAP
struct AreaInfo;
struct LocationInfo;
- class MeshTriangle
+ class TC_COMMON_API MeshTriangle
{
public:
MeshTriangle() : idx0(0), idx1(0), idx2(0) { }
@@ -44,7 +44,7 @@ namespace VMAP
uint32 idx2;
};
- class WmoLiquid
+ class TC_COMMON_API WmoLiquid
{
public:
WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type);
@@ -70,7 +70,7 @@ namespace VMAP
};
/*! holding additional info for WMO group files */
- class GroupModel
+ class TC_COMMON_API GroupModel
{
public:
GroupModel() : iBound(), iMogpFlags(0), iGroupWMOID(0), iLiquid(NULL) { }
@@ -103,7 +103,7 @@ namespace VMAP
};
/*! Holds a model (converted M2 or WMO) in its original coordinate space */
- class WorldModel
+ class TC_COMMON_API WorldModel
{
public:
WorldModel(): RootWMOID(0) { }
diff --git a/src/common/Collision/RegularGrid.h b/src/common/Collision/RegularGrid.h
index 6a2a07968ad..563cf516406 100644
--- a/src/common/Collision/RegularGrid.h
+++ b/src/common/Collision/RegularGrid.h
@@ -20,7 +20,7 @@ class NodeCreatorFunc = NodeCreator<Node>,
/*class BoundsFunc = BoundsTrait<T>,*/
class PositionFunc = PositionTrait<T>
>
-class RegularGrid2D
+class TC_COMMON_API RegularGrid2D
{
public:
diff --git a/src/common/Common.h b/src/common/Common.h
index e8adc55d20d..4ab5ae867b9 100644
--- a/src/common/Common.h
+++ b/src/common/Common.h
@@ -130,9 +130,9 @@ enum LocaleConstant
#define MAX_LOCALES 8
#define MAX_ACCOUNT_TUTORIAL_VALUES 8
-extern char const* localeNames[TOTAL_LOCALES];
+TC_COMMON_API extern char const* localeNames[TOTAL_LOCALES];
-LocaleConstant GetLocaleByName(const std::string& name);
+TC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name);
typedef std::vector<std::string> StringVector;
diff --git a/src/common/Configuration/BuiltInConfig.h b/src/common/Configuration/BuiltInConfig.h
index 4ae4ed40189..0ffa059bc41 100644
--- a/src/common/Configuration/BuiltInConfig.h
+++ b/src/common/Configuration/BuiltInConfig.h
@@ -19,6 +19,7 @@
#define BUILT_IN_CONFIG_H
#include <string>
+#include "Define.h"
/// Provides helper functions to access built-in values
/// which can be overwritten in config
@@ -26,16 +27,16 @@ namespace BuiltInConfig
{
/// Returns the CMake command when any is specified in the config,
/// returns the built-in path otherwise
- std::string GetCMakeCommand();
+ TC_COMMON_API std::string GetCMakeCommand();
/// Returns the build directory path when any is specified in the config,
/// returns the built-in one otherwise
- std::string GetBuildDirectory();
+ TC_COMMON_API std::string GetBuildDirectory();
/// Returns the source directory path when any is specified in the config,
/// returns the built-in one otherwise
- std::string GetSourceDirectory();
+ TC_COMMON_API std::string GetSourceDirectory();
/// Returns the path to the mysql executable (`mysql`) when any is specified
/// in the config, returns the built-in one otherwise
- std::string GetMySQLExecutable();
+ TC_COMMON_API std::string GetMySQLExecutable();
} // namespace BuiltInConfig
diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp
index fba438dbd33..aafd902c558 100644
--- a/src/common/Configuration/Config.cpp
+++ b/src/common/Configuration/Config.cpp
@@ -21,6 +21,7 @@
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/ini_parser.hpp>
#include "Config.h"
+#include "Log.h"
using namespace boost::property_tree;
@@ -69,11 +70,18 @@ bool ConfigMgr::Reload(std::string& error)
std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def) const
{
- std::string value = _config.get<std::string>(ptree::path_type(name, '/'), def);
-
- value.erase(std::remove(value.begin(), value.end(), '"'), value.end());
-
- return value;
+ try
+ {
+ std::string value = _config.get<std::string>(ptree::path_type(name, '/'));
+ value.erase(std::remove(value.begin(), value.end(), '"'), value.end());
+ return value;
+ }
+ catch (boost::property_tree::ptree_bad_path)
+ {
+ TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %s\" to this file",
+ name.c_str(), _filename.c_str(), name.c_str(), def.c_str());
+ return def;
+ }
}
bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) const
@@ -84,20 +92,40 @@ bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) const
val.erase(std::remove(val.begin(), val.end(), '"'), val.end());
return (val == "true" || val == "TRUE" || val == "yes" || val == "YES" || val == "1");
}
- catch (std::exception const& /*ex*/)
+ catch (boost::property_tree::ptree_bad_path)
{
+ TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %d\" to this file",
+ name.c_str(), _filename.c_str(), name.c_str(), def ? 1 : 0);
return def;
}
}
int ConfigMgr::GetIntDefault(std::string const& name, int def) const
{
- return _config.get<int>(ptree::path_type(name, '/'), def);
+ try
+ {
+ return _config.get<int>(ptree::path_type(name, '/'));
+ }
+ catch (boost::property_tree::ptree_bad_path)
+ {
+ TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %d\" to this file",
+ name.c_str(), _filename.c_str(), name.c_str(), def);
+ return def;
+ }
}
float ConfigMgr::GetFloatDefault(std::string const& name, float def) const
{
- return _config.get<float>(ptree::path_type(name, '/'), def);
+ try
+ {
+ return _config.get<float>(ptree::path_type(name, '/'));
+ }
+ catch (boost::property_tree::ptree_bad_path)
+ {
+ TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %f\" to this file",
+ name.c_str(), _filename.c_str(), name.c_str(), def);
+ return def;
+ }
}
std::string const& ConfigMgr::GetFilename()
diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h
index 6882517b509..ff6d279f9ce 100644
--- a/src/common/Configuration/Config.h
+++ b/src/common/Configuration/Config.h
@@ -19,12 +19,14 @@
#ifndef CONFIG_H
#define CONFIG_H
+#include "Define.h"
+
#include <string>
#include <list>
#include <mutex>
#include <boost/property_tree/ptree.hpp>
-class ConfigMgr
+class TC_COMMON_API ConfigMgr
{
ConfigMgr() { }
~ConfigMgr() { }
diff --git a/src/common/Cryptography/ARC4.h b/src/common/Cryptography/ARC4.h
index f39e662e295..7e680176836 100644
--- a/src/common/Cryptography/ARC4.h
+++ b/src/common/Cryptography/ARC4.h
@@ -22,7 +22,7 @@
#include <openssl/evp.h>
#include "Define.h"
-class ARC4
+class TC_COMMON_API ARC4
{
public:
ARC4(uint8 len);
diff --git a/src/common/Cryptography/Authentication/AuthCrypt.h b/src/common/Cryptography/Authentication/AuthCrypt.h
index 878391e3ce8..db4de8a7bd1 100644
--- a/src/common/Cryptography/Authentication/AuthCrypt.h
+++ b/src/common/Cryptography/Authentication/AuthCrypt.h
@@ -23,7 +23,7 @@
class BigNumber;
-class AuthCrypt
+class TC_COMMON_API AuthCrypt
{
public:
AuthCrypt();
diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h
index a5bda50dc72..1d21be1b431 100644
--- a/src/common/Cryptography/BigNumber.h
+++ b/src/common/Cryptography/BigNumber.h
@@ -24,7 +24,7 @@
struct bignum_st;
-class BigNumber
+class TC_COMMON_API BigNumber
{
public:
BigNumber();
diff --git a/src/common/Cryptography/HMACSHA1.h b/src/common/Cryptography/HMACSHA1.h
index 29a926d5b16..049847489a6 100644
--- a/src/common/Cryptography/HMACSHA1.h
+++ b/src/common/Cryptography/HMACSHA1.h
@@ -28,7 +28,7 @@ class BigNumber;
#define SEED_KEY_SIZE 16
-class HmacHash
+class TC_COMMON_API HmacHash
{
public:
HmacHash(uint32 len, uint8 *seed);
diff --git a/src/common/Cryptography/OpenSSLCrypto.h b/src/common/Cryptography/OpenSSLCrypto.h
index df1b14b5eda..65155df9af8 100644
--- a/src/common/Cryptography/OpenSSLCrypto.h
+++ b/src/common/Cryptography/OpenSSLCrypto.h
@@ -18,6 +18,8 @@
#ifndef OPENSSL_CRYPTO_H
#define OPENSSL_CRYPTO_H
+#include "Define.h"
+
/**
* A group of functions which setup openssl crypto module to work properly in multithreaded enviroment
* If not setup properly - it will crash
@@ -25,9 +27,9 @@
namespace OpenSSLCrypto
{
/// Needs to be called before threads using openssl are spawned
- void threadsSetup();
+ TC_COMMON_API void threadsSetup();
/// Needs to be called after threads using openssl are despawned
- void threadsCleanup();
+ TC_COMMON_API void threadsCleanup();
}
-#endif \ No newline at end of file
+#endif
diff --git a/src/common/Cryptography/SHA1.h b/src/common/Cryptography/SHA1.h
index ffa02176a2d..970ab5c0cb9 100644
--- a/src/common/Cryptography/SHA1.h
+++ b/src/common/Cryptography/SHA1.h
@@ -25,7 +25,7 @@
class BigNumber;
-class SHA1Hash
+class TC_COMMON_API SHA1Hash
{
public:
SHA1Hash();
diff --git a/src/common/Debugging/Errors.h b/src/common/Debugging/Errors.h
index 37d247ada82..e4b3563ca96 100644
--- a/src/common/Debugging/Errors.h
+++ b/src/common/Debugging/Errors.h
@@ -23,18 +23,18 @@
namespace Trinity
{
- DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message) ATTR_NORETURN;
- DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) ATTR_NORETURN ATTR_PRINTF(5, 6);
+ DECLSPEC_NORETURN TC_COMMON_API void Assert(char const* file, int line, char const* function, char const* message) ATTR_NORETURN;
+ DECLSPEC_NORETURN TC_COMMON_API void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) ATTR_NORETURN ATTR_PRINTF(5, 6);
- DECLSPEC_NORETURN void Fatal(char const* file, int line, char const* function, char const* message, ...) ATTR_NORETURN ATTR_PRINTF(4, 5);
+ DECLSPEC_NORETURN TC_COMMON_API void Fatal(char const* file, int line, char const* function, char const* message, ...) ATTR_NORETURN ATTR_PRINTF(4, 5);
- DECLSPEC_NORETURN void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN;
+ DECLSPEC_NORETURN TC_COMMON_API void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN;
- DECLSPEC_NORETURN void Abort(char const* file, int line, char const* function) ATTR_NORETURN;
+ DECLSPEC_NORETURN TC_COMMON_API void Abort(char const* file, int line, char const* function) ATTR_NORETURN;
- void Warning(char const* file, int line, char const* function, char const* message);
+ TC_COMMON_API void Warning(char const* file, int line, char const* function, char const* message);
- DECLSPEC_NORETURN void AbortHandler(int sigval) ATTR_NORETURN;
+ DECLSPEC_NORETURN TC_COMMON_API void AbortHandler(int sigval) ATTR_NORETURN;
} // namespace Trinity
diff --git a/src/common/Define.h b/src/common/Define.h
index b34edb6a549..d03d26ad780 100644
--- a/src/common/Define.h
+++ b/src/common/Define.h
@@ -95,6 +95,45 @@
#endif
#endif //COMPILER == COMPILER_GNU
+#ifdef TRINITY_API_USE_DYNAMIC_LINKING
+# if COMPILER == COMPILER_MICROSOFT
+# define TC_API_EXPORT __declspec(dllexport)
+# define TC_API_IMPORT __declspec(dllimport)
+# elif COMPILER == COMPILER_GNU
+# define TC_API_EXPORT __attribute__((visibility("default")))
+# define TC_API_IMPORT
+# else
+# error compiler not supported!
+# endif
+#else
+# define TC_API_EXPORT
+# define TC_API_IMPORT
+#endif
+
+#ifdef TRINITY_API_EXPORT_COMMON
+# define TC_COMMON_API TC_API_EXPORT
+#else
+# define TC_COMMON_API TC_API_IMPORT
+#endif
+
+#ifdef TRINITY_API_EXPORT_DATABASE
+# define TC_DATABASE_API TC_API_EXPORT
+#else
+# define TC_DATABASE_API TC_API_IMPORT
+#endif
+
+#ifdef TRINITY_API_EXPORT_SHARED
+# define TC_SHARED_API TC_API_EXPORT
+#else
+# define TC_SHARED_API TC_API_IMPORT
+#endif
+
+#ifdef TRINITY_API_EXPORT_GAME
+# define TC_GAME_API TC_API_EXPORT
+#else
+# define TC_GAME_API TC_API_IMPORT
+#endif
+
#define UI64FMTD "%" PRIu64
#define UI64LIT(N) UINT64_C(N)
diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp
index 5343fbd6531..2162e36847f 100644
--- a/src/common/GitRevision.cpp
+++ b/src/common/GitRevision.cpp
@@ -1,5 +1,4 @@
#include "GitRevision.h"
-#include "CompilerDefs.h"
#include "revision_data.h"
char const* GitRevision::GetHash()
diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h
index 7fddcb7605a..aace8ad2076 100644
--- a/src/common/GitRevision.h
+++ b/src/common/GitRevision.h
@@ -19,22 +19,23 @@
#define __GITREVISION_H__
#include <string>
+#include "Define.h"
namespace GitRevision
{
- char const* GetHash();
- char const* GetDate();
- char const* GetBranch();
- char const* GetCMakeCommand();
- char const* GetBuildDirectory();
- char const* GetSourceDirectory();
- char const* GetMySQLExecutable();
- char const* GetFullDatabase();
- char const* GetFullVersion();
- char const* GetCompanyNameStr();
- char const* GetLegalCopyrightStr();
- char const* GetFileVersionStr();
- char const* GetProductVersionStr();
+ TC_COMMON_API char const* GetHash();
+ TC_COMMON_API char const* GetDate();
+ TC_COMMON_API char const* GetBranch();
+ TC_COMMON_API char const* GetCMakeCommand();
+ TC_COMMON_API char const* GetBuildDirectory();
+ TC_COMMON_API char const* GetSourceDirectory();
+ TC_COMMON_API char const* GetMySQLExecutable();
+ TC_COMMON_API char const* GetFullDatabase();
+ TC_COMMON_API char const* GetFullVersion();
+ TC_COMMON_API char const* GetCompanyNameStr();
+ TC_COMMON_API char const* GetLegalCopyrightStr();
+ TC_COMMON_API char const* GetFileVersionStr();
+ TC_COMMON_API char const* GetProductVersionStr();
}
#endif
diff --git a/src/common/Logging/Appender.h b/src/common/Logging/Appender.h
index f0bfe423a66..22fe1112239 100644
--- a/src/common/Logging/Appender.h
+++ b/src/common/Logging/Appender.h
@@ -59,7 +59,7 @@ enum AppenderFlags
APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10 // only used by FileAppender
};
-struct LogMessage
+struct TC_COMMON_API LogMessage
{
LogMessage(LogLevel _level, std::string const& _type, std::string&& _text)
: level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(NULL))
@@ -85,7 +85,7 @@ struct LogMessage
}
};
-class Appender
+class TC_COMMON_API Appender
{
public:
Appender(uint8 _id, std::string const& name, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE);
@@ -123,7 +123,7 @@ Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, Appe
return new AppenderImpl(id, name, level, flags, std::forward<ExtraAppenderArgs>(extraArgs));
}
-class InvalidAppenderArgsException : public std::length_error
+class TC_COMMON_API InvalidAppenderArgsException : public std::length_error
{
public:
explicit InvalidAppenderArgsException(std::string const& message) : std::length_error(message) { }
diff --git a/src/common/Logging/AppenderConsole.h b/src/common/Logging/AppenderConsole.h
index 5d7eae36b40..96d17207158 100644
--- a/src/common/Logging/AppenderConsole.h
+++ b/src/common/Logging/AppenderConsole.h
@@ -42,7 +42,7 @@ enum ColorTypes
const uint8 MaxColors = uint8(WHITE) + 1;
-class AppenderConsole : public Appender
+class TC_COMMON_API AppenderConsole : public Appender
{
public:
typedef std::integral_constant<AppenderType, APPENDER_CONSOLE>::type TypeIndex;
diff --git a/src/common/Logging/AppenderFile.h b/src/common/Logging/AppenderFile.h
index 9ba5d59259c..956b7a70b93 100644
--- a/src/common/Logging/AppenderFile.h
+++ b/src/common/Logging/AppenderFile.h
@@ -21,7 +21,7 @@
#include <atomic>
#include "Appender.h"
-class AppenderFile : public Appender
+class TC_COMMON_API AppenderFile : public Appender
{
public:
typedef std::integral_constant<AppenderType, APPENDER_FILE>::type TypeIndex;
diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h
index 062f14d525c..6460e404c90 100644
--- a/src/common/Logging/Log.h
+++ b/src/common/Logging/Log.h
@@ -34,7 +34,7 @@
#define LOGGER_ROOT "root"
-class Log
+class TC_COMMON_API Log
{
typedef std::unordered_map<std::string, Logger> LoggerMap;
diff --git a/src/common/Logging/LogOperation.h b/src/common/Logging/LogOperation.h
index 618629b5423..56e2307d492 100644
--- a/src/common/Logging/LogOperation.h
+++ b/src/common/Logging/LogOperation.h
@@ -19,11 +19,12 @@
#define LOGOPERATION_H
#include <memory>
+#include "Define.h"
class Logger;
struct LogMessage;
-class LogOperation
+class TC_COMMON_API LogOperation
{
public:
LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg)
diff --git a/src/common/Logging/Logger.h b/src/common/Logging/Logger.h
index 67eab4295a4..4ac2e4494cc 100644
--- a/src/common/Logging/Logger.h
+++ b/src/common/Logging/Logger.h
@@ -20,7 +20,7 @@
#include "Appender.h"
-class Logger
+class TC_COMMON_API Logger
{
public:
Logger();
diff --git a/src/common/Utilities/Containers.h b/src/common/Utilities/Containers.h
index f3e9432ca4c..7c889068011 100644
--- a/src/common/Utilities/Containers.h
+++ b/src/common/Utilities/Containers.h
@@ -20,6 +20,7 @@
#include "Define.h"
#include "Random.h"
+#include "Util.h"
#include <algorithm>
#include <functional>
#include <list>
diff --git a/src/common/Utilities/EventMap.h b/src/common/Utilities/EventMap.h
index a1aaa9af269..bb40980181d 100644
--- a/src/common/Utilities/EventMap.h
+++ b/src/common/Utilities/EventMap.h
@@ -22,7 +22,7 @@
#include "Duration.h"
#include "Util.h"
-class EventMap
+class TC_COMMON_API EventMap
{
/**
* Internal storage type.
diff --git a/src/common/Utilities/EventProcessor.h b/src/common/Utilities/EventProcessor.h
index e5eafed79b9..e10558e6a21 100644
--- a/src/common/Utilities/EventProcessor.h
+++ b/src/common/Utilities/EventProcessor.h
@@ -25,7 +25,7 @@
// Note. All times are in milliseconds here.
-class BasicEvent
+class TC_COMMON_API BasicEvent
{
public:
BasicEvent()
@@ -55,7 +55,7 @@ class BasicEvent
typedef std::multimap<uint64, BasicEvent*> EventList;
-class EventProcessor
+class TC_COMMON_API EventProcessor
{
public:
EventProcessor();
diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h
index 5dea6117f97..b3ca00219ef 100644
--- a/src/common/Utilities/Random.h
+++ b/src/common/Utilities/Random.h
@@ -24,28 +24,28 @@
#include <random>
/* Return a random number in the range min..max. */
-int32 irand(int32 min, int32 max);
+TC_COMMON_API int32 irand(int32 min, int32 max);
/* Return a random number in the range min..max (inclusive). */
-uint32 urand(uint32 min, uint32 max);
+TC_COMMON_API uint32 urand(uint32 min, uint32 max);
/* Return a random millisecond value between min and max seconds. Functionally equivalent to urand(min*IN_MILLISECONDS, max*IN_MILLISECONDS). */
-uint32 urandms(uint32 min, uint32 max);
+TC_COMMON_API uint32 urandms(uint32 min, uint32 max);
/* Return a random number in the range 0 .. UINT32_MAX. */
-uint32 rand32();
+TC_COMMON_API uint32 rand32();
/* Return a random time in the range min..max (up to millisecond precision). Only works for values where millisecond difference is a valid uint32. */
-Milliseconds randtime(Milliseconds const& min, Milliseconds const& max);
+TC_COMMON_API Milliseconds randtime(Milliseconds const& min, Milliseconds const& max);
/* Return a random number in the range min..max */
-float frand(float min, float max);
+TC_COMMON_API float frand(float min, float max);
/* Return a random double from 0.0 to 1.0 (exclusive). */
-double rand_norm();
+TC_COMMON_API double rand_norm();
/* Return a random double from 0.0 to 100.0 (exclusive). */
-double rand_chance();
+TC_COMMON_API double rand_chance();
/* Return true if a random roll fits in the specified chance (range 0-100). */
inline bool roll_chance_f(float chance)
@@ -62,7 +62,7 @@ inline bool roll_chance_i(int chance)
/*
* SFMT wrapper satisfying UniformRandomNumberGenerator concept for use in <random> algorithms
*/
-class SFMTEngine
+class TC_COMMON_API SFMTEngine
{
public:
typedef uint32 result_type;
diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h
index 8cf5d914128..c5163ef33d5 100644
--- a/src/common/Utilities/TaskScheduler.h
+++ b/src/common/Utilities/TaskScheduler.h
@@ -46,7 +46,7 @@ class TaskContext;
/// with the same duration or a new one.
/// It also provides access to the repeat counter which is useful for task that repeat itself often
/// but behave different every time (spoken event dialogs for example).
-class TaskScheduler
+class TC_COMMON_API TaskScheduler
{
friend class TaskContext;
@@ -131,7 +131,7 @@ class TaskScheduler
};
};
- class TaskQueue
+ class TC_COMMON_API TaskQueue
{
std::multiset<TaskContainer, Compare> container;
@@ -408,7 +408,7 @@ private:
void Dispatch(success_t const& callback);
};
-class TaskContext
+class TC_COMMON_API TaskContext
{
friend class TaskScheduler;
diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h
index 25fce88954d..cd0a8bae823 100644
--- a/src/common/Utilities/Util.h
+++ b/src/common/Utilities/Util.h
@@ -40,7 +40,7 @@ template<typename T, class S> struct Finder
bool operator()(const std::pair<int, S> &obj) { return obj.second.*idMember_ == val_; }
};
-class Tokenizer
+class TC_COMMON_API Tokenizer
{
public:
typedef std::vector<char const*> StorageType;
@@ -68,15 +68,15 @@ private:
StorageType m_storage;
};
-void stripLineInvisibleChars(std::string &src);
+TC_COMMON_API void stripLineInvisibleChars(std::string &src);
-int32 MoneyStringToMoney(const std::string& moneyString);
+TC_COMMON_API int32 MoneyStringToMoney(const std::string& moneyString);
-struct tm* localtime_r(const time_t* time, struct tm *result);
+TC_COMMON_API struct tm* localtime_r(const time_t* time, struct tm *result);
-std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false);
-uint32 TimeStringToSecs(const std::string& timestring);
-std::string TimeToTimestampStr(time_t t);
+TC_COMMON_API std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false);
+TC_COMMON_API uint32 TimeStringToSecs(const std::string& timestring);
+TC_COMMON_API std::string TimeToTimestampStr(time_t t);
inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
{
@@ -111,20 +111,20 @@ inline T RoundToInterval(T& num, T floor, T ceil)
}
// UTF8 handling
-bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr);
+TC_COMMON_API bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr);
// in wsize==max size of buffer, out wsize==real string size
-bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize);
+TC_COMMON_API bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize);
inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize)
{
return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize);
}
-bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str);
+TC_COMMON_API bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str);
// size==real string size
-bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str);
+TC_COMMON_API bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str);
-size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence
-void utf8truncate(std::string& utf8str, size_t len);
+TC_COMMON_API size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence
+TC_COMMON_API void utf8truncate(std::string& utf8str, size_t len);
inline bool isBasicLatinCharacter(wchar_t wchar)
{
@@ -303,21 +303,21 @@ inline void wstrToLower(std::wstring& str)
std::transform( str.begin(), str.end(), str.begin(), wcharToLower );
}
-std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension);
+TC_COMMON_API std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension);
-bool utf8ToConsole(const std::string& utf8str, std::string& conStr);
-bool consoleToUtf8(const std::string& conStr, std::string& utf8str);
-bool Utf8FitTo(const std::string& str, std::wstring const& search);
-void utf8printf(FILE* out, const char *str, ...);
-void vutf8printf(FILE* out, const char *str, va_list* ap);
-bool Utf8ToUpperOnlyLatin(std::string& utf8String);
+TC_COMMON_API bool utf8ToConsole(const std::string& utf8str, std::string& conStr);
+TC_COMMON_API bool consoleToUtf8(const std::string& conStr, std::string& utf8str);
+TC_COMMON_API bool Utf8FitTo(const std::string& str, std::wstring const& search);
+TC_COMMON_API void utf8printf(FILE* out, const char *str, ...);
+TC_COMMON_API void vutf8printf(FILE* out, const char *str, va_list* ap);
+TC_COMMON_API bool Utf8ToUpperOnlyLatin(std::string& utf8String);
-bool IsIPAddress(char const* ipaddress);
+TC_COMMON_API bool IsIPAddress(char const* ipaddress);
-uint32 CreatePIDFile(std::string const& filename);
-uint32 GetPID();
+TC_COMMON_API uint32 CreatePIDFile(std::string const& filename);
+TC_COMMON_API uint32 GetPID();
-std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false);
+TC_COMMON_API std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false);
// simple class for not-modifyable list
template <typename T>
diff --git a/src/server/authserver/Server/AuthSocketMgr.h b/src/server/authserver/Server/AuthSocketMgr.h
index a16b7d405b9..9923f2b2f11 100644
--- a/src/server/authserver/Server/AuthSocketMgr.h
+++ b/src/server/authserver/Server/AuthSocketMgr.h
@@ -32,9 +32,9 @@ public:
return instance;
}
- bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override
+ bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount = 1) override
{
- if (!BaseSocketMgr::StartNetwork(service, bindIp, port))
+ if (!BaseSocketMgr::StartNetwork(service, bindIp, port, threadCount))
return false;
_acceptor->AsyncAcceptWithCallback<&AuthSocketMgr::OnSocketAccept>();
diff --git a/src/server/database/CMakeLists.txt b/src/server/database/CMakeLists.txt
index 6d75ba963e7..06772cd5309 100644
--- a/src/server/database/CMakeLists.txt
+++ b/src/server/database/CMakeLists.txt
@@ -47,6 +47,8 @@ target_include_directories(database
PRIVATE
${CMAKE_CURRENT_BINARY_DIR})
+add_definitions(-DTRINITY_API_EXPORT_DATABASE)
+
target_link_libraries(database
PUBLIC
common
@@ -58,6 +60,18 @@ set_target_properties(database
FOLDER
"server")
+if( BUILD_SHARED_LIBS )
+ if( UNIX )
+ install(TARGETS database
+ LIBRARY
+ DESTINATION lib)
+ elseif( WIN32 )
+ install(TARGETS database
+ RUNTIME
+ DESTINATION "${CMAKE_INSTALL_PREFIX}")
+ endif()
+endif()
+
# Generate precompiled header
if (USE_COREPCH)
add_cxx_pch(database ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
diff --git a/src/server/database/Database/AdhocStatement.h b/src/server/database/Database/AdhocStatement.h
index ab85493a14e..9315038bce1 100644
--- a/src/server/database/Database/AdhocStatement.h
+++ b/src/server/database/Database/AdhocStatement.h
@@ -25,7 +25,7 @@ typedef std::future<QueryResult> QueryResultFuture;
typedef std::promise<QueryResult> QueryResultPromise;
/*! Raw, ad-hoc query. */
-class BasicStatementTask : public SQLOperation
+class TC_DATABASE_API BasicStatementTask : public SQLOperation
{
public:
BasicStatementTask(const char* sql, bool async = false);
diff --git a/src/server/database/Database/DatabaseEnv.h b/src/server/database/Database/DatabaseEnv.h
index c9a7672ac57..05a4d5aad75 100644
--- a/src/server/database/Database/DatabaseEnv.h
+++ b/src/server/database/Database/DatabaseEnv.h
@@ -39,10 +39,10 @@
#include "Implementation/WorldDatabase.h"
/// Accessor to the world database
-extern WorldDatabaseWorkerPool WorldDatabase;
+TC_DATABASE_API extern WorldDatabaseWorkerPool WorldDatabase;
/// Accessor to the character database
-extern CharacterDatabaseWorkerPool CharacterDatabase;
+TC_DATABASE_API extern CharacterDatabaseWorkerPool CharacterDatabase;
/// Accessor to the realm/login database
-extern LoginDatabaseWorkerPool LoginDatabase;
+TC_DATABASE_API extern LoginDatabaseWorkerPool LoginDatabase;
#endif
diff --git a/src/server/database/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp
index 6a8e86ffca9..f358bdd54b4 100644
--- a/src/server/database/Database/DatabaseLoader.cpp
+++ b/src/server/database/Database/DatabaseLoader.cpp
@@ -177,9 +177,9 @@ bool DatabaseLoader::Process(std::queue<Predicate>& queue)
return true;
}
-template
-DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(DatabaseWorkerPool<LoginDatabaseConnection>& pool, std::string const& name);
-template
-DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(DatabaseWorkerPool<WorldDatabaseConnection>& pool, std::string const& name);
-template
-DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(DatabaseWorkerPool<CharacterDatabaseConnection>& pool, std::string const& name);
+template TC_DATABASE_API
+DatabaseLoader& DatabaseLoader::AddDatabase<LoginDatabaseConnection>(LoginDatabaseWorkerPool&, std::string const&);
+template TC_DATABASE_API
+DatabaseLoader& DatabaseLoader::AddDatabase<CharacterDatabaseConnection>(CharacterDatabaseWorkerPool&, std::string const&);
+template TC_DATABASE_API
+DatabaseLoader& DatabaseLoader::AddDatabase<WorldDatabaseConnection>(WorldDatabaseWorkerPool&, std::string const&);
diff --git a/src/server/database/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h
index d3812eb060d..647c1e113e3 100644
--- a/src/server/database/Database/DatabaseLoader.h
+++ b/src/server/database/Database/DatabaseLoader.h
@@ -27,7 +27,7 @@
// A helper class to initiate all database worker pools,
// handles updating, delays preparing of statements and cleans up on failure.
-class DatabaseLoader
+class TC_DATABASE_API DatabaseLoader
{
public:
DatabaseLoader(std::string const& logger, uint32 const defaultUpdateMask);
diff --git a/src/server/database/Database/DatabaseWorker.h b/src/server/database/Database/DatabaseWorker.h
index c21a3d2a343..d6b43943f7d 100644
--- a/src/server/database/Database/DatabaseWorker.h
+++ b/src/server/database/Database/DatabaseWorker.h
@@ -24,7 +24,7 @@
class MySQLConnection;
class SQLOperation;
-class DatabaseWorker
+class TC_DATABASE_API DatabaseWorker
{
public:
DatabaseWorker(ProducerConsumerQueue<SQLOperation*>* newQueue, MySQLConnection* connection);
diff --git a/src/server/database/Database/DatabaseWorkerPool.cpp b/src/server/database/Database/DatabaseWorkerPool.cpp
index 5d914b6e0e8..087a35682aa 100644
--- a/src/server/database/Database/DatabaseWorkerPool.cpp
+++ b/src/server/database/Database/DatabaseWorkerPool.cpp
@@ -317,6 +317,6 @@ T* DatabaseWorkerPool<T>::GetFreeConnection()
return connection;
}
-template class DatabaseWorkerPool<LoginDatabaseConnection>;
-template class DatabaseWorkerPool<WorldDatabaseConnection>;
-template class DatabaseWorkerPool<CharacterDatabaseConnection>;
+template class TC_DATABASE_API DatabaseWorkerPool<LoginDatabaseConnection>;
+template class TC_DATABASE_API DatabaseWorkerPool<WorldDatabaseConnection>;
+template class TC_DATABASE_API DatabaseWorkerPool<CharacterDatabaseConnection>;
diff --git a/src/server/database/Database/Field.h b/src/server/database/Database/Field.h
index ec9e626ee1b..fd4ddc79450 100644
--- a/src/server/database/Database/Field.h
+++ b/src/server/database/Database/Field.h
@@ -53,7 +53,7 @@
| SUM, AVG | DECIMAL |
| COUNT | BIGINT |
*/
-class Field
+class TC_DATABASE_API Field
{
friend class ResultSet;
friend class PreparedResultSet;
diff --git a/src/server/database/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h
index e1c0238efe6..430243a8f1e 100644
--- a/src/server/database/Database/Implementation/CharacterDatabase.h
+++ b/src/server/database/Database/Implementation/CharacterDatabase.h
@@ -537,7 +537,7 @@ enum CharacterDatabaseStatements
MAX_CHARACTERDATABASE_STATEMENTS
};
-class CharacterDatabaseConnection : public MySQLConnection
+class TC_DATABASE_API CharacterDatabaseConnection : public MySQLConnection
{
public:
typedef CharacterDatabaseStatements Statements;
diff --git a/src/server/database/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h
index a3789fa2557..e206be16d73 100644
--- a/src/server/database/Database/Implementation/LoginDatabase.h
+++ b/src/server/database/Database/Implementation/LoginDatabase.h
@@ -116,7 +116,7 @@ enum LoginDatabaseStatements
MAX_LOGINDATABASE_STATEMENTS
};
-class LoginDatabaseConnection : public MySQLConnection
+class TC_DATABASE_API LoginDatabaseConnection : public MySQLConnection
{
public:
typedef LoginDatabaseStatements Statements;
diff --git a/src/server/database/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h
index 6ac4ce589e3..e0a02423446 100644
--- a/src/server/database/Database/Implementation/WorldDatabase.h
+++ b/src/server/database/Database/Implementation/WorldDatabase.h
@@ -103,7 +103,7 @@ enum WorldDatabaseStatements
MAX_WORLDDATABASE_STATEMENTS
};
-class WorldDatabaseConnection : public MySQLConnection
+class TC_DATABASE_API WorldDatabaseConnection : public MySQLConnection
{
public:
typedef WorldDatabaseStatements Statements;
diff --git a/src/server/database/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h
index a0b908593df..566995988c0 100644
--- a/src/server/database/Database/MySQLConnection.h
+++ b/src/server/database/Database/MySQLConnection.h
@@ -35,7 +35,7 @@ enum ConnectionFlags
CONNECTION_BOTH = CONNECTION_ASYNC | CONNECTION_SYNCH
};
-struct MySQLConnectionInfo
+struct TC_DATABASE_API MySQLConnectionInfo
{
explicit MySQLConnectionInfo(std::string const& infoString)
{
@@ -62,7 +62,7 @@ struct MySQLConnectionInfo
typedef std::map<uint32 /*index*/, std::pair<std::string /*query*/, ConnectionFlags /*sync/async*/> > PreparedStatementMap;
-class MySQLConnection
+class TC_DATABASE_API MySQLConnection
{
template <class T> friend class DatabaseWorkerPool;
friend class PingOperation;
diff --git a/src/server/database/Database/MySQLThreading.h b/src/server/database/Database/MySQLThreading.h
index 1cfa11d7e5b..b6083500989 100644
--- a/src/server/database/Database/MySQLThreading.h
+++ b/src/server/database/Database/MySQLThreading.h
@@ -20,7 +20,7 @@
#include "Log.h"
-class MySQL
+class TC_DATABASE_API MySQL
{
public:
static void Library_Init()
diff --git a/src/server/database/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h
index 7d6c98463d0..faaec27014f 100644
--- a/src/server/database/Database/PreparedStatement.h
+++ b/src/server/database/Database/PreparedStatement.h
@@ -70,7 +70,7 @@ struct PreparedStatementData
class MySQLPreparedStatement;
//- Upper-level class that is used in code
-class PreparedStatement
+class TC_DATABASE_API PreparedStatement
{
friend class PreparedStatementTask;
friend class MySQLPreparedStatement;
@@ -109,7 +109,7 @@ class PreparedStatement
//- Class of which the instances are unique per MySQLConnection
//- access to these class objects is only done when a prepared statement task
//- is executed.
-class MySQLPreparedStatement
+class TC_DATABASE_API MySQLPreparedStatement
{
friend class MySQLConnection;
friend class PreparedStatement;
@@ -157,7 +157,7 @@ typedef std::future<PreparedQueryResult> PreparedQueryResultFuture;
typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise;
//- Lower-level class, enqueuable operation
-class PreparedStatementTask : public SQLOperation
+class TC_DATABASE_API PreparedStatementTask : public SQLOperation
{
public:
PreparedStatementTask(PreparedStatement* stmt, bool async = false);
diff --git a/src/server/database/Database/QueryHolder.h b/src/server/database/Database/QueryHolder.h
index 9a5a03fda42..2446a4db2bd 100644
--- a/src/server/database/Database/QueryHolder.h
+++ b/src/server/database/Database/QueryHolder.h
@@ -20,7 +20,7 @@
#include <future>
-class SQLQueryHolder
+class TC_DATABASE_API SQLQueryHolder
{
friend class SQLQueryHolderTask;
private:
@@ -46,7 +46,7 @@ class SQLQueryHolder
typedef std::future<SQLQueryHolder*> QueryResultHolderFuture;
typedef std::promise<SQLQueryHolder*> QueryResultHolderPromise;
-class SQLQueryHolderTask : public SQLOperation
+class TC_DATABASE_API SQLQueryHolderTask : public SQLOperation
{
private:
SQLQueryHolder* m_holder;
diff --git a/src/server/database/Database/QueryResult.h b/src/server/database/Database/QueryResult.h
index d4d63b5ec85..3b1691db1a6 100644
--- a/src/server/database/Database/QueryResult.h
+++ b/src/server/database/Database/QueryResult.h
@@ -27,7 +27,7 @@
#endif
#include <mysql.h>
-class ResultSet
+class TC_DATABASE_API ResultSet
{
public:
ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount);
@@ -60,7 +60,7 @@ class ResultSet
typedef std::shared_ptr<ResultSet> QueryResult;
-class PreparedResultSet
+class TC_DATABASE_API PreparedResultSet
{
public:
PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount);
diff --git a/src/server/database/Database/SQLOperation.h b/src/server/database/Database/SQLOperation.h
index f0500d1f232..5b3032eab87 100644
--- a/src/server/database/Database/SQLOperation.h
+++ b/src/server/database/Database/SQLOperation.h
@@ -53,7 +53,7 @@ union SQLResultSetUnion
class MySQLConnection;
-class SQLOperation
+class TC_DATABASE_API SQLOperation
{
public:
SQLOperation(): m_conn(NULL) { }
diff --git a/src/server/database/Database/Transaction.h b/src/server/database/Database/Transaction.h
index 5780c0363d9..7b5b6addfe4 100644
--- a/src/server/database/Database/Transaction.h
+++ b/src/server/database/Database/Transaction.h
@@ -25,7 +25,7 @@
class PreparedStatement;
/*! Transactions, high level class. */
-class Transaction
+class TC_DATABASE_API Transaction
{
friend class TransactionTask;
friend class MySQLConnection;
@@ -58,7 +58,7 @@ class Transaction
typedef std::shared_ptr<Transaction> SQLTransaction;
/*! Low level class*/
-class TransactionTask : public SQLOperation
+class TC_DATABASE_API TransactionTask : public SQLOperation
{
template <class T> friend class DatabaseWorkerPool;
friend class DatabaseWorker;
diff --git a/src/server/database/Logging/AppenderDB.h b/src/server/database/Logging/AppenderDB.h
index a6acc66b48c..225ae969802 100644
--- a/src/server/database/Logging/AppenderDB.h
+++ b/src/server/database/Logging/AppenderDB.h
@@ -20,7 +20,7 @@
#include "Appender.h"
-class AppenderDB: public Appender
+class TC_DATABASE_API AppenderDB: public Appender
{
public:
typedef std::integral_constant<AppenderType, APPENDER_DB>::type TypeIndex;
diff --git a/src/server/database/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp
index b18d6c67612..5f5b519d2b3 100644
--- a/src/server/database/Updater/DBUpdater.cpp
+++ b/src/server/database/Updater/DBUpdater.cpp
@@ -436,6 +436,6 @@ void DBUpdater<T>::ApplyFile(DatabaseWorkerPool<T>& pool, std::string const& hos
}
}
-template class DBUpdater<LoginDatabaseConnection>;
-template class DBUpdater<WorldDatabaseConnection>;
-template class DBUpdater<CharacterDatabaseConnection>;
+template class TC_DATABASE_API DBUpdater<LoginDatabaseConnection>;
+template class TC_DATABASE_API DBUpdater<WorldDatabaseConnection>;
+template class TC_DATABASE_API DBUpdater<CharacterDatabaseConnection>;
diff --git a/src/server/database/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h
index dbb897d2527..cc5d3aad68b 100644
--- a/src/server/database/Updater/DBUpdater.h
+++ b/src/server/database/Updater/DBUpdater.h
@@ -23,7 +23,7 @@
#include <string>
#include <boost/filesystem.hpp>
-class UpdateException : public std::exception
+class TC_DATABASE_API UpdateException : public std::exception
{
public:
UpdateException(std::string const& msg) : _msg(msg) { }
@@ -41,7 +41,7 @@ enum BaseLocation
LOCATION_DOWNLOAD
};
-struct UpdateResult
+struct TC_DATABASE_API UpdateResult
{
UpdateResult()
: updated(0), recent(0), archived(0) { }
@@ -66,7 +66,7 @@ private:
};
template <class T>
-class DBUpdater
+class TC_DATABASE_API DBUpdater
{
public:
using Path = boost::filesystem::path;
diff --git a/src/server/database/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h
index c87efea2b02..a17658818ce 100644
--- a/src/server/database/Updater/UpdateFetcher.h
+++ b/src/server/database/Updater/UpdateFetcher.h
@@ -25,7 +25,7 @@
#include <memory>
#include <vector>
-class UpdateFetcher
+class TC_DATABASE_API UpdateFetcher
{
typedef boost::filesystem::path Path;
diff --git a/src/server/game/AI/CoreAI/CombatAI.h b/src/server/game/AI/CoreAI/CombatAI.h
index 55b91b6969e..f1718fbdb6a 100644
--- a/src/server/game/AI/CoreAI/CombatAI.h
+++ b/src/server/game/AI/CoreAI/CombatAI.h
@@ -25,7 +25,7 @@
class Creature;
-class AggressorAI : public CreatureAI
+class TC_GAME_API AggressorAI : public CreatureAI
{
public:
explicit AggressorAI(Creature* c) : CreatureAI(c) { }
@@ -36,7 +36,7 @@ class AggressorAI : public CreatureAI
typedef std::vector<uint32> SpellVct;
-class CombatAI : public CreatureAI
+class TC_GAME_API CombatAI : public CreatureAI
{
public:
explicit CombatAI(Creature* c) : CreatureAI(c) { }
@@ -55,7 +55,7 @@ class CombatAI : public CreatureAI
SpellVct spells;
};
-class CasterAI : public CombatAI
+class TC_GAME_API CasterAI : public CombatAI
{
public:
explicit CasterAI(Creature* c) : CombatAI(c) { m_attackDist = MELEE_RANGE; }
@@ -67,7 +67,7 @@ class CasterAI : public CombatAI
float m_attackDist;
};
-struct ArcherAI : public CreatureAI
+struct TC_GAME_API ArcherAI : public CreatureAI
{
public:
explicit ArcherAI(Creature* c);
@@ -80,7 +80,7 @@ struct ArcherAI : public CreatureAI
float m_minRange;
};
-struct TurretAI : public CreatureAI
+struct TC_GAME_API TurretAI : public CreatureAI
{
public:
explicit TurretAI(Creature* c);
@@ -97,7 +97,7 @@ struct TurretAI : public CreatureAI
#define VEHICLE_CONDITION_CHECK_TIME 1000
#define VEHICLE_DISMISS_TIME 5000
-struct VehicleAI : public CreatureAI
+struct TC_GAME_API VehicleAI : public CreatureAI
{
public:
explicit VehicleAI(Creature* creature);
diff --git a/src/server/game/AI/CoreAI/GameObjectAI.h b/src/server/game/AI/CoreAI/GameObjectAI.h
index 4f256a5de31..7a2f23ac804 100644
--- a/src/server/game/AI/CoreAI/GameObjectAI.h
+++ b/src/server/game/AI/CoreAI/GameObjectAI.h
@@ -26,7 +26,7 @@
#include "GameObject.h"
#include "CreatureAI.h"
-class GameObjectAI
+class TC_GAME_API GameObjectAI
{
protected:
GameObject* const go;
@@ -63,7 +63,7 @@ class GameObjectAI
virtual void EventInform(uint32 /*eventId*/) { }
};
-class NullGameObjectAI : public GameObjectAI
+class TC_GAME_API NullGameObjectAI : public GameObjectAI
{
public:
explicit NullGameObjectAI(GameObject* g);
diff --git a/src/server/game/AI/CoreAI/GuardAI.h b/src/server/game/AI/CoreAI/GuardAI.h
index 63f2750a5d4..a6aa4b6624a 100644
--- a/src/server/game/AI/CoreAI/GuardAI.h
+++ b/src/server/game/AI/CoreAI/GuardAI.h
@@ -23,7 +23,7 @@
class Creature;
-class GuardAI : public ScriptedAI
+class TC_GAME_API GuardAI : public ScriptedAI
{
public:
explicit GuardAI(Creature* creature);
diff --git a/src/server/game/AI/CoreAI/PassiveAI.h b/src/server/game/AI/CoreAI/PassiveAI.h
index bd72cd7fbe7..5a6dba7046d 100644
--- a/src/server/game/AI/CoreAI/PassiveAI.h
+++ b/src/server/game/AI/CoreAI/PassiveAI.h
@@ -21,7 +21,7 @@
#include "CreatureAI.h"
-class PassiveAI : public CreatureAI
+class TC_GAME_API PassiveAI : public CreatureAI
{
public:
explicit PassiveAI(Creature* c);
@@ -33,7 +33,7 @@ class PassiveAI : public CreatureAI
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
-class PossessedAI : public CreatureAI
+class TC_GAME_API PossessedAI : public CreatureAI
{
public:
explicit PossessedAI(Creature* c);
@@ -49,7 +49,7 @@ class PossessedAI : public CreatureAI
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
-class NullCreatureAI : public CreatureAI
+class TC_GAME_API NullCreatureAI : public CreatureAI
{
public:
explicit NullCreatureAI(Creature* c);
@@ -63,7 +63,7 @@ class NullCreatureAI : public CreatureAI
static int Permissible(const Creature*) { return PERMIT_BASE_IDLE; }
};
-class CritterAI : public PassiveAI
+class TC_GAME_API CritterAI : public PassiveAI
{
public:
explicit CritterAI(Creature* c) : PassiveAI(c) { }
@@ -72,7 +72,7 @@ class CritterAI : public PassiveAI
void EnterEvadeMode(EvadeReason why) override;
};
-class TriggerAI : public NullCreatureAI
+class TC_GAME_API TriggerAI : public NullCreatureAI
{
public:
explicit TriggerAI(Creature* c) : NullCreatureAI(c) { }
diff --git a/src/server/game/AI/CoreAI/PetAI.h b/src/server/game/AI/CoreAI/PetAI.h
index 9c33baa9a9f..3ad34047b01 100644
--- a/src/server/game/AI/CoreAI/PetAI.h
+++ b/src/server/game/AI/CoreAI/PetAI.h
@@ -25,7 +25,7 @@
class Creature;
class Spell;
-class PetAI : public CreatureAI
+class TC_GAME_API PetAI : public CreatureAI
{
public:
diff --git a/src/server/game/AI/CoreAI/ReactorAI.h b/src/server/game/AI/CoreAI/ReactorAI.h
index e5abaac2f00..d281ca11fdf 100644
--- a/src/server/game/AI/CoreAI/ReactorAI.h
+++ b/src/server/game/AI/CoreAI/ReactorAI.h
@@ -23,7 +23,7 @@
class Unit;
-class ReactorAI : public CreatureAI
+class TC_GAME_API ReactorAI : public CreatureAI
{
public:
diff --git a/src/server/game/AI/CoreAI/TotemAI.h b/src/server/game/AI/CoreAI/TotemAI.h
index e1d1618037f..a0e796ed7e0 100644
--- a/src/server/game/AI/CoreAI/TotemAI.h
+++ b/src/server/game/AI/CoreAI/TotemAI.h
@@ -25,7 +25,7 @@
class Creature;
class Totem;
-class TotemAI : public CreatureAI
+class TC_GAME_API TotemAI : public CreatureAI
{
public:
diff --git a/src/server/game/AI/CoreAI/UnitAI.h b/src/server/game/AI/CoreAI/UnitAI.h
index f5a0066a5e3..344ccc06249 100644
--- a/src/server/game/AI/CoreAI/UnitAI.h
+++ b/src/server/game/AI/CoreAI/UnitAI.h
@@ -40,7 +40,7 @@ enum SelectAggroTarget
};
// default predicate function to select target based on distance, player and/or aura criteria
-struct DefaultTargetSelector : public std::unary_function<Unit*, bool>
+struct TC_GAME_API DefaultTargetSelector : public std::unary_function<Unit*, bool>
{
const Unit* me;
float m_dist;
@@ -90,7 +90,7 @@ struct DefaultTargetSelector : public std::unary_function<Unit*, bool>
// Target selector for spell casts checking range, auras and attributes
/// @todo Add more checks from Spell::CheckCast
-struct SpellTargetSelector : public std::unary_function<Unit*, bool>
+struct TC_GAME_API SpellTargetSelector : public std::unary_function<Unit*, bool>
{
public:
SpellTargetSelector(Unit* caster, uint32 spellId);
@@ -104,7 +104,7 @@ struct SpellTargetSelector : public std::unary_function<Unit*, bool>
// Very simple target selector, will just skip main target
// NOTE: When passing to UnitAI::SelectTarget remember to use 0 as position for random selection
// because tank will not be in the temporary list
-struct NonTankTargetSelector : public std::unary_function<Unit*, bool>
+struct TC_GAME_API NonTankTargetSelector : public std::unary_function<Unit*, bool>
{
public:
NonTankTargetSelector(Unit* source, bool playerOnly = true) : _source(source), _playerOnly(playerOnly) { }
@@ -115,7 +115,7 @@ struct NonTankTargetSelector : public std::unary_function<Unit*, bool>
bool _playerOnly;
};
-class UnitAI
+class TC_GAME_API UnitAI
{
protected:
Unit* const me;
diff --git a/src/server/game/AI/CreatureAI.h b/src/server/game/AI/CreatureAI.h
index e009e2ed0b6..f175050e107 100644
--- a/src/server/game/AI/CreatureAI.h
+++ b/src/server/game/AI/CreatureAI.h
@@ -66,7 +66,7 @@ enum SCEquip
};
typedef std::set<AreaBoundary const*> CreatureBoundary;
-class CreatureAI : public UnitAI
+class TC_GAME_API CreatureAI : public UnitAI
{
protected:
Creature* const me;
@@ -137,8 +137,8 @@ class CreatureAI : public UnitAI
virtual void AttackedBy(Unit* /*attacker*/) { }
virtual bool IsEscorted() const { return false; }
- // Called when creature is spawned or respawned (for reseting variables)
- virtual void JustRespawned() { Reset(); }
+ // Called when creature is spawned or respawned
+ virtual void JustRespawned() { }
// Called at waypoint reached or point movement finished
virtual void MovementInform(uint32 /*type*/, uint32 /*id*/) { }
diff --git a/src/server/game/AI/CreatureAISelector.h b/src/server/game/AI/CreatureAISelector.h
index 7c7bc705ade..0e3be1a8604 100644
--- a/src/server/game/AI/CreatureAISelector.h
+++ b/src/server/game/AI/CreatureAISelector.h
@@ -27,9 +27,9 @@ class GameObject;
namespace FactorySelector
{
- CreatureAI* selectAI(Creature*);
- MovementGenerator* selectMovementGenerator(Creature*);
- GameObjectAI* SelectGameObjectAI(GameObject*);
+ TC_GAME_API CreatureAI* selectAI(Creature*);
+ TC_GAME_API MovementGenerator* selectMovementGenerator(Creature*);
+ TC_GAME_API GameObjectAI* SelectGameObjectAI(GameObject*);
}
#endif
diff --git a/src/server/game/AI/PlayerAI/PlayerAI.h b/src/server/game/AI/PlayerAI/PlayerAI.h
index 429bf1d856c..b717816f9a3 100644
--- a/src/server/game/AI/PlayerAI/PlayerAI.h
+++ b/src/server/game/AI/PlayerAI/PlayerAI.h
@@ -22,7 +22,7 @@
#include "Player.h"
#include "Creature.h"
-class PlayerAI : public UnitAI
+class TC_GAME_API PlayerAI : public UnitAI
{
public:
explicit PlayerAI(Player* player) : UnitAI(static_cast<Unit*>(player)), me(player), _isSelfHealer(PlayerAI::IsPlayerHealer(player)), _isSelfRangedAttacker(PlayerAI::IsPlayerRangedAttacker(player)) { }
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
index 2010ae45ba5..6f04a852b61 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.cpp
@@ -628,27 +628,27 @@ void WorldBossAI::UpdateAI(uint32 diff)
}
// SD2 grid searchers.
-Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/)
+TC_GAME_API Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive /*= true*/)
{
return source->FindNearestCreature(entry, maxSearchRange, alive);
}
-GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange)
+TC_GAME_API GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange)
{
return source->FindNearestGameObject(entry, maxSearchRange);
}
-void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange)
+TC_GAME_API void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange)
{
source->GetCreatureListWithEntryInGrid(list, entry, maxSearchRange);
}
-void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange)
+TC_GAME_API void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange)
{
source->GetGameObjectListWithEntryInGrid(list, entry, maxSearchRange);
}
-void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange)
+TC_GAME_API void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange)
{
source->GetPlayerListInGrid(list, maxSearchRange);
}
diff --git a/src/server/game/AI/ScriptedAI/ScriptedCreature.h b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
index 5452a033a17..42befa26a23 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedCreature.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedCreature.h
@@ -38,7 +38,7 @@ T* EnsureAI(U* ai)
class InstanceScript;
-class SummonList
+class TC_GAME_API SummonList
{
public:
typedef GuidList StorageType;
@@ -123,7 +123,7 @@ private:
StorageType storage_;
};
-class EntryCheckPredicate
+class TC_GAME_API EntryCheckPredicate
{
public:
EntryCheckPredicate(uint32 entry) : _entry(entry) { }
@@ -133,13 +133,13 @@ class EntryCheckPredicate
uint32 _entry;
};
-class DummyEntryCheckPredicate
+class TC_GAME_API DummyEntryCheckPredicate
{
public:
bool operator()(ObjectGuid) { return true; }
};
-struct ScriptedAI : public CreatureAI
+struct TC_GAME_API ScriptedAI : public CreatureAI
{
explicit ScriptedAI(Creature* creature);
virtual ~ScriptedAI() { }
@@ -334,7 +334,7 @@ struct ScriptedAI : public CreatureAI
bool _isHeroic;
};
-class BossAI : public ScriptedAI
+class TC_GAME_API BossAI : public ScriptedAI
{
public:
BossAI(Creature* creature, uint32 bossId);
@@ -379,7 +379,7 @@ class BossAI : public ScriptedAI
uint32 const _bossId;
};
-class WorldBossAI : public ScriptedAI
+class TC_GAME_API WorldBossAI : public ScriptedAI
{
public:
WorldBossAI(Creature* creature);
@@ -410,10 +410,10 @@ class WorldBossAI : public ScriptedAI
};
// SD2 grid searchers.
-Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive = true);
-GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange);
-void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
-void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
-void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange);
+TC_GAME_API Creature* GetClosestCreatureWithEntry(WorldObject* source, uint32 entry, float maxSearchRange, bool alive = true);
+TC_GAME_API GameObject* GetClosestGameObjectWithEntry(WorldObject* source, uint32 entry, float maxSearchRange);
+TC_GAME_API void GetCreatureListWithEntryInGrid(std::list<Creature*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
+TC_GAME_API void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& list, WorldObject* source, uint32 entry, float maxSearchRange);
+TC_GAME_API void GetPlayerListInGrid(std::list<Player*>& list, WorldObject* source, float maxSearchRange);
#endif // SCRIPTEDCREATURE_H_
diff --git a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
index 673f3e671a0..37a1464d812 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedEscortAI.h
@@ -49,7 +49,7 @@ enum eEscortState
STATE_ESCORT_PAUSED = 0x004 //will not proceed with waypoints before state is removed
};
-struct npc_escortAI : public ScriptedAI
+struct TC_GAME_API npc_escortAI : public ScriptedAI
{
public:
explicit npc_escortAI(Creature* creature);
diff --git a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
index d1c976b45c8..e17fb7c8507 100644
--- a/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
+++ b/src/server/game/AI/ScriptedAI/ScriptedFollowerAI.h
@@ -32,7 +32,7 @@ enum eFollowState
STATE_FOLLOW_POSTEVENT = 0x020 //can be set at complete and allow post event to run
};
-class FollowerAI : public ScriptedAI
+class TC_GAME_API FollowerAI : public ScriptedAI
{
public:
explicit FollowerAI(Creature* creature);
diff --git a/src/server/game/AI/SmartScripts/SmartAI.h b/src/server/game/AI/SmartScripts/SmartAI.h
index 3abe1e5774c..aa7c9ace0b3 100644
--- a/src/server/game/AI/SmartScripts/SmartAI.h
+++ b/src/server/game/AI/SmartScripts/SmartAI.h
@@ -42,7 +42,7 @@ enum SmartEscortVars
SMART_MAX_AID_DIST = SMART_ESCORT_MAX_PLAYER_DIST / 2
};
-class SmartAI : public CreatureAI
+class TC_GAME_API SmartAI : public CreatureAI
{
public:
~SmartAI(){ }
@@ -230,7 +230,7 @@ class SmartAI : public CreatureAI
bool mJustReset;
};
-class SmartGameObjectAI : public GameObjectAI
+class TC_GAME_API SmartGameObjectAI : public GameObjectAI
{
public:
SmartGameObjectAI(GameObject* g) : GameObjectAI(g) { }
diff --git a/src/server/game/AI/SmartScripts/SmartScript.h b/src/server/game/AI/SmartScripts/SmartScript.h
index e8b89a813b5..a28f2234860 100644
--- a/src/server/game/AI/SmartScripts/SmartScript.h
+++ b/src/server/game/AI/SmartScripts/SmartScript.h
@@ -28,7 +28,7 @@
#include "SmartScriptMgr.h"
//#include "SmartAI.h"
-class SmartScript
+class TC_GAME_API SmartScript
{
public:
SmartScript();
diff --git a/src/server/game/AI/SmartScripts/SmartScriptMgr.h b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
index 748792b9b42..3105f087bf7 100644
--- a/src/server/game/AI/SmartScripts/SmartScriptMgr.h
+++ b/src/server/game/AI/SmartScripts/SmartScriptMgr.h
@@ -1440,7 +1440,7 @@ public:
};
typedef std::unordered_map<uint32, ObjectGuidList*> ObjectListMap;
-class SmartWaypointMgr
+class TC_GAME_API SmartWaypointMgr
{
private:
SmartWaypointMgr() { }
@@ -1472,7 +1472,7 @@ typedef std::unordered_map<int32, SmartAIEventList> SmartAIEventMap;
typedef std::map<uint32 /*entry*/, std::pair<uint32 /*spellId*/, SpellEffIndex /*effIndex*/> > CacheSpellContainer;
typedef std::pair<CacheSpellContainer::const_iterator, CacheSpellContainer::const_iterator> CacheSpellContainerBounds;
-class SmartAIMgr
+class TC_GAME_API SmartAIMgr
{
private:
SmartAIMgr() { }
diff --git a/src/server/game/Accounts/AccountMgr.h b/src/server/game/Accounts/AccountMgr.h
index faf28cc707f..f3bb1abe64e 100644
--- a/src/server/game/Accounts/AccountMgr.h
+++ b/src/server/game/Accounts/AccountMgr.h
@@ -49,7 +49,7 @@ typedef std::map<uint32, rbac::RBACPermission*> RBACPermissionsContainer;
typedef std::map<uint8, rbac::RBACPermissionContainer> RBACDefaultPermissionsContainer;
}
-class AccountMgr
+class TC_GAME_API AccountMgr
{
private:
AccountMgr();
diff --git a/src/server/game/Accounts/RBAC.h b/src/server/game/Accounts/RBAC.h
index 1dc98f8b2c1..5f883175157 100644
--- a/src/server/game/Accounts/RBAC.h
+++ b/src/server/game/Accounts/RBAC.h
@@ -714,7 +714,7 @@ enum RBACCommandResult
typedef std::set<uint32> RBACPermissionContainer;
-class RBACPermission
+class TC_GAME_API RBACPermission
{
public:
RBACPermission(uint32 id = 0, std::string const& name = ""):
@@ -749,7 +749,7 @@ class RBACPermission
* - Granted permissions: through linked permissions and directly assigned
* - Denied permissions: through linked permissions and directly assigned
*/
-class RBACData
+class TC_GAME_API RBACData
{
public:
RBACData(uint32 id, std::string const& name, int32 realmId, uint8 secLevel = 255):
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index aba56bfbfc1..c4ac5f0e808 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -212,7 +212,7 @@ struct AchievementCriteriaData
bool Meets(uint32 criteria_id, Player const* source, Unit const* target, uint32 miscValue1 = 0) const;
};
-struct AchievementCriteriaDataSet
+struct TC_GAME_API AchievementCriteriaDataSet
{
AchievementCriteriaDataSet() : criteria_id(0) { }
typedef std::vector<AchievementCriteriaData> Storage;
@@ -262,7 +262,7 @@ enum ProgressType
PROGRESS_HIGHEST
};
-class AchievementMgr
+class TC_GAME_API AchievementMgr
{
public:
AchievementMgr(Player* player);
@@ -306,7 +306,7 @@ class AchievementMgr
TimedAchievementMap m_timedAchievements; // Criteria id/time left in MS
};
-class AchievementGlobalMgr
+class TC_GAME_API AchievementGlobalMgr
{
AchievementGlobalMgr() { }
~AchievementGlobalMgr() { }
diff --git a/src/server/game/AuctionHouse/AuctionHouseMgr.h b/src/server/game/AuctionHouse/AuctionHouseMgr.h
index 7fc039114e7..42322929a30 100644
--- a/src/server/game/AuctionHouse/AuctionHouseMgr.h
+++ b/src/server/game/AuctionHouse/AuctionHouseMgr.h
@@ -70,7 +70,7 @@ enum AuctionHouses
AUCTIONHOUSE_NEUTRAL = 7
};
-struct AuctionEntry
+struct TC_GAME_API AuctionEntry
{
uint32 Id;
uint8 houseId;
@@ -101,7 +101,7 @@ struct AuctionEntry
};
//this class is used as auctionhouse instance
-class AuctionHouseObject
+class TC_GAME_API AuctionHouseObject
{
public:
~AuctionHouseObject()
@@ -146,7 +146,7 @@ class AuctionHouseObject
};
-class AuctionHouseMgr
+class TC_GAME_API AuctionHouseMgr
{
private:
AuctionHouseMgr();
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBot.h b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
index 8f90e8fa76f..1a438e01cdb 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBot.h
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBot.h
@@ -196,7 +196,7 @@ enum AuctionBotConfigFloatValues
};
// All basic config data used by other AHBot classes for self-configure.
-class AuctionBotConfig
+class TC_GAME_API AuctionBotConfig
{
private:
AuctionBotConfig(): _itemsPerCycleBoost(1000), _itemsPerCycleNormal(20) {}
@@ -270,7 +270,7 @@ typedef AuctionHouseBotStatusInfoPerType AuctionHouseBotStatusInfo[MAX_AUCTION_H
// This class handle both Selling and Buying method
// (holder of AuctionBotBuyer and AuctionBotSeller objects)
-class AuctionHouseBot
+class TC_GAME_API AuctionHouseBot
{
private:
AuctionHouseBot();
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h
index e1b6b425c48..979f73c0099 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotBuyer.h
@@ -67,7 +67,7 @@ private:
// This class handle all Buyer method
// (holder of AuctionBotConfig for each auction house type)
-class AuctionBotBuyer : public AuctionBotAgent
+class TC_GAME_API AuctionBotBuyer : public AuctionBotAgent
{
public:
AuctionBotBuyer();
diff --git a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h
index dd82b0f3dda..563c2cda04a 100644
--- a/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h
+++ b/src/server/game/AuctionHouseBot/AuctionHouseBotSeller.h
@@ -115,7 +115,7 @@ private:
// This class handle all Selling method
// (holder of AHB_Seller_Config data for each auction house type)
-class AuctionBotSeller : public AuctionBotAgent
+class TC_GAME_API AuctionBotSeller : public AuctionBotAgent
{
public:
typedef std::vector<uint32> ItemPool;
diff --git a/src/server/game/Battlefield/Battlefield.h b/src/server/game/Battlefield/Battlefield.h
index ade3e8c9699..6968e31c7bd 100644
--- a/src/server/game/Battlefield/Battlefield.h
+++ b/src/server/game/Battlefield/Battlefield.h
@@ -67,7 +67,7 @@ class BfGraveyard;
typedef std::vector<BfGraveyard*> GraveyardVect;
typedef std::map<ObjectGuid, time_t> PlayerTimerMap;
-class BfCapturePoint
+class TC_GAME_API BfCapturePoint
{
public:
BfCapturePoint(Battlefield* bf);
@@ -135,7 +135,7 @@ class BfCapturePoint
ObjectGuid m_capturePointGUID;
};
-class BfGraveyard
+class TC_GAME_API BfGraveyard
{
public:
BfGraveyard(Battlefield* Bf);
@@ -182,7 +182,7 @@ class BfGraveyard
Battlefield* m_Bf;
};
-class Battlefield : public ZoneScript
+class TC_GAME_API Battlefield : public ZoneScript
{
friend class BattlefieldMgr;
diff --git a/src/server/game/Battlefield/BattlefieldMgr.h b/src/server/game/Battlefield/BattlefieldMgr.h
index 5d2c13538f6..2f2af12927e 100644
--- a/src/server/game/Battlefield/BattlefieldMgr.h
+++ b/src/server/game/Battlefield/BattlefieldMgr.h
@@ -24,7 +24,7 @@ class Player;
class ZoneScript;
// class to handle player enter / leave / areatrigger / GO use events
-class BattlefieldMgr
+class TC_GAME_API BattlefieldMgr
{
public:
static BattlefieldMgr* instance();
diff --git a/src/server/game/Battlefield/Zones/BattlefieldWG.h b/src/server/game/Battlefield/Zones/BattlefieldWG.h
index e5cc392cef3..52789d38d8e 100644
--- a/src/server/game/Battlefield/Zones/BattlefieldWG.h
+++ b/src/server/game/Battlefield/Zones/BattlefieldWG.h
@@ -266,7 +266,7 @@ class WintergraspCapturePoint : public BfCapturePoint
* WinterGrasp Battlefield *
* ######################### */
-class BattlefieldWG : public Battlefield
+class TC_GAME_API BattlefieldWG : public Battlefield
{
public:
~BattlefieldWG();
@@ -1098,7 +1098,7 @@ StaticWintergraspWorkshopInfo const WorkshopData[WG_MAX_WORKSHOP] =
// ********************************************************************
// Structure for different buildings that can be destroyed during battle
-struct BfWGGameObjectBuilding
+struct TC_GAME_API BfWGGameObjectBuilding
{
private:
// WG object
@@ -1150,7 +1150,7 @@ public:
};
// Structure for the 6 workshop
-struct WintergraspWorkshop
+struct TC_GAME_API WintergraspWorkshop
{
private:
BattlefieldWG* _wg; // Pointer to wintergrasp
diff --git a/src/server/game/Battlegrounds/Arena.h b/src/server/game/Battlegrounds/Arena.h
index 863f1fc8c6f..1fe99f1f414 100644
--- a/src/server/game/Battlegrounds/Arena.h
+++ b/src/server/game/Battlegrounds/Arena.h
@@ -36,7 +36,7 @@ enum ArenaWorldStates
ARENA_WORLD_STATE_ALIVE_PLAYERS_GOLD = 3601
};
-class Arena : public Battleground
+class TC_GAME_API Arena : public Battleground
{
protected:
Arena();
diff --git a/src/server/game/Battlegrounds/ArenaScore.h b/src/server/game/Battlegrounds/ArenaScore.h
index c2d9d18c00b..9427a108565 100644
--- a/src/server/game/Battlegrounds/ArenaScore.h
+++ b/src/server/game/Battlegrounds/ArenaScore.h
@@ -21,7 +21,7 @@
#include "BattlegroundScore.h"
#include "SharedDefines.h"
-struct ArenaScore : public BattlegroundScore
+struct TC_GAME_API ArenaScore : public BattlegroundScore
{
friend class Arena;
@@ -56,7 +56,7 @@ struct ArenaScore : public BattlegroundScore
uint8 TeamId; // BattlegroundTeamId
};
-struct ArenaTeamScore
+struct TC_GAME_API ArenaTeamScore
{
friend class Arena;
friend class Battleground;
diff --git a/src/server/game/Battlegrounds/ArenaTeam.h b/src/server/game/Battlegrounds/ArenaTeam.h
index f27c3761bde..7e9f490bff9 100644
--- a/src/server/game/Battlegrounds/ArenaTeam.h
+++ b/src/server/game/Battlegrounds/ArenaTeam.h
@@ -85,7 +85,7 @@ enum ArenaTeamTypes
ARENA_TEAM_5v5 = 5
};
-struct ArenaTeamMember
+struct TC_GAME_API ArenaTeamMember
{
ObjectGuid Guid;
std::string Name;
@@ -113,7 +113,7 @@ struct ArenaTeamStats
#define MAX_ARENA_SLOT 3 // 0..2 slots
-class ArenaTeam
+class TC_GAME_API ArenaTeam
{
public:
ArenaTeam();
diff --git a/src/server/game/Battlegrounds/ArenaTeamMgr.h b/src/server/game/Battlegrounds/ArenaTeamMgr.h
index 269795092c7..7f6800bd71b 100644
--- a/src/server/game/Battlegrounds/ArenaTeamMgr.h
+++ b/src/server/game/Battlegrounds/ArenaTeamMgr.h
@@ -20,7 +20,7 @@
#include "ArenaTeam.h"
-class ArenaTeamMgr
+class TC_GAME_API ArenaTeamMgr
{
private:
ArenaTeamMgr();
diff --git a/src/server/game/Battlegrounds/Battleground.h b/src/server/game/Battlegrounds/Battleground.h
index 03f138a5a8b..bb6ae360536 100644
--- a/src/server/game/Battlegrounds/Battleground.h
+++ b/src/server/game/Battlegrounds/Battleground.h
@@ -221,7 +221,7 @@ This class is used to:
3. some certain cases, same for all battlegrounds
4. It has properties same for all battlegrounds
*/
-class Battleground
+class TC_GAME_API Battleground
{
public:
Battleground();
diff --git a/src/server/game/Battlegrounds/BattlegroundMgr.h b/src/server/game/Battlegrounds/BattlegroundMgr.h
index 50100ce47f6..dbba964d4b3 100644
--- a/src/server/game/Battlegrounds/BattlegroundMgr.h
+++ b/src/server/game/Battlegrounds/BattlegroundMgr.h
@@ -55,7 +55,7 @@ struct BattlegroundTemplate
bool IsArena() const { return BattlemasterEntry->type == MAP_ARENA; }
};
-class BattlegroundMgr
+class TC_GAME_API BattlegroundMgr
{
private:
BattlegroundMgr();
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.cpp b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
index 34588c7e380..796afe472fe 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.cpp
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.cpp
@@ -161,9 +161,9 @@ GroupQueueInfo* BattlegroundQueue::AddGroup(Player* leader, Group* grp, Battlegr
//announce world (this don't need mutex)
if (isRated && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
{
- ArenaTeam* Team = sArenaTeamMgr->GetArenaTeamById(arenateamid);
- if (Team)
- sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, Team->GetName().c_str(), ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
+ ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(arenateamid);
+ if (team)
+ sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_JOIN, team->GetName().c_str(), ginfo->ArenaType, ginfo->ArenaType, ginfo->ArenaTeamRating);
}
//add players from group to ginfo
@@ -354,8 +354,8 @@ void BattlegroundQueue::RemovePlayer(ObjectGuid guid, bool decreaseInvitedCount)
// announce to world if arena team left queue for rated match, show only once
if (group->ArenaType && group->IsRated && group->Players.empty() && sWorld->getBoolConfig(CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE))
- if (ArenaTeam* Team = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
- sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, Team->GetName().c_str(), group->ArenaType, group->ArenaType, group->ArenaTeamRating);
+ if (ArenaTeam* team = sArenaTeamMgr->GetArenaTeamById(group->ArenaTeamId))
+ sWorld->SendWorldText(LANG_ARENA_QUEUE_ANNOUNCE_WORLD_EXIT, team->GetName().c_str(), group->ArenaType, group->ArenaType, group->ArenaTeamRating);
// if player leaves queue and he is invited to rated arena match, then he have to lose
if (group->IsInvitedToBGInstanceGUID && group->IsRated && decreaseInvitedCount)
diff --git a/src/server/game/Battlegrounds/BattlegroundQueue.h b/src/server/game/Battlegrounds/BattlegroundQueue.h
index 31f108053d9..f56ccb9bdbf 100644
--- a/src/server/game/Battlegrounds/BattlegroundQueue.h
+++ b/src/server/game/Battlegrounds/BattlegroundQueue.h
@@ -72,7 +72,7 @@ enum BattlegroundQueueInvitationType
};
class Battleground;
-class BattlegroundQueue
+class TC_GAME_API BattlegroundQueue
{
public:
BattlegroundQueue();
@@ -142,7 +142,7 @@ class BattlegroundQueue
This class is used to invite player to BG again, when minute lasts from his first invitation
it is capable to solve all possibilities
*/
-class BGQueueInviteEvent : public BasicEvent
+class TC_GAME_API BGQueueInviteEvent : public BasicEvent
{
public:
BGQueueInviteEvent(ObjectGuid pl_guid, uint32 BgInstanceGUID, BattlegroundTypeId BgTypeId, uint8 arenaType, uint32 removeTime) :
@@ -165,7 +165,7 @@ class BGQueueInviteEvent : public BasicEvent
We must store removeInvite time in case player left queue and joined and is invited again
We must store bgQueueTypeId, because battleground can be deleted already, when player entered it
*/
-class BGQueueRemoveEvent : public BasicEvent
+class TC_GAME_API BGQueueRemoveEvent : public BasicEvent
{
public:
BGQueueRemoveEvent(ObjectGuid pl_guid, uint32 bgInstanceGUID, BattlegroundTypeId BgTypeId, BattlegroundQueueTypeId bgQueueTypeId, uint32 removeTime)
diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt
index bba0614d421..df0d2b7cc2a 100644
--- a/src/server/game/CMakeLists.txt
+++ b/src/server/game/CMakeLists.txt
@@ -21,6 +21,8 @@ endif ()
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+add_definitions(-DTRINITY_API_EXPORT_GAME)
+
add_library(game
${PRIVATE_SOURCES}
${PRIVATE_PCH_SOURCE}
@@ -41,13 +43,27 @@ target_include_directories(game
target_link_libraries(game
PUBLIC
shared
- Detour)
+ Detour
+ PRIVATE
+ efsw)
set_target_properties(game
PROPERTIES
FOLDER
"server")
+if( BUILD_SHARED_LIBS )
+ if( UNIX )
+ install(TARGETS game
+ LIBRARY
+ DESTINATION lib)
+ elseif( WIN32 )
+ install(TARGETS game
+ RUNTIME
+ DESTINATION "${CMAKE_INSTALL_PREFIX}")
+ endif()
+endif()
+
# Generate precompiled header
if (USE_COREPCH)
add_cxx_pch(game ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
diff --git a/src/server/game/Calendar/CalendarMgr.h b/src/server/game/Calendar/CalendarMgr.h
index 084685f372c..c282e3e202c 100644
--- a/src/server/game/Calendar/CalendarMgr.h
+++ b/src/server/game/Calendar/CalendarMgr.h
@@ -126,7 +126,7 @@ enum CalendarError
#define CALENDAR_MAX_GUILD_EVENTS 100
#define CALENDAR_MAX_INVITES 100
-struct CalendarInvite
+struct TC_GAME_API CalendarInvite
{
public:
CalendarInvite(CalendarInvite const& calendarInvite, uint64 inviteId, uint64 eventId)
@@ -186,7 +186,7 @@ struct CalendarInvite
std::string _text;
};
-struct CalendarEvent
+struct TC_GAME_API CalendarEvent
{
public:
CalendarEvent(CalendarEvent const& calendarEvent, uint64 eventId)
@@ -266,7 +266,7 @@ typedef std::vector<CalendarInvite*> CalendarInviteStore;
typedef std::set<CalendarEvent*> CalendarEventStore;
typedef std::map<uint64 /* eventId */, CalendarInviteStore > CalendarEventInviteStore;
-class CalendarMgr
+class TC_GAME_API CalendarMgr
{
private:
CalendarMgr();
diff --git a/src/server/game/Chat/Channels/Channel.h b/src/server/game/Chat/Channels/Channel.h
index 26bc6989d07..319105d2a8d 100644
--- a/src/server/game/Chat/Channels/Channel.h
+++ b/src/server/game/Chat/Channels/Channel.h
@@ -118,7 +118,7 @@ enum ChannelMemberFlags
// 0x80
};
-class Channel
+class TC_GAME_API Channel
{
struct PlayerInfo
{
diff --git a/src/server/game/Chat/Channels/ChannelMgr.h b/src/server/game/Chat/Channels/ChannelMgr.h
index 2cd4edc4fb1..abe45690997 100644
--- a/src/server/game/Chat/Channels/ChannelMgr.h
+++ b/src/server/game/Chat/Channels/ChannelMgr.h
@@ -28,7 +28,7 @@
#define MAX_CHANNEL_PASS_STR 31
-class ChannelMgr
+class TC_GAME_API ChannelMgr
{
typedef std::map<std::wstring, Channel*> ChannelMap;
diff --git a/src/server/game/Chat/Chat.h b/src/server/game/Chat/Chat.h
index 7ce0792cdf9..a061ff63b00 100644
--- a/src/server/game/Chat/Chat.h
+++ b/src/server/game/Chat/Chat.h
@@ -36,7 +36,7 @@ class WorldObject;
struct GameTele;
-class ChatCommand
+class TC_GAME_API ChatCommand
{
typedef bool(*pHandler)(ChatHandler*, char const*);
@@ -52,7 +52,7 @@ class ChatCommand
std::vector<ChatCommand> ChildCommands;
};
-class ChatHandler
+class TC_GAME_API ChatHandler
{
public:
WorldSession* GetSession() { return m_session; }
@@ -161,7 +161,7 @@ class ChatHandler
bool sentErrorMessage;
};
-class CliHandler : public ChatHandler
+class TC_GAME_API CliHandler : public ChatHandler
{
public:
typedef void Print(void*, char const*);
diff --git a/src/server/game/Chat/ChatLink.h b/src/server/game/Chat/ChatLink.h
index 4adb61bbbf1..0d413ce49df 100644
--- a/src/server/game/Chat/ChatLink.h
+++ b/src/server/game/Chat/ChatLink.h
@@ -34,7 +34,7 @@ class Quest;
///////////////////////////////////////////////////////////////////////////////////////////////////
// ChatLink - abstract base class for various links
-class ChatLink
+class TC_GAME_API ChatLink
{
public:
ChatLink() : _color(0), _startPos(0), _endPos(0) { }
@@ -54,7 +54,7 @@ protected:
};
// ItemChatLink - link to item
-class ItemChatLink : public ChatLink
+class TC_GAME_API ItemChatLink : public ChatLink
{
public:
ItemChatLink() : ChatLink(), _item(NULL), _suffix(NULL), _property(NULL)
@@ -74,7 +74,7 @@ protected:
};
// QuestChatLink - link to quest
-class QuestChatLink : public ChatLink
+class TC_GAME_API QuestChatLink : public ChatLink
{
public:
QuestChatLink() : ChatLink(), _quest(nullptr), _questLevel(0) { }
@@ -87,7 +87,7 @@ protected:
};
// SpellChatLink - link to quest
-class SpellChatLink : public ChatLink
+class TC_GAME_API SpellChatLink : public ChatLink
{
public:
SpellChatLink() : ChatLink(), _spell(nullptr) { }
@@ -99,7 +99,7 @@ protected:
};
// AchievementChatLink - link to quest
-class AchievementChatLink : public ChatLink
+class TC_GAME_API AchievementChatLink : public ChatLink
{
public:
AchievementChatLink() : ChatLink(), _guid(0), _achievement(NULL)
@@ -116,7 +116,7 @@ protected:
};
// TradeChatLink - link to trade info
-class TradeChatLink : public SpellChatLink
+class TC_GAME_API TradeChatLink : public SpellChatLink
{
public:
TradeChatLink() : SpellChatLink(), _minSkillLevel(0), _maxSkillLevel(0), _guid(0) { }
@@ -129,7 +129,7 @@ private:
};
// TalentChatLink - link to talent
-class TalentChatLink : public SpellChatLink
+class TC_GAME_API TalentChatLink : public SpellChatLink
{
public:
TalentChatLink() : SpellChatLink(), _talentId(0), _rankId(0) { }
@@ -141,7 +141,7 @@ private:
};
// EnchantmentChatLink - link to enchantment
-class EnchantmentChatLink : public SpellChatLink
+class TC_GAME_API EnchantmentChatLink : public SpellChatLink
{
public:
EnchantmentChatLink() : SpellChatLink() { }
@@ -149,7 +149,7 @@ public:
};
// GlyphChatLink - link to glyph
-class GlyphChatLink : public SpellChatLink
+class TC_GAME_API GlyphChatLink : public SpellChatLink
{
public:
GlyphChatLink() : SpellChatLink(), _slotId(0), _glyph(NULL) { }
@@ -159,7 +159,7 @@ private:
GlyphPropertiesEntry const* _glyph;
};
-class LinkExtractor
+class TC_GAME_API LinkExtractor
{
public:
explicit LinkExtractor(const char* msg);
diff --git a/src/server/game/Combat/HostileRefManager.h b/src/server/game/Combat/HostileRefManager.h
index 96152ed46f7..855f9e3d272 100644
--- a/src/server/game/Combat/HostileRefManager.h
+++ b/src/server/game/Combat/HostileRefManager.h
@@ -29,7 +29,7 @@ class SpellInfo;
//=================================================
-class HostileRefManager : public RefManager<Unit, ThreatManager>
+class TC_GAME_API HostileRefManager : public RefManager<Unit, ThreatManager>
{
private:
Unit* iOwner;
diff --git a/src/server/game/Combat/ThreatManager.h b/src/server/game/Combat/ThreatManager.h
index 0f4efdbeab9..a68d803304d 100644
--- a/src/server/game/Combat/ThreatManager.h
+++ b/src/server/game/Combat/ThreatManager.h
@@ -39,14 +39,14 @@ class SpellInfo;
//==============================================================
// Class to calculate the real threat based
-struct ThreatCalcHelper
+struct TC_GAME_API ThreatCalcHelper
{
static float calcThreat(Unit* hatedUnit, Unit* hatingUnit, float threat, SpellSchoolMask schoolMask = SPELL_SCHOOL_MASK_NORMAL, SpellInfo const* threatSpell = NULL);
static bool isValidProcess(Unit* hatedUnit, Unit* hatingUnit, SpellInfo const* threatSpell = NULL);
};
//==============================================================
-class HostileReference : public Reference<Unit, ThreatManager>
+class TC_GAME_API HostileReference : public Reference<Unit, ThreatManager>
{
public:
HostileReference(Unit* refUnit, ThreatManager* threatManager, float threat);
@@ -141,7 +141,7 @@ class HostileReference : public Reference<Unit, ThreatManager>
//==============================================================
class ThreatManager;
-class ThreatContainer
+class TC_GAME_API ThreatContainer
{
friend class ThreatManager;
@@ -198,7 +198,7 @@ class ThreatContainer
//=================================================
-class ThreatManager
+class TC_GAME_API ThreatManager
{
public:
friend class HostileReference;
diff --git a/src/server/game/Combat/UnitEvents.h b/src/server/game/Combat/UnitEvents.h
index e501cdaa4a2..f50edcf3c7d 100644
--- a/src/server/game/Combat/UnitEvents.h
+++ b/src/server/game/Combat/UnitEvents.h
@@ -81,7 +81,7 @@ class UnitBaseEvent
//==============================================================
-class ThreatRefStatusChangeEvent : public UnitBaseEvent
+class TC_GAME_API ThreatRefStatusChangeEvent : public UnitBaseEvent
{
private:
HostileReference* iHostileReference;
diff --git a/src/server/game/Conditions/ConditionMgr.h b/src/server/game/Conditions/ConditionMgr.h
index 0b49552acb4..83e714781c3 100644
--- a/src/server/game/Conditions/ConditionMgr.h
+++ b/src/server/game/Conditions/ConditionMgr.h
@@ -159,7 +159,7 @@ enum MaxConditionTargets
MAX_CONDITION_TARGETS = 3
};
-struct ConditionSourceInfo
+struct TC_GAME_API ConditionSourceInfo
{
WorldObject* mConditionTargets[MAX_CONDITION_TARGETS]; // an array of targets available for conditions
Condition const* mLastFailedCondition;
@@ -172,7 +172,7 @@ struct ConditionSourceInfo
}
};
-struct Condition
+struct TC_GAME_API Condition
{
ConditionSourceType SourceType; //SourceTypeOrReferenceId
uint32 SourceGroup;
@@ -224,7 +224,7 @@ typedef std::unordered_map<uint32, ConditionsByEntryMap> ConditionEntriesByCreat
typedef std::unordered_map<std::pair<int32, uint32 /*SAI source_type*/>, ConditionsByEntryMap> SmartEventConditionContainer;
typedef std::unordered_map<uint32, ConditionContainer> ConditionReferenceContainer;//only used for references
-class ConditionMgr
+class TC_GAME_API ConditionMgr
{
private:
ConditionMgr();
diff --git a/src/server/game/Conditions/DisableMgr.h b/src/server/game/Conditions/DisableMgr.h
index e74b7a9c319..cae1e0329e8 100644
--- a/src/server/game/Conditions/DisableMgr.h
+++ b/src/server/game/Conditions/DisableMgr.h
@@ -57,11 +57,11 @@ enum MMapDisableTypes
namespace DisableMgr
{
- void LoadDisables();
- bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0);
- void CheckQuestDisables();
- bool IsVMAPDisabledFor(uint32 entry, uint8 flags);
- bool IsPathfindingEnabled(uint32 mapId);
+ TC_GAME_API void LoadDisables();
+ TC_GAME_API bool IsDisabledFor(DisableType type, uint32 entry, Unit const* unit, uint8 flags = 0);
+ TC_GAME_API void CheckQuestDisables();
+ TC_GAME_API bool IsVMAPDisabledFor(uint32 entry, uint8 flags);
+ TC_GAME_API bool IsPathfindingEnabled(uint32 mapId);
}
#endif //TRINITY_DISABLEMGR_H
diff --git a/src/server/game/DataStores/DBCStores.h b/src/server/game/DataStores/DBCStores.h
index 56ee1f618dd..beb0bb514cc 100644
--- a/src/server/game/DataStores/DBCStores.h
+++ b/src/server/game/DataStores/DBCStores.h
@@ -27,18 +27,18 @@
#include <list>
typedef std::list<uint32> SimpleFactionsList;
-SimpleFactionsList const* GetFactionTeamList(uint32 faction);
+TC_GAME_API SimpleFactionsList const* GetFactionTeamList(uint32 faction);
-char* GetPetName(uint32 petfamily, uint32 dbclang);
-uint32 GetTalentSpellCost(uint32 spellId);
-TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
+TC_GAME_API char* GetPetName(uint32 petfamily, uint32 dbclang);
+TC_GAME_API uint32 GetTalentSpellCost(uint32 spellId);
+TC_GAME_API TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
-char const* GetRaceName(uint8 race, uint8 locale);
-char const* GetClassName(uint8 class_, uint8 locale);
+TC_GAME_API char const* GetRaceName(uint8 race, uint8 locale);
+TC_GAME_API char const* GetClassName(uint8 class_, uint8 locale);
-WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid);
+TC_GAME_API WMOAreaTableEntry const* GetWMOAreaTableEntryByTripple(int32 rootid, int32 adtid, int32 groupid);
-uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
+TC_GAME_API uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
enum ContentLevels
{
@@ -46,154 +46,154 @@ enum ContentLevels
CONTENT_61_70,
CONTENT_71_80
};
-ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
+TC_GAME_API ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
-bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
+TC_GAME_API bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
-void Zone2MapCoordinates(float &x, float &y, uint32 zone);
-void Map2ZoneCoordinates(float &x, float &y, uint32 zone);
+TC_GAME_API void Zone2MapCoordinates(float &x, float &y, uint32 zone);
+TC_GAME_API void Map2ZoneCoordinates(float &x, float &y, uint32 zone);
typedef std::map<uint32/*pair32(map, diff)*/, MapDifficulty> MapDifficultyMap;
-MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
-MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty);
+TC_GAME_API MapDifficulty const* GetMapDifficultyData(uint32 mapId, Difficulty difficulty);
+TC_GAME_API MapDifficulty const* GetDownscaledMapDifficultyData(uint32 mapId, Difficulty &difficulty);
-uint32 const* /*[MAX_TALENT_TABS]*/ GetTalentTabPages(uint8 cls);
+TC_GAME_API uint32 const* /*[MAX_TALENT_TABS]*/ GetTalentTabPages(uint8 cls);
-uint32 GetLiquidFlags(uint32 liquidType);
+TC_GAME_API uint32 GetLiquidFlags(uint32 liquidType);
-PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level);
-PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id);
+TC_GAME_API PvPDifficultyEntry const* GetBattlegroundBracketByLevel(uint32 mapid, uint32 level);
+TC_GAME_API PvPDifficultyEntry const* GetBattlegroundBracketById(uint32 mapid, BattlegroundBracketId id);
-CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
-CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color);
+TC_GAME_API CharStartOutfitEntry const* GetCharStartOutfitEntry(uint8 race, uint8 class_, uint8 gender);
+TC_GAME_API CharSectionsEntry const* GetCharSectionEntry(uint8 race, CharSectionType genType, uint8 gender, uint8 type, uint8 color);
-LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
+TC_GAME_API LFGDungeonEntry const* GetLFGDungeon(uint32 mapId, Difficulty difficulty);
-uint32 GetDefaultMapLight(uint32 mapId);
+TC_GAME_API uint32 GetDefaultMapLight(uint32 mapId);
typedef std::unordered_multimap<uint32, SkillRaceClassInfoEntry const*> SkillRaceClassInfoMap;
typedef std::pair<SkillRaceClassInfoMap::iterator, SkillRaceClassInfoMap::iterator> SkillRaceClassInfoBounds;
-SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
-
-ResponseCodes ValidateName(std::string const& name, LocaleConstant locale);
-
-EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender);
-
-extern DBCStorage <AchievementEntry> sAchievementStore;
-extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
-extern DBCStorage <AreaTableEntry> sAreaTableStore;
-extern DBCStorage <AreaGroupEntry> sAreaGroupStore;
-extern DBCStorage <AreaPOIEntry> sAreaPOIStore;
-extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
-extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore;
-extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
-extern DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore;
-extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore;
-extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
-extern DBCStorage <ChatChannelsEntry> sChatChannelsStore;
-extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
-extern DBCStorage <CharSectionsEntry> sCharSectionsStore;
-extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
-extern DBCStorage <ChrClassesEntry> sChrClassesStore;
-extern DBCStorage <ChrRacesEntry> sChrRacesStore;
-extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore;
-extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
-extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore;
-extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
-extern DBCStorage <CreatureModelDataEntry> sCreatureModelDataStore;
-extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore;
-extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore;
-extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore;
-extern DBCStorage <DestructibleModelDataEntry> sDestructibleModelDataStore;
-extern DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore;
-extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
-extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
-extern DBCStorage <EmotesEntry> sEmotesStore;
-extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
-extern DBCStorage <EmotesTextSoundEntry> sEmotesTextSoundStore;
-extern DBCStorage <FactionEntry> sFactionStore;
-extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
-extern DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore;
-extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore;
-extern DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore;
-extern DBCStorage <GlyphSlotEntry> sGlyphSlotStore;
-
-extern DBCStorage <GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore;
-extern DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore;
-extern DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore;
-extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore;
-extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore;
-extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore;
-extern DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore;
-extern DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore;
-extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
-//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
-extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
-extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
-extern DBCStorage <HolidaysEntry> sHolidaysStore;
-extern DBCStorage <ItemEntry> sItemStore;
-extern DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore;
-//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
-extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
-extern DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore;
-extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
-extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
-extern DBCStorage <ItemSetEntry> sItemSetStore;
-extern DBCStorage <LFGDungeonEntry> sLFGDungeonStore;
-extern DBCStorage <LiquidTypeEntry> sLiquidTypeStore;
-extern DBCStorage <LockEntry> sLockStore;
-extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
-extern DBCStorage <MapEntry> sMapStore;
-//extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
-extern MapDifficultyMap sMapDifficultyMap;
-extern DBCStorage <MovieEntry> sMovieStore;
-extern DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore;
-extern DBCStorage <PowerDisplayEntry> sPowerDisplayStore;
-extern DBCStorage <QuestSortEntry> sQuestSortStore;
-extern DBCStorage <QuestXPEntry> sQuestXPStore;
-extern DBCStorage <QuestFactionRewEntry> sQuestFactionRewardStore;
-extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
-extern DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore;
-extern DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore;
-extern DBCStorage <SkillLineEntry> sSkillLineStore;
-extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
-extern DBCStorage <SkillTiersEntry> sSkillTiersStore;
-extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
-extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
-extern DBCStorage <SpellCategoryEntry> sSpellCategoryStore;
-extern DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore;
-extern DBCStorage <SpellDurationEntry> sSpellDurationStore;
-extern DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore;
-extern DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore;
-extern DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore;
-extern PetFamilySpellsStore sPetFamilySpellsStore;
-extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
-extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
-extern DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore;
-extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
-extern DBCStorage <SpellEntry> sSpellStore;
-extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
-extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore;
-extern DBCStorage <TalentEntry> sTalentStore;
-extern DBCStorage <TalentTabEntry> sTalentTabStore;
-extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore;
-extern DBCStorage <TaxiPathEntry> sTaxiPathStore;
-extern TaxiMask sTaxiNodesMask;
-extern TaxiMask sOldContinentsNodesMask;
-extern TaxiMask sHordeTaxiNodesMask;
-extern TaxiMask sAllianceTaxiNodesMask;
-extern TaxiMask sDeathKnightTaxiNodesMask;
-extern TaxiPathSetBySource sTaxiPathSetBySource;
-extern TaxiPathNodesByPath sTaxiPathNodesByPath;
-extern DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore;
-extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
-extern DBCStorage <VehicleEntry> sVehicleStore;
-extern DBCStorage <VehicleSeatEntry> sVehicleSeatStore;
-extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore;
-//extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates
-extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore;
-extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore;
-
-void LoadDBCStores(const std::string& dataPath);
+TC_GAME_API SkillRaceClassInfoEntry const* GetSkillRaceClassInfo(uint32 skill, uint8 race, uint8 class_);
+
+TC_GAME_API ResponseCodes ValidateName(std::string const& name, LocaleConstant locale);
+
+TC_GAME_API EmotesTextSoundEntry const* FindTextSoundEmoteFor(uint32 emote, uint32 race, uint32 gender);
+
+TC_GAME_API extern DBCStorage <AchievementEntry> sAchievementStore;
+TC_GAME_API extern DBCStorage <AchievementCriteriaEntry> sAchievementCriteriaStore;
+TC_GAME_API extern DBCStorage <AreaTableEntry> sAreaTableStore;
+TC_GAME_API extern DBCStorage <AreaGroupEntry> sAreaGroupStore;
+TC_GAME_API extern DBCStorage <AreaPOIEntry> sAreaPOIStore;
+TC_GAME_API extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
+TC_GAME_API extern DBCStorage <AuctionHouseEntry> sAuctionHouseStore;
+TC_GAME_API extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
+TC_GAME_API extern DBCStorage <BannedAddOnsEntry> sBannedAddOnsStore;
+TC_GAME_API extern DBCStorage <BarberShopStyleEntry> sBarberShopStyleStore;
+TC_GAME_API extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
+TC_GAME_API extern DBCStorage <ChatChannelsEntry> sChatChannelsStore;
+TC_GAME_API extern DBCStorage <CharStartOutfitEntry> sCharStartOutfitStore;
+TC_GAME_API extern DBCStorage <CharSectionsEntry> sCharSectionsStore;
+TC_GAME_API extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
+TC_GAME_API extern DBCStorage <ChrClassesEntry> sChrClassesStore;
+TC_GAME_API extern DBCStorage <ChrRacesEntry> sChrRacesStore;
+TC_GAME_API extern DBCStorage <CinematicSequencesEntry> sCinematicSequencesStore;
+TC_GAME_API extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
+TC_GAME_API extern DBCStorage <CreatureDisplayInfoExtraEntry> sCreatureDisplayInfoExtraStore;
+TC_GAME_API extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
+TC_GAME_API extern DBCStorage <CreatureModelDataEntry> sCreatureModelDataStore;
+TC_GAME_API extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore;
+TC_GAME_API extern DBCStorage <CreatureTypeEntry> sCreatureTypeStore;
+TC_GAME_API extern DBCStorage <CurrencyTypesEntry> sCurrencyTypesStore;
+TC_GAME_API extern DBCStorage <DestructibleModelDataEntry> sDestructibleModelDataStore;
+TC_GAME_API extern DBCStorage <DungeonEncounterEntry> sDungeonEncounterStore;
+TC_GAME_API extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
+TC_GAME_API extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
+TC_GAME_API extern DBCStorage <EmotesEntry> sEmotesStore;
+TC_GAME_API extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
+TC_GAME_API extern DBCStorage <EmotesTextSoundEntry> sEmotesTextSoundStore;
+TC_GAME_API extern DBCStorage <FactionEntry> sFactionStore;
+TC_GAME_API extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
+TC_GAME_API extern DBCStorage <GameObjectDisplayInfoEntry> sGameObjectDisplayInfoStore;
+TC_GAME_API extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore;
+TC_GAME_API extern DBCStorage <GlyphPropertiesEntry> sGlyphPropertiesStore;
+TC_GAME_API extern DBCStorage <GlyphSlotEntry> sGlyphSlotStore;
+
+TC_GAME_API extern DBCStorage <GtBarberShopCostBaseEntry> sGtBarberShopCostBaseStore;
+TC_GAME_API extern DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore;
+TC_GAME_API extern DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore;
+TC_GAME_API extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore;
+TC_GAME_API extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore;
+TC_GAME_API extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore;
+TC_GAME_API extern DBCStorage <GtNPCManaCostScalerEntry> sGtNPCManaCostScalerStore;
+TC_GAME_API extern DBCStorage <GtOCTClassCombatRatingScalarEntry> sGtOCTClassCombatRatingScalarStore;
+TC_GAME_API extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
+//TC_GAME_API extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
+TC_GAME_API extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
+TC_GAME_API extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
+TC_GAME_API extern DBCStorage <HolidaysEntry> sHolidaysStore;
+TC_GAME_API extern DBCStorage <ItemEntry> sItemStore;
+TC_GAME_API extern DBCStorage <ItemBagFamilyEntry> sItemBagFamilyStore;
+//TC_GAME_API extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
+TC_GAME_API extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
+TC_GAME_API extern DBCStorage <ItemLimitCategoryEntry> sItemLimitCategoryStore;
+TC_GAME_API extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
+TC_GAME_API extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
+TC_GAME_API extern DBCStorage <ItemSetEntry> sItemSetStore;
+TC_GAME_API extern DBCStorage <LFGDungeonEntry> sLFGDungeonStore;
+TC_GAME_API extern DBCStorage <LiquidTypeEntry> sLiquidTypeStore;
+TC_GAME_API extern DBCStorage <LockEntry> sLockStore;
+TC_GAME_API extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
+TC_GAME_API extern DBCStorage <MapEntry> sMapStore;
+//TC_GAME_API extern DBCStorage <MapDifficultyEntry> sMapDifficultyStore; -- use GetMapDifficultyData insteed
+TC_GAME_API extern MapDifficultyMap sMapDifficultyMap;
+TC_GAME_API extern DBCStorage <MovieEntry> sMovieStore;
+TC_GAME_API extern DBCStorage <OverrideSpellDataEntry> sOverrideSpellDataStore;
+TC_GAME_API extern DBCStorage <PowerDisplayEntry> sPowerDisplayStore;
+TC_GAME_API extern DBCStorage <QuestSortEntry> sQuestSortStore;
+TC_GAME_API extern DBCStorage <QuestXPEntry> sQuestXPStore;
+TC_GAME_API extern DBCStorage <QuestFactionRewEntry> sQuestFactionRewardStore;
+TC_GAME_API extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
+TC_GAME_API extern DBCStorage <ScalingStatDistributionEntry> sScalingStatDistributionStore;
+TC_GAME_API extern DBCStorage <ScalingStatValuesEntry> sScalingStatValuesStore;
+TC_GAME_API extern DBCStorage <SkillLineEntry> sSkillLineStore;
+TC_GAME_API extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
+TC_GAME_API extern DBCStorage <SkillTiersEntry> sSkillTiersStore;
+TC_GAME_API extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
+TC_GAME_API extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
+TC_GAME_API extern DBCStorage <SpellCategoryEntry> sSpellCategoryStore;
+TC_GAME_API extern DBCStorage <SpellDifficultyEntry> sSpellDifficultyStore;
+TC_GAME_API extern DBCStorage <SpellDurationEntry> sSpellDurationStore;
+TC_GAME_API extern DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore;
+TC_GAME_API extern DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore;
+TC_GAME_API extern DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore;
+TC_GAME_API extern PetFamilySpellsStore sPetFamilySpellsStore;
+TC_GAME_API extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
+TC_GAME_API extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
+TC_GAME_API extern DBCStorage <SpellRuneCostEntry> sSpellRuneCostStore;
+TC_GAME_API extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
+TC_GAME_API extern DBCStorage <SpellEntry> sSpellStore;
+TC_GAME_API extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
+TC_GAME_API extern DBCStorage <SummonPropertiesEntry> sSummonPropertiesStore;
+TC_GAME_API extern DBCStorage <TalentEntry> sTalentStore;
+TC_GAME_API extern DBCStorage <TalentTabEntry> sTalentTabStore;
+TC_GAME_API extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore;
+TC_GAME_API extern DBCStorage <TaxiPathEntry> sTaxiPathStore;
+TC_GAME_API extern TaxiMask sTaxiNodesMask;
+TC_GAME_API extern TaxiMask sOldContinentsNodesMask;
+TC_GAME_API extern TaxiMask sHordeTaxiNodesMask;
+TC_GAME_API extern TaxiMask sAllianceTaxiNodesMask;
+TC_GAME_API extern TaxiMask sDeathKnightTaxiNodesMask;
+TC_GAME_API extern TaxiPathSetBySource sTaxiPathSetBySource;
+TC_GAME_API extern TaxiPathNodesByPath sTaxiPathNodesByPath;
+TC_GAME_API extern DBCStorage <TeamContributionPointsEntry> sTeamContributionPointsStore;
+TC_GAME_API extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
+TC_GAME_API extern DBCStorage <VehicleEntry> sVehicleStore;
+TC_GAME_API extern DBCStorage <VehicleSeatEntry> sVehicleSeatStore;
+TC_GAME_API extern DBCStorage <WMOAreaTableEntry> sWMOAreaTableStore;
+//TC_GAME_API extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates
+TC_GAME_API extern DBCStorage <WorldMapOverlayEntry> sWorldMapOverlayStore;
+TC_GAME_API extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore;
+
+TC_GAME_API void LoadDBCStores(const std::string& dataPath);
#endif
diff --git a/src/server/game/DungeonFinding/LFG.h b/src/server/game/DungeonFinding/LFG.h
index 73c123723b1..b837a0df272 100644
--- a/src/server/game/DungeonFinding/LFG.h
+++ b/src/server/game/DungeonFinding/LFG.h
@@ -101,9 +101,9 @@ typedef std::map<ObjectGuid, LfgLockMap> LfgLockPartyMap;
typedef std::map<ObjectGuid, uint8> LfgRolesMap;
typedef std::map<ObjectGuid, ObjectGuid> LfgGroupsMap;
-std::string ConcatenateDungeons(LfgDungeonSet const& dungeons);
-std::string GetRolesString(uint8 roles);
-std::string GetStateString(LfgState state);
+TC_GAME_API std::string ConcatenateDungeons(LfgDungeonSet const& dungeons);
+TC_GAME_API std::string GetRolesString(uint8 roles);
+TC_GAME_API std::string GetStateString(LfgState state);
} // namespace lfg
diff --git a/src/server/game/DungeonFinding/LFGGroupData.h b/src/server/game/DungeonFinding/LFGGroupData.h
index 7ae4777cd4d..62a41b6b350 100644
--- a/src/server/game/DungeonFinding/LFGGroupData.h
+++ b/src/server/game/DungeonFinding/LFGGroupData.h
@@ -31,7 +31,7 @@ enum LfgGroupEnum
/**
Stores all lfg data needed about a group.
*/
-class LfgGroupData
+class TC_GAME_API LfgGroupData
{
public:
LfgGroupData();
diff --git a/src/server/game/DungeonFinding/LFGMgr.h b/src/server/game/DungeonFinding/LFGMgr.h
index 7be08d448db..c72c0a3cdab 100644
--- a/src/server/game/DungeonFinding/LFGMgr.h
+++ b/src/server/game/DungeonFinding/LFGMgr.h
@@ -289,7 +289,7 @@ struct LFGDungeonData
uint32 Entry() const { return id + (type << 24); }
};
-class LFGMgr
+class TC_GAME_API LFGMgr
{
private:
LFGMgr();
diff --git a/src/server/game/DungeonFinding/LFGPlayerData.h b/src/server/game/DungeonFinding/LFGPlayerData.h
index 859317ca956..91e4153a6d5 100644
--- a/src/server/game/DungeonFinding/LFGPlayerData.h
+++ b/src/server/game/DungeonFinding/LFGPlayerData.h
@@ -26,7 +26,7 @@ namespace lfg
/**
Stores all lfg data needed about the player.
*/
-class LfgPlayerData
+class TC_GAME_API LfgPlayerData
{
public:
LfgPlayerData();
diff --git a/src/server/game/DungeonFinding/LFGQueue.h b/src/server/game/DungeonFinding/LFGQueue.h
index ed8193ab605..7c35c4d04e3 100644
--- a/src/server/game/DungeonFinding/LFGQueue.h
+++ b/src/server/game/DungeonFinding/LFGQueue.h
@@ -83,7 +83,7 @@ typedef std::map<ObjectGuid, LfgQueueData> LfgQueueDataContainer;
/**
Stores all data related to queue
*/
-class LFGQueue
+class TC_GAME_API LFGQueue
{
public:
diff --git a/src/server/game/DungeonFinding/LFGScripts.h b/src/server/game/DungeonFinding/LFGScripts.h
index 377614bc55d..ec64604a282 100644
--- a/src/server/game/DungeonFinding/LFGScripts.h
+++ b/src/server/game/DungeonFinding/LFGScripts.h
@@ -29,7 +29,7 @@ class Group;
namespace lfg
{
-class LFGPlayerScript : public PlayerScript
+class TC_GAME_API LFGPlayerScript : public PlayerScript
{
public:
LFGPlayerScript();
@@ -40,7 +40,7 @@ class LFGPlayerScript : public PlayerScript
void OnMapChanged(Player* player) override;
};
-class LFGGroupScript : public GroupScript
+class TC_GAME_API LFGGroupScript : public GroupScript
{
public:
LFGGroupScript();
diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h
index 5062645eac8..c9dd0b01509 100644
--- a/src/server/game/Entities/Corpse/Corpse.h
+++ b/src/server/game/Entities/Corpse/Corpse.h
@@ -46,7 +46,7 @@ enum CorpseFlags
CORPSE_FLAG_LOOTABLE = 0x20
};
-class Corpse : public WorldObject, public GridObject<Corpse>
+class TC_GAME_API Corpse : public WorldObject, public GridObject<Corpse>
{
public:
explicit Corpse(CorpseType type = CORPSE_BONES);
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 0803345f4f0..c4b6776f30b 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -75,7 +75,7 @@ enum CreatureFlagsExtra
#define CREATURE_MAX_SPELLS 8
// from `creature_template` table
-struct CreatureTemplate
+struct TC_GAME_API CreatureTemplate
{
uint32 Entry;
uint32 DifficultyEntry[MAX_DIFFICULTY - 1];
@@ -179,7 +179,7 @@ typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer;
#pragma pack(push, 1)
// Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage).
-struct CreatureBaseStats
+struct TC_GAME_API CreatureBaseStats
{
uint32 BaseHealth[MAX_EXPANSIONS];
uint32 BaseMana;
@@ -401,7 +401,7 @@ struct TrainerSpell
typedef std::unordered_map<uint32 /*spellid*/, TrainerSpell> TrainerSpellMap;
-struct TrainerSpellData
+struct TC_GAME_API TrainerSpellData
{
TrainerSpellData() : trainerType(0) { }
~TrainerSpellData() { spellList.clear(); }
@@ -421,7 +421,7 @@ struct TrainerSpellData
typedef std::vector<uint8> CreatureTextRepeatIds;
typedef std::unordered_map<uint8, CreatureTextRepeatIds> CreatureTextRepeatGroup;
-class Creature : public Unit, public GridObject<Creature>, public MapObject
+class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public MapObject
{
public:
@@ -754,7 +754,7 @@ class Creature : public Unit, public GridObject<Creature>, public MapObject
CreatureTextRepeatGroup m_textRepeat;
};
-class AssistDelayEvent : public BasicEvent
+class TC_GAME_API AssistDelayEvent : public BasicEvent
{
public:
AssistDelayEvent(ObjectGuid victim, Unit& owner) : BasicEvent(), m_victim(victim), m_owner(owner) { }
@@ -769,7 +769,7 @@ class AssistDelayEvent : public BasicEvent
Unit& m_owner;
};
-class ForcedDespawnDelayEvent : public BasicEvent
+class TC_GAME_API ForcedDespawnDelayEvent : public BasicEvent
{
public:
ForcedDespawnDelayEvent(Creature& owner) : BasicEvent(), m_owner(owner) { }
diff --git a/src/server/game/Entities/Creature/CreatureGroups.h b/src/server/game/Entities/Creature/CreatureGroups.h
index d337d388b6e..14472a30293 100644
--- a/src/server/game/Entities/Creature/CreatureGroups.h
+++ b/src/server/game/Entities/Creature/CreatureGroups.h
@@ -38,7 +38,7 @@ struct FormationInfo
typedef std::unordered_map<uint32/*memberDBGUID*/, FormationInfo*> CreatureGroupInfoType;
-class FormationMgr
+class TC_GAME_API FormationMgr
{
private:
FormationMgr() { }
@@ -53,7 +53,7 @@ class FormationMgr
CreatureGroupInfoType CreatureGroupMap;
};
-class CreatureGroup
+class TC_GAME_API CreatureGroup
{
private:
Creature* m_leader; //Important do not forget sometimes to work with pointers instead synonims :D:D
diff --git a/src/server/game/Entities/Creature/GossipDef.h b/src/server/game/Entities/Creature/GossipDef.h
index 1e64e83c86a..01b27032286 100644
--- a/src/server/game/Entities/Creature/GossipDef.h
+++ b/src/server/game/Entities/Creature/GossipDef.h
@@ -157,7 +157,7 @@ struct QuestMenuItem
typedef std::vector<QuestMenuItem> QuestMenuItemList;
-class GossipMenu
+class TC_GAME_API GossipMenu
{
public:
GossipMenu();
@@ -222,7 +222,7 @@ class GossipMenu
LocaleConstant _locale;
};
-class QuestMenu
+class TC_GAME_API QuestMenu
{
public:
QuestMenu();
@@ -252,7 +252,7 @@ class QuestMenu
QuestMenuItemList _questMenuItems;
};
-class PlayerMenu
+class TC_GAME_API PlayerMenu
{
public:
explicit PlayerMenu(WorldSession* session);
diff --git a/src/server/game/Entities/Creature/TemporarySummon.h b/src/server/game/Entities/Creature/TemporarySummon.h
index b80e7d3e2bc..87cb883b261 100644
--- a/src/server/game/Entities/Creature/TemporarySummon.h
+++ b/src/server/game/Entities/Creature/TemporarySummon.h
@@ -37,7 +37,7 @@ struct TempSummonData
uint32 time; ///< Despawn time, usable only with certain temp summon types
};
-class TempSummon : public Creature
+class TC_GAME_API TempSummon : public Creature
{
public:
explicit TempSummon(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
@@ -64,7 +64,7 @@ class TempSummon : public Creature
ObjectGuid m_summonerGUID;
};
-class Minion : public TempSummon
+class TC_GAME_API Minion : public TempSummon
{
public:
Minion(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
@@ -82,7 +82,7 @@ class Minion : public TempSummon
float m_followAngle;
};
-class Guardian : public Minion
+class TC_GAME_API Guardian : public Minion
{
public:
Guardian(SummonPropertiesEntry const* properties, Unit* owner, bool isWorldObject);
@@ -106,7 +106,7 @@ class Guardian : public Minion
float m_statFromOwner[MAX_STATS];
};
-class Puppet : public Minion
+class TC_GAME_API Puppet : public Minion
{
public:
Puppet(SummonPropertiesEntry const* properties, Unit* owner);
@@ -116,7 +116,7 @@ class Puppet : public Minion
void RemoveFromWorld() override;
};
-class ForcedUnsummonDelayEvent : public BasicEvent
+class TC_GAME_API ForcedUnsummonDelayEvent : public BasicEvent
{
public:
ForcedUnsummonDelayEvent(TempSummon& owner) : BasicEvent(), m_owner(owner) { }
diff --git a/src/server/game/Entities/DynamicObject/DynamicObject.h b/src/server/game/Entities/DynamicObject/DynamicObject.h
index 9443a5b5b89..d7c1f0190fd 100644
--- a/src/server/game/Entities/DynamicObject/DynamicObject.h
+++ b/src/server/game/Entities/DynamicObject/DynamicObject.h
@@ -32,7 +32,7 @@ enum DynamicObjectType
DYNAMIC_OBJECT_FARSIGHT_FOCUS = 0x2
};
-class DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MapObject
+class TC_GAME_API DynamicObject : public WorldObject, public GridObject<DynamicObject>, public MapObject
{
public:
DynamicObject(bool isWorldObject);
diff --git a/src/server/game/Entities/GameObject/GameObject.h b/src/server/game/Entities/GameObject/GameObject.h
index 7be78556a50..49f94013ac2 100644
--- a/src/server/game/Entities/GameObject/GameObject.h
+++ b/src/server/game/Entities/GameObject/GameObject.h
@@ -640,7 +640,7 @@ class GameObjectModel;
// 5 sec for bobber catch
#define FISHING_BOBBER_READY_TIME 5
-class GameObject : public WorldObject, public GridObject<GameObject>, public MapObject
+class TC_GAME_API GameObject : public WorldObject, public GridObject<GameObject>, public MapObject
{
public:
explicit GameObject();
diff --git a/src/server/game/Entities/Item/Container/Bag.h b/src/server/game/Entities/Item/Container/Bag.h
index 5bfafa4238c..89615f94e52 100644
--- a/src/server/game/Entities/Item/Container/Bag.h
+++ b/src/server/game/Entities/Item/Container/Bag.h
@@ -25,7 +25,7 @@
#include "Item.h"
#include "ItemPrototype.h"
-class Bag : public Item
+class TC_GAME_API Bag : public Item
{
public:
diff --git a/src/server/game/Entities/Item/Item.h b/src/server/game/Entities/Item/Item.h
index 378d7f5e2e4..8658200c28c 100644
--- a/src/server/game/Entities/Item/Item.h
+++ b/src/server/game/Entities/Item/Item.h
@@ -203,7 +203,7 @@ enum ItemUpdateState
bool ItemCanGoIntoBag(ItemTemplate const* proto, ItemTemplate const* pBagProto);
-class Item : public Object
+class TC_GAME_API Item : public Object
{
public:
static Item* CreateItem(uint32 itemEntry, uint32 count, Player const* player = NULL);
diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
index a7b410bc04b..b44a3e7ad7b 100644
--- a/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
+++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.cpp
@@ -44,7 +44,7 @@ typedef std::unordered_map<uint32, EnchStoreList> EnchantmentStore;
static EnchantmentStore RandomItemEnch;
-void LoadRandomEnchantmentsTable()
+TC_GAME_API void LoadRandomEnchantmentsTable()
{
uint32 oldMSTime = getMSTime();
@@ -77,7 +77,7 @@ void LoadRandomEnchantmentsTable()
TC_LOG_ERROR("server.loading", ">> Loaded 0 Item Enchantment definitions. DB table `item_enchantment_template` is empty.");
}
-uint32 GetItemEnchantMod(int32 entry)
+TC_GAME_API uint32 GetItemEnchantMod(int32 entry)
{
if (!entry)
return 0;
@@ -118,7 +118,7 @@ uint32 GetItemEnchantMod(int32 entry)
return 0;
}
-uint32 GenerateEnchSuffixFactor(uint32 item_id)
+TC_GAME_API uint32 GenerateEnchSuffixFactor(uint32 item_id)
{
ItemTemplate const* itemProto = sObjectMgr->GetItemTemplate(item_id);
diff --git a/src/server/game/Entities/Item/ItemEnchantmentMgr.h b/src/server/game/Entities/Item/ItemEnchantmentMgr.h
index 2d5c27177b1..8ce9ae780fe 100644
--- a/src/server/game/Entities/Item/ItemEnchantmentMgr.h
+++ b/src/server/game/Entities/Item/ItemEnchantmentMgr.h
@@ -21,8 +21,9 @@
#include "Common.h"
-void LoadRandomEnchantmentsTable();
-uint32 GetItemEnchantMod(int32 entry);
-uint32 GenerateEnchSuffixFactor(uint32 item_id);
+TC_GAME_API void LoadRandomEnchantmentsTable();
+TC_GAME_API uint32 GetItemEnchantMod(int32 entry);
+TC_GAME_API uint32 GenerateEnchSuffixFactor(uint32 item_id);
+
#endif
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index ba03c16fa1e..029a8c08fd7 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -90,7 +90,7 @@ class ZoneScript;
typedef std::unordered_map<Player*, UpdateData> UpdateDataMapType;
-class Object
+class TC_GAME_API Object
{
public:
virtual ~Object();
@@ -397,7 +397,7 @@ enum MapObjectCellMoveState
MAP_OBJECT_CELL_MOVE_INACTIVE, //in move list but should not move
};
-class MapObject
+class TC_GAME_API MapObject
{
friend class Map; //map for moving creatures
friend class ObjectGridLoader; //grid loader for loading creatures
@@ -422,7 +422,7 @@ class MapObject
}
};
-class WorldObject : public Object, public WorldLocation
+class TC_GAME_API WorldObject : public Object, public WorldLocation
{
protected:
explicit WorldObject(bool isWorldObject); //note: here it means if it is in grid object list or world object list
diff --git a/src/server/game/Entities/Object/ObjectGuid.cpp b/src/server/game/Entities/Object/ObjectGuid.cpp
index 3e2bd000b6e..2fb766c5201 100644
--- a/src/server/game/Entities/Object/ObjectGuid.cpp
+++ b/src/server/game/Entities/Object/ObjectGuid.cpp
@@ -95,4 +95,19 @@ void ObjectGuidGeneratorBase::HandleCounterOverflow(HighGuid high)
{
TC_LOG_ERROR("misc", "%s guid overflow!! Can't continue, shutting down server. ", ObjectGuid::GetTypeName(high));
World::StopNow(ERROR_EXIT_CODE);
-} \ No newline at end of file
+}
+
+#define GUID_TRAIT_INSTANTIATE_GUID( HIGH_GUID ) \
+ template class TC_GAME_API ObjectGuidGenerator< HIGH_GUID >;
+
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Container)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Player)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::GameObject)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Transport)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Unit)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Pet)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Vehicle)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::DynamicObject)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Mo_Transport)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Instance)
+GUID_TRAIT_INSTANTIATE_GUID(HighGuid::Group)
diff --git a/src/server/game/Entities/Object/ObjectGuid.h b/src/server/game/Entities/Object/ObjectGuid.h
index 44644421567..71c66622790 100644
--- a/src/server/game/Entities/Object/ObjectGuid.h
+++ b/src/server/game/Entities/Object/ObjectGuid.h
@@ -111,7 +111,7 @@ struct PackedGuidReader
ObjectGuid* GuidPtr;
};
-class ObjectGuid
+class TC_GAME_API ObjectGuid
{
public:
static ObjectGuid const Empty;
@@ -252,9 +252,9 @@ typedef std::unordered_set<ObjectGuid> GuidUnorderedSet;
// minimum buffer size for packed guid is 9 bytes
#define PACKED_GUID_MIN_BUFFER_SIZE 9
-class PackedGuid
+class TC_GAME_API PackedGuid
{
- friend ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid);
+ friend TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid);
public:
explicit PackedGuid() : _packedGuid(PACKED_GUID_MIN_BUFFER_SIZE) { _packedGuid.appendPackGUID(0); }
@@ -270,8 +270,7 @@ class PackedGuid
ByteBuffer _packedGuid;
};
-
-class ObjectGuidGeneratorBase
+class TC_GAME_API ObjectGuidGeneratorBase
{
public:
ObjectGuidGeneratorBase(ObjectGuid::LowType start = 1) : _nextGuid(start) { }
@@ -286,7 +285,7 @@ protected:
};
template<HighGuid high>
-class ObjectGuidGenerator : public ObjectGuidGeneratorBase
+class TC_GAME_API ObjectGuidGenerator : public ObjectGuidGeneratorBase
{
public:
explicit ObjectGuidGenerator(ObjectGuid::LowType start = 1) : ObjectGuidGeneratorBase(start) { }
@@ -299,11 +298,11 @@ public:
}
};
-ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid);
-ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid);
+TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, ObjectGuid const& guid);
+TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, ObjectGuid& guid);
-ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid);
-ByteBuffer& operator>>(ByteBuffer& buf, PackedGuidReader const& guid);
+TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, PackedGuid const& guid);
+TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, PackedGuidReader const& guid);
inline PackedGuid ObjectGuid::WriteAsPacked() const { return PackedGuid(*this); }
diff --git a/src/server/game/Entities/Object/ObjectPosSelector.h b/src/server/game/Entities/Object/ObjectPosSelector.h
index 26a23678009..84c694abf08 100644
--- a/src/server/game/Entities/Object/ObjectPosSelector.h
+++ b/src/server/game/Entities/Object/ObjectPosSelector.h
@@ -30,7 +30,7 @@ inline UsedPosType operator ~(UsedPosType uptype)
return uptype==USED_POS_PLUS ? USED_POS_MINUS : USED_POS_PLUS;
}
-struct ObjectPosSelector
+struct TC_GAME_API ObjectPosSelector
{
struct UsedPos
{
diff --git a/src/server/game/Entities/Object/Position.h b/src/server/game/Entities/Object/Position.h
index 18d356c28d4..6325cc51fe2 100644
--- a/src/server/game/Entities/Object/Position.h
+++ b/src/server/game/Entities/Object/Position.h
@@ -22,7 +22,7 @@
class ByteBuffer;
-struct Position
+struct TC_GAME_API Position
{
Position(float x = 0, float y = 0, float z = 0, float o = 0)
: m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { }
@@ -216,11 +216,11 @@ public:
}
};
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
-ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
-ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
+TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
+TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
+TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
+TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
+TC_GAME_API ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
+TC_GAME_API ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
#endif // Trinity_game_Position_h__
diff --git a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
index 0b4e59f4f9b..8208a5e9894 100644
--- a/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
+++ b/src/server/game/Entities/Object/Updates/UpdateFieldFlags.h
@@ -35,10 +35,10 @@ enum UpdatefieldFlags
UF_FLAG_DYNAMIC = 0x100
};
-extern uint32 ItemUpdateFieldFlags[CONTAINER_END];
-extern uint32 UnitUpdateFieldFlags[PLAYER_END];
-extern uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END];
-extern uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END];
-extern uint32 CorpseUpdateFieldFlags[CORPSE_END];
+TC_GAME_API extern uint32 ItemUpdateFieldFlags[CONTAINER_END];
+TC_GAME_API extern uint32 UnitUpdateFieldFlags[PLAYER_END];
+TC_GAME_API extern uint32 GameObjectUpdateFieldFlags[GAMEOBJECT_END];
+TC_GAME_API extern uint32 DynamicObjectUpdateFieldFlags[DYNAMICOBJECT_END];
+TC_GAME_API extern uint32 CorpseUpdateFieldFlags[CORPSE_END];
#endif // _UPDATEFIELDFLAGS_H
diff --git a/src/server/game/Entities/Pet/Pet.h b/src/server/game/Entities/Pet/Pet.h
index b0863a371e6..3a65fb44e04 100644
--- a/src/server/game/Entities/Pet/Pet.h
+++ b/src/server/game/Entities/Pet/Pet.h
@@ -37,7 +37,7 @@ typedef std::vector<uint32> AutoSpellList;
class Player;
-class Pet : public Guardian
+class TC_GAME_API Pet : public Guardian
{
public:
explicit Pet(Player* owner, PetType type = MAX_PET_TYPE);
diff --git a/src/server/game/Entities/Player/KillRewarder.h b/src/server/game/Entities/Player/KillRewarder.h
index 08530de900c..210e5ff0246 100644
--- a/src/server/game/Entities/Player/KillRewarder.h
+++ b/src/server/game/Entities/Player/KillRewarder.h
@@ -24,7 +24,7 @@ class Player;
class Unit;
class Group;
-class KillRewarder
+class TC_GAME_API KillRewarder
{
public:
KillRewarder(Player* killer, Unit* victim, bool isBattleGround);
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index dc8d9b03a6d..91a4a403fab 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -833,7 +833,7 @@ enum PlayerDelayedOperations
// Player summoning auto-decline time (in secs)
#define MAX_PLAYER_SUMMON_DELAY (2*MINUTE)
// Maximum money amount : 2^31 - 1
-extern uint32 const MAX_MONEY_AMOUNT;
+TC_GAME_API extern uint32 const MAX_MONEY_AMOUNT;
enum BindExtensionState
{
@@ -919,7 +919,7 @@ enum PlayerCommandStates
CHEAT_WATERWALK = 0x10
};
-class PlayerTaxi
+class TC_GAME_API PlayerTaxi
{
public:
PlayerTaxi();
@@ -1025,7 +1025,7 @@ struct ResurrectionData
#define SPELL_DK_RAISE_ALLY 46619
-class Player : public Unit, public GridObject<Player>
+class TC_GAME_API Player : public Unit, public GridObject<Player>
{
friend class WorldSession;
friend void Item::AddToUpdateQueueOf(Player* player);
@@ -2594,8 +2594,8 @@ class Player : public Unit, public GridObject<Player>
WorldLocation _corpseLocation;
};
-void AddItemsSetItem(Player* player, Item* item);
-void RemoveItemsSetItem(Player* player, ItemTemplate const* proto);
+TC_GAME_API void AddItemsSetItem(Player* player, Item* item);
+TC_GAME_API void RemoveItemsSetItem(Player* player, ItemTemplate const* proto);
// "the bodies of template functions must be made available in a header file"
template <class T> T Player::ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell)
diff --git a/src/server/game/Entities/Player/SocialMgr.h b/src/server/game/Entities/Player/SocialMgr.h
index 0512e61033c..803301b95c7 100644
--- a/src/server/game/Entities/Player/SocialMgr.h
+++ b/src/server/game/Entities/Player/SocialMgr.h
@@ -99,7 +99,7 @@ enum FriendsResult
#define SOCIALMGR_FRIEND_LIMIT 50
#define SOCIALMGR_IGNORE_LIMIT 50
-class PlayerSocial
+class TC_GAME_API PlayerSocial
{
friend class SocialMgr;
public:
diff --git a/src/server/game/Entities/Player/TradeData.h b/src/server/game/Entities/Player/TradeData.h
index 276e6f3db1c..396d784fee7 100644
--- a/src/server/game/Entities/Player/TradeData.h
+++ b/src/server/game/Entities/Player/TradeData.h
@@ -31,7 +31,7 @@ enum TradeSlots
class Item;
class Player;
-class TradeData
+class TC_GAME_API TradeData
{
public:
TradeData(Player* player, Player* trader) :
diff --git a/src/server/game/Entities/Totem/Totem.h b/src/server/game/Entities/Totem/Totem.h
index bbe7943f4b6..42be4525a0c 100644
--- a/src/server/game/Entities/Totem/Totem.h
+++ b/src/server/game/Entities/Totem/Totem.h
@@ -32,7 +32,7 @@ enum TotemType
#define SENTRY_TOTEM_ENTRY 3968
-class Totem : public Minion
+class TC_GAME_API Totem : public Minion
{
public:
Totem(SummonPropertiesEntry const* properties, Unit* owner);
diff --git a/src/server/game/Entities/Transport/Transport.h b/src/server/game/Entities/Transport/Transport.h
index 987fbf70739..4cd20c8b613 100644
--- a/src/server/game/Entities/Transport/Transport.h
+++ b/src/server/game/Entities/Transport/Transport.h
@@ -25,7 +25,7 @@
struct CreatureData;
-class Transport : public GameObject, public TransportBase
+class TC_GAME_API Transport : public GameObject, public TransportBase
{
friend Transport* TransportMgr::CreateTransport(uint32, ObjectGuid::LowType, Map*);
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index b1b93f1c987..d82b2cd8422 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -533,8 +533,8 @@ enum UnitMoveType
#define MAX_MOVE_TYPE 9
-extern float baseMoveSpeed[MAX_MOVE_TYPE];
-extern float playerBaseMoveSpeed[MAX_MOVE_TYPE];
+TC_GAME_API extern float baseMoveSpeed[MAX_MOVE_TYPE];
+TC_GAME_API extern float playerBaseMoveSpeed[MAX_MOVE_TYPE];
enum WeaponAttackType
{
@@ -826,7 +826,7 @@ struct CleanDamage
struct CalcDamageInfo;
-class DamageInfo
+class TC_GAME_API DamageInfo
{
private:
Unit* const m_attacker;
@@ -889,7 +889,7 @@ public:
SpellSchoolMask GetSchoolMask() const { return _schoolMask; };
};
-class ProcEventInfo
+class TC_GAME_API ProcEventInfo
{
public:
ProcEventInfo(Unit* actor, Unit* actionTarget, Unit* procTarget, uint32 typeMask,
@@ -947,7 +947,7 @@ struct CalcDamageInfo
};
// Spell damage info structure based on structure sending in SMSG_SPELLNONMELEEDAMAGELOG opcode
-struct SpellNonMeleeDamage
+struct TC_GAME_API SpellNonMeleeDamage
{
SpellNonMeleeDamage(Unit* _attacker, Unit* _target, uint32 _SpellID, uint32 _schoolMask)
: target(_target), attacker(_attacker), SpellID(_SpellID), damage(0), overkill(0), schoolMask(_schoolMask),
@@ -1108,7 +1108,7 @@ enum ActionBarIndex
#define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START)
-struct CharmInfo
+struct TC_GAME_API CharmInfo
{
public:
explicit CharmInfo(Unit* unit);
@@ -1210,7 +1210,7 @@ enum PlayerTotemType
struct SpellProcEventEntry; // used only privately
-class Unit : public WorldObject
+class TC_GAME_API Unit : public WorldObject
{
public:
typedef std::set<Unit*> AttackerSet;
diff --git a/src/server/game/Entities/Vehicle/Vehicle.h b/src/server/game/Entities/Vehicle/Vehicle.h
index cd28c4082d4..f8992708a46 100644
--- a/src/server/game/Entities/Vehicle/Vehicle.h
+++ b/src/server/game/Entities/Vehicle/Vehicle.h
@@ -29,7 +29,7 @@ struct VehicleEntry;
class Unit;
class VehicleJoinEvent;
-class Vehicle : public TransportBase
+class TC_GAME_API Vehicle : public TransportBase
{
protected:
friend bool Unit::CreateVehicleKit(uint32 id, uint32 creatureEntry);
@@ -118,7 +118,7 @@ class Vehicle : public TransportBase
PendingJoinEventContainer _pendingJoinEvents; ///< Collection of delayed join events for prospective passengers
};
-class VehicleJoinEvent : public BasicEvent
+class TC_GAME_API VehicleJoinEvent : public BasicEvent
{
friend class Vehicle;
protected:
diff --git a/src/server/game/Events/GameEventMgr.h b/src/server/game/Events/GameEventMgr.h
index d2982a402f2..44ed2fb1332 100644
--- a/src/server/game/Events/GameEventMgr.h
+++ b/src/server/game/Events/GameEventMgr.h
@@ -93,7 +93,7 @@ class Player;
class Creature;
class Quest;
-class GameEventMgr
+class TC_GAME_API GameEventMgr
{
private:
GameEventMgr();
@@ -182,8 +182,8 @@ class GameEventMgr
#define sGameEventMgr GameEventMgr::instance()
-bool IsHolidayActive(HolidayIds id);
-bool IsEventActive(uint16 event_id);
+TC_GAME_API bool IsHolidayActive(HolidayIds id);
+TC_GAME_API bool IsEventActive(uint16 event_id);
#endif
diff --git a/src/server/game/Globals/ObjectAccessor.cpp b/src/server/game/Globals/ObjectAccessor.cpp
index 762c9b9c28e..247c4943113 100644
--- a/src/server/game/Globals/ObjectAccessor.cpp
+++ b/src/server/game/Globals/ObjectAccessor.cpp
@@ -34,6 +34,53 @@
#include <boost/thread/shared_mutex.hpp>
#include <boost/thread/locks.hpp>
+template<class T>
+void HashMapHolder<T>::Insert(T* o)
+{
+ boost::unique_lock<boost::shared_mutex> lock(*GetLock());
+
+ GetContainer()[o->GetGUID()] = o;
+}
+
+template<class T>
+void HashMapHolder<T>::Remove(T* o)
+{
+ boost::unique_lock<boost::shared_mutex> lock(*GetLock());
+
+ GetContainer().erase(o->GetGUID());
+}
+
+template<class T>
+T* HashMapHolder<T>::Find(ObjectGuid guid)
+{
+ boost::shared_lock<boost::shared_mutex> lock(*GetLock());
+
+ typename MapType::iterator itr = GetContainer().find(guid);
+ return (itr != GetContainer().end()) ? itr->second : NULL;
+}
+
+template<class T>
+auto HashMapHolder<T>::GetContainer() -> MapType&
+{
+ static MapType _objectMap;
+ return _objectMap;
+}
+
+template<class T>
+boost::shared_mutex* HashMapHolder<T>::GetLock()
+{
+ static boost::shared_mutex _lock;
+ return &_lock;
+}
+
+HashMapHolder<Player>::MapType const& ObjectAccessor::GetPlayers()
+{
+ return HashMapHolder<Player>::GetContainer();
+}
+
+template class TC_GAME_API HashMapHolder<Player>;
+template class TC_GAME_API HashMapHolder<Transport>;
+
WorldObject* ObjectAccessor::GetWorldObject(WorldObject const& p, ObjectGuid const& guid)
{
switch (guid.GetHigh())
@@ -206,11 +253,6 @@ Player* ObjectAccessor::FindConnectedPlayerByName(std::string const& name)
return NULL;
}
-HashMapHolder<Player>::MapType const& ObjectAccessor::GetPlayers()
-{
- return HashMapHolder<Player>::GetContainer();
-}
-
void ObjectAccessor::SaveAllPlayers()
{
boost::shared_lock<boost::shared_mutex> lock(*HashMapHolder<Player>::GetLock());
@@ -219,14 +261,3 @@ void ObjectAccessor::SaveAllPlayers()
for (HashMapHolder<Player>::MapType::const_iterator itr = m.begin(); itr != m.end(); ++itr)
itr->second->SaveToDB();
}
-
-/// Define the static members of HashMapHolder
-
-template <class T> typename HashMapHolder<T>::MapType HashMapHolder<T>::_objectMap;
-template <class T> boost::shared_mutex HashMapHolder<T>::_lock;
-
-/// Global definitions for the hashmap storage
-
-template class HashMapHolder<Player>;
-
-template class HashMapHolder<Transport>;
diff --git a/src/server/game/Globals/ObjectAccessor.h b/src/server/game/Globals/ObjectAccessor.h
index d8466dbb1bc..be7066c84a9 100644
--- a/src/server/game/Globals/ObjectAccessor.h
+++ b/src/server/game/Globals/ObjectAccessor.h
@@ -42,76 +42,56 @@ class WorldRunnable;
class Transport;
template <class T>
-class HashMapHolder
+class TC_GAME_API HashMapHolder
{
- public:
- static_assert(std::is_same<Player, T>::value
- || std::is_same<Transport, T>::value,
- "Only Player and Transport can be registered in global HashMapHolder");
+ //Non instanceable only static
+ HashMapHolder() { }
- typedef std::unordered_map<ObjectGuid, T*> MapType;
+public:
+ static_assert(std::is_same<Player, T>::value
+ || std::is_same<Transport, T>::value,
+ "Only Player and Transport can be registered in global HashMapHolder");
- static void Insert(T* o)
- {
- boost::unique_lock<boost::shared_mutex> lock(_lock);
+ typedef std::unordered_map<ObjectGuid, T*> MapType;
- _objectMap[o->GetGUID()] = o;
- }
+ static void Insert(T* o);
- static void Remove(T* o)
- {
- boost::unique_lock<boost::shared_mutex> lock(_lock);
+ static void Remove(T* o);
- _objectMap.erase(o->GetGUID());
- }
+ static T* Find(ObjectGuid guid);
- static T* Find(ObjectGuid guid)
- {
- boost::shared_lock<boost::shared_mutex> lock(_lock);
+ static MapType& GetContainer();
- typename MapType::iterator itr = _objectMap.find(guid);
- return (itr != _objectMap.end()) ? itr->second : NULL;
- }
-
- static MapType& GetContainer() { return _objectMap; }
-
- static boost::shared_mutex* GetLock() { return &_lock; }
-
- private:
- //Non instanceable only static
- HashMapHolder() { }
-
- static boost::shared_mutex _lock;
- static MapType _objectMap;
+ static boost::shared_mutex* GetLock();
};
namespace ObjectAccessor
{
// these functions return objects only if in map of specified object
- WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const&);
- Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask);
- Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid);
- GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid);
- Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid);
- DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid);
- Unit* GetUnit(WorldObject const&, ObjectGuid const& guid);
- Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid);
- Pet* GetPet(WorldObject const&, ObjectGuid const& guid);
- Player* GetPlayer(Map const*, ObjectGuid const& guid);
- Player* GetPlayer(WorldObject const&, ObjectGuid const& guid);
- Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&);
+ TC_GAME_API WorldObject* GetWorldObject(WorldObject const&, ObjectGuid const&);
+ TC_GAME_API Object* GetObjectByTypeMask(WorldObject const&, ObjectGuid const&, uint32 typemask);
+ TC_GAME_API Corpse* GetCorpse(WorldObject const& u, ObjectGuid const& guid);
+ TC_GAME_API GameObject* GetGameObject(WorldObject const& u, ObjectGuid const& guid);
+ TC_GAME_API Transport* GetTransport(WorldObject const& u, ObjectGuid const& guid);
+ TC_GAME_API DynamicObject* GetDynamicObject(WorldObject const& u, ObjectGuid const& guid);
+ TC_GAME_API Unit* GetUnit(WorldObject const&, ObjectGuid const& guid);
+ TC_GAME_API Creature* GetCreature(WorldObject const& u, ObjectGuid const& guid);
+ TC_GAME_API Pet* GetPet(WorldObject const&, ObjectGuid const& guid);
+ TC_GAME_API Player* GetPlayer(Map const*, ObjectGuid const& guid);
+ TC_GAME_API Player* GetPlayer(WorldObject const&, ObjectGuid const& guid);
+ TC_GAME_API Creature* GetCreatureOrPetOrVehicle(WorldObject const&, ObjectGuid const&);
// these functions return objects if found in whole world
// ACCESS LIKE THAT IS NOT THREAD SAFE
- Player* FindPlayer(ObjectGuid const&);
- Player* FindPlayerByName(std::string const& name);
+ TC_GAME_API Player* FindPlayer(ObjectGuid const&);
+ TC_GAME_API Player* FindPlayerByName(std::string const& name);
// this returns Player even if he is not in world, for example teleporting
- Player* FindConnectedPlayer(ObjectGuid const&);
- Player* FindConnectedPlayerByName(std::string const& name);
+ TC_GAME_API Player* FindConnectedPlayer(ObjectGuid const&);
+ TC_GAME_API Player* FindConnectedPlayerByName(std::string const& name);
// when using this, you must use the hashmapholder's lock
- HashMapHolder<Player>::MapType const& GetPlayers();
+ TC_GAME_API HashMapHolder<Player>::MapType const& GetPlayers();
template<class T>
void AddObject(T* object)
@@ -125,7 +105,8 @@ namespace ObjectAccessor
HashMapHolder<T>::Remove(object);
}
- void SaveAllPlayers();
+ TC_GAME_API void SaveAllPlayers();
};
#endif
+
diff --git a/src/server/game/Globals/ObjectMgr.h b/src/server/game/Globals/ObjectMgr.h
index 3d6ae293edb..73c03849699 100644
--- a/src/server/game/Globals/ObjectMgr.h
+++ b/src/server/game/Globals/ObjectMgr.h
@@ -372,15 +372,15 @@ typedef std::multimap<uint32, ScriptInfo> ScriptMap;
typedef std::map<uint32, ScriptMap > ScriptMapMap;
typedef std::multimap<uint32, uint32> SpellScriptsContainer;
typedef std::pair<SpellScriptsContainer::iterator, SpellScriptsContainer::iterator> SpellScriptsBounds;
-extern ScriptMapMap sSpellScripts;
-extern ScriptMapMap sEventScripts;
-extern ScriptMapMap sWaypointScripts;
+TC_GAME_API extern ScriptMapMap sSpellScripts;
+TC_GAME_API extern ScriptMapMap sEventScripts;
+TC_GAME_API extern ScriptMapMap sWaypointScripts;
std::string GetScriptsTableNameByType(ScriptsType type);
ScriptMapMap* GetScriptsMapByType(ScriptsType type);
std::string GetScriptCommandName(ScriptCommands command);
-struct SpellClickInfo
+struct TC_GAME_API SpellClickInfo
{
uint32 spellId;
uint8 castFlags;
@@ -637,7 +637,7 @@ SkillRangeType GetSkillRangeType(SkillRaceClassInfoEntry const* rcEntry);
#define MAX_PET_NAME 12 // max allowed by client name length
#define MAX_CHARTER_NAME 24 // max allowed by client name length
-bool normalizePlayerName(std::string& name);
+TC_GAME_API bool normalizePlayerName(std::string& name);
struct LanguageDesc
{
@@ -646,7 +646,7 @@ struct LanguageDesc
uint32 skill_id;
};
-extern LanguageDesc lang_description[LANGUAGES_COUNT];
+TC_GAME_API extern LanguageDesc lang_description[LANGUAGES_COUNT];
LanguageDesc const* GetLanguageDescByID(uint32 lang);
enum EncounterCreditType
@@ -671,7 +671,7 @@ typedef std::unordered_map<uint32, DungeonEncounterList> DungeonEncounterContain
class PlayerDumpReader;
-class ObjectMgr
+class TC_GAME_API ObjectMgr
{
friend class PlayerDumpReader;
diff --git a/src/server/game/Grids/GridStates.h b/src/server/game/Grids/GridStates.h
index 9420bef4b9d..b567da43b69 100644
--- a/src/server/game/Grids/GridStates.h
+++ b/src/server/game/Grids/GridStates.h
@@ -24,32 +24,32 @@
class Map;
-class GridState
+class TC_GAME_API GridState
{
public:
virtual ~GridState() { };
virtual void Update(Map &, NGridType&, GridInfo &, uint32 t_diff) const = 0;
};
-class InvalidState : public GridState
+class TC_GAME_API InvalidState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
-class ActiveState : public GridState
+class TC_GAME_API ActiveState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
-class IdleState : public GridState
+class TC_GAME_API IdleState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
};
-class RemovalState : public GridState
+class TC_GAME_API RemovalState : public GridState
{
public:
void Update(Map &, NGridType &, GridInfo &, uint32 t_diff) const override;
diff --git a/src/server/game/Grids/Notifiers/GridNotifiers.h b/src/server/game/Grids/Notifiers/GridNotifiers.h
index 6edeadf6b94..84aa29f96b7 100644
--- a/src/server/game/Grids/Notifiers/GridNotifiers.h
+++ b/src/server/game/Grids/Notifiers/GridNotifiers.h
@@ -38,7 +38,7 @@ class Player;
namespace Trinity
{
- struct VisibleNotifier
+ struct TC_GAME_API VisibleNotifier
{
Player &i_player;
UpdateData i_data;
@@ -61,7 +61,7 @@ namespace Trinity
void Visit(DynamicObjectMapType &);
};
- struct PlayerRelocationNotifier : public VisibleNotifier
+ struct TC_GAME_API PlayerRelocationNotifier : public VisibleNotifier
{
PlayerRelocationNotifier(Player &player) : VisibleNotifier(player) { }
@@ -70,7 +70,7 @@ namespace Trinity
void Visit(PlayerMapType &);
};
- struct CreatureRelocationNotifier
+ struct TC_GAME_API CreatureRelocationNotifier
{
Creature &i_creature;
CreatureRelocationNotifier(Creature &c) : i_creature(c) { }
@@ -79,7 +79,7 @@ namespace Trinity
void Visit(PlayerMapType &);
};
- struct DelayedUnitRelocation
+ struct TC_GAME_API DelayedUnitRelocation
{
Map &i_map;
Cell &cell;
@@ -92,7 +92,7 @@ namespace Trinity
void Visit(PlayerMapType &);
};
- struct AIRelocationNotifier
+ struct TC_GAME_API AIRelocationNotifier
{
Unit &i_unit;
bool isCreature;
@@ -120,7 +120,7 @@ namespace Trinity
void Visit(CorpseMapType &m) { updateObjects<Corpse>(m); }
};
- struct MessageDistDeliverer
+ struct TC_GAME_API MessageDistDeliverer
{
WorldObject* i_source;
WorldPacket* i_message;
@@ -566,7 +566,7 @@ namespace Trinity
// WorldObject check classes
- class AnyDeadUnitObjectInRangeCheck
+ class TC_GAME_API AnyDeadUnitObjectInRangeCheck
{
public:
AnyDeadUnitObjectInRangeCheck(Unit* searchObj, float range) : i_searchObj(searchObj), i_range(range) { }
@@ -579,7 +579,7 @@ namespace Trinity
float i_range;
};
- class AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck
+ class TC_GAME_API AnyDeadUnitSpellTargetInRangeCheck : public AnyDeadUnitObjectInRangeCheck
{
public:
AnyDeadUnitSpellTargetInRangeCheck(Unit* searchObj, float range, SpellInfo const* spellInfo, SpellTargetCheckTypes check)
diff --git a/src/server/game/Grids/ObjectGridLoader.h b/src/server/game/Grids/ObjectGridLoader.h
index 9dc4c7e048b..f2893da609e 100644
--- a/src/server/game/Grids/ObjectGridLoader.h
+++ b/src/server/game/Grids/ObjectGridLoader.h
@@ -27,7 +27,7 @@
class ObjectWorldLoader;
-class ObjectGridLoader
+class TC_GAME_API ObjectGridLoader
{
friend class ObjectWorldLoader;
@@ -55,7 +55,7 @@ class ObjectGridLoader
};
//Stop the creatures before unloading the NGrid
-class ObjectGridStoper
+class TC_GAME_API ObjectGridStoper
{
public:
void Visit(CreatureMapType &m);
@@ -63,7 +63,7 @@ class ObjectGridStoper
};
//Move the foreign creatures back to respawn positions before unloading the NGrid
-class ObjectGridEvacuator
+class TC_GAME_API ObjectGridEvacuator
{
public:
void Visit(CreatureMapType &m);
diff --git a/src/server/game/Groups/Group.h b/src/server/game/Groups/Group.h
index 42fd9b582e8..18b8119246f 100644
--- a/src/server/game/Groups/Group.h
+++ b/src/server/game/Groups/Group.h
@@ -158,7 +158,7 @@ struct InstanceGroupBind
/** request member stats checken **/
/// @todo uninvite people that not accepted invite
-class Group
+class TC_GAME_API Group
{
public:
struct MemberSlot
diff --git a/src/server/game/Groups/GroupMgr.h b/src/server/game/Groups/GroupMgr.h
index ee6ae18f3ea..14ff3519aa6 100644
--- a/src/server/game/Groups/GroupMgr.h
+++ b/src/server/game/Groups/GroupMgr.h
@@ -20,7 +20,7 @@
#include "Group.h"
-class GroupMgr
+class TC_GAME_API GroupMgr
{
private:
GroupMgr();
diff --git a/src/server/game/Groups/GroupReference.h b/src/server/game/Groups/GroupReference.h
index 4718dda1832..6e7373de7d7 100644
--- a/src/server/game/Groups/GroupReference.h
+++ b/src/server/game/Groups/GroupReference.h
@@ -24,7 +24,7 @@
class Group;
class Player;
-class GroupReference : public Reference<Group, Player>
+class TC_GAME_API GroupReference : public Reference<Group, Player>
{
protected:
uint8 iSubGroup;
diff --git a/src/server/game/Guilds/Guild.h b/src/server/game/Guilds/Guild.h
index 2bc57a70671..e25a3201957 100644
--- a/src/server/game/Guilds/Guild.h
+++ b/src/server/game/Guilds/Guild.h
@@ -223,7 +223,7 @@ enum GuildMemberFlags
};
// Emblem info
-class EmblemInfo
+class TC_GAME_API EmblemInfo
{
public:
EmblemInfo() : m_style(0), m_color(0), m_borderStyle(0), m_borderColor(0), m_backgroundColor(0) { }
@@ -279,7 +279,7 @@ typedef std::vector <GuildBankRightsAndSlots> GuildBankRightsAndSlotsVec;
typedef std::set <uint8> SlotIds;
-class Guild
+class TC_GAME_API Guild
{
private:
// Class representing guild member
diff --git a/src/server/game/Guilds/GuildMgr.h b/src/server/game/Guilds/GuildMgr.h
index d8662f50f43..ad2555c2e71 100644
--- a/src/server/game/Guilds/GuildMgr.h
+++ b/src/server/game/Guilds/GuildMgr.h
@@ -20,7 +20,7 @@
#include "Guild.h"
-class GuildMgr
+class TC_GAME_API GuildMgr
{
private:
GuildMgr();
diff --git a/src/server/game/Instances/InstanceSaveMgr.h b/src/server/game/Instances/InstanceSaveMgr.h
index 255b68165e3..18e22602e07 100644
--- a/src/server/game/Instances/InstanceSaveMgr.h
+++ b/src/server/game/Instances/InstanceSaveMgr.h
@@ -41,7 +41,7 @@ class Group;
- player-instance binds for permanent heroic/raid saves
- group-instance binds (both solo and permanent) cache the player binds for the group leader
*/
-class InstanceSave
+class TC_GAME_API InstanceSave
{
friend class InstanceSaveManager;
public:
@@ -147,7 +147,7 @@ class InstanceSave
typedef std::unordered_map<uint32 /*PAIR32(map, difficulty)*/, time_t /*resetTime*/> ResetTimeByMapDifficultyMap;
-class InstanceSaveManager
+class TC_GAME_API InstanceSaveManager
{
friend class InstanceSave;
diff --git a/src/server/game/Instances/InstanceScript.h b/src/server/game/Instances/InstanceScript.h
index ce83061e162..949cdf5abcb 100644
--- a/src/server/game/Instances/InstanceScript.h
+++ b/src/server/game/Instances/InstanceScript.h
@@ -79,7 +79,7 @@ struct BossBoundaryEntry
AreaBoundary const* Boundary;
};
-struct BossBoundaryData
+struct TC_GAME_API BossBoundaryData
{
typedef std::vector<BossBoundaryEntry> StorageType;
typedef StorageType::const_iterator const_iterator;
@@ -134,7 +134,7 @@ typedef std::map<uint32 /*entry*/, MinionInfo> MinionInfoMap;
typedef std::map<uint32 /*type*/, ObjectGuid /*guid*/> ObjectGuidMap;
typedef std::map<uint32 /*entry*/, uint32 /*type*/> ObjectInfoMap;
-class InstanceScript : public ZoneScript
+class TC_GAME_API InstanceScript : public ZoneScript
{
public:
explicit InstanceScript(Map* map) : instance(map), completedEncounters(0) { }
diff --git a/src/server/game/Loot/LootMgr.cpp b/src/server/game/Loot/LootMgr.cpp
index 19dc210ea5b..5cede9a32d5 100644
--- a/src/server/game/Loot/LootMgr.cpp
+++ b/src/server/game/Loot/LootMgr.cpp
@@ -1871,3 +1871,20 @@ void LoadLootTemplates_Reference()
TC_LOG_INFO("server.loading", ">> Loaded refence loot templates in %u ms", GetMSTimeDiffToNow(oldMSTime));
}
+
+void LoadLootTables()
+{
+ LoadLootTemplates_Creature();
+ LoadLootTemplates_Fishing();
+ LoadLootTemplates_Gameobject();
+ LoadLootTemplates_Item();
+ LoadLootTemplates_Mail();
+ LoadLootTemplates_Milling();
+ LoadLootTemplates_Pickpocketing();
+ LoadLootTemplates_Skinning();
+ LoadLootTemplates_Disenchant();
+ LoadLootTemplates_Prospecting();
+ LoadLootTemplates_Spell();
+
+ LoadLootTemplates_Reference();
+}
diff --git a/src/server/game/Loot/LootMgr.h b/src/server/game/Loot/LootMgr.h
index af6f3e56707..41feb7b26e2 100644
--- a/src/server/game/Loot/LootMgr.h
+++ b/src/server/game/Loot/LootMgr.h
@@ -122,7 +122,7 @@ enum LootSlotType
class Player;
class LootStore;
-struct LootStoreItem
+struct TC_GAME_API LootStoreItem
{
uint32 itemid; // id of the item
uint32 reference; // referenced TemplateleId
@@ -148,7 +148,7 @@ struct LootStoreItem
typedef std::set<ObjectGuid::LowType> AllowedLooterSet;
-struct LootItem
+struct TC_GAME_API LootItem
{
uint32 itemid;
uint32 randomSuffix;
@@ -203,7 +203,7 @@ typedef std::unordered_map<uint32, LootTemplate*> LootTemplateMap;
typedef std::set<uint32> LootIdSet;
-class LootStore
+class TC_GAME_API LootStore
{
public:
explicit LootStore(char const* name, char const* entryName, bool ratesAllowed)
@@ -239,7 +239,7 @@ class LootStore
bool m_ratesAllowed;
};
-class LootTemplate
+class TC_GAME_API LootTemplate
{
class LootGroup; // A set of loot definitions for items (refs are not allowed inside)
typedef std::vector<LootGroup*> LootGroups;
@@ -307,7 +307,7 @@ struct LootView;
ByteBuffer& operator<<(ByteBuffer& b, LootItem const& li);
ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv);
-struct Loot
+struct TC_GAME_API Loot
{
friend ByteBuffer& operator<<(ByteBuffer& b, LootView const& lv);
@@ -409,48 +409,33 @@ struct LootView
: loot(_loot), viewer(_viewer), permission(_permission) { }
};
-extern LootStore LootTemplates_Creature;
-extern LootStore LootTemplates_Fishing;
-extern LootStore LootTemplates_Gameobject;
-extern LootStore LootTemplates_Item;
-extern LootStore LootTemplates_Mail;
-extern LootStore LootTemplates_Milling;
-extern LootStore LootTemplates_Pickpocketing;
-extern LootStore LootTemplates_Reference;
-extern LootStore LootTemplates_Skinning;
-extern LootStore LootTemplates_Disenchant;
-extern LootStore LootTemplates_Prospecting;
-extern LootStore LootTemplates_Spell;
-
-void LoadLootTemplates_Creature();
-void LoadLootTemplates_Fishing();
-void LoadLootTemplates_Gameobject();
-void LoadLootTemplates_Item();
-void LoadLootTemplates_Mail();
-void LoadLootTemplates_Milling();
-void LoadLootTemplates_Pickpocketing();
-void LoadLootTemplates_Skinning();
-void LoadLootTemplates_Disenchant();
-void LoadLootTemplates_Prospecting();
-
-void LoadLootTemplates_Spell();
-void LoadLootTemplates_Reference();
-
-inline void LoadLootTables()
-{
- LoadLootTemplates_Creature();
- LoadLootTemplates_Fishing();
- LoadLootTemplates_Gameobject();
- LoadLootTemplates_Item();
- LoadLootTemplates_Mail();
- LoadLootTemplates_Milling();
- LoadLootTemplates_Pickpocketing();
- LoadLootTemplates_Skinning();
- LoadLootTemplates_Disenchant();
- LoadLootTemplates_Prospecting();
- LoadLootTemplates_Spell();
-
- LoadLootTemplates_Reference();
-}
+TC_GAME_API extern LootStore LootTemplates_Creature;
+TC_GAME_API extern LootStore LootTemplates_Fishing;
+TC_GAME_API extern LootStore LootTemplates_Gameobject;
+TC_GAME_API extern LootStore LootTemplates_Item;
+TC_GAME_API extern LootStore LootTemplates_Mail;
+TC_GAME_API extern LootStore LootTemplates_Milling;
+TC_GAME_API extern LootStore LootTemplates_Pickpocketing;
+TC_GAME_API extern LootStore LootTemplates_Reference;
+TC_GAME_API extern LootStore LootTemplates_Skinning;
+TC_GAME_API extern LootStore LootTemplates_Disenchant;
+TC_GAME_API extern LootStore LootTemplates_Prospecting;
+TC_GAME_API extern LootStore LootTemplates_Spell;
+
+TC_GAME_API void LoadLootTemplates_Creature();
+TC_GAME_API void LoadLootTemplates_Fishing();
+TC_GAME_API void LoadLootTemplates_Gameobject();
+TC_GAME_API void LoadLootTemplates_Item();
+TC_GAME_API void LoadLootTemplates_Mail();
+TC_GAME_API void LoadLootTemplates_Milling();
+TC_GAME_API void LoadLootTemplates_Pickpocketing();
+TC_GAME_API void LoadLootTemplates_Skinning();
+TC_GAME_API void LoadLootTemplates_Disenchant();
+TC_GAME_API void LoadLootTemplates_Prospecting();
+
+TC_GAME_API void LoadLootTemplates_Spell();
+TC_GAME_API void LoadLootTemplates_Reference();
+
+TC_GAME_API void LoadLootTables();
#endif
diff --git a/src/server/game/Mails/Mail.h b/src/server/game/Mails/Mail.h
index 407edf2badb..ee1a0aae2c9 100644
--- a/src/server/game/Mails/Mail.h
+++ b/src/server/game/Mails/Mail.h
@@ -79,7 +79,7 @@ enum MailShowFlags
MAIL_SHOW_RETURN = 0x0010
};
-class MailSender
+class TC_GAME_API MailSender
{
public: // Constructors
MailSender(MailMessageType messageType, ObjectGuid::LowType sender_guidlow_or_entry, MailStationery stationery = MAIL_STATIONERY_DEFAULT)
@@ -100,7 +100,7 @@ class MailSender
MailStationery m_stationery;
};
-class MailReceiver
+class TC_GAME_API MailReceiver
{
public: // Constructors
explicit MailReceiver(ObjectGuid::LowType receiver_lowguid) : m_receiver(NULL), m_receiver_lowguid(receiver_lowguid) { }
@@ -114,7 +114,7 @@ class MailReceiver
ObjectGuid::LowType m_receiver_lowguid;
};
-class MailDraft
+class TC_GAME_API MailDraft
{
typedef std::map<ObjectGuid::LowType, Item*> MailItemMap;
@@ -162,7 +162,7 @@ struct MailItemInfo
};
typedef std::vector<MailItemInfo> MailItemInfoVec;
-struct Mail
+struct TC_GAME_API Mail
{
uint32 messageID;
uint8 messageType;
diff --git a/src/server/game/Maps/AreaBoundary.h b/src/server/game/Maps/AreaBoundary.h
index a134b783ca6..a8780ddb60f 100644
--- a/src/server/game/Maps/AreaBoundary.h
+++ b/src/server/game/Maps/AreaBoundary.h
@@ -20,7 +20,7 @@
#include "Position.h"
-class AreaBoundary
+class TC_GAME_API AreaBoundary
{
public:
enum BoundaryType
@@ -66,7 +66,7 @@ class AreaBoundary
bool m_isInvertedBoundary;
};
-class RectangleBoundary : public AreaBoundary
+class TC_GAME_API RectangleBoundary : public AreaBoundary
{
public:
// X axis is north/south, Y axis is east/west, larger values are northwest
@@ -79,7 +79,7 @@ class RectangleBoundary : public AreaBoundary
const float _minX, _maxX, _minY, _maxY;
};
-class CircleBoundary : public AreaBoundary
+class TC_GAME_API CircleBoundary : public AreaBoundary
{
public:
CircleBoundary(Position const& center, double radius, bool isInverted = false);
@@ -95,7 +95,7 @@ class CircleBoundary : public AreaBoundary
const double _radiusSq;
};
-class EllipseBoundary : public AreaBoundary
+class TC_GAME_API EllipseBoundary : public AreaBoundary
{
public:
EllipseBoundary(Position const& center, double radiusX, double radiusY, bool isInverted = false);
@@ -109,7 +109,7 @@ class EllipseBoundary : public AreaBoundary
const double _radiusYSq, _scaleXSq;
};
-class TriangleBoundary : public AreaBoundary
+class TC_GAME_API TriangleBoundary : public AreaBoundary
{
public:
TriangleBoundary(Position const& pointA, Position const& pointB, Position const& pointC, bool isInverted = false);
@@ -123,7 +123,7 @@ class TriangleBoundary : public AreaBoundary
const double _abx, _bcx, _cax, _aby, _bcy, _cay;
};
-class ParallelogramBoundary : public AreaBoundary
+class TC_GAME_API ParallelogramBoundary : public AreaBoundary
{
public:
// Note: AB must be orthogonal to AD
@@ -138,7 +138,7 @@ class ParallelogramBoundary : public AreaBoundary
const double _abx, _dax, _aby, _day;
};
-class ZRangeBoundary : public AreaBoundary
+class TC_GAME_API ZRangeBoundary : public AreaBoundary
{
public:
ZRangeBoundary(float minZ, float maxZ, bool isInverted = false);
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 7b94895c3de..8640150d86b 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -2993,15 +2993,15 @@ void Map::RemoveFromActive(DynamicObject* obj)
RemoveFromActiveHelper(obj);
}
-template bool Map::AddToMap(Corpse*);
-template bool Map::AddToMap(Creature*);
-template bool Map::AddToMap(GameObject*);
-template bool Map::AddToMap(DynamicObject*);
-
-template void Map::RemoveFromMap(Corpse*, bool);
-template void Map::RemoveFromMap(Creature*, bool);
-template void Map::RemoveFromMap(GameObject*, bool);
-template void Map::RemoveFromMap(DynamicObject*, bool);
+template TC_GAME_API bool Map::AddToMap(Corpse*);
+template TC_GAME_API bool Map::AddToMap(Creature*);
+template TC_GAME_API bool Map::AddToMap(GameObject*);
+template TC_GAME_API bool Map::AddToMap(DynamicObject*);
+
+template TC_GAME_API void Map::RemoveFromMap(Corpse*, bool);
+template TC_GAME_API void Map::RemoveFromMap(Creature*, bool);
+template TC_GAME_API void Map::RemoveFromMap(GameObject*, bool);
+template TC_GAME_API void Map::RemoveFromMap(DynamicObject*, bool);
/* ******* Dungeon Instance Maps ******* */
diff --git a/src/server/game/Maps/Map.h b/src/server/game/Maps/Map.h
index 1da3f40c1d0..5f134613e85 100644
--- a/src/server/game/Maps/Map.h
+++ b/src/server/game/Maps/Map.h
@@ -154,7 +154,7 @@ struct LiquidData
float depth_level;
};
-class GridMap
+class TC_GAME_API GridMap
{
uint32 _flags;
union{
@@ -253,7 +253,7 @@ typedef std::map<uint32/*leaderDBGUID*/, CreatureGroup*> CreatureGroupHol
typedef std::unordered_map<uint32 /*zoneId*/, ZoneDynamicInfo> ZoneDynamicInfoMap;
-class Map : public GridRefManager<NGridType>
+class TC_GAME_API Map : public GridRefManager<NGridType>
{
friend class MapReference;
public:
@@ -277,6 +277,7 @@ class Map : public GridRefManager<NGridType>
virtual bool AddPlayerToMap(Player*);
virtual void RemovePlayerFromMap(Player*, bool);
+
template<class T> bool AddToMap(T *);
template<class T> void RemoveFromMap(T *, bool);
@@ -292,7 +293,8 @@ class Map : public GridRefManager<NGridType>
void GameObjectRelocation(GameObject* go, float x, float y, float z, float orientation, bool respawnRelocationOnFail = true);
void DynamicObjectRelocation(DynamicObject* go, float x, float y, float z, float orientation);
- template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor);
+ template<class T, class CONTAINER>
+ void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER> &visitor);
bool IsRemovalGrid(float x, float y) const
{
@@ -754,7 +756,7 @@ enum InstanceResetMethod
INSTANCE_RESET_RESPAWN_DELAY
};
-class InstanceMap : public Map
+class TC_GAME_API InstanceMap : public Map
{
public:
InstanceMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode, Map* _parent);
@@ -786,7 +788,7 @@ class InstanceMap : public Map
uint32 i_script_id;
};
-class BattlegroundMap : public Map
+class TC_GAME_API BattlegroundMap : public Map
{
public:
BattlegroundMap(uint32 id, time_t, uint32 InstanceId, Map* _parent, uint8 spawnMode);
diff --git a/src/server/game/Maps/MapInstanced.h b/src/server/game/Maps/MapInstanced.h
index 7fa66bde06a..eea54e1f013 100644
--- a/src/server/game/Maps/MapInstanced.h
+++ b/src/server/game/Maps/MapInstanced.h
@@ -23,7 +23,7 @@
#include "InstanceSaveMgr.h"
#include "DBCEnums.h"
-class MapInstanced : public Map
+class TC_GAME_API MapInstanced : public Map
{
friend class MapManager;
public:
diff --git a/src/server/game/Maps/MapManager.h b/src/server/game/Maps/MapManager.h
index b13d6552022..e74453a1196 100644
--- a/src/server/game/Maps/MapManager.h
+++ b/src/server/game/Maps/MapManager.h
@@ -28,7 +28,7 @@
class Transport;
struct TransportCreatureProto;
-class MapManager
+class TC_GAME_API MapManager
{
public:
static MapManager* instance();
diff --git a/src/server/game/Maps/MapUpdater.h b/src/server/game/Maps/MapUpdater.h
index 3d0f0b9e7e8..d95011d5a42 100644
--- a/src/server/game/Maps/MapUpdater.h
+++ b/src/server/game/Maps/MapUpdater.h
@@ -28,7 +28,7 @@
class MapUpdateRequest;
class Map;
-class MapUpdater
+class TC_GAME_API MapUpdater
{
public:
diff --git a/src/server/game/Maps/TransportMgr.h b/src/server/game/Maps/TransportMgr.h
index 32fca6bd26e..229fea882a4 100644
--- a/src/server/game/Maps/TransportMgr.h
+++ b/src/server/game/Maps/TransportMgr.h
@@ -82,7 +82,7 @@ struct TransportTemplate
typedef std::map<uint32, TransportAnimationEntry const*> TransportPathContainer;
typedef std::map<uint32, TransportRotationEntry const*> TransportPathRotationContainer;
-struct TransportAnimation
+struct TC_GAME_API TransportAnimation
{
TransportAnimation() : TotalTime(0) { }
@@ -96,9 +96,9 @@ struct TransportAnimation
typedef std::map<uint32, TransportAnimation> TransportAnimationContainer;
-class TransportMgr
+class TC_GAME_API TransportMgr
{
- friend void LoadDBCStores(std::string const&);
+ friend TC_GAME_API void LoadDBCStores(std::string const&);
public:
static TransportMgr* instance();
diff --git a/src/server/game/Movement/MotionMaster.h b/src/server/game/Movement/MotionMaster.h
index 76ae12986d5..d1c6474fb36 100644
--- a/src/server/game/Movement/MotionMaster.h
+++ b/src/server/game/Movement/MotionMaster.h
@@ -79,7 +79,7 @@ enum RotateDirection
// assume it is 25 yard per 0.6 second
#define SPEED_CHARGE 42.0f
-class MotionMaster //: private std::stack<MovementGenerator *>
+class TC_GAME_API MotionMaster //: private std::stack<MovementGenerator *>
{
private:
//typedef std::stack<MovementGenerator *> Impl;
diff --git a/src/server/game/Movement/MovementGenerator.h b/src/server/game/Movement/MovementGenerator.h
index 56e5dc7058a..d9dd17fabc2 100755
--- a/src/server/game/Movement/MovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerator.h
@@ -27,7 +27,7 @@
class Unit;
-class MovementGenerator
+class TC_GAME_API MovementGenerator
{
public:
virtual ~MovementGenerator();
diff --git a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
index 9aa778c5651..161f9e3e970 100755
--- a/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
+++ b/src/server/game/Movement/MovementGenerators/IdleMovementGenerator.h
@@ -32,7 +32,7 @@ class IdleMovementGenerator : public MovementGenerator
MovementGeneratorType GetMovementGeneratorType() const override { return IDLE_MOTION_TYPE; }
};
-extern IdleMovementGenerator si_idleMovement;
+TC_GAME_API extern IdleMovementGenerator si_idleMovement;
class RotateMovementGenerator : public MovementGenerator
{
diff --git a/src/server/game/Movement/PathGenerator.h b/src/server/game/Movement/PathGenerator.h
index 71e0e88f0b2..3cad62abf25 100644
--- a/src/server/game/Movement/PathGenerator.h
+++ b/src/server/game/Movement/PathGenerator.h
@@ -49,7 +49,7 @@ enum PathType
PATHFIND_SHORT = 0x20, // path is longer or equal to its limited path length
};
-class PathGenerator
+class TC_GAME_API PathGenerator
{
public:
explicit PathGenerator(Unit const* owner);
diff --git a/src/server/game/Movement/Spline/MoveSpline.h b/src/server/game/Movement/Spline/MoveSpline.h
index 209f978d658..0e62862cecc 100644
--- a/src/server/game/Movement/Spline/MoveSpline.h
+++ b/src/server/game/Movement/Spline/MoveSpline.h
@@ -37,7 +37,7 @@ namespace Movement
// MoveSpline represents smooth catmullrom or linear curve and point that moves belong it
// curve can be cyclic - in this case movement will be cyclic
// point can have vertical acceleration motion componemt(used in fall, parabolic movement)
- class MoveSpline
+ class TC_GAME_API MoveSpline
{
public:
typedef Spline<int32> MySpline;
diff --git a/src/server/game/Movement/Spline/MoveSplineInit.h b/src/server/game/Movement/Spline/MoveSplineInit.h
index a94c84d92f3..3f38da97916 100644
--- a/src/server/game/Movement/Spline/MoveSplineInit.h
+++ b/src/server/game/Movement/Spline/MoveSplineInit.h
@@ -35,7 +35,7 @@ namespace Movement
};
// Transforms coordinates from global to transport offsets
- class TransportPathTransform
+ class TC_GAME_API TransportPathTransform
{
public:
TransportPathTransform(Unit* owner, bool transformForTransport)
@@ -49,7 +49,7 @@ namespace Movement
/* Initializes and launches spline movement
*/
- class MoveSplineInit
+ class TC_GAME_API MoveSplineInit
{
public:
diff --git a/src/server/game/Movement/Spline/MovementTypedefs.h b/src/server/game/Movement/Spline/MovementTypedefs.h
index 031ec729949..c87fea47a82 100644
--- a/src/server/game/Movement/Spline/MovementTypedefs.h
+++ b/src/server/game/Movement/Spline/MovementTypedefs.h
@@ -69,8 +69,8 @@ namespace Movement
typedef counter<uint32, 0xFFFFFFFF> UInt32Counter;
- extern float gravity;
- extern UInt32Counter splineIdGen;
+ TC_GAME_API extern float gravity;
+ TC_GAME_API extern UInt32Counter splineIdGen;
}
#endif // TRINITYSERVER_TYPEDEFS_H
diff --git a/src/server/game/Movement/Waypoints/WaypointManager.h b/src/server/game/Movement/Waypoints/WaypointManager.h
index a1f98c52b0b..63dc4184308 100644
--- a/src/server/game/Movement/Waypoints/WaypointManager.h
+++ b/src/server/game/Movement/Waypoints/WaypointManager.h
@@ -44,7 +44,7 @@ struct WaypointData
typedef std::vector<WaypointData*> WaypointPath;
typedef std::unordered_map<uint32, WaypointPath> WaypointPathContainer;
-class WaypointMgr
+class TC_GAME_API WaypointMgr
{
public:
static WaypointMgr* instance();
diff --git a/src/server/game/OutdoorPvP/OutdoorPvP.h b/src/server/game/OutdoorPvP/OutdoorPvP.h
index 79f34ff10ea..255f3cd0f99 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvP.h
+++ b/src/server/game/OutdoorPvP/OutdoorPvP.h
@@ -84,7 +84,7 @@ class Unit;
struct GossipMenuItems;
class OutdoorPvP;
-class OPvPCapturePoint
+class TC_GAME_API OPvPCapturePoint
{
public:
@@ -185,7 +185,7 @@ class OPvPCapturePoint
};
// base class for specific outdoor pvp handlers
-class OutdoorPvP : public ZoneScript
+class TC_GAME_API OutdoorPvP : public ZoneScript
{
friend class OutdoorPvPMgr;
diff --git a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h
index b1158075c57..e53a78ac271 100644
--- a/src/server/game/OutdoorPvP/OutdoorPvPMgr.h
+++ b/src/server/game/OutdoorPvP/OutdoorPvPMgr.h
@@ -35,7 +35,7 @@ struct OutdoorPvPData
};
// class to handle player enter / leave / areatrigger / GO use events
-class OutdoorPvPMgr
+class TC_GAME_API OutdoorPvPMgr
{
private:
OutdoorPvPMgr();
diff --git a/src/server/game/Pools/PoolMgr.cpp b/src/server/game/Pools/PoolMgr.cpp
index 81d318fb1d9..812d8ea3940 100644
--- a/src/server/game/Pools/PoolMgr.cpp
+++ b/src/server/game/Pools/PoolMgr.cpp
@@ -60,6 +60,11 @@ bool ActivePoolData::IsActiveObject<Quest>(uint32 quest_id) const
return mActiveQuests.find(quest_id) != mActiveQuests.end();
}
+template TC_GAME_API bool ActivePoolData::IsActiveObject<Creature>(uint32) const;
+template TC_GAME_API bool ActivePoolData::IsActiveObject<GameObject>(uint32) const;
+template TC_GAME_API bool ActivePoolData::IsActiveObject<Pool>(uint32) const;
+template TC_GAME_API bool ActivePoolData::IsActiveObject<Quest>(uint32) const;
+
template<>
void ActivePoolData::ActivateObject<Creature>(uint32 db_guid, uint32 pool_id)
{
diff --git a/src/server/game/Pools/PoolMgr.h b/src/server/game/Pools/PoolMgr.h
index 6c48a011b73..f1af3a3530e 100644
--- a/src/server/game/Pools/PoolMgr.h
+++ b/src/server/game/Pools/PoolMgr.h
@@ -43,7 +43,7 @@ class Pool // for Pool of Pool
typedef std::set<ObjectGuid::LowType> ActivePoolObjects;
typedef std::map<uint32, uint32> ActivePoolPools;
-class ActivePoolData
+class TC_GAME_API ActivePoolData
{
public:
template<typename T>
@@ -66,7 +66,7 @@ class ActivePoolData
};
template <class T>
-class PoolGroup
+class TC_GAME_API PoolGroup
{
typedef std::vector<PoolObject> PoolObjectList;
public:
@@ -101,7 +101,7 @@ typedef std::multimap<uint32, uint32> PooledQuestRelation;
typedef std::pair<PooledQuestRelation::const_iterator, PooledQuestRelation::const_iterator> PooledQuestRelationBounds;
typedef std::pair<PooledQuestRelation::iterator, PooledQuestRelation::iterator> PooledQuestRelationBoundsNC;
-class PoolMgr
+class TC_GAME_API PoolMgr
{
private:
PoolMgr();
diff --git a/src/server/game/Quests/QuestDef.h b/src/server/game/Quests/QuestDef.h
index a502fef6140..75b52bb4537 100644
--- a/src/server/game/Quests/QuestDef.h
+++ b/src/server/game/Quests/QuestDef.h
@@ -190,7 +190,7 @@ struct QuestLocale
// This Quest class provides a convenient way to access a few pretotaled (cached) quest details,
// all base quest information, and any utility functions such as generating the amount of
// xp to give
-class Quest
+class TC_GAME_API Quest
{
friend class ObjectMgr;
public:
diff --git a/src/server/game/Reputation/ReputationMgr.h b/src/server/game/Reputation/ReputationMgr.h
index 6f319a39b0c..5a51c9eb383 100644
--- a/src/server/game/Reputation/ReputationMgr.h
+++ b/src/server/game/Reputation/ReputationMgr.h
@@ -61,7 +61,7 @@ typedef std::map<uint32, ReputationRank> ForcedReactions;
class Player;
-class ReputationMgr
+class TC_GAME_API ReputationMgr
{
public: // constructors and global modifiers
explicit ReputationMgr(Player* owner) : _player(owner),
diff --git a/src/server/game/Scripting/ScriptMgr.cpp b/src/server/game/Scripting/ScriptMgr.cpp
index 96477e2013e..4218746893f 100644
--- a/src/server/game/Scripting/ScriptMgr.cpp
+++ b/src/server/game/Scripting/ScriptMgr.cpp
@@ -1688,32 +1688,32 @@ template<class TScript> std::vector<TScript*> ScriptRegistry<TScript>::Scripts;
template<class TScript> uint32 ScriptRegistry<TScript>::_scriptIdCounter = 0;
// Specialize for each script type class like so:
-template class ScriptRegistry<SpellScriptLoader>;
-template class ScriptRegistry<ServerScript>;
-template class ScriptRegistry<WorldScript>;
-template class ScriptRegistry<FormulaScript>;
-template class ScriptRegistry<WorldMapScript>;
-template class ScriptRegistry<InstanceMapScript>;
-template class ScriptRegistry<BattlegroundMapScript>;
-template class ScriptRegistry<ItemScript>;
-template class ScriptRegistry<CreatureScript>;
-template class ScriptRegistry<GameObjectScript>;
-template class ScriptRegistry<AreaTriggerScript>;
-template class ScriptRegistry<BattlegroundScript>;
-template class ScriptRegistry<OutdoorPvPScript>;
-template class ScriptRegistry<CommandScript>;
-template class ScriptRegistry<WeatherScript>;
-template class ScriptRegistry<AuctionHouseScript>;
-template class ScriptRegistry<ConditionScript>;
-template class ScriptRegistry<VehicleScript>;
-template class ScriptRegistry<DynamicObjectScript>;
-template class ScriptRegistry<TransportScript>;
-template class ScriptRegistry<AchievementCriteriaScript>;
-template class ScriptRegistry<PlayerScript>;
-template class ScriptRegistry<GuildScript>;
-template class ScriptRegistry<GroupScript>;
-template class ScriptRegistry<UnitScript>;
-template class ScriptRegistry<AccountScript>;
+template class TC_GAME_API ScriptRegistry<SpellScriptLoader>;
+template class TC_GAME_API ScriptRegistry<ServerScript>;
+template class TC_GAME_API ScriptRegistry<WorldScript>;
+template class TC_GAME_API ScriptRegistry<FormulaScript>;
+template class TC_GAME_API ScriptRegistry<WorldMapScript>;
+template class TC_GAME_API ScriptRegistry<InstanceMapScript>;
+template class TC_GAME_API ScriptRegistry<BattlegroundMapScript>;
+template class TC_GAME_API ScriptRegistry<ItemScript>;
+template class TC_GAME_API ScriptRegistry<CreatureScript>;
+template class TC_GAME_API ScriptRegistry<GameObjectScript>;
+template class TC_GAME_API ScriptRegistry<AreaTriggerScript>;
+template class TC_GAME_API ScriptRegistry<BattlegroundScript>;
+template class TC_GAME_API ScriptRegistry<OutdoorPvPScript>;
+template class TC_GAME_API ScriptRegistry<CommandScript>;
+template class TC_GAME_API ScriptRegistry<WeatherScript>;
+template class TC_GAME_API ScriptRegistry<AuctionHouseScript>;
+template class TC_GAME_API ScriptRegistry<ConditionScript>;
+template class TC_GAME_API ScriptRegistry<VehicleScript>;
+template class TC_GAME_API ScriptRegistry<DynamicObjectScript>;
+template class TC_GAME_API ScriptRegistry<TransportScript>;
+template class TC_GAME_API ScriptRegistry<AchievementCriteriaScript>;
+template class TC_GAME_API ScriptRegistry<PlayerScript>;
+template class TC_GAME_API ScriptRegistry<GuildScript>;
+template class TC_GAME_API ScriptRegistry<GroupScript>;
+template class TC_GAME_API ScriptRegistry<UnitScript>;
+template class TC_GAME_API ScriptRegistry<AccountScript>;
// Undefine utility macros.
#undef GET_SCRIPT_RET
diff --git a/src/server/game/Scripting/ScriptMgr.h b/src/server/game/Scripting/ScriptMgr.h
index c22ffaf05a4..337e7de4861 100644
--- a/src/server/game/Scripting/ScriptMgr.h
+++ b/src/server/game/Scripting/ScriptMgr.h
@@ -147,7 +147,7 @@ struct OutdoorPvPData;
event on all registered scripts of that type.
*/
-class ScriptObject
+class TC_GAME_API ScriptObject
{
friend class ScriptMgr;
@@ -186,7 +186,7 @@ template<class TObject> class UpdatableScript
virtual void OnUpdate(TObject* /*obj*/, uint32 /*diff*/) { }
};
-class SpellScriptLoader : public ScriptObject
+class TC_GAME_API SpellScriptLoader : public ScriptObject
{
protected:
@@ -201,7 +201,7 @@ class SpellScriptLoader : public ScriptObject
virtual AuraScript* GetAuraScript() const { return NULL; }
};
-class ServerScript : public ScriptObject
+class TC_GAME_API ServerScript : public ScriptObject
{
protected:
@@ -231,7 +231,7 @@ class ServerScript : public ScriptObject
virtual void OnPacketReceive(WorldSession* /*session*/, WorldPacket& /*packet*/) { }
};
-class WorldScript : public ScriptObject
+class TC_GAME_API WorldScript : public ScriptObject
{
protected:
@@ -264,7 +264,7 @@ class WorldScript : public ScriptObject
virtual void OnShutdown() { }
};
-class FormulaScript : public ScriptObject
+class TC_GAME_API FormulaScript : public ScriptObject
{
protected:
@@ -331,14 +331,14 @@ template<class TMap> class MapScript : public UpdatableScript<TMap>
virtual void OnPlayerLeave(TMap* /*map*/, Player* /*player*/) { }
};
-class WorldMapScript : public ScriptObject, public MapScript<Map>
+class TC_GAME_API WorldMapScript : public ScriptObject, public MapScript<Map>
{
protected:
WorldMapScript(const char* name, uint32 mapId);
};
-class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
+class TC_GAME_API InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
{
protected:
@@ -350,14 +350,14 @@ class InstanceMapScript : public ScriptObject, public MapScript<InstanceMap>
virtual InstanceScript* GetInstanceScript(InstanceMap* /*map*/) const { return NULL; }
};
-class BattlegroundMapScript : public ScriptObject, public MapScript<BattlegroundMap>
+class TC_GAME_API BattlegroundMapScript : public ScriptObject, public MapScript<BattlegroundMap>
{
protected:
BattlegroundMapScript(const char* name, uint32 mapId);
};
-class ItemScript : public ScriptObject
+class TC_GAME_API ItemScript : public ScriptObject
{
protected:
@@ -381,7 +381,7 @@ class ItemScript : public ScriptObject
virtual bool OnRemove(Player* /*player*/, Item* /*item*/) { return false; }
};
-class UnitScript : public ScriptObject
+class TC_GAME_API UnitScript : public ScriptObject
{
protected:
@@ -404,7 +404,7 @@ class UnitScript : public ScriptObject
virtual void ModifySpellDamageTaken(Unit* /*target*/, Unit* /*attacker*/, int32& /*damage*/) { }
};
-class CreatureScript : public UnitScript, public UpdatableScript<Creature>
+class TC_GAME_API CreatureScript : public UnitScript, public UpdatableScript<Creature>
{
protected:
@@ -440,7 +440,7 @@ class CreatureScript : public UnitScript, public UpdatableScript<Creature>
virtual CreatureAI* GetAI(Creature* /*creature*/) const { return NULL; }
};
-class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
+class TC_GAME_API GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
{
protected:
@@ -485,7 +485,7 @@ class GameObjectScript : public ScriptObject, public UpdatableScript<GameObject>
virtual GameObjectAI* GetAI(GameObject* /*go*/) const { return NULL; }
};
-class AreaTriggerScript : public ScriptObject
+class TC_GAME_API AreaTriggerScript : public ScriptObject
{
protected:
@@ -497,7 +497,7 @@ class AreaTriggerScript : public ScriptObject
virtual bool OnTrigger(Player* /*player*/, AreaTriggerEntry const* /*trigger*/) { return false; }
};
-class BattlegroundScript : public ScriptObject
+class TC_GAME_API BattlegroundScript : public ScriptObject
{
protected:
@@ -509,7 +509,7 @@ class BattlegroundScript : public ScriptObject
virtual Battleground* GetBattleground() const = 0;
};
-class OutdoorPvPScript : public ScriptObject
+class TC_GAME_API OutdoorPvPScript : public ScriptObject
{
protected:
@@ -521,7 +521,7 @@ class OutdoorPvPScript : public ScriptObject
virtual OutdoorPvP* GetOutdoorPvP() const = 0;
};
-class CommandScript : public ScriptObject
+class TC_GAME_API CommandScript : public ScriptObject
{
protected:
@@ -533,7 +533,7 @@ class CommandScript : public ScriptObject
virtual std::vector<ChatCommand> GetCommands() const = 0;
};
-class WeatherScript : public ScriptObject, public UpdatableScript<Weather>
+class TC_GAME_API WeatherScript : public ScriptObject, public UpdatableScript<Weather>
{
protected:
@@ -545,7 +545,7 @@ class WeatherScript : public ScriptObject, public UpdatableScript<Weather>
virtual void OnChange(Weather* /*weather*/, WeatherState /*state*/, float /*grade*/) { }
};
-class AuctionHouseScript : public ScriptObject
+class TC_GAME_API AuctionHouseScript : public ScriptObject
{
protected:
@@ -566,7 +566,7 @@ class AuctionHouseScript : public ScriptObject
virtual void OnAuctionExpire(AuctionHouseObject* /*ah*/, AuctionEntry* /*entry*/) { }
};
-class ConditionScript : public ScriptObject
+class TC_GAME_API ConditionScript : public ScriptObject
{
protected:
@@ -578,7 +578,7 @@ class ConditionScript : public ScriptObject
virtual bool OnConditionCheck(Condition const* /*condition*/, ConditionSourceInfo& /*sourceInfo*/) { return true; }
};
-class VehicleScript : public ScriptObject
+class TC_GAME_API VehicleScript : public ScriptObject
{
protected:
@@ -605,14 +605,14 @@ class VehicleScript : public ScriptObject
virtual void OnRemovePassenger(Vehicle* /*veh*/, Unit* /*passenger*/) { }
};
-class DynamicObjectScript : public ScriptObject, public UpdatableScript<DynamicObject>
+class TC_GAME_API DynamicObjectScript : public ScriptObject, public UpdatableScript<DynamicObject>
{
protected:
DynamicObjectScript(const char* name);
};
-class TransportScript : public ScriptObject, public UpdatableScript<Transport>
+class TC_GAME_API TransportScript : public ScriptObject, public UpdatableScript<Transport>
{
protected:
@@ -633,7 +633,7 @@ class TransportScript : public ScriptObject, public UpdatableScript<Transport>
virtual void OnRelocate(Transport* /*transport*/, uint32 /*waypointId*/, uint32 /*mapId*/, float /*x*/, float /*y*/, float /*z*/) { }
};
-class AchievementCriteriaScript : public ScriptObject
+class TC_GAME_API AchievementCriteriaScript : public ScriptObject
{
protected:
@@ -645,7 +645,7 @@ class AchievementCriteriaScript : public ScriptObject
virtual bool OnCheck(Player* source, Unit* target) = 0;
};
-class PlayerScript : public UnitScript
+class TC_GAME_API PlayerScript : public UnitScript
{
protected:
@@ -742,7 +742,7 @@ class PlayerScript : public UnitScript
virtual void OnQuestStatusChange(Player* /*player*/, uint32 /*questId*/, QuestStatus /*status*/) { }
};
-class AccountScript : public ScriptObject
+class TC_GAME_API AccountScript : public ScriptObject
{
protected:
@@ -769,7 +769,7 @@ class AccountScript : public ScriptObject
virtual void OnFailedPasswordChange(uint32 /*accountId*/) {}
};
-class GuildScript : public ScriptObject
+class TC_GAME_API GuildScript : public ScriptObject
{
protected:
@@ -810,7 +810,7 @@ class GuildScript : public ScriptObject
virtual void OnBankEvent(Guild* /*guild*/, uint8 /*eventType*/, uint8 /*tabId*/, ObjectGuid::LowType /*playerGuid*/, uint32 /*itemOrMoney*/, uint16 /*itemStackCount*/, uint8 /*destTabId*/) { }
};
-class GroupScript : public ScriptObject
+class TC_GAME_API GroupScript : public ScriptObject
{
protected:
@@ -840,11 +840,11 @@ class GroupScript : public ScriptObject
// namespace
// {
typedef std::list<std::string> UnusedScriptNamesContainer;
- extern UnusedScriptNamesContainer UnusedScriptNames;
+ TC_GAME_API extern UnusedScriptNamesContainer UnusedScriptNames;
// }
// Manages registration, loading, and execution of scripts.
-class ScriptMgr
+class TC_GAME_API ScriptMgr
{
friend class ScriptObject;
diff --git a/src/server/game/Scripting/ScriptSystem.cpp b/src/server/game/Scripting/ScriptSystem.cpp
index 309838a919e..52c5c1640af 100644
--- a/src/server/game/Scripting/ScriptSystem.cpp
+++ b/src/server/game/Scripting/ScriptSystem.cpp
@@ -21,7 +21,7 @@
#include "DatabaseEnv.h"
#include "ScriptMgr.h"
-ScriptPointVector const SystemMgr::_empty;
+TC_GAME_API ScriptPointVector const SystemMgr::_empty;
SystemMgr* SystemMgr::instance()
{
diff --git a/src/server/game/Scripting/ScriptSystem.h b/src/server/game/Scripting/ScriptSystem.h
index 9e6a0d2a5a7..7cf8ffc85b0 100644
--- a/src/server/game/Scripting/ScriptSystem.h
+++ b/src/server/game/Scripting/ScriptSystem.h
@@ -45,7 +45,7 @@ struct ScriptPointMove
typedef std::vector<ScriptPointMove> ScriptPointVector;
-class SystemMgr
+class TC_GAME_API SystemMgr
{
private:
SystemMgr() { }
diff --git a/src/server/game/Server/Protocol/Opcodes.h b/src/server/game/Server/Protocol/Opcodes.h
index 0d30134aa9f..48ed03004ea 100644
--- a/src/server/game/Server/Protocol/Opcodes.h
+++ b/src/server/game/Server/Protocol/Opcodes.h
@@ -1373,7 +1373,7 @@ struct OpcodeHandler
void (WorldSession::*handler)(WorldPacket& recvPacket);
};
-extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
+TC_GAME_API extern OpcodeHandler opcodeTable[NUM_MSG_TYPES];
#pragma pack(pop)
diff --git a/src/server/game/Server/Protocol/PacketLog.h b/src/server/game/Server/Protocol/PacketLog.h
index b211cfbf3ca..5e7661a884b 100644
--- a/src/server/game/Server/Protocol/PacketLog.h
+++ b/src/server/game/Server/Protocol/PacketLog.h
@@ -31,7 +31,7 @@ enum Direction
class WorldPacket;
-class PacketLog
+class TC_GAME_API PacketLog
{
private:
PacketLog();
diff --git a/src/server/game/Server/WorldSession.h b/src/server/game/Server/WorldSession.h
index d98143fcec0..584367bd375 100644
--- a/src/server/game/Server/WorldSession.h
+++ b/src/server/game/Server/WorldSession.h
@@ -246,7 +246,7 @@ struct PacketCounter
};
/// Player session in the World
-class WorldSession
+class TC_GAME_API WorldSession
{
public:
WorldSession(uint32 id, std::string&& name, std::shared_ptr<WorldSocket> sock, AccountTypes sec, uint8 expansion, time_t mute_time, LocaleConstant locale, uint32 recruiter, bool isARecruiter);
diff --git a/src/server/game/Server/WorldSocket.h b/src/server/game/Server/WorldSocket.h
index 9b36e458511..3874b60b0bb 100644
--- a/src/server/game/Server/WorldSocket.h
+++ b/src/server/game/Server/WorldSocket.h
@@ -48,7 +48,7 @@ struct ClientPktHeader
struct AuthSession;
-class WorldSocket : public Socket<WorldSocket>
+class TC_GAME_API WorldSocket : public Socket<WorldSocket>
{
typedef Socket<WorldSocket> BaseSocket;
diff --git a/src/server/game/Server/WorldSocketMgr.cpp b/src/server/game/Server/WorldSocketMgr.cpp
index cbdb6a4a70b..2faf0704d4f 100644
--- a/src/server/game/Server/WorldSocketMgr.cpp
+++ b/src/server/game/Server/WorldSocketMgr.cpp
@@ -53,7 +53,7 @@ WorldSocketMgr& WorldSocketMgr::Instance()
return instance;
}
-bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port)
+bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount)
{
_tcpNoDelay = sConfigMgr->GetBoolDefault("Network.TcpNodelay", true);
@@ -71,7 +71,7 @@ bool WorldSocketMgr::StartNetwork(boost::asio::io_service& service, std::string
return false;
}
- BaseSocketMgr::StartNetwork(service, bindIp, port);
+ BaseSocketMgr::StartNetwork(service, bindIp, port, threadCount);
_acceptor->SetSocketFactory(std::bind(&BaseSocketMgr::GetSocketForAccept, this));
diff --git a/src/server/game/Server/WorldSocketMgr.h b/src/server/game/Server/WorldSocketMgr.h
index fddf3bee4c6..a5aee344bf7 100644
--- a/src/server/game/Server/WorldSocketMgr.h
+++ b/src/server/game/Server/WorldSocketMgr.h
@@ -30,7 +30,7 @@
class WorldSocket;
/// Manages all sockets connected to peers and network threads
-class WorldSocketMgr : public SocketMgr<WorldSocket>
+class TC_GAME_API WorldSocketMgr : public SocketMgr<WorldSocket>
{
typedef SocketMgr<WorldSocket> BaseSocketMgr;
@@ -38,7 +38,7 @@ public:
static WorldSocketMgr& Instance();
/// Start network, listen at address:port .
- bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port) override;
+ bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int networkThreads) override;
/// Stops all network threads, It will wait for all running threads .
void StopNetwork() override;
diff --git a/src/server/game/Skills/SkillDiscovery.h b/src/server/game/Skills/SkillDiscovery.h
index b7fe1cdc8b2..c2020e5b075 100644
--- a/src/server/game/Skills/SkillDiscovery.h
+++ b/src/server/game/Skills/SkillDiscovery.h
@@ -23,8 +23,9 @@
class Player;
-void LoadSkillDiscoveryTable();
-uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player);
-bool HasDiscoveredAllSpells(uint32 spellId, Player* player);
-uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player);
+TC_GAME_API void LoadSkillDiscoveryTable();
+TC_GAME_API uint32 GetSkillDiscoverySpell(uint32 skillId, uint32 spellId, Player* player);
+TC_GAME_API bool HasDiscoveredAllSpells(uint32 spellId, Player* player);
+TC_GAME_API uint32 GetExplicitDiscoverySpell(uint32 spellId, Player* player);
+
#endif
diff --git a/src/server/game/Skills/SkillExtraItems.h b/src/server/game/Skills/SkillExtraItems.h
index 2889b221600..5a477b65f0b 100644
--- a/src/server/game/Skills/SkillExtraItems.h
+++ b/src/server/game/Skills/SkillExtraItems.h
@@ -23,12 +23,14 @@
// predef classes used in functions
class Player;
+
// returns true and sets the appropriate info if the player can create a perfect item with the given spellId
-bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType);
+TC_GAME_API bool CanCreatePerfectItem(Player* player, uint32 spellId, float &perfectCreateChance, uint32 &perfectItemType);
// load perfection proc info from DB
-void LoadSkillPerfectItemTable();
+TC_GAME_API void LoadSkillPerfectItemTable();
// returns true and sets the appropriate info if the player can create extra items with the given spellId
-bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax);
+TC_GAME_API bool CanCreateExtraItems(Player* player, uint32 spellId, float &additionalChance, uint8 &additionalMax);
// function to load the extra item creation info from DB
-void LoadSkillExtraItemTable();
+TC_GAME_API void LoadSkillExtraItemTable();
+
#endif
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.h b/src/server/game/Spells/Auras/SpellAuraEffects.h
index b400520a08a..32a7b97fff2 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.h
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.h
@@ -27,7 +27,7 @@ class Aura;
typedef void(AuraEffect::*pAuraEffectHandler)(AuraApplication const* aurApp, uint8 mode, bool apply) const;
-class AuraEffect
+class TC_GAME_API AuraEffect
{
friend void Aura::_InitEffects(uint8 effMask, Unit* caster, int32 *baseAmount);
friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32* baseAmount, Item* castItem, ObjectGuid casterGUID);
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index da075fa25cd..750110dc146 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -39,7 +39,7 @@ class ChargeDropEvent;
// update aura target map every 500 ms instead of every update - reduce amount of grid searcher calls
#define UPDATE_TARGET_MAP_INTERVAL 500
-class AuraApplication
+class TC_GAME_API AuraApplication
{
friend void Unit::_ApplyAura(AuraApplication * aurApp, uint8 effMask);
friend void Unit::_UnapplyAura(AuraApplicationMap::iterator &i, AuraRemoveMode removeMode);
@@ -82,7 +82,7 @@ class AuraApplication
void ClientUpdate(bool remove = false);
};
-class Aura
+class TC_GAME_API Aura
{
friend Aura* Unit::_TryStackingOrRefreshingExistingAura(SpellInfo const* newAura, uint8 effMask, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID);
public:
@@ -273,7 +273,7 @@ class Aura
Unit::AuraApplicationList m_removedApplications;
};
-class UnitAura : public Aura
+class TC_GAME_API UnitAura : public Aura
{
friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID);
protected:
@@ -294,7 +294,7 @@ class UnitAura : public Aura
DiminishingGroup m_AuraDRGroup:8; // Diminishing
};
-class DynObjAura : public Aura
+class TC_GAME_API DynObjAura : public Aura
{
friend Aura* Aura::Create(SpellInfo const* spellproto, uint8 effMask, WorldObject* owner, Unit* caster, int32 *baseAmount, Item* castItem, ObjectGuid casterGUID);
protected:
@@ -305,7 +305,7 @@ class DynObjAura : public Aura
void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override;
};
-class ChargeDropEvent : public BasicEvent
+class TC_GAME_API ChargeDropEvent : public BasicEvent
{
friend class Aura;
protected:
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 696d2801645..e634aa62a1c 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -80,7 +80,7 @@ enum SpellRangeFlag
SPELL_RANGE_RANGED = 2 //hunter range and ranged weapon
};
-struct SpellDestination
+struct TC_GAME_API SpellDestination
{
SpellDestination();
SpellDestination(float x, float y, float z, float orientation = 0.0f, uint32 mapId = MAPID_INVALID);
@@ -95,7 +95,7 @@ struct SpellDestination
Position _transportOffset;
};
-class SpellCastTargets
+class TC_GAME_API SpellCastTargets
{
public:
SpellCastTargets();
@@ -218,7 +218,7 @@ enum SpellEffectHandleMode
typedef std::list<std::pair<uint32, ObjectGuid>> DispelList;
-class Spell
+class TC_GAME_API Spell
{
friend void Unit::SetCurrentCastSpell(Spell* pSpell);
friend class SpellScript;
@@ -708,7 +708,7 @@ class Spell
namespace Trinity
{
- struct WorldObjectSpellTargetCheck
+ struct TC_GAME_API WorldObjectSpellTargetCheck
{
Unit* _caster;
Unit* _referer;
@@ -723,7 +723,7 @@ namespace Trinity
bool operator()(WorldObject* target);
};
- struct WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck
+ struct TC_GAME_API WorldObjectSpellNearbyTargetCheck : public WorldObjectSpellTargetCheck
{
float _range;
Position const* _position;
@@ -732,7 +732,7 @@ namespace Trinity
bool operator()(WorldObject* target);
};
- struct WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck
+ struct TC_GAME_API WorldObjectSpellAreaTargetCheck : public WorldObjectSpellTargetCheck
{
float _range;
Position const* _position;
@@ -741,7 +741,7 @@ namespace Trinity
bool operator()(WorldObject* target);
};
- struct WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck
+ struct TC_GAME_API WorldObjectSpellConeTargetCheck : public WorldObjectSpellAreaTargetCheck
{
float _coneAngle;
WorldObjectSpellConeTargetCheck(float coneAngle, float range, Unit* caster,
@@ -749,7 +749,7 @@ namespace Trinity
bool operator()(WorldObject* target);
};
- struct WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck
+ struct TC_GAME_API WorldObjectSpellTrajTargetCheck : public WorldObjectSpellAreaTargetCheck
{
WorldObjectSpellTrajTargetCheck(float range, Position const* position, Unit* caster, SpellInfo const* spellInfo);
bool operator()(WorldObject* target);
@@ -758,7 +758,7 @@ namespace Trinity
typedef void(Spell::*pEffect)(SpellEffIndex effIndex);
-class SpellEvent : public BasicEvent
+class TC_GAME_API SpellEvent : public BasicEvent
{
public:
SpellEvent(Spell* spell);
diff --git a/src/server/game/Spells/SpellHistory.h b/src/server/game/Spells/SpellHistory.h
index f0a53fe130d..ccc8a7daa96 100644
--- a/src/server/game/Spells/SpellHistory.h
+++ b/src/server/game/Spells/SpellHistory.h
@@ -31,7 +31,7 @@ class SpellInfo;
class Unit;
struct SpellCategoryEntry;
-class SpellHistory
+class TC_GAME_API SpellHistory
{
public:
typedef std::chrono::system_clock Clock;
diff --git a/src/server/game/Spells/SpellInfo.h b/src/server/game/Spells/SpellInfo.h
index 34208f268bd..1530235174a 100644
--- a/src/server/game/Spells/SpellInfo.h
+++ b/src/server/game/Spells/SpellInfo.h
@@ -194,7 +194,7 @@ enum SpellCustomAttributes
uint32 GetTargetFlagMask(SpellTargetObjectTypes objType);
-class SpellImplicitTargetInfo
+class TC_GAME_API SpellImplicitTargetInfo
{
private:
Targets _target;
@@ -225,7 +225,7 @@ private:
static StaticData _data[TOTAL_SPELL_TARGETS];
};
-class SpellEffectInfo
+class TC_GAME_API SpellEffectInfo
{
SpellInfo const* _spellInfo;
uint8 _effIndex;
@@ -291,7 +291,7 @@ private:
static StaticData _data[TOTAL_SPELL_EFFECTS];
};
-class SpellInfo
+class TC_GAME_API SpellInfo
{
public:
uint32 Id;
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 635a545bd5b..50f750f2ca5 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -3242,6 +3242,8 @@ void SpellMgr::LoadSpellInfoCorrections()
spellInfo->AttributesEx4 = 0;
break;
case 8145: // Tremor Totem (instant pulse)
+ spellInfo->AttributesEx2 |= SPELL_ATTR2_CAN_TARGET_NOT_IN_LOS;
+ /*no break*/
case 6474: // Earthbind Totem (instant pulse)
spellInfo->AttributesEx5 |= SPELL_ATTR5_START_PERIODIC_AT_APPLY;
break;
diff --git a/src/server/game/Spells/SpellMgr.h b/src/server/game/Spells/SpellMgr.h
index 827e3c671ab..269a3a90e9d 100644
--- a/src/server/game/Spells/SpellMgr.h
+++ b/src/server/game/Spells/SpellMgr.h
@@ -441,7 +441,7 @@ enum EffectRadiusIndex
};
// Spell pet auras
-class PetAura
+class TC_GAME_API PetAura
{
private:
typedef std::unordered_map<uint32, uint32> PetAuraMap;
@@ -488,7 +488,7 @@ class PetAura
};
typedef std::map<uint32, PetAura> SpellPetAuraMap;
-struct SpellArea
+struct TC_GAME_API SpellArea
{
uint32 spellId;
uint32 areaId; // zone/subzone/or 0 is not limited to zone
@@ -593,13 +593,13 @@ inline bool IsProfessionOrRidingSkill(uint32 skill)
bool IsPartOfSkillLine(uint32 skillId, uint32 spellId);
// spell diminishing returns
-DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, bool triggered);
-DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group);
-DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group);
-int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const* spellproto);
-bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group);
+TC_GAME_API DiminishingGroup GetDiminishingReturnsGroupForSpell(SpellInfo const* spellproto, bool triggered);
+TC_GAME_API DiminishingReturnsType GetDiminishingReturnsGroupType(DiminishingGroup group);
+TC_GAME_API DiminishingLevels GetDiminishingReturnsMaxLevel(DiminishingGroup group);
+TC_GAME_API int32 GetDiminishingReturnsLimitDuration(DiminishingGroup group, SpellInfo const* spellproto);
+TC_GAME_API bool IsDiminishingReturnsGroupDurationLimited(DiminishingGroup group);
-class SpellMgr
+class TC_GAME_API SpellMgr
{
// Constructors
private:
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index 77a993fffae..1d4efd8073d 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -52,7 +52,7 @@ enum SpellScriptState
#define SPELL_SCRIPT_STATE_END SPELL_SCRIPT_STATE_UNLOADING + 1
// helper class from which SpellScript and SpellAura derive, use these classes instead
-class _SpellScript
+class TC_GAME_API _SpellScript
{
// internal use classes & functions
// DO NOT OVERRIDE THESE IN SCRIPTS
@@ -68,7 +68,7 @@ class _SpellScript
std::string const* _GetScriptName() const;
protected:
- class EffectHook
+ class TC_GAME_API EffectHook
{
public:
EffectHook(uint8 _effIndex);
@@ -82,7 +82,7 @@ class _SpellScript
uint8 effIndex;
};
- class EffectNameCheck
+ class TC_GAME_API EffectNameCheck
{
public:
EffectNameCheck(uint16 _effName) { effName = _effName; }
@@ -92,7 +92,7 @@ class _SpellScript
uint16 effName;
};
- class EffectAuraNameCheck
+ class TC_GAME_API EffectAuraNameCheck
{
public:
EffectAuraNameCheck(uint16 _effAurName) { effAurName = _effAurName; }
@@ -149,7 +149,7 @@ enum SpellScriptHookType
#define HOOK_SPELL_END SPELL_SCRIPT_HOOK_CHECK_CAST + 1
#define HOOK_SPELL_COUNT HOOK_SPELL_END - HOOK_SPELL_START
-class SpellScript : public _SpellScript
+class TC_GAME_API SpellScript : public _SpellScript
{
// internal use classes & functions
// DO NOT OVERRIDE THESE IN SCRIPTS
@@ -165,7 +165,7 @@ class SpellScript : public _SpellScript
SPELLSCRIPT_FUNCTION_TYPE_DEFINES(SpellScript)
- class CastHandler
+ class TC_GAME_API CastHandler
{
public:
CastHandler(SpellCastFnType _pCastHandlerScript);
@@ -174,7 +174,7 @@ class SpellScript : public _SpellScript
SpellCastFnType pCastHandlerScript;
};
- class CheckCastHandler
+ class TC_GAME_API CheckCastHandler
{
public:
CheckCastHandler(SpellCheckCastFnType checkCastHandlerScript);
@@ -183,7 +183,7 @@ class SpellScript : public _SpellScript
SpellCheckCastFnType _checkCastHandlerScript;
};
- class EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook
+ class TC_GAME_API EffectHandler : public _SpellScript::EffectNameCheck, public _SpellScript::EffectHook
{
public:
EffectHandler(SpellEffectFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName);
@@ -194,7 +194,7 @@ class SpellScript : public _SpellScript
SpellEffectFnType pEffectHandlerScript;
};
- class HitHandler
+ class TC_GAME_API HitHandler
{
public:
HitHandler(SpellHitFnType _pHitHandlerScript);
@@ -203,7 +203,7 @@ class SpellScript : public _SpellScript
SpellHitFnType pHitHandlerScript;
};
- class TargetHook : public _SpellScript::EffectHook
+ class TC_GAME_API TargetHook : public _SpellScript::EffectHook
{
public:
TargetHook(uint8 _effectIndex, uint16 _targetType, bool _area, bool _dest);
@@ -216,7 +216,7 @@ class SpellScript : public _SpellScript
bool dest;
};
- class ObjectAreaTargetSelectHandler : public TargetHook
+ class TC_GAME_API ObjectAreaTargetSelectHandler : public TargetHook
{
public:
ObjectAreaTargetSelectHandler(SpellObjectAreaTargetSelectFnType _pObjectAreaTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType);
@@ -225,7 +225,7 @@ class SpellScript : public _SpellScript
SpellObjectAreaTargetSelectFnType pObjectAreaTargetSelectHandlerScript;
};
- class ObjectTargetSelectHandler : public TargetHook
+ class TC_GAME_API ObjectTargetSelectHandler : public TargetHook
{
public:
ObjectTargetSelectHandler(SpellObjectTargetSelectFnType _pObjectTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType);
@@ -234,7 +234,7 @@ class SpellScript : public _SpellScript
SpellObjectTargetSelectFnType pObjectTargetSelectHandlerScript;
};
- class DestinationTargetSelectHandler : public TargetHook
+ class TC_GAME_API DestinationTargetSelectHandler : public TargetHook
{
public:
DestinationTargetSelectHandler(SpellDestinationTargetSelectFnType _DestinationTargetSelectHandlerScript, uint8 _effIndex, uint16 _targetType);
@@ -470,7 +470,7 @@ enum AuraScriptHookType
#define HOOK_AURA_EFFECT_END HOOK_AURA_EFFECT_CALC_SPELLMOD + 1
#define HOOK_AURA_EFFECT_COUNT HOOK_AURA_EFFECT_END - HOOK_AURA_EFFECT_START
*/
-class AuraScript : public _SpellScript
+class TC_GAME_API AuraScript : public _SpellScript
{
// internal use classes & functions
// DO NOT OVERRIDE THESE IN SCRIPTS
@@ -493,7 +493,7 @@ class AuraScript : public _SpellScript
AURASCRIPT_FUNCTION_TYPE_DEFINES(AuraScript)
- class CheckAreaTargetHandler
+ class TC_GAME_API CheckAreaTargetHandler
{
public:
CheckAreaTargetHandler(AuraCheckAreaTargetFnType pHandlerScript);
@@ -501,7 +501,7 @@ class AuraScript : public _SpellScript
private:
AuraCheckAreaTargetFnType pHandlerScript;
};
- class AuraDispelHandler
+ class TC_GAME_API AuraDispelHandler
{
public:
AuraDispelHandler(AuraDispelFnType pHandlerScript);
@@ -509,14 +509,14 @@ class AuraScript : public _SpellScript
private:
AuraDispelFnType pHandlerScript;
};
- class EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook
+ class TC_GAME_API EffectBase : public _SpellScript::EffectAuraNameCheck, public _SpellScript::EffectHook
{
public:
EffectBase(uint8 _effIndex, uint16 _effName);
std::string ToString();
bool CheckEffect(SpellInfo const* spellInfo, uint8 effIndex) override;
};
- class EffectPeriodicHandler : public EffectBase
+ class TC_GAME_API EffectPeriodicHandler : public EffectBase
{
public:
EffectPeriodicHandler(AuraEffectPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName);
@@ -524,7 +524,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectPeriodicFnType pEffectHandlerScript;
};
- class EffectUpdatePeriodicHandler : public EffectBase
+ class TC_GAME_API EffectUpdatePeriodicHandler : public EffectBase
{
public:
EffectUpdatePeriodicHandler(AuraEffectUpdatePeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName);
@@ -532,7 +532,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectUpdatePeriodicFnType pEffectHandlerScript;
};
- class EffectCalcAmountHandler : public EffectBase
+ class TC_GAME_API EffectCalcAmountHandler : public EffectBase
{
public:
EffectCalcAmountHandler(AuraEffectCalcAmountFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName);
@@ -540,7 +540,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectCalcAmountFnType pEffectHandlerScript;
};
- class EffectCalcPeriodicHandler : public EffectBase
+ class TC_GAME_API EffectCalcPeriodicHandler : public EffectBase
{
public:
EffectCalcPeriodicHandler(AuraEffectCalcPeriodicFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName);
@@ -548,7 +548,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectCalcPeriodicFnType pEffectHandlerScript;
};
- class EffectCalcSpellModHandler : public EffectBase
+ class TC_GAME_API EffectCalcSpellModHandler : public EffectBase
{
public:
EffectCalcSpellModHandler(AuraEffectCalcSpellModFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName);
@@ -556,7 +556,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectCalcSpellModFnType pEffectHandlerScript;
};
- class EffectApplyHandler : public EffectBase
+ class TC_GAME_API EffectApplyHandler : public EffectBase
{
public:
EffectApplyHandler(AuraEffectApplicationModeFnType _pEffectHandlerScript, uint8 _effIndex, uint16 _effName, AuraEffectHandleModes _mode);
@@ -565,7 +565,7 @@ class AuraScript : public _SpellScript
AuraEffectApplicationModeFnType pEffectHandlerScript;
AuraEffectHandleModes mode;
};
- class EffectAbsorbHandler : public EffectBase
+ class TC_GAME_API EffectAbsorbHandler : public EffectBase
{
public:
EffectAbsorbHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex);
@@ -573,7 +573,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectAbsorbFnType pEffectHandlerScript;
};
- class EffectManaShieldHandler : public EffectBase
+ class TC_GAME_API EffectManaShieldHandler : public EffectBase
{
public:
EffectManaShieldHandler(AuraEffectAbsorbFnType _pEffectHandlerScript, uint8 _effIndex);
@@ -581,7 +581,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectAbsorbFnType pEffectHandlerScript;
};
- class EffectSplitHandler : public EffectBase
+ class TC_GAME_API EffectSplitHandler : public EffectBase
{
public:
EffectSplitHandler(AuraEffectSplitFnType _pEffectHandlerScript, uint8 _effIndex);
@@ -589,7 +589,7 @@ class AuraScript : public _SpellScript
private:
AuraEffectSplitFnType pEffectHandlerScript;
};
- class CheckProcHandler
+ class TC_GAME_API CheckProcHandler
{
public:
CheckProcHandler(AuraCheckProcFnType handlerScript);
@@ -597,7 +597,7 @@ class AuraScript : public _SpellScript
private:
AuraCheckProcFnType _HandlerScript;
};
- class AuraProcHandler
+ class TC_GAME_API AuraProcHandler
{
public:
AuraProcHandler(AuraProcFnType handlerScript);
@@ -605,7 +605,7 @@ class AuraScript : public _SpellScript
private:
AuraProcFnType _HandlerScript;
};
- class EffectProcHandler : public EffectBase
+ class TC_GAME_API EffectProcHandler : public EffectBase
{
public:
EffectProcHandler(AuraEffectProcFnType effectHandlerScript, uint8 effIndex, uint16 effName);
@@ -645,7 +645,7 @@ class AuraScript : public _SpellScript
AuraApplication const* m_auraApplication;
bool m_defaultActionPrevented;
- class ScriptStateStore
+ class TC_GAME_API ScriptStateStore
{
public:
AuraApplication const* _auraApplication;
diff --git a/src/server/game/Texts/CreatureTextMgr.h b/src/server/game/Texts/CreatureTextMgr.h
index e364eb6eefa..d7953463a97 100644
--- a/src/server/game/Texts/CreatureTextMgr.h
+++ b/src/server/game/Texts/CreatureTextMgr.h
@@ -75,7 +75,7 @@ typedef std::unordered_map<uint32, CreatureTextHolder> CreatureTextMap; // a
typedef std::map<CreatureTextId, CreatureTextLocale> LocaleCreatureTextMap;
-class CreatureTextMgr
+class TC_GAME_API CreatureTextMgr
{
private:
CreatureTextMgr() { }
diff --git a/src/server/game/Tickets/TicketMgr.h b/src/server/game/Tickets/TicketMgr.h
index 59f38e6d23f..ff2cd656dce 100644
--- a/src/server/game/Tickets/TicketMgr.h
+++ b/src/server/game/Tickets/TicketMgr.h
@@ -84,7 +84,7 @@ enum TicketType
TICKET_TYPE_CHARACTER_DELETED = 2,
};
-class GmTicket
+class TC_GAME_API GmTicket
{
public:
GmTicket();
@@ -181,7 +181,7 @@ private:
};
typedef std::map<uint32, GmTicket*> GmTicketList;
-class TicketMgr
+class TC_GAME_API TicketMgr
{
private:
TicketMgr();
diff --git a/src/server/game/Tools/CharacterDatabaseCleaner.h b/src/server/game/Tools/CharacterDatabaseCleaner.h
index ecbd6d0a790..f1e6900a6bb 100644
--- a/src/server/game/Tools/CharacterDatabaseCleaner.h
+++ b/src/server/game/Tools/CharacterDatabaseCleaner.h
@@ -30,20 +30,20 @@ namespace CharacterDatabaseCleaner
CLEANING_FLAG_QUESTSTATUS = 0x10
};
- void CleanDatabase();
+ TC_GAME_API void CleanDatabase();
- void CheckUnique(const char* column, const char* table, bool (*check)(uint32));
+ TC_GAME_API void CheckUnique(const char* column, const char* table, bool (*check)(uint32));
- bool AchievementProgressCheck(uint32 criteria);
- bool SkillCheck(uint32 skill);
- bool SpellCheck(uint32 spell_id);
- bool TalentCheck(uint32 talent_id);
+ TC_GAME_API bool AchievementProgressCheck(uint32 criteria);
+ TC_GAME_API bool SkillCheck(uint32 skill);
+ TC_GAME_API bool SpellCheck(uint32 spell_id);
+ TC_GAME_API bool TalentCheck(uint32 talent_id);
- void CleanCharacterAchievementProgress();
- void CleanCharacterSkills();
- void CleanCharacterSpell();
- void CleanCharacterTalent();
- void CleanCharacterQuestStatus();
+ TC_GAME_API void CleanCharacterAchievementProgress();
+ TC_GAME_API void CleanCharacterSkills();
+ TC_GAME_API void CleanCharacterSpell();
+ TC_GAME_API void CleanCharacterTalent();
+ TC_GAME_API void CleanCharacterQuestStatus();
}
#endif
diff --git a/src/server/game/Tools/PlayerDump.cpp b/src/server/game/Tools/PlayerDump.cpp
index 7d46588332e..4c5ac1dab5e 100644
--- a/src/server/game/Tools/PlayerDump.cpp
+++ b/src/server/game/Tools/PlayerDump.cpp
@@ -549,11 +549,11 @@ DumpReturn PlayerDumpReader::LoadDump(std::string const& file, uint32 account, s
ROLLBACK(DUMP_FILE_BROKEN);
const char null[5] = "NULL";
- if (!ChangeNth(line, 69, null)) // characters.deleteInfos_Account
+ if (!ChangeNth(line, 74, null)) // characters.deleteInfos_Account
ROLLBACK(DUMP_FILE_BROKEN);
- if (!ChangeNth(line, 70, null)) // characters.deleteInfos_Name
+ if (!ChangeNth(line, 75, null)) // characters.deleteInfos_Name
ROLLBACK(DUMP_FILE_BROKEN);
- if (!ChangeNth(line, 71, null)) // characters.deleteDate
+ if (!ChangeNth(line, 76, null)) // characters.deleteDate
ROLLBACK(DUMP_FILE_BROKEN);
break;
}
diff --git a/src/server/game/Tools/PlayerDump.h b/src/server/game/Tools/PlayerDump.h
index 95d6ed2d04b..12cafc6ad48 100644
--- a/src/server/game/Tools/PlayerDump.h
+++ b/src/server/game/Tools/PlayerDump.h
@@ -62,7 +62,7 @@ enum DumpReturn
DUMP_CHARACTER_DELETED
};
-class PlayerDump
+class TC_GAME_API PlayerDump
{
public:
typedef std::set<ObjectGuid::LowType> DumpGuidSet;
@@ -72,7 +72,7 @@ class PlayerDump
PlayerDump() { }
};
-class PlayerDumpWriter : public PlayerDump
+class TC_GAME_API PlayerDumpWriter : public PlayerDump
{
public:
PlayerDumpWriter() { }
@@ -90,7 +90,7 @@ class PlayerDumpWriter : public PlayerDump
DumpGuidSet items;
};
-class PlayerDumpReader : public PlayerDump
+class TC_GAME_API PlayerDumpReader : public PlayerDump
{
public:
PlayerDumpReader() { }
diff --git a/src/server/game/Warden/Warden.h b/src/server/game/Warden/Warden.h
index 35ee18d4c02..b0aa496cbe8 100644
--- a/src/server/game/Warden/Warden.h
+++ b/src/server/game/Warden/Warden.h
@@ -92,7 +92,7 @@ struct ClientWardenModule
class WorldSession;
-class Warden
+class TC_GAME_API Warden
{
friend class WardenWin;
friend class WardenMac;
diff --git a/src/server/game/Warden/WardenCheckMgr.h b/src/server/game/Warden/WardenCheckMgr.h
index a09dc3a6dbb..7349fd5b589 100644
--- a/src/server/game/Warden/WardenCheckMgr.h
+++ b/src/server/game/Warden/WardenCheckMgr.h
@@ -48,7 +48,7 @@ struct WardenCheckResult
BigNumber Result; // MEM_CHECK
};
-class WardenCheckMgr
+class TC_GAME_API WardenCheckMgr
{
private:
WardenCheckMgr();
diff --git a/src/server/game/Warden/WardenMac.h b/src/server/game/Warden/WardenMac.h
index 26a2d86524e..c7435502f63 100644
--- a/src/server/game/Warden/WardenMac.h
+++ b/src/server/game/Warden/WardenMac.h
@@ -28,7 +28,7 @@
class WorldSession;
class Warden;
-class WardenMac : public Warden
+class TC_GAME_API WardenMac : public Warden
{
public:
WardenMac();
diff --git a/src/server/game/Warden/WardenWin.h b/src/server/game/Warden/WardenWin.h
index 4bf1af77c47..b3e6d7c586c 100644
--- a/src/server/game/Warden/WardenWin.h
+++ b/src/server/game/Warden/WardenWin.h
@@ -62,7 +62,7 @@ struct WardenInitModuleRequest
class WorldSession;
class Warden;
-class WardenWin : public Warden
+class TC_GAME_API WardenWin : public Warden
{
public:
WardenWin();
diff --git a/src/server/game/Weather/Weather.h b/src/server/game/Weather/Weather.h
index c1f029d6264..6a770615308 100644
--- a/src/server/game/Weather/Weather.h
+++ b/src/server/game/Weather/Weather.h
@@ -62,7 +62,7 @@ enum WeatherState
};
/// Weather for one zone
-class Weather
+class TC_GAME_API Weather
{
public:
diff --git a/src/server/game/Weather/WeatherMgr.h b/src/server/game/Weather/WeatherMgr.h
index 97c541fd3c0..e3dd4ac9ec4 100644
--- a/src/server/game/Weather/WeatherMgr.h
+++ b/src/server/game/Weather/WeatherMgr.h
@@ -30,15 +30,15 @@ class Player;
namespace WeatherMgr
{
- void LoadWeatherData();
+ TC_GAME_API void LoadWeatherData();
- Weather* FindWeather(uint32 id);
- Weather* AddWeather(uint32 zone_id);
- void RemoveWeather(uint32 zone_id);
+ TC_GAME_API Weather* FindWeather(uint32 id);
+ TC_GAME_API Weather* AddWeather(uint32 zone_id);
+ TC_GAME_API void RemoveWeather(uint32 zone_id);
- void SendFineWeatherUpdateToPlayer(Player* player);
+ TC_GAME_API void SendFineWeatherUpdateToPlayer(Player* player);
- void Update(uint32 diff);
+ TC_GAME_API void Update(uint32 diff);
}
#endif
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 2263fbca49f..6380aece941 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -67,17 +67,18 @@
#include "WorldSession.h"
-std::atomic<bool> World::m_stopEvent(false);
-uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
-std::atomic<uint32> World::m_worldLoopCounter(0);
+TC_GAME_API std::atomic<bool> World::m_stopEvent(false);
+TC_GAME_API uint8 World::m_ExitCode = SHUTDOWN_EXIT_CODE;
-float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
-float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
-float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
+TC_GAME_API std::atomic<uint32> World::m_worldLoopCounter(0);
-int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
-int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
-int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+TC_GAME_API float World::m_MaxVisibleDistanceOnContinents = DEFAULT_VISIBILITY_DISTANCE;
+TC_GAME_API float World::m_MaxVisibleDistanceInInstances = DEFAULT_VISIBILITY_INSTANCE;
+TC_GAME_API float World::m_MaxVisibleDistanceInBGArenas = DEFAULT_VISIBILITY_BGARENAS;
+
+TC_GAME_API int32 World::m_visibility_notify_periodOnContinents = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+TC_GAME_API int32 World::m_visibility_notify_periodInInstances = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
+TC_GAME_API int32 World::m_visibility_notify_periodInBGArenas = DEFAULT_VISIBILITY_NOTIFY_PERIOD;
/// World constructor
World::World()
@@ -1066,7 +1067,6 @@ void World::LoadConfigSettings(bool reload)
m_bool_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS] = sConfigMgr->GetBoolDefault("Arena.AutoDistributePoints", false);
m_int_configs[CONFIG_ARENA_AUTO_DISTRIBUTE_INTERVAL_DAYS] = sConfigMgr->GetIntDefault ("Arena.AutoDistributeInterval", 7);
m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.Enable", false);
- m_bool_configs[CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY] = sConfigMgr->GetBoolDefault("Arena.QueueAnnouncer.PlayerOnly", false);
m_int_configs[CONFIG_ARENA_SEASON_ID] = sConfigMgr->GetIntDefault ("Arena.ArenaSeason.ID", 1);
m_int_configs[CONFIG_ARENA_START_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartRating", 0);
m_int_configs[CONFIG_ARENA_START_PERSONAL_RATING] = sConfigMgr->GetIntDefault ("Arena.ArenaStartPersonalRating", 1000);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 6d1f6313ae5..a59d9ef882a 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -129,7 +129,6 @@ enum WorldBoolConfigs
CONFIG_BG_XP_FOR_KILL,
CONFIG_ARENA_AUTO_DISTRIBUTE_POINTS,
CONFIG_ARENA_QUEUE_ANNOUNCER_ENABLE,
- CONFIG_ARENA_QUEUE_ANNOUNCER_PLAYERONLY,
CONFIG_ARENA_SEASON_IN_PROGRESS,
CONFIG_ARENA_LOG_EXTENDED_INFO,
CONFIG_OFFHAND_CHECK_AT_SPELL_UNLEARN,
@@ -537,7 +536,7 @@ struct CharacterInfo
};
/// The World
-class World
+class TC_GAME_API World
{
public:
static World* instance();
@@ -869,7 +868,7 @@ class World
std::deque<std::future<PreparedQueryResult>> m_realmCharCallbacks;
};
-extern Realm realm;
+TC_GAME_API extern Realm realm;
#define sWorld World::instance()
diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt
index aadfd3e616c..d12c44c447c 100644
--- a/src/server/scripts/CMakeLists.txt
+++ b/src/server/scripts/CMakeLists.txt
@@ -50,7 +50,7 @@ endif ()
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
-add_library(scripts
+add_library(scripts STATIC
${PRIVATE_SOURCES}
${PRIVATE_PCH_SOURCE}
)
diff --git a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
index 0f6913b7ebc..3f236c060d7 100644
--- a/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
+++ b/src/server/scripts/EasternKingdoms/Karazhan/bosses_opera.cpp
@@ -674,6 +674,12 @@ public:
void Initialize()
{
+ // Hello, developer from the future! It's me again!
+ // This time, you're fixing Karazhan scripts. Awesome. These are a mess of hacks. An amalgamation of hacks, so to speak. Maybe even a Patchwerk thereof.
+ // Anyway, I digress.
+ // @todo This line below is obviously a hack. Duh. I'm just coming in here to hackfix the encounter to actually be completable.
+ // It needs a rewrite. Badly. Please, take good care of it.
+ me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC | UNIT_FLAG_NON_ATTACKABLE);
CycloneTimer = 30000;
ChainLightningTimer = 10000;
}
@@ -701,8 +707,6 @@ public:
void EnterCombat(Unit* /*who*/) override
{
Talk(SAY_CRONE_AGGRO);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
}
void JustDied(Unit* /*killer*/) override
@@ -716,9 +720,6 @@ public:
if (!UpdateVictim())
return;
- if (me->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE))
- me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);
-
if (CycloneTimer <= diff)
{
if (Creature* Cyclone = DoSpawnCreature(CREATURE_CYCLONE, float(urand(0, 9)), float(urand(0, 9)), 0, 0, TEMPSUMMON_TIMED_DESPAWN, 15000))
diff --git a/src/server/scripts/Pet/pet_generic.cpp b/src/server/scripts/Pet/pet_generic.cpp
index 0ec6f08ae58..ff57bc0415c 100644
--- a/src/server/scripts/Pet/pet_generic.cpp
+++ b/src/server/scripts/Pet/pet_generic.cpp
@@ -21,9 +21,10 @@
*/
/* ContentData
- npc_pet_gen_egbert 100% Egbert run's around
- npc_pet_gen_pandaren_monk 100% Pandaren Monk drinks and bows with you
- npc_pet_gen_mojo 100% Mojo follows you when you kiss it
+ npc_pet_gen_baby_blizzard_bear 100% Baby Blizzard Bear sits down occasionally
+ npc_pet_gen_egbert 100% Egbert run's around
+ npc_pet_gen_pandaren_monk 100% Pandaren Monk drinks and bows with you
+ npc_pet_gen_mojo 100% Mojo follows you when you kiss it
EndContentData */
#include "ScriptMgr.h"
@@ -31,6 +32,63 @@
#include "PassiveAI.h"
#include "Player.h"
+enum BabyBlizzardBearMisc
+{
+ SPELL_BBB_PET_SIT = 61853,
+ EVENT_BBB_PET_SIT = 1,
+ EVENT_BBB_PET_SIT_INTER = 2
+};
+
+class npc_pet_gen_baby_blizzard_bear : public CreatureScript
+{
+public:
+ npc_pet_gen_baby_blizzard_bear() : CreatureScript("npc_pet_gen_baby_blizzard_bear") {}
+
+ struct npc_pet_gen_baby_blizzard_bearAI : public NullCreatureAI
+ {
+ npc_pet_gen_baby_blizzard_bearAI(Creature* creature) : NullCreatureAI(creature)
+ {
+ if (Unit* owner = me->GetCharmerOrOwner())
+ me->GetMotionMaster()->MoveFollow(owner, PET_FOLLOW_DIST, me->GetFollowAngle());
+ _events.ScheduleEvent(EVENT_BBB_PET_SIT, urandms(10, 30));
+ }
+
+ void UpdateAI(uint32 diff) override
+ {
+ _events.Update(diff);
+
+ if (Unit* owner = me->GetCharmerOrOwner())
+ if (!me->IsWithinDist(owner, 25.f))
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+
+ while (uint32 eventId = _events.ExecuteEvent())
+ {
+ switch (eventId)
+ {
+ case EVENT_BBB_PET_SIT:
+ me->CastSpell(me, SPELL_BBB_PET_SIT, false);
+ _events.ScheduleEvent(EVENT_BBB_PET_SIT_INTER, urandms(15, 30));
+ break;
+ case EVENT_BBB_PET_SIT_INTER:
+ me->InterruptSpell(CURRENT_CHANNELED_SPELL);
+ _events.ScheduleEvent(EVENT_BBB_PET_SIT, urandms(10, 30));
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ private:
+ EventMap _events;
+ };
+
+ CreatureAI* GetAI(Creature* creature) const
+ {
+ return new npc_pet_gen_baby_blizzard_bearAI(creature);
+ }
+};
+
enum EgbertMisc
{
SPELL_EGBERT = 40669,
@@ -260,6 +318,7 @@ class npc_pet_gen_mojo : public CreatureScript
void AddSC_generic_pet_scripts()
{
+ new npc_pet_gen_baby_blizzard_bear();
new npc_pet_gen_egbert();
new npc_pet_gen_pandaren_monk();
new npc_pet_gen_mojo();
diff --git a/src/server/scripts/Spells/spell_generic.cpp b/src/server/scripts/Spells/spell_generic.cpp
index abde43ef952..ce729277e42 100644
--- a/src/server/scripts/Spells/spell_generic.cpp
+++ b/src/server/scripts/Spells/spell_generic.cpp
@@ -4155,6 +4155,40 @@ public:
}
};
+// 34098 - ClearAllDebuffs
+class spell_gen_clear_debuffs : public SpellScriptLoader
+{
+ public:
+ spell_gen_clear_debuffs() : SpellScriptLoader("spell_gen_clear_debuffs") { }
+
+ class spell_gen_clear_debuffs_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_gen_clear_debuffs_SpellScript);
+
+ void HandleScript(SpellEffIndex /*effIndex*/)
+ {
+ if (Unit* target = GetHitUnit())
+ {
+ target->RemoveOwnedAuras([](Aura const* aura)
+ {
+ SpellInfo const* spellInfo = aura->GetSpellInfo();
+ return !spellInfo->IsPositive() && !spellInfo->IsPassive();
+ });
+ }
+ }
+
+ void Register() override
+ {
+ OnEffectHitTarget += SpellEffectFn(spell_gen_clear_debuffs_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
+ }
+ };
+
+ SpellScript* GetSpellScript() const override
+ {
+ return new spell_gen_clear_debuffs_SpellScript();
+ }
+};
+
void AddSC_generic_spell_scripts()
{
new spell_gen_absorb0_hitlimit1();
@@ -4241,4 +4275,5 @@ void AddSC_generic_spell_scripts()
new spell_gen_stand();
new spell_gen_mixology_bonus();
new spell_gen_landmine_knockback_achievement();
+ new spell_gen_clear_debuffs();
}
diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt
index aedbe68d51c..1ab340a4f3e 100644
--- a/src/server/shared/CMakeLists.txt
+++ b/src/server/shared/CMakeLists.txt
@@ -21,6 +21,8 @@ endif()
GroupSources(${CMAKE_CURRENT_SOURCE_DIR})
+add_definitions(-DTRINITY_API_EXPORT_SHARED)
+
add_library(shared
${PRIVATE_SOURCES}
${PRIVATE_PCH_SOURCE}
@@ -47,6 +49,18 @@ set_target_properties(shared
FOLDER
"server")
+if( BUILD_SHARED_LIBS )
+ if( UNIX )
+ install(TARGETS shared
+ LIBRARY
+ DESTINATION lib)
+ elseif( WIN32 )
+ install(TARGETS shared
+ RUNTIME
+ DESTINATION "${CMAKE_INSTALL_PREFIX}")
+ endif()
+endif()
+
# Generate precompiled header
if (USE_COREPCH)
add_cxx_pch(shared ${PRIVATE_PCH_HEADER} ${PRIVATE_PCH_SOURCE})
diff --git a/src/server/shared/DataStores/DBCFileLoader.h b/src/server/shared/DataStores/DBCFileLoader.h
index 00b1ee54a4a..abe18d1425e 100644
--- a/src/server/shared/DataStores/DBCFileLoader.h
+++ b/src/server/shared/DataStores/DBCFileLoader.h
@@ -37,7 +37,7 @@ enum DbcFieldFormat
FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc
};
-class DBCFileLoader
+class TC_SHARED_API DBCFileLoader
{
public:
DBCFileLoader();
diff --git a/src/server/shared/Networking/SocketMgr.h b/src/server/shared/Networking/SocketMgr.h
index b14aac4ca47..e479cd2450d 100644
--- a/src/server/shared/Networking/SocketMgr.h
+++ b/src/server/shared/Networking/SocketMgr.h
@@ -19,7 +19,6 @@
#define SocketMgr_h__
#include "AsyncAcceptor.h"
-#include "Config.h"
#include "Errors.h"
#include "NetworkThread.h"
#include <boost/asio/ip/tcp.hpp>
@@ -36,15 +35,9 @@ public:
ASSERT(!_threads && !_acceptor && !_threadCount, "StopNetwork must be called prior to SocketMgr destruction");
}
- virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port)
+ virtual bool StartNetwork(boost::asio::io_service& service, std::string const& bindIp, uint16 port, int threadCount)
{
- _threadCount = sConfigMgr->GetIntDefault("Network.Threads", 1);
-
- if (_threadCount <= 0)
- {
- TC_LOG_ERROR("misc", "Network.Threads is wrong in your config file");
- return false;
- }
+ ASSERT(threadCount > 0);
try
{
@@ -56,6 +49,7 @@ public:
return false;
}
+ _threadCount = threadCount;
_threads = CreateThreads();
ASSERT(_threads);
diff --git a/src/server/shared/Packets/ByteBuffer.h b/src/server/shared/Packets/ByteBuffer.h
index 2aff6b5aabf..a779075e2ed 100644
--- a/src/server/shared/Packets/ByteBuffer.h
+++ b/src/server/shared/Packets/ByteBuffer.h
@@ -37,7 +37,7 @@
class MessageBuffer;
// Root of ByteBuffer exception hierarchy
-class ByteBufferException : public std::exception
+class TC_SHARED_API ByteBufferException : public std::exception
{
public:
~ByteBufferException() throw() { }
@@ -51,7 +51,7 @@ private:
std::string msg_;
};
-class ByteBufferPositionException : public ByteBufferException
+class TC_SHARED_API ByteBufferPositionException : public ByteBufferException
{
public:
ByteBufferPositionException(bool add, size_t pos, size_t size, size_t valueSize);
@@ -59,7 +59,7 @@ public:
~ByteBufferPositionException() throw() { }
};
-class ByteBufferSourceException : public ByteBufferException
+class TC_SHARED_API ByteBufferSourceException : public ByteBufferException
{
public:
ByteBufferSourceException(size_t pos, size_t size, size_t valueSize);
@@ -67,7 +67,7 @@ public:
~ByteBufferSourceException() throw() { }
};
-class ByteBuffer
+class TC_SHARED_API ByteBuffer
{
public:
const static size_t DEFAULT_SIZE = 0x1000;
diff --git a/src/server/worldserver/Main.cpp b/src/server/worldserver/Main.cpp
index 229375c4e51..a81401bf7b8 100644
--- a/src/server/worldserver/Main.cpp
+++ b/src/server/worldserver/Main.cpp
@@ -222,7 +222,15 @@ extern int main(int argc, char** argv)
uint16 worldPort = uint16(sWorld->getIntConfig(CONFIG_PORT_WORLD));
std::string worldListener = sConfigMgr->GetStringDefault("BindIP", "0.0.0.0");
- sWorldSocketMgr.StartNetwork(_ioService, worldListener, worldPort);
+ int networkThreads = sConfigMgr->GetIntDefault("Network.Threads", 1);
+
+ if (networkThreads <= 0)
+ {
+ TC_LOG_ERROR("server.worldserver", "Network.Threads cannot be less than 0");
+ return false;
+ }
+
+ sWorldSocketMgr.StartNetwork(_ioService, worldListener, worldPort, networkThreads);
// Set server online (allow connecting now)
LoginDatabase.DirectPExecute("UPDATE realmlist SET flag = flag & ~%u, population = 0 WHERE id = '%u'", REALM_FLAG_OFFLINE, realm.Id.Realm);
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 8e68d9f08fe..b5664c38640 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -2989,6 +2989,27 @@ AuctionHouseBot.MinTime = 1
AuctionHouseBot.MaxTime = 72
#
+# AuctionHouseBot.Class.CLASS.Allow.Zero = 0
+# Description: Include items without a sell or buy price.
+# Default: 0 - (Disabled)
+# 1 - (Enabled)
+
+AuctionHouseBot.Class.Consumable.Allow.Zero = 0
+AuctionHouseBot.Class.Container.Allow.Zero = 0
+AuctionHouseBot.Class.Weapon.Allow.Zero = 0
+AuctionHouseBot.Class.Gem.Allow.Zero = 0
+AuctionHouseBot.Class.Armor.Allow.Zero = 0
+AuctionHouseBot.Class.Reagent.Allow.Zero = 0
+AuctionHouseBot.Class.Projectile.Allow.Zero = 0
+AuctionHouseBot.Class.TradeGood.Allow.Zero = 0
+AuctionHouseBot.Class.Recipe.Allow.Zero = 0
+AuctionHouseBot.Class.Quiver.Allow.Zero = 0
+AuctionHouseBot.Class.Quest.Allow.Zero = 0
+AuctionHouseBot.Class.Key.Allow.Zero = 0
+AuctionHouseBot.Class.Misc.Allow.Zero = 0
+AuctionHouseBot.Class.Glyph.Allow.Zero = 0
+
+#
# AuctionHouseBot.Items.Vendor
# Description: Include items that can be bought from vendors.
# Default: 0 - (Disabled)
@@ -3116,8 +3137,6 @@ AuctionHouseBot.Class.Key.Price.Ratio = 100
AuctionHouseBot.Class.Misc.Price.Ratio = 100
AuctionHouseBot.Class.Glyph.Price.Ratio = 100
-
-
#
# AuctionHouseBot.Items.ItemLevel.*
# Description: Prevent seller from listing items below/above this item level