aboutsummaryrefslogtreecommitdiff
path: root/src/server/shared
diff options
context:
space:
mode:
authorclick <none@none>2010-06-05 21:22:47 +0200
committerclick <none@none>2010-06-05 21:22:47 +0200
commit455bfb01645510c677b88c693e0092244e1901e4 (patch)
treef9a1d305217c4967fdd572b595a98e2f58a0c482 /src/server/shared
parenta2d6e7ff8c95e688adc625c01387af2ca3cde3a0 (diff)
Move core/realm files to new subdirectory
--HG-- branch : trunk rename : src/framework/CMakeLists.txt => src/server/framework/CMakeLists.txt rename : src/framework/Dynamic/FactoryHolder.h => src/server/framework/Dynamic/FactoryHolder.h rename : src/framework/Dynamic/ObjectRegistry.h => src/server/framework/Dynamic/ObjectRegistry.h rename : src/framework/GameSystem/Grid.h => src/server/framework/GameSystem/Grid.h rename : src/framework/GameSystem/GridLoader.h => src/server/framework/GameSystem/GridLoader.h rename : src/framework/GameSystem/GridRefManager.h => src/server/framework/GameSystem/GridRefManager.h rename : src/framework/GameSystem/GridReference.h => src/server/framework/GameSystem/GridReference.h rename : src/framework/GameSystem/NGrid.h => src/server/framework/GameSystem/NGrid.h rename : src/framework/GameSystem/TypeContainer.h => src/server/framework/GameSystem/TypeContainer.h rename : src/framework/GameSystem/TypeContainerFunctions.h => src/server/framework/GameSystem/TypeContainerFunctions.h rename : src/framework/GameSystem/TypeContainerFunctionsPtr.h => src/server/framework/GameSystem/TypeContainerFunctionsPtr.h rename : src/framework/GameSystem/TypeContainerVisitor.h => src/server/framework/GameSystem/TypeContainerVisitor.h rename : src/framework/Network/SocketDefines.h => src/server/framework/Network/SocketDefines.h rename : src/framework/Platform/CompilerDefs.h => src/server/framework/Platform/CompilerDefs.h rename : src/framework/Platform/Define.h => src/server/framework/Platform/Define.h rename : src/framework/Policies/CreationPolicy.h => src/server/framework/Policies/CreationPolicy.h rename : src/framework/Policies/ObjectLifeTime.cpp => src/server/framework/Policies/ObjectLifeTime.cpp rename : src/framework/Policies/ObjectLifeTime.h => src/server/framework/Policies/ObjectLifeTime.h rename : src/framework/Policies/Singleton.h => src/server/framework/Policies/Singleton.h rename : src/framework/Policies/SingletonImp.h => src/server/framework/Policies/SingletonImp.h rename : src/framework/Policies/ThreadingModel.h => src/server/framework/Policies/ThreadingModel.h rename : src/framework/Utilities/ByteConverter.h => src/server/framework/Utilities/ByteConverter.h rename : src/framework/Utilities/Callback.h => src/server/framework/Utilities/Callback.h rename : src/framework/Utilities/CountedReference/Reference.h => src/server/framework/Utilities/CountedReference/Reference.h rename : src/framework/Utilities/CountedReference/ReferenceHolder.h => src/server/framework/Utilities/CountedReference/ReferenceHolder.h rename : src/framework/Utilities/CountedReference/ReferenceImpl.h => src/server/framework/Utilities/CountedReference/ReferenceImpl.h rename : src/framework/Utilities/EventProcessor.cpp => src/server/framework/Utilities/EventProcessor.cpp rename : src/framework/Utilities/EventProcessor.h => src/server/framework/Utilities/EventProcessor.h rename : src/framework/Utilities/LinkedList.h => src/server/framework/Utilities/LinkedList.h rename : src/framework/Utilities/LinkedReference/RefManager.h => src/server/framework/Utilities/LinkedReference/RefManager.h rename : src/framework/Utilities/LinkedReference/Reference.h => src/server/framework/Utilities/LinkedReference/Reference.h rename : src/framework/Utilities/TypeList.h => src/server/framework/Utilities/TypeList.h rename : src/framework/Utilities/UnorderedMap.h => src/server/framework/Utilities/UnorderedMap.h rename : src/game/AccountMgr.cpp => src/server/game/AccountMgr.cpp rename : src/game/AccountMgr.h => src/server/game/AccountMgr.h rename : src/game/AchievementMgr.cpp => src/server/game/AchievementMgr.cpp rename : src/game/AchievementMgr.h => src/server/game/AchievementMgr.h rename : src/game/AddonHandler.cpp => src/server/game/AddonHandler.cpp rename : src/game/AddonHandler.h => src/server/game/AddonHandler.h rename : src/game/AddonMgr.cpp => src/server/game/AddonMgr.cpp rename : src/game/AddonMgr.h => src/server/game/AddonMgr.h rename : src/game/ArenaTeam.cpp => src/server/game/ArenaTeam.cpp rename : src/game/ArenaTeam.h => src/server/game/ArenaTeam.h rename : src/game/ArenaTeamHandler.cpp => src/server/game/ArenaTeamHandler.cpp rename : src/game/AuctionHouseBot.cpp => src/server/game/AuctionHouseBot.cpp rename : src/game/AuctionHouseBot.h => src/server/game/AuctionHouseBot.h rename : src/game/AuctionHouseHandler.cpp => src/server/game/AuctionHouseHandler.cpp rename : src/game/AuctionHouseMgr.cpp => src/server/game/AuctionHouseMgr.cpp rename : src/game/AuctionHouseMgr.h => src/server/game/AuctionHouseMgr.h rename : src/game/Bag.cpp => src/server/game/Bag.cpp rename : src/game/Bag.h => src/server/game/Bag.h rename : src/game/BattleGround.cpp => src/server/game/BattleGround.cpp rename : src/game/BattleGround.h => src/server/game/BattleGround.h rename : src/game/BattleGroundAA.cpp => src/server/game/BattleGroundAA.cpp rename : src/game/BattleGroundAA.h => src/server/game/BattleGroundAA.h rename : src/game/BattleGroundAB.cpp => src/server/game/BattleGroundAB.cpp rename : src/game/BattleGroundAB.h => src/server/game/BattleGroundAB.h rename : src/game/BattleGroundAV.cpp => src/server/game/BattleGroundAV.cpp rename : src/game/BattleGroundAV.h => src/server/game/BattleGroundAV.h rename : src/game/BattleGroundBE.cpp => src/server/game/BattleGroundBE.cpp rename : src/game/BattleGroundBE.h => src/server/game/BattleGroundBE.h rename : src/game/BattleGroundDS.cpp => src/server/game/BattleGroundDS.cpp rename : src/game/BattleGroundDS.h => src/server/game/BattleGroundDS.h rename : src/game/BattleGroundEY.cpp => src/server/game/BattleGroundEY.cpp rename : src/game/BattleGroundEY.h => src/server/game/BattleGroundEY.h rename : src/game/BattleGroundHandler.cpp => src/server/game/BattleGroundHandler.cpp rename : src/game/BattleGroundIC.cpp => src/server/game/BattleGroundIC.cpp rename : src/game/BattleGroundIC.h => src/server/game/BattleGroundIC.h rename : src/game/BattleGroundMgr.cpp => src/server/game/BattleGroundMgr.cpp rename : src/game/BattleGroundMgr.h => src/server/game/BattleGroundMgr.h rename : src/game/BattleGroundNA.cpp => src/server/game/BattleGroundNA.cpp rename : src/game/BattleGroundNA.h => src/server/game/BattleGroundNA.h rename : src/game/BattleGroundRB.cpp => src/server/game/BattleGroundRB.cpp rename : src/game/BattleGroundRB.h => src/server/game/BattleGroundRB.h rename : src/game/BattleGroundRL.cpp => src/server/game/BattleGroundRL.cpp rename : src/game/BattleGroundRL.h => src/server/game/BattleGroundRL.h rename : src/game/BattleGroundRV.cpp => src/server/game/BattleGroundRV.cpp rename : src/game/BattleGroundRV.h => src/server/game/BattleGroundRV.h rename : src/game/BattleGroundSA.cpp => src/server/game/BattleGroundSA.cpp rename : src/game/BattleGroundSA.h => src/server/game/BattleGroundSA.h rename : src/game/BattleGroundWS.cpp => src/server/game/BattleGroundWS.cpp rename : src/game/BattleGroundWS.h => src/server/game/BattleGroundWS.h rename : src/game/CMakeLists.txt => src/server/game/CMakeLists.txt rename : src/game/Calendar.cpp => src/server/game/Calendar.cpp rename : src/game/Calendar.h => src/server/game/Calendar.h rename : src/game/CalendarHandler.cpp => src/server/game/CalendarHandler.cpp rename : src/game/Cell.h => src/server/game/Cell.h rename : src/game/CellImpl.h => src/server/game/CellImpl.h rename : src/game/Channel.cpp => src/server/game/Channel.cpp rename : src/game/Channel.h => src/server/game/Channel.h rename : src/game/ChannelHandler.cpp => src/server/game/ChannelHandler.cpp rename : src/game/ChannelMgr.cpp => src/server/game/ChannelMgr.cpp rename : src/game/ChannelMgr.h => src/server/game/ChannelMgr.h rename : src/game/CharacterHandler.cpp => src/server/game/CharacterHandler.cpp rename : src/game/Chat.cpp => src/server/game/Chat.cpp rename : src/game/Chat.h => src/server/game/Chat.h rename : src/game/ChatHandler.cpp => src/server/game/ChatHandler.cpp rename : src/game/CombatAI.cpp => src/server/game/CombatAI.cpp rename : src/game/CombatAI.h => src/server/game/CombatAI.h rename : src/game/CombatHandler.cpp => src/server/game/CombatHandler.cpp rename : src/game/ConditionMgr.cpp => src/server/game/ConditionMgr.cpp rename : src/game/ConditionMgr.h => src/server/game/ConditionMgr.h rename : src/game/ConfusedMovementGenerator.cpp => src/server/game/ConfusedMovementGenerator.cpp rename : src/game/ConfusedMovementGenerator.h => src/server/game/ConfusedMovementGenerator.h rename : src/game/Corpse.cpp => src/server/game/Corpse.cpp rename : src/game/Corpse.h => src/server/game/Corpse.h rename : src/game/Creature.cpp => src/server/game/Creature.cpp rename : src/game/Creature.h => src/server/game/Creature.h rename : src/game/CreatureAI.cpp => src/server/game/CreatureAI.cpp rename : src/game/CreatureAI.h => src/server/game/CreatureAI.h rename : src/game/CreatureAIFactory.h => src/server/game/CreatureAIFactory.h rename : src/game/CreatureAIImpl.h => src/server/game/CreatureAIImpl.h rename : src/game/CreatureAIRegistry.cpp => src/server/game/CreatureAIRegistry.cpp rename : src/game/CreatureAIRegistry.h => src/server/game/CreatureAIRegistry.h rename : src/game/CreatureAISelector.cpp => src/server/game/CreatureAISelector.cpp rename : src/game/CreatureAISelector.h => src/server/game/CreatureAISelector.h rename : src/game/CreatureEventAI.cpp => src/server/game/CreatureEventAI.cpp rename : src/game/CreatureEventAI.h => src/server/game/CreatureEventAI.h rename : src/game/CreatureEventAIMgr.cpp => src/server/game/CreatureEventAIMgr.cpp rename : src/game/CreatureEventAIMgr.h => src/server/game/CreatureEventAIMgr.h rename : src/game/CreatureGroups.cpp => src/server/game/CreatureGroups.cpp rename : src/game/CreatureGroups.h => src/server/game/CreatureGroups.h rename : src/game/DBCEnums.h => src/server/game/DBCEnums.h rename : src/game/DBCStores.cpp => src/server/game/DBCStores.cpp rename : src/game/DBCStores.h => src/server/game/DBCStores.h rename : src/game/DBCStructure.h => src/server/game/DBCStructure.h rename : src/game/DBCfmt.h => src/server/game/DBCfmt.h rename : src/game/Debugcmds.cpp => src/server/game/Debugcmds.cpp rename : src/game/DestinationHolder.cpp => src/server/game/DestinationHolder.cpp rename : src/game/DestinationHolder.h => src/server/game/DestinationHolder.h rename : src/game/DestinationHolderImp.h => src/server/game/DestinationHolderImp.h rename : src/game/DuelHandler.cpp => src/server/game/DuelHandler.cpp rename : src/game/DynamicObject.cpp => src/server/game/DynamicObject.cpp rename : src/game/DynamicObject.h => src/server/game/DynamicObject.h rename : src/game/FleeingMovementGenerator.cpp => src/server/game/FleeingMovementGenerator.cpp rename : src/game/FleeingMovementGenerator.h => src/server/game/FleeingMovementGenerator.h rename : src/game/FollowerRefManager.h => src/server/game/FollowerRefManager.h rename : src/game/FollowerReference.cpp => src/server/game/FollowerReference.cpp rename : src/game/FollowerReference.h => src/server/game/FollowerReference.h rename : src/game/Formulas.h => src/server/game/Formulas.h rename : src/game/GameEventMgr.cpp => src/server/game/GameEventMgr.cpp rename : src/game/GameEventMgr.h => src/server/game/GameEventMgr.h rename : src/game/GameObject.cpp => src/server/game/GameObject.cpp rename : src/game/GameObject.h => src/server/game/GameObject.h rename : src/game/GlobalEvents.cpp => src/server/game/GlobalEvents.cpp rename : src/game/GlobalEvents.h => src/server/game/GlobalEvents.h rename : src/game/GossipDef.cpp => src/server/game/GossipDef.cpp rename : src/game/GossipDef.h => src/server/game/GossipDef.h rename : src/game/GridDefines.h => src/server/game/GridDefines.h rename : src/game/GridNotifiers.cpp => src/server/game/GridNotifiers.cpp rename : src/game/GridNotifiers.h => src/server/game/GridNotifiers.h rename : src/game/GridNotifiersImpl.h => src/server/game/GridNotifiersImpl.h rename : src/game/GridStates.cpp => src/server/game/GridStates.cpp rename : src/game/GridStates.h => src/server/game/GridStates.h rename : src/game/Group.cpp => src/server/game/Group.cpp rename : src/game/Group.h => src/server/game/Group.h rename : src/game/GroupHandler.cpp => src/server/game/GroupHandler.cpp rename : src/game/GroupRefManager.h => src/server/game/GroupRefManager.h rename : src/game/GroupReference.cpp => src/server/game/GroupReference.cpp rename : src/game/GroupReference.h => src/server/game/GroupReference.h rename : src/game/GuardAI.cpp => src/server/game/GuardAI.cpp rename : src/game/GuardAI.h => src/server/game/GuardAI.h rename : src/game/Guild.cpp => src/server/game/Guild.cpp rename : src/game/Guild.h => src/server/game/Guild.h rename : src/game/GuildHandler.cpp => src/server/game/GuildHandler.cpp rename : src/game/HomeMovementGenerator.cpp => src/server/game/HomeMovementGenerator.cpp rename : src/game/HomeMovementGenerator.h => src/server/game/HomeMovementGenerator.h rename : src/game/HostileRefManager.cpp => src/server/game/HostileRefManager.cpp rename : src/game/HostileRefManager.h => src/server/game/HostileRefManager.h rename : src/game/IdleMovementGenerator.cpp => src/server/game/IdleMovementGenerator.cpp rename : src/game/IdleMovementGenerator.h => src/server/game/IdleMovementGenerator.h rename : src/game/InstanceData.cpp => src/server/game/InstanceData.cpp rename : src/game/InstanceData.h => src/server/game/InstanceData.h rename : src/game/InstanceSaveMgr.cpp => src/server/game/InstanceSaveMgr.cpp rename : src/game/InstanceSaveMgr.h => src/server/game/InstanceSaveMgr.h rename : src/game/Item.cpp => src/server/game/Item.cpp rename : src/game/Item.h => src/server/game/Item.h rename : src/game/ItemEnchantmentMgr.cpp => src/server/game/ItemEnchantmentMgr.cpp rename : src/game/ItemEnchantmentMgr.h => src/server/game/ItemEnchantmentMgr.h rename : src/game/ItemHandler.cpp => src/server/game/ItemHandler.cpp rename : src/game/ItemPrototype.h => src/server/game/ItemPrototype.h rename : src/game/LFG.h => src/server/game/LFG.h rename : src/game/LFGHandler.cpp => src/server/game/LFGHandler.cpp rename : src/game/LFGMgr.cpp => src/server/game/LFGMgr.cpp rename : src/game/LFGMgr.h => src/server/game/LFGMgr.h rename : src/game/Language.h => src/server/game/Language.h rename : src/game/Level0.cpp => src/server/game/Level0.cpp rename : src/game/Level1.cpp => src/server/game/Level1.cpp rename : src/game/Level2.cpp => src/server/game/Level2.cpp rename : src/game/Level3.cpp => src/server/game/Level3.cpp rename : src/game/LootHandler.cpp => src/server/game/LootHandler.cpp rename : src/game/LootMgr.cpp => src/server/game/LootMgr.cpp rename : src/game/LootMgr.h => src/server/game/LootMgr.h rename : src/game/Mail.cpp => src/server/game/Mail.cpp rename : src/game/Mail.h => src/server/game/Mail.h rename : src/game/Map.cpp => src/server/game/Map.cpp rename : src/game/Map.h => src/server/game/Map.h rename : src/game/MapInstanced.cpp => src/server/game/MapInstanced.cpp rename : src/game/MapInstanced.h => src/server/game/MapInstanced.h rename : src/game/MapManager.cpp => src/server/game/MapManager.cpp rename : src/game/MapManager.h => src/server/game/MapManager.h rename : src/game/MapRefManager.h => src/server/game/MapRefManager.h rename : src/game/MapReference.h => src/server/game/MapReference.h rename : src/game/MapUpdater.cpp => src/server/game/MapUpdater.cpp rename : src/game/MapUpdater.h => src/server/game/MapUpdater.h rename : src/game/MiscHandler.cpp => src/server/game/MiscHandler.cpp rename : src/game/MotionMaster.cpp => src/server/game/MotionMaster.cpp rename : src/game/MotionMaster.h => src/server/game/MotionMaster.h rename : src/game/MovementGenerator.cpp => src/server/game/MovementGenerator.cpp rename : src/game/MovementGenerator.h => src/server/game/MovementGenerator.h rename : src/game/MovementGeneratorImpl.h => src/server/game/MovementGeneratorImpl.h rename : src/game/MovementHandler.cpp => src/server/game/MovementHandler.cpp rename : src/game/NPCHandler.cpp => src/server/game/NPCHandler.cpp rename : src/game/NPCHandler.h => src/server/game/NPCHandler.h rename : src/game/Object.cpp => src/server/game/Object.cpp rename : src/game/Object.h => src/server/game/Object.h rename : src/game/ObjectAccessor.cpp => src/server/game/ObjectAccessor.cpp rename : src/game/ObjectAccessor.h => src/server/game/ObjectAccessor.h rename : src/game/ObjectDefines.h => src/server/game/ObjectDefines.h rename : src/game/ObjectGridLoader.cpp => src/server/game/ObjectGridLoader.cpp rename : src/game/ObjectGridLoader.h => src/server/game/ObjectGridLoader.h rename : src/game/ObjectMgr.cpp => src/server/game/ObjectMgr.cpp rename : src/game/ObjectMgr.h => src/server/game/ObjectMgr.h rename : src/game/ObjectPosSelector.cpp => src/server/game/ObjectPosSelector.cpp rename : src/game/ObjectPosSelector.h => src/server/game/ObjectPosSelector.h rename : src/game/Opcodes.cpp => src/server/game/Opcodes.cpp rename : src/game/Opcodes.h => src/server/game/Opcodes.h rename : src/game/OutdoorPvP.cpp => src/server/game/OutdoorPvP.cpp rename : src/game/OutdoorPvP.h => src/server/game/OutdoorPvP.h rename : src/game/OutdoorPvPEP.cpp => src/server/game/OutdoorPvPEP.cpp rename : src/game/OutdoorPvPEP.h => src/server/game/OutdoorPvPEP.h rename : src/game/OutdoorPvPHP.cpp => src/server/game/OutdoorPvPHP.cpp rename : src/game/OutdoorPvPHP.h => src/server/game/OutdoorPvPHP.h rename : src/game/OutdoorPvPImpl.h => src/server/game/OutdoorPvPImpl.h rename : src/game/OutdoorPvPMgr.cpp => src/server/game/OutdoorPvPMgr.cpp rename : src/game/OutdoorPvPMgr.h => src/server/game/OutdoorPvPMgr.h rename : src/game/OutdoorPvPNA.cpp => src/server/game/OutdoorPvPNA.cpp rename : src/game/OutdoorPvPNA.h => src/server/game/OutdoorPvPNA.h rename : src/game/OutdoorPvPSI.cpp => src/server/game/OutdoorPvPSI.cpp rename : src/game/OutdoorPvPSI.h => src/server/game/OutdoorPvPSI.h rename : src/game/OutdoorPvPTF.cpp => src/server/game/OutdoorPvPTF.cpp rename : src/game/OutdoorPvPTF.h => src/server/game/OutdoorPvPTF.h rename : src/game/OutdoorPvPZM.cpp => src/server/game/OutdoorPvPZM.cpp rename : src/game/OutdoorPvPZM.h => src/server/game/OutdoorPvPZM.h rename : src/game/PassiveAI.cpp => src/server/game/PassiveAI.cpp rename : src/game/PassiveAI.h => src/server/game/PassiveAI.h rename : src/game/Path.h => src/server/game/Path.h rename : src/game/Pet.cpp => src/server/game/Pet.cpp rename : src/game/Pet.h => src/server/game/Pet.h rename : src/game/PetAI.cpp => src/server/game/PetAI.cpp rename : src/game/PetAI.h => src/server/game/PetAI.h rename : src/game/PetHandler.cpp => src/server/game/PetHandler.cpp rename : src/game/PetitionsHandler.cpp => src/server/game/PetitionsHandler.cpp rename : src/game/Player.cpp => src/server/game/Player.cpp rename : src/game/Player.h => src/server/game/Player.h rename : src/game/PlayerDump.cpp => src/server/game/PlayerDump.cpp rename : src/game/PlayerDump.h => src/server/game/PlayerDump.h rename : src/game/PointMovementGenerator.cpp => src/server/game/PointMovementGenerator.cpp rename : src/game/PointMovementGenerator.h => src/server/game/PointMovementGenerator.h rename : src/game/PoolHandler.cpp => src/server/game/PoolHandler.cpp rename : src/game/PoolHandler.h => src/server/game/PoolHandler.h rename : src/game/QueryHandler.cpp => src/server/game/QueryHandler.cpp rename : src/game/QuestDef.cpp => src/server/game/QuestDef.cpp rename : src/game/QuestDef.h => src/server/game/QuestDef.h rename : src/game/QuestHandler.cpp => src/server/game/QuestHandler.cpp rename : src/game/RandomMovementGenerator.cpp => src/server/game/RandomMovementGenerator.cpp rename : src/game/RandomMovementGenerator.h => src/server/game/RandomMovementGenerator.h rename : src/game/ReactorAI.cpp => src/server/game/ReactorAI.cpp rename : src/game/ReactorAI.h => src/server/game/ReactorAI.h rename : src/game/ReputationMgr.cpp => src/server/game/ReputationMgr.cpp rename : src/game/ReputationMgr.h => src/server/game/ReputationMgr.h rename : src/game/ScriptLoader.cpp => src/server/game/ScriptLoader.cpp rename : src/game/ScriptLoader.h => src/server/game/ScriptLoader.h rename : src/game/ScriptMgr.cpp => src/server/game/ScriptMgr.cpp rename : src/game/ScriptMgr.h => src/server/game/ScriptMgr.h rename : src/game/ScriptSystem.cpp => src/server/game/ScriptSystem.cpp rename : src/game/ScriptSystem.h => src/server/game/ScriptSystem.h rename : src/game/ScriptedCreature.cpp => src/server/game/ScriptedCreature.cpp rename : src/game/ScriptedCreature.h => src/server/game/ScriptedCreature.h rename : src/game/ScriptedEscortAI.cpp => src/server/game/ScriptedEscortAI.cpp rename : src/game/ScriptedEscortAI.h => src/server/game/ScriptedEscortAI.h rename : src/game/ScriptedFollowerAI.cpp => src/server/game/ScriptedFollowerAI.cpp rename : src/game/ScriptedFollowerAI.h => src/server/game/ScriptedFollowerAI.h rename : src/game/ScriptedGossip.h => src/server/game/ScriptedGossip.h rename : src/game/ScriptedGuardAI.cpp => src/server/game/ScriptedGuardAI.cpp rename : src/game/ScriptedGuardAI.h => src/server/game/ScriptedGuardAI.h rename : src/game/ScriptedInstance.h => src/server/game/ScriptedInstance.h rename : src/game/ScriptedPch.cpp => src/server/game/ScriptedPch.cpp rename : src/game/ScriptedPch.h => src/server/game/ScriptedPch.h rename : src/game/ScriptedSimpleAI.cpp => src/server/game/ScriptedSimpleAI.cpp rename : src/game/ScriptedSimpleAI.h => src/server/game/ScriptedSimpleAI.h rename : src/game/ScriptedSmartAI.cpp => src/server/game/ScriptedSmartAI.cpp rename : src/game/ScriptedSmartAI.h => src/server/game/ScriptedSmartAI.h rename : src/game/SharedDefines.h => src/server/game/SharedDefines.h rename : src/game/SkillDiscovery.cpp => src/server/game/SkillDiscovery.cpp rename : src/game/SkillDiscovery.h => src/server/game/SkillDiscovery.h rename : src/game/SkillExtraItems.cpp => src/server/game/SkillExtraItems.cpp rename : src/game/SkillExtraItems.h => src/server/game/SkillExtraItems.h rename : src/game/SkillHandler.cpp => src/server/game/SkillHandler.cpp rename : src/game/SocialMgr.cpp => src/server/game/SocialMgr.cpp rename : src/game/SocialMgr.h => src/server/game/SocialMgr.h rename : src/game/Spell.cpp => src/server/game/Spell.cpp rename : src/game/Spell.h => src/server/game/Spell.h rename : src/game/SpellAuraDefines.h => src/server/game/SpellAuraDefines.h rename : src/game/SpellAuraEffects.cpp => src/server/game/SpellAuraEffects.cpp rename : src/game/SpellAuraEffects.h => src/server/game/SpellAuraEffects.h rename : src/game/SpellAuras.cpp => src/server/game/SpellAuras.cpp rename : src/game/SpellAuras.h => src/server/game/SpellAuras.h rename : src/game/SpellEffects.cpp => src/server/game/SpellEffects.cpp rename : src/game/SpellHandler.cpp => src/server/game/SpellHandler.cpp rename : src/game/SpellMgr.cpp => src/server/game/SpellMgr.cpp rename : src/game/SpellMgr.h => src/server/game/SpellMgr.h rename : src/game/StatSystem.cpp => src/server/game/StatSystem.cpp rename : src/game/TargetedMovementGenerator.cpp => src/server/game/TargetedMovementGenerator.cpp rename : src/game/TargetedMovementGenerator.h => src/server/game/TargetedMovementGenerator.h rename : src/game/TaxiHandler.cpp => src/server/game/TaxiHandler.cpp rename : src/game/TemporarySummon.cpp => src/server/game/TemporarySummon.cpp rename : src/game/TemporarySummon.h => src/server/game/TemporarySummon.h rename : src/game/ThreatManager.cpp => src/server/game/ThreatManager.cpp rename : src/game/ThreatManager.h => src/server/game/ThreatManager.h rename : src/game/TicketHandler.cpp => src/server/game/TicketHandler.cpp rename : src/game/TimeMgr.cpp => src/server/game/TimeMgr.cpp rename : src/game/TimeMgr.h => src/server/game/TimeMgr.h rename : src/game/Tools.cpp => src/server/game/Tools.cpp rename : src/game/Tools.h => src/server/game/Tools.h rename : src/game/Totem.cpp => src/server/game/Totem.cpp rename : src/game/Totem.h => src/server/game/Totem.h rename : src/game/TotemAI.cpp => src/server/game/TotemAI.cpp rename : src/game/TotemAI.h => src/server/game/TotemAI.h rename : src/game/TradeHandler.cpp => src/server/game/TradeHandler.cpp rename : src/game/Transports.cpp => src/server/game/Transports.cpp rename : src/game/Transports.h => src/server/game/Transports.h rename : src/game/Traveller.h => src/server/game/Traveller.h rename : src/game/Unit.cpp => src/server/game/Unit.cpp rename : src/game/Unit.h => src/server/game/Unit.h rename : src/game/UnitAI.cpp => src/server/game/UnitAI.cpp rename : src/game/UnitAI.h => src/server/game/UnitAI.h rename : src/game/UnitEvents.h => src/server/game/UnitEvents.h rename : src/game/UpdateData.cpp => src/server/game/UpdateData.cpp rename : src/game/UpdateData.h => src/server/game/UpdateData.h rename : src/game/UpdateFields.h => src/server/game/UpdateFields.h rename : src/game/UpdateMask.h => src/server/game/UpdateMask.h rename : src/game/Vehicle.cpp => src/server/game/Vehicle.cpp rename : src/game/Vehicle.h => src/server/game/Vehicle.h rename : src/game/VoiceChatHandler.cpp => src/server/game/VoiceChatHandler.cpp rename : src/game/WaypointManager.cpp => src/server/game/WaypointManager.cpp rename : src/game/WaypointManager.h => src/server/game/WaypointManager.h rename : src/game/WaypointMovementGenerator.cpp => src/server/game/WaypointMovementGenerator.cpp rename : src/game/WaypointMovementGenerator.h => src/server/game/WaypointMovementGenerator.h rename : src/game/Weather.cpp => src/server/game/Weather.cpp rename : src/game/Weather.h => src/server/game/Weather.h rename : src/game/World.cpp => src/server/game/World.cpp rename : src/game/World.h => src/server/game/World.h rename : src/game/WorldLog.cpp => src/server/game/WorldLog.cpp rename : src/game/WorldLog.h => src/server/game/WorldLog.h rename : src/game/WorldSession.cpp => src/server/game/WorldSession.cpp rename : src/game/WorldSession.h => src/server/game/WorldSession.h rename : src/game/WorldSocket.cpp => src/server/game/WorldSocket.cpp rename : src/game/WorldSocket.h => src/server/game/WorldSocket.h rename : src/game/WorldSocketMgr.cpp => src/server/game/WorldSocketMgr.cpp rename : src/game/WorldSocketMgr.h => src/server/game/WorldSocketMgr.h rename : src/game/ZoneScript.h => src/server/game/ZoneScript.h rename : src/game/pchdef.cpp => src/server/game/pchdef.cpp rename : src/game/pchdef.h => src/server/game/pchdef.h rename : src/game/pchlinux.cpp => src/server/game/pchlinux.cpp rename : src/game/pchlinux.h => src/server/game/pchlinux.h rename : src/scripts/CMakeLists.txt => src/server/scripts/CMakeLists.txt rename : src/scripts/custom/custom_example.cpp => src/server/scripts/custom/custom_example.cpp rename : src/scripts/custom/custom_gossip_codebox.cpp => src/server/scripts/custom/custom_gossip_codebox.cpp rename : src/scripts/custom/npc_acherus_taxi.cpp => src/server/scripts/custom/npc_acherus_taxi.cpp rename : src/scripts/custom/npc_wyrmresttempel_taxi.cpp => src/server/scripts/custom/npc_wyrmresttempel_taxi.cpp rename : src/scripts/custom/on_events.cpp => src/server/scripts/custom/on_events.cpp rename : src/scripts/custom/test.cpp => src/server/scripts/custom/test.cpp rename : src/scripts/eastern_kingdoms/alterac_mountains.cpp => src/server/scripts/eastern_kingdoms/alterac_mountains.cpp rename : src/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp => src/server/scripts/eastern_kingdoms/alterac_valley/alterac_valley.cpp rename : src/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp => src/server/scripts/eastern_kingdoms/alterac_valley/boss_balinda.cpp rename : src/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp => src/server/scripts/eastern_kingdoms/alterac_valley/boss_drekthar.cpp rename : src/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp => src/server/scripts/eastern_kingdoms/alterac_valley/boss_galvangar.cpp rename : src/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp => src/server/scripts/eastern_kingdoms/alterac_valley/boss_vanndar.cpp rename : src/scripts/eastern_kingdoms/arathi_highlands.cpp => src/server/scripts/eastern_kingdoms/arathi_highlands.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h => src/server/scripts/eastern_kingdoms/blackrock_depths/blackrock_depths.h rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_ambassador_flamelash.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_anubshiah.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_emperor_dagran_thaurissan.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_general_angerforge.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_gorosh_the_dervish.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_grizzle.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_high_interrogator_gerstahn.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_magmus.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_moira_bronzebeard.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/boss_tomb_of_seven.cpp rename : src/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp => src/server/scripts/eastern_kingdoms/blackrock_depths/instance_blackrock_depths.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h => src/server/scripts/eastern_kingdoms/blackrock_spire/blackrock_spire.h rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_drakkisath.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_gyth.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_halycon.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_highlord_omokk.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_mother_smolderweb.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_overlord_wyrmthalak.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_pyroguard_emberseer.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_quartermaster_zigris.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_rend_blackhand.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_shadow_hunter_voshgajin.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_the_beast.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/boss_warmaster_voone.cpp rename : src/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp => src/server/scripts/eastern_kingdoms/blackrock_spire/instance_blackrock_spire.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_broodlord_lashlayer.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_chromaggus.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_ebonroc.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_firemaw.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_flamegor.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_nefarian.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_razorgore.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_vaelastrasz.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/boss_victor_nefarius.cpp rename : src/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp => src/server/scripts/eastern_kingdoms/blackwing_lair/instance_blackwing_lair.cpp rename : src/scripts/eastern_kingdoms/blasted_lands.cpp => src/server/scripts/eastern_kingdoms/blasted_lands.cpp rename : src/scripts/eastern_kingdoms/boss_kruul.cpp => src/server/scripts/eastern_kingdoms/boss_kruul.cpp rename : src/scripts/eastern_kingdoms/burning_steppes.cpp => src/server/scripts/eastern_kingdoms/burning_steppes.cpp rename : src/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp => src/server/scripts/eastern_kingdoms/deadmines/boss_mr_smite.cpp rename : src/scripts/eastern_kingdoms/deadmines/deadmines.cpp => src/server/scripts/eastern_kingdoms/deadmines/deadmines.cpp rename : src/scripts/eastern_kingdoms/deadmines/deadmines.h => src/server/scripts/eastern_kingdoms/deadmines/deadmines.h rename : src/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp => src/server/scripts/eastern_kingdoms/deadmines/instance_deadmines.cpp rename : src/scripts/eastern_kingdoms/dun_morogh.cpp => src/server/scripts/eastern_kingdoms/dun_morogh.cpp rename : src/scripts/eastern_kingdoms/duskwood.cpp => src/server/scripts/eastern_kingdoms/duskwood.cpp rename : src/scripts/eastern_kingdoms/eastern_plaguelands.cpp => src/server/scripts/eastern_kingdoms/eastern_plaguelands.cpp rename : src/scripts/eastern_kingdoms/elwynn_forest.cpp => src/server/scripts/eastern_kingdoms/elwynn_forest.cpp rename : src/scripts/eastern_kingdoms/eversong_woods.cpp => src/server/scripts/eastern_kingdoms/eversong_woods.cpp rename : src/scripts/eastern_kingdoms/ghostlands.cpp => src/server/scripts/eastern_kingdoms/ghostlands.cpp rename : src/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp => src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.cpp rename : src/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h => src/server/scripts/eastern_kingdoms/gnomeregan/gnomeregan.h rename : src/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp => src/server/scripts/eastern_kingdoms/gnomeregan/instance_gnomeregan.cpp rename : src/scripts/eastern_kingdoms/hinterlands.cpp => src/server/scripts/eastern_kingdoms/hinterlands.cpp rename : src/scripts/eastern_kingdoms/ironforge.cpp => src/server/scripts/eastern_kingdoms/ironforge.cpp rename : src/scripts/eastern_kingdoms/isle_of_queldanas.cpp => src/server/scripts/eastern_kingdoms/isle_of_queldanas.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_curator.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_curator.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_maiden_of_virtue.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_midnight.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_moroes.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_netherspite.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_nightbane.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_prince_malchezaar.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_shade_of_aran.cpp rename : src/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp => src/server/scripts/eastern_kingdoms/karazhan/boss_terestian_illhoof.cpp rename : src/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp => src/server/scripts/eastern_kingdoms/karazhan/bosses_opera.cpp rename : src/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp => src/server/scripts/eastern_kingdoms/karazhan/instance_karazhan.cpp rename : src/scripts/eastern_kingdoms/karazhan/karazhan.cpp => src/server/scripts/eastern_kingdoms/karazhan/karazhan.cpp rename : src/scripts/eastern_kingdoms/karazhan/karazhan.h => src/server/scripts/eastern_kingdoms/karazhan/karazhan.h rename : src/scripts/eastern_kingdoms/loch_modan.cpp => src/server/scripts/eastern_kingdoms/loch_modan.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp => src/server/scripts/eastern_kingdoms/magisters_terrace/boss_felblood_kaelthas.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp => src/server/scripts/eastern_kingdoms/magisters_terrace/boss_priestess_delrissa.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp => src/server/scripts/eastern_kingdoms/magisters_terrace/boss_selin_fireheart.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp => src/server/scripts/eastern_kingdoms/magisters_terrace/boss_vexallus.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp => src/server/scripts/eastern_kingdoms/magisters_terrace/instance_magisters_terrace.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp => src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.cpp rename : src/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h => src/server/scripts/eastern_kingdoms/magisters_terrace/magisters_terrace.h rename : src/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_baron_geddon.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_garr.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_garr.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_gehennas.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_golemagg.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_lucifron.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_magmadar.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_majordomo_executus.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_ragnaros.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_shazzrah.cpp rename : src/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp => src/server/scripts/eastern_kingdoms/molten_core/boss_sulfuron_harbinger.cpp rename : src/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp => src/server/scripts/eastern_kingdoms/molten_core/instance_molten_core.cpp rename : src/scripts/eastern_kingdoms/molten_core/molten_core.cpp => src/server/scripts/eastern_kingdoms/molten_core/molten_core.cpp rename : src/scripts/eastern_kingdoms/molten_core/molten_core.h => src/server/scripts/eastern_kingdoms/molten_core/molten_core.h rename : src/scripts/eastern_kingdoms/redridge_mountains.cpp => src/server/scripts/eastern_kingdoms/redridge_mountains.cpp rename : src/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp => src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter1.cpp rename : src/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp => src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter2.cpp rename : src/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp => src/server/scripts/eastern_kingdoms/scarlet_enclave/chapter5.cpp rename : src/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp => src/server/scripts/eastern_kingdoms/scarlet_enclave/the_scarlet_enclave.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_arcanist_doan.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_azshir_the_sleepless.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_bloodmage_thalnos.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_headless_horseman.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_herod.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_high_inquisitor_fairbanks.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_houndmaster_loksey.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_interrogator_vishas.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_mograine_and_whitemane.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/boss_scorn.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp => src/server/scripts/eastern_kingdoms/scarlet_monastery/instance_scarlet_monastery.cpp rename : src/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h => src/server/scripts/eastern_kingdoms/scarlet_monastery/scarlet_monastery.h rename : src/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_darkmaster_gandling.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_death_knight_darkreaver.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_doctor_theolen_krastinov.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_illucia_barov.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_instructor_malicia.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_jandice_barov.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_kormok.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_lord_alexei_barov.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_lorekeeper_polkelt.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_ras_frostwhisper.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_the_ravenian.cpp rename : src/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp => src/server/scripts/eastern_kingdoms/scholomance/boss_vectus.cpp rename : src/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp => src/server/scripts/eastern_kingdoms/scholomance/instance_scholomance.cpp rename : src/scripts/eastern_kingdoms/scholomance/scholomance.h => src/server/scripts/eastern_kingdoms/scholomance/scholomance.h rename : src/scripts/eastern_kingdoms/searing_gorge.cpp => src/server/scripts/eastern_kingdoms/searing_gorge.cpp rename : src/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp => src/server/scripts/eastern_kingdoms/shadowfang_keep/instance_shadowfang_keep.cpp rename : src/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp => src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.cpp rename : src/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h => src/server/scripts/eastern_kingdoms/shadowfang_keep/shadowfang_keep.h rename : src/scripts/eastern_kingdoms/silvermoon_city.cpp => src/server/scripts/eastern_kingdoms/silvermoon_city.cpp rename : src/scripts/eastern_kingdoms/silverpine_forest.cpp => src/server/scripts/eastern_kingdoms/silverpine_forest.cpp rename : src/scripts/eastern_kingdoms/stormwind_city.cpp => src/server/scripts/eastern_kingdoms/stormwind_city.cpp rename : src/scripts/eastern_kingdoms/stranglethorn_vale.cpp => src/server/scripts/eastern_kingdoms/stranglethorn_vale.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_baron_rivendare.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_baroness_anastari.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_cannon_master_willey.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_dathrohan_balnazzar.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_magistrate_barthilas.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_maleki_the_pallid.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_nerubenkan.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_order_of_silver_hand.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_postmaster_malown.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_ramstein_the_gorger.cpp rename : src/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp => src/server/scripts/eastern_kingdoms/stratholme/boss_timmy_the_cruel.cpp rename : src/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp => src/server/scripts/eastern_kingdoms/stratholme/instance_stratholme.cpp rename : src/scripts/eastern_kingdoms/stratholme/stratholme.cpp => src/server/scripts/eastern_kingdoms/stratholme/stratholme.cpp rename : src/scripts/eastern_kingdoms/stratholme/stratholme.h => src/server/scripts/eastern_kingdoms/stratholme/stratholme.h rename : src/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp => src/server/scripts/eastern_kingdoms/sunken_temple/instance_sunken_temple.cpp rename : src/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp => src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.cpp rename : src/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h => src/server/scripts/eastern_kingdoms/sunken_temple/sunken_temple.h rename : src/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_brutallus.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_eredar_twins.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_felmyst.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kalecgos.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_kiljaeden.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/boss_muru.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/instance_sunwell_plateau.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp => src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.cpp rename : src/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h => src/server/scripts/eastern_kingdoms/sunwell_plateau/sunwell_plateau.h rename : src/scripts/eastern_kingdoms/tirisfal_glades.cpp => src/server/scripts/eastern_kingdoms/tirisfal_glades.cpp rename : src/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp => src/server/scripts/eastern_kingdoms/uldaman/boss_archaedas.cpp rename : src/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp => src/server/scripts/eastern_kingdoms/uldaman/boss_ironaya.cpp rename : src/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp => src/server/scripts/eastern_kingdoms/uldaman/instance_uldaman.cpp rename : src/scripts/eastern_kingdoms/uldaman/uldaman.cpp => src/server/scripts/eastern_kingdoms/uldaman/uldaman.cpp rename : src/scripts/eastern_kingdoms/undercity.cpp => src/server/scripts/eastern_kingdoms/undercity.cpp rename : src/scripts/eastern_kingdoms/western_plaguelands.cpp => src/server/scripts/eastern_kingdoms/western_plaguelands.cpp rename : src/scripts/eastern_kingdoms/westfall.cpp => src/server/scripts/eastern_kingdoms/westfall.cpp rename : src/scripts/eastern_kingdoms/wetlands.cpp => src/server/scripts/eastern_kingdoms/wetlands.cpp rename : src/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp => src/server/scripts/eastern_kingdoms/zulaman/boss_akilzon.cpp rename : src/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp => src/server/scripts/eastern_kingdoms/zulaman/boss_halazzi.cpp rename : src/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp => src/server/scripts/eastern_kingdoms/zulaman/boss_hexlord.cpp rename : src/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp => src/server/scripts/eastern_kingdoms/zulaman/boss_janalai.cpp rename : src/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp => src/server/scripts/eastern_kingdoms/zulaman/boss_nalorakk.cpp rename : src/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp => src/server/scripts/eastern_kingdoms/zulaman/boss_zuljin.cpp rename : src/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp => src/server/scripts/eastern_kingdoms/zulaman/instance_zulaman.cpp rename : src/scripts/eastern_kingdoms/zulaman/zulaman.cpp => src/server/scripts/eastern_kingdoms/zulaman/zulaman.cpp rename : src/scripts/eastern_kingdoms/zulaman/zulaman.h => src/server/scripts/eastern_kingdoms/zulaman/zulaman.h rename : src/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_arlokk.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_gahzranka.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_grilek.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_hakkar.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_hazzarah.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_jeklik.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_jindo.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_mandokir.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_marli.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_renataki.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_thekal.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_venoxis.cpp rename : src/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp => src/server/scripts/eastern_kingdoms/zulgurub/boss_wushoolay.cpp rename : src/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp => src/server/scripts/eastern_kingdoms/zulgurub/instance_zulgurub.cpp rename : src/scripts/eastern_kingdoms/zulgurub/zulgurub.h => src/server/scripts/eastern_kingdoms/zulgurub/zulgurub.h rename : src/scripts/examples/example_creature.cpp => src/server/scripts/examples/example_creature.cpp rename : src/scripts/examples/example_escort.cpp => src/server/scripts/examples/example_escort.cpp rename : src/scripts/examples/example_gossip_codebox.cpp => src/server/scripts/examples/example_gossip_codebox.cpp rename : src/scripts/examples/example_misc.cpp => src/server/scripts/examples/example_misc.cpp rename : src/scripts/kalimdor/ashenvale.cpp => src/server/scripts/kalimdor/ashenvale.cpp rename : src/scripts/kalimdor/azshara.cpp => src/server/scripts/kalimdor/azshara.cpp rename : src/scripts/kalimdor/azuremyst_isle.cpp => src/server/scripts/kalimdor/azuremyst_isle.cpp rename : src/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp => src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.cpp rename : src/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h => src/server/scripts/kalimdor/blackfathom_depths/blackfathom_deeps.h rename : src/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp => src/server/scripts/kalimdor/blackfathom_depths/boss_aku_mai.cpp rename : src/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp => src/server/scripts/kalimdor/blackfathom_depths/boss_gelihast.cpp rename : src/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp => src/server/scripts/kalimdor/blackfathom_depths/boss_kelris.cpp rename : src/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp => src/server/scripts/kalimdor/blackfathom_depths/instance_blackfathom_deeps.cpp rename : src/scripts/kalimdor/bloodmyst_isle.cpp => src/server/scripts/kalimdor/bloodmyst_isle.cpp rename : src/scripts/kalimdor/boss_azuregos.cpp => src/server/scripts/kalimdor/boss_azuregos.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_epoch.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_infinite.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_mal_ganis.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_meathook.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/boss_salramm.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.cpp rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/culling_of_stratholme.h rename : src/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp => src/server/scripts/kalimdor/caverns_of_time/culling_of_stratholme/instance_culling_of_stratholme.cpp rename : src/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp => src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_aeonus.cpp rename : src/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp => src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_chrono_lord_deja.cpp rename : src/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp => src/server/scripts/kalimdor/caverns_of_time/dark_portal/boss_temporus.cpp rename : src/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp => src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.cpp rename : src/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h => src/server/scripts/kalimdor/caverns_of_time/dark_portal/dark_portal.h rename : src/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp => src/server/scripts/kalimdor/caverns_of_time/dark_portal/instance_dark_portal.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_anetheron.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_archimonde.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_azgalor.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_kazrogal.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/boss_rage_winterchill.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h => src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal.h rename : src/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h => src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjalAI.h rename : src/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.cpp rename : src/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h => src/server/scripts/kalimdor/caverns_of_time/hyjal/hyjal_trash.h rename : src/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp => src/server/scripts/kalimdor/caverns_of_time/hyjal/instance_hyjal.cpp rename : src/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp => src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_captain_skarloc.cpp rename : src/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp => src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_epoch_hunter.cpp rename : src/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp => src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/boss_leutenant_drake.cpp rename : src/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp => src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/instance_old_hillsbrad.cpp rename : src/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp => src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.cpp rename : src/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h => src/server/scripts/kalimdor/caverns_of_time/old_hillsbrad/old_hillsbrad.h rename : src/scripts/kalimdor/darkshore.cpp => src/server/scripts/kalimdor/darkshore.cpp rename : src/scripts/kalimdor/desolace.cpp => src/server/scripts/kalimdor/desolace.cpp rename : src/scripts/kalimdor/durotar.cpp => src/server/scripts/kalimdor/durotar.cpp rename : src/scripts/kalimdor/dustwallow_marsh.cpp => src/server/scripts/kalimdor/dustwallow_marsh.cpp rename : src/scripts/kalimdor/felwood.cpp => src/server/scripts/kalimdor/felwood.cpp rename : src/scripts/kalimdor/feralas.cpp => src/server/scripts/kalimdor/feralas.cpp rename : src/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp => src/server/scripts/kalimdor/maraudon/boss_celebras_the_cursed.cpp rename : src/scripts/kalimdor/maraudon/boss_landslide.cpp => src/server/scripts/kalimdor/maraudon/boss_landslide.cpp rename : src/scripts/kalimdor/maraudon/boss_noxxion.cpp => src/server/scripts/kalimdor/maraudon/boss_noxxion.cpp rename : src/scripts/kalimdor/maraudon/boss_princess_theradras.cpp => src/server/scripts/kalimdor/maraudon/boss_princess_theradras.cpp rename : src/scripts/kalimdor/moonglade.cpp => src/server/scripts/kalimdor/moonglade.cpp rename : src/scripts/kalimdor/mulgore.cpp => src/server/scripts/kalimdor/mulgore.cpp rename : src/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp => src/server/scripts/kalimdor/onyxias_lair/boss_onyxia.cpp rename : src/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp => src/server/scripts/kalimdor/onyxias_lair/instance_onyxias_lair.cpp rename : src/scripts/kalimdor/onyxias_lair/onyxias_lair.h => src/server/scripts/kalimdor/onyxias_lair/onyxias_lair.h rename : src/scripts/kalimdor/orgrimmar.cpp => src/server/scripts/kalimdor/orgrimmar.cpp rename : src/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp => src/server/scripts/kalimdor/razorfen_downs/boss_amnennar_the_coldbringer.cpp rename : src/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp => src/server/scripts/kalimdor/razorfen_downs/instance_razorfen_downs.cpp rename : src/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp => src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.cpp rename : src/scripts/kalimdor/razorfen_downs/razorfen_downs.h => src/server/scripts/kalimdor/razorfen_downs/razorfen_downs.h rename : src/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp => src/server/scripts/kalimdor/razorfen_kraul/instance_razorfen_kraul.cpp rename : src/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp => src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.cpp rename : src/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h => src/server/scripts/kalimdor/razorfen_kraul/razorfen_kraul.h rename : src/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ayamiss.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_buru.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_kurinnaxx.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_moam.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_ossirian.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/boss_rajaxx.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp => src/server/scripts/kalimdor/ruins_of_ahnqiraj/instance_ruins_of_ahnqiraj.cpp rename : src/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h => src/server/scripts/kalimdor/ruins_of_ahnqiraj/ruins_of_ahnqiraj.h rename : src/scripts/kalimdor/silithus.cpp => src/server/scripts/kalimdor/silithus.cpp rename : src/scripts/kalimdor/stonetalon_mountains.cpp => src/server/scripts/kalimdor/stonetalon_mountains.cpp rename : src/scripts/kalimdor/tanaris.cpp => src/server/scripts/kalimdor/tanaris.cpp rename : src/scripts/kalimdor/teldrassil.cpp => src/server/scripts/kalimdor/teldrassil.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_bug_trio.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_cthun.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_fankriss.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_huhuran.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_ouro.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_sartura.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_skeram.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_twinemperors.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/boss_viscidus.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/instance_temple_of_ahnqiraj.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp => src/server/scripts/kalimdor/temple_of_ahnqiraj/mob_anubisath_sentinel.cpp rename : src/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h => src/server/scripts/kalimdor/temple_of_ahnqiraj/temple_of_ahnqiraj.h rename : src/scripts/kalimdor/the_barrens.cpp => src/server/scripts/kalimdor/the_barrens.cpp rename : src/scripts/kalimdor/thousand_needles.cpp => src/server/scripts/kalimdor/thousand_needles.cpp rename : src/scripts/kalimdor/thunder_bluff.cpp => src/server/scripts/kalimdor/thunder_bluff.cpp rename : src/scripts/kalimdor/ungoro_crater.cpp => src/server/scripts/kalimdor/ungoro_crater.cpp rename : src/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp => src/server/scripts/kalimdor/wailing_caverns/instance_wailing_caverns.cpp rename : src/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp => src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.cpp rename : src/scripts/kalimdor/wailing_caverns/wailing_caverns.h => src/server/scripts/kalimdor/wailing_caverns/wailing_caverns.h rename : src/scripts/kalimdor/winterspring.cpp => src/server/scripts/kalimdor/winterspring.cpp rename : src/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp => src/server/scripts/kalimdor/zulfarrak/instance_zulfarrak.cpp rename : src/scripts/kalimdor/zulfarrak/zulfarrak.cpp => src/server/scripts/kalimdor/zulfarrak/zulfarrak.cpp rename : src/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h => src/server/scripts/northrend/azjol_nerub/ahnkahet/ahnkahet.h rename : src/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp => src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_amanitar.cpp rename : src/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp => src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_elder_nadox.cpp rename : src/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp => src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_herald_volazj.cpp rename : src/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp => src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_jedoga_shadowseeker.cpp rename : src/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp => src/server/scripts/northrend/azjol_nerub/ahnkahet/boss_prince_taldaram.cpp rename : src/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp => src/server/scripts/northrend/azjol_nerub/ahnkahet/instance_ahnkahet.cpp rename : src/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h => src/server/scripts/northrend/azjol_nerub/azjol_nerub/azjol_nerub.h rename : src/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp => src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_anubarak.cpp rename : src/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp => src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_hadronox.cpp rename : src/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp => src/server/scripts/northrend/azjol_nerub/azjol_nerub/boss_krikthir_the_gatewatcher.cpp rename : src/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp => src/server/scripts/northrend/azjol_nerub/azjol_nerub/instance_azjol_nerub.cpp rename : src/scripts/northrend/borean_tundra.cpp => src/server/scripts/northrend/borean_tundra.cpp rename : src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp => src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_argent_challenge.cpp rename : src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp => src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_black_knight.cpp rename : src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp => src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/boss_grand_champions.cpp rename : src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp => src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/instance_trial_of_the_champion.cpp rename : src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp => src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.cpp rename : src/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h => src/server/scripts/northrend/crusaders_coliseum/trial_of_the_champion/trial_of_the_champion.h rename : src/scripts/northrend/crystalsong_forest.cpp => src/server/scripts/northrend/crystalsong_forest.cpp rename : src/scripts/northrend/dalaran.cpp => src/server/scripts/northrend/dalaran.cpp rename : src/scripts/northrend/dragonblight.cpp => src/server/scripts/northrend/dragonblight.cpp rename : src/scripts/northrend/draktharon_keep/boss_dred.cpp => src/server/scripts/northrend/draktharon_keep/boss_dred.cpp rename : src/scripts/northrend/draktharon_keep/boss_novos.cpp => src/server/scripts/northrend/draktharon_keep/boss_novos.cpp rename : src/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp => src/server/scripts/northrend/draktharon_keep/boss_tharon_ja.cpp rename : src/scripts/northrend/draktharon_keep/boss_trollgore.cpp => src/server/scripts/northrend/draktharon_keep/boss_trollgore.cpp rename : src/scripts/northrend/draktharon_keep/drak_tharon_keep.h => src/server/scripts/northrend/draktharon_keep/drak_tharon_keep.h rename : src/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp => src/server/scripts/northrend/draktharon_keep/instance_drak_tharon_keep.cpp rename : src/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp => src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_bronjahm.cpp rename : src/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp => src/server/scripts/northrend/frozen_halls/forge_of_souls/boss_devourer_of_souls.cpp rename : src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp => src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.cpp rename : src/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h => src/server/scripts/northrend/frozen_halls/forge_of_souls/forge_of_souls.h rename : src/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp => src/server/scripts/northrend/frozen_halls/forge_of_souls/instance_forge_of_souls.cpp rename : src/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp => src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_falric.cpp rename : src/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp => src/server/scripts/northrend/frozen_halls/halls_of_reflection/boss_marwyn.cpp rename : src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp => src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.cpp rename : src/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h => src/server/scripts/northrend/frozen_halls/halls_of_reflection/halls_of_reflection.h rename : src/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp => src/server/scripts/northrend/frozen_halls/halls_of_reflection/instance_halls_of_reflection.cpp rename : src/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp => src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_forgemaster_garfrost.cpp rename : src/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp => src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_krickandick.cpp rename : src/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp => src/server/scripts/northrend/frozen_halls/pit_of_saron/boss_scourgelord_tyrannus.cpp rename : src/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp => src/server/scripts/northrend/frozen_halls/pit_of_saron/instance_pit_of_saron.cpp rename : src/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp => src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.cpp rename : src/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h => src/server/scripts/northrend/frozen_halls/pit_of_saron/pit_of_saron.h rename : src/scripts/northrend/grizzly_hills.cpp => src/server/scripts/northrend/grizzly_hills.cpp rename : src/scripts/northrend/gundrak/boss_drakkari_colossus.cpp => src/server/scripts/northrend/gundrak/boss_drakkari_colossus.cpp rename : src/scripts/northrend/gundrak/boss_eck.cpp => src/server/scripts/northrend/gundrak/boss_eck.cpp rename : src/scripts/northrend/gundrak/boss_gal_darah.cpp => src/server/scripts/northrend/gundrak/boss_gal_darah.cpp rename : src/scripts/northrend/gundrak/boss_moorabi.cpp => src/server/scripts/northrend/gundrak/boss_moorabi.cpp rename : src/scripts/northrend/gundrak/boss_slad_ran.cpp => src/server/scripts/northrend/gundrak/boss_slad_ran.cpp rename : src/scripts/northrend/gundrak/gundrak.h => src/server/scripts/northrend/gundrak/gundrak.h rename : src/scripts/northrend/gundrak/instance_gundrak.cpp => src/server/scripts/northrend/gundrak/instance_gundrak.cpp rename : src/scripts/northrend/howling_fjord.cpp => src/server/scripts/northrend/howling_fjord.cpp rename : src/scripts/northrend/icecrown.cpp => src/server/scripts/northrend/icecrown.cpp rename : src/scripts/northrend/naxxramas/boss_anubrekhan.cpp => src/server/scripts/northrend/naxxramas/boss_anubrekhan.cpp rename : src/scripts/northrend/naxxramas/boss_faerlina.cpp => src/server/scripts/northrend/naxxramas/boss_faerlina.cpp rename : src/scripts/northrend/naxxramas/boss_four_horsemen.cpp => src/server/scripts/northrend/naxxramas/boss_four_horsemen.cpp rename : src/scripts/northrend/naxxramas/boss_gluth.cpp => src/server/scripts/northrend/naxxramas/boss_gluth.cpp rename : src/scripts/northrend/naxxramas/boss_gothik.cpp => src/server/scripts/northrend/naxxramas/boss_gothik.cpp rename : src/scripts/northrend/naxxramas/boss_grobbulus.cpp => src/server/scripts/northrend/naxxramas/boss_grobbulus.cpp rename : src/scripts/northrend/naxxramas/boss_heigan.cpp => src/server/scripts/northrend/naxxramas/boss_heigan.cpp rename : src/scripts/northrend/naxxramas/boss_highlord_mograine.cpp => src/server/scripts/northrend/naxxramas/boss_highlord_mograine.cpp rename : src/scripts/northrend/naxxramas/boss_kelthuzad.cpp => src/server/scripts/northrend/naxxramas/boss_kelthuzad.cpp rename : src/scripts/northrend/naxxramas/boss_loatheb.cpp => src/server/scripts/northrend/naxxramas/boss_loatheb.cpp rename : src/scripts/northrend/naxxramas/boss_maexxna.cpp => src/server/scripts/northrend/naxxramas/boss_maexxna.cpp rename : src/scripts/northrend/naxxramas/boss_noth.cpp => src/server/scripts/northrend/naxxramas/boss_noth.cpp rename : src/scripts/northrend/naxxramas/boss_patchwerk.cpp => src/server/scripts/northrend/naxxramas/boss_patchwerk.cpp rename : src/scripts/northrend/naxxramas/boss_razuvious.cpp => src/server/scripts/northrend/naxxramas/boss_razuvious.cpp rename : src/scripts/northrend/naxxramas/boss_sapphiron.cpp => src/server/scripts/northrend/naxxramas/boss_sapphiron.cpp rename : src/scripts/northrend/naxxramas/boss_thaddius.cpp => src/server/scripts/northrend/naxxramas/boss_thaddius.cpp rename : src/scripts/northrend/naxxramas/instance_naxxramas.cpp => src/server/scripts/northrend/naxxramas/instance_naxxramas.cpp rename : src/scripts/northrend/naxxramas/naxxramas.h => src/server/scripts/northrend/naxxramas/naxxramas.h rename : src/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp => src/server/scripts/northrend/nexus/eye_of_eternity/boss_malygos.cpp rename : src/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h => src/server/scripts/northrend/nexus/eye_of_eternity/eye_of_eternity.h rename : src/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp => src/server/scripts/northrend/nexus/eye_of_eternity/instance_eye_of_eternity.cpp rename : src/scripts/northrend/nexus/nexus/boss_anomalus.cpp => src/server/scripts/northrend/nexus/nexus/boss_anomalus.cpp rename : src/scripts/northrend/nexus/nexus/boss_keristrasza.cpp => src/server/scripts/northrend/nexus/nexus/boss_keristrasza.cpp rename : src/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp => src/server/scripts/northrend/nexus/nexus/boss_magus_telestra.cpp rename : src/scripts/northrend/nexus/nexus/boss_ormorok.cpp => src/server/scripts/northrend/nexus/nexus/boss_ormorok.cpp rename : src/scripts/northrend/nexus/nexus/commander_kolurg.cpp => src/server/scripts/northrend/nexus/nexus/commander_kolurg.cpp rename : src/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp => src/server/scripts/northrend/nexus/nexus/commander_stoutbeard.cpp rename : src/scripts/northrend/nexus/nexus/instance_nexus.cpp => src/server/scripts/northrend/nexus/nexus/instance_nexus.cpp rename : src/scripts/northrend/nexus/nexus/nexus.h => src/server/scripts/northrend/nexus/nexus/nexus.h rename : src/scripts/northrend/nexus/oculus/boss_drakos.cpp => src/server/scripts/northrend/nexus/oculus/boss_drakos.cpp rename : src/scripts/northrend/nexus/oculus/boss_eregos.cpp => src/server/scripts/northrend/nexus/oculus/boss_eregos.cpp rename : src/scripts/northrend/nexus/oculus/boss_urom.cpp => src/server/scripts/northrend/nexus/oculus/boss_urom.cpp rename : src/scripts/northrend/nexus/oculus/boss_varos.cpp => src/server/scripts/northrend/nexus/oculus/boss_varos.cpp rename : src/scripts/northrend/nexus/oculus/instance_oculus.cpp => src/server/scripts/northrend/nexus/oculus/instance_oculus.cpp rename : src/scripts/northrend/nexus/oculus/oculus.cpp => src/server/scripts/northrend/nexus/oculus/oculus.cpp rename : src/scripts/northrend/nexus/oculus/oculus.h => src/server/scripts/northrend/nexus/oculus/oculus.h rename : src/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp => src/server/scripts/northrend/obsidian_sanctum/boss_sartharion.cpp rename : src/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp => src/server/scripts/northrend/obsidian_sanctum/instance_obsidian_sanctum.cpp rename : src/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h => src/server/scripts/northrend/obsidian_sanctum/obsidian_sanctum.h rename : src/scripts/northrend/sholazar_basin.cpp => src/server/scripts/northrend/sholazar_basin.cpp rename : src/scripts/northrend/storm_peaks.cpp => src/server/scripts/northrend/storm_peaks.cpp rename : src/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp => src/server/scripts/northrend/ulduar/halls_of_lightning/boss_bjarngrim.cpp rename : src/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp => src/server/scripts/northrend/ulduar/halls_of_lightning/boss_ionar.cpp rename : src/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp => src/server/scripts/northrend/ulduar/halls_of_lightning/boss_loken.cpp rename : src/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp => src/server/scripts/northrend/ulduar/halls_of_lightning/boss_volkhan.cpp rename : src/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h => src/server/scripts/northrend/ulduar/halls_of_lightning/halls_of_lightning.h rename : src/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp => src/server/scripts/northrend/ulduar/halls_of_lightning/instance_halls_of_lightning.cpp rename : src/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp => src/server/scripts/northrend/ulduar/halls_of_stone/boss_krystallus.cpp rename : src/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp => src/server/scripts/northrend/ulduar/halls_of_stone/boss_maiden_of_grief.cpp rename : src/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp => src/server/scripts/northrend/ulduar/halls_of_stone/boss_sjonnir.cpp rename : src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp => src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.cpp rename : src/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h => src/server/scripts/northrend/ulduar/halls_of_stone/halls_of_stone.h rename : src/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp => src/server/scripts/northrend/ulduar/halls_of_stone/instance_halls_of_stone.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_algalon.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_algalon.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_assembly_of_iron.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_auriaya.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_flame_leviathan.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_freya.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_freya.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_general_vezax.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_hodir.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_hodir.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_ignis.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_ignis.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_kologarn.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_mimiron.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_razorscale.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_thorim.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_thorim.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_xt002.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_xt002.cpp rename : src/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp => src/server/scripts/northrend/ulduar/ulduar/boss_yoggsaron.cpp rename : src/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp => src/server/scripts/northrend/ulduar/ulduar/instance_ulduar.cpp rename : src/scripts/northrend/ulduar/ulduar/ulduar.h => src/server/scripts/northrend/ulduar/ulduar/ulduar.h rename : src/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp => src/server/scripts/northrend/ulduar/ulduar/ulduar_teleporter.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_ingvar_the_plunderer.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_keleseth.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_keep/boss_skarvald_dalronn.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_keep/instance_utgarde_keep.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h => src/server/scripts/northrend/utgarde_keep/utgarde_keep/utgarde_keep.h rename : src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_palehoof.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_skadi.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_svala.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/boss_ymiron.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp => src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/instance_pinnacle.cpp rename : src/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h => src/server/scripts/northrend/utgarde_keep/utgarde_pinnacle/utgarde_pinnacle.h rename : src/scripts/northrend/vault_of_archavon/boss_archavon.cpp => src/server/scripts/northrend/vault_of_archavon/boss_archavon.cpp rename : src/scripts/northrend/vault_of_archavon/boss_emalon.cpp => src/server/scripts/northrend/vault_of_archavon/boss_emalon.cpp rename : src/scripts/northrend/vault_of_archavon/boss_koralon.cpp => src/server/scripts/northrend/vault_of_archavon/boss_koralon.cpp rename : src/scripts/northrend/vault_of_archavon/boss_toravon.cpp => src/server/scripts/northrend/vault_of_archavon/boss_toravon.cpp rename : src/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp => src/server/scripts/northrend/vault_of_archavon/instance_vault_of_archavon.cpp rename : src/scripts/northrend/vault_of_archavon/vault_of_archavon.h => src/server/scripts/northrend/vault_of_archavon/vault_of_archavon.h rename : src/scripts/northrend/violet_hold/boss_cyanigosa.cpp => src/server/scripts/northrend/violet_hold/boss_cyanigosa.cpp rename : src/scripts/northrend/violet_hold/boss_erekem.cpp => src/server/scripts/northrend/violet_hold/boss_erekem.cpp rename : src/scripts/northrend/violet_hold/boss_ichoron.cpp => src/server/scripts/northrend/violet_hold/boss_ichoron.cpp rename : src/scripts/northrend/violet_hold/boss_lavanthor.cpp => src/server/scripts/northrend/violet_hold/boss_lavanthor.cpp rename : src/scripts/northrend/violet_hold/boss_moragg.cpp => src/server/scripts/northrend/violet_hold/boss_moragg.cpp rename : src/scripts/northrend/violet_hold/boss_xevozz.cpp => src/server/scripts/northrend/violet_hold/boss_xevozz.cpp rename : src/scripts/northrend/violet_hold/boss_zuramat.cpp => src/server/scripts/northrend/violet_hold/boss_zuramat.cpp rename : src/scripts/northrend/violet_hold/instance_violet_hold.cpp => src/server/scripts/northrend/violet_hold/instance_violet_hold.cpp rename : src/scripts/northrend/violet_hold/violet_hold.cpp => src/server/scripts/northrend/violet_hold/violet_hold.cpp rename : src/scripts/northrend/violet_hold/violet_hold.h => src/server/scripts/northrend/violet_hold/violet_hold.h rename : src/scripts/northrend/zuldrak.cpp => src/server/scripts/northrend/zuldrak.cpp rename : src/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp => src/server/scripts/outland/auchindoun/auchenai_crypts/boss_exarch_maladaar.cpp rename : src/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp => src/server/scripts/outland/auchindoun/auchenai_crypts/boss_shirrak_the_dead_watcher.cpp rename : src/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp => src/server/scripts/outland/auchindoun/mana_tombs/boss_nexusprince_shaffar.cpp rename : src/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp => src/server/scripts/outland/auchindoun/mana_tombs/boss_pandemonius.cpp rename : src/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp => src/server/scripts/outland/auchindoun/sethekk_halls/boss_darkweaver_syth.cpp rename : src/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp => src/server/scripts/outland/auchindoun/sethekk_halls/boss_tailonking_ikiss.cpp rename : src/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp => src/server/scripts/outland/auchindoun/sethekk_halls/instance_sethekk_halls.cpp rename : src/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h => src/server/scripts/outland/auchindoun/sethekk_halls/sethekk_halls.h rename : src/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp => src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_ambassador_hellmaw.cpp rename : src/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp => src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_blackheart_the_inciter.cpp rename : src/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp => src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_grandmaster_vorpil.cpp rename : src/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp => src/server/scripts/outland/auchindoun/shadow_labyrinth/boss_murmur.cpp rename : src/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp => src/server/scripts/outland/auchindoun/shadow_labyrinth/instance_shadow_labyrinth.cpp rename : src/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h => src/server/scripts/outland/auchindoun/shadow_labyrinth/shadow_labyrinth.h rename : src/scripts/outland/black_temple/black_temple.cpp => src/server/scripts/outland/black_temple/black_temple.cpp rename : src/scripts/outland/black_temple/black_temple.h => src/server/scripts/outland/black_temple/black_temple.h rename : src/scripts/outland/black_temple/boss_bloodboil.cpp => src/server/scripts/outland/black_temple/boss_bloodboil.cpp rename : src/scripts/outland/black_temple/boss_illidan.cpp => src/server/scripts/outland/black_temple/boss_illidan.cpp rename : src/scripts/outland/black_temple/boss_mother_shahraz.cpp => src/server/scripts/outland/black_temple/boss_mother_shahraz.cpp rename : src/scripts/outland/black_temple/boss_reliquary_of_souls.cpp => src/server/scripts/outland/black_temple/boss_reliquary_of_souls.cpp rename : src/scripts/outland/black_temple/boss_shade_of_akama.cpp => src/server/scripts/outland/black_temple/boss_shade_of_akama.cpp rename : src/scripts/outland/black_temple/boss_supremus.cpp => src/server/scripts/outland/black_temple/boss_supremus.cpp rename : src/scripts/outland/black_temple/boss_teron_gorefiend.cpp => src/server/scripts/outland/black_temple/boss_teron_gorefiend.cpp rename : src/scripts/outland/black_temple/boss_warlord_najentus.cpp => src/server/scripts/outland/black_temple/boss_warlord_najentus.cpp rename : src/scripts/outland/black_temple/illidari_council.cpp => src/server/scripts/outland/black_temple/illidari_council.cpp rename : src/scripts/outland/black_temple/instance_black_temple.cpp => src/server/scripts/outland/black_temple/instance_black_temple.cpp rename : src/scripts/outland/blades_edge_mountains.cpp => src/server/scripts/outland/blades_edge_mountains.cpp rename : src/scripts/outland/boss_doomlord_kazzak.cpp => src/server/scripts/outland/boss_doomlord_kazzak.cpp rename : src/scripts/outland/boss_doomwalker.cpp => src/server/scripts/outland/boss_doomwalker.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_fathomlord_karathress.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_hydross_the_unstable.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lady_vashj.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_leotheras_the_blind.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_lurker_below.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/boss_morogrim_tidewalker.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/instance_serpent_shrine.cpp rename : src/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h => src/server/scripts/outland/coilfang_resevoir/serpent_shrine/serpent_shrine.h rename : src/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp => src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_hydromancer_thespia.cpp rename : src/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp => src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_mekgineer_steamrigger.cpp rename : src/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp => src/server/scripts/outland/coilfang_resevoir/steam_vault/boss_warlord_kalithresh.cpp rename : src/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp => src/server/scripts/outland/coilfang_resevoir/steam_vault/instance_steam_vault.cpp rename : src/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h => src/server/scripts/outland/coilfang_resevoir/steam_vault/steam_vault.h rename : src/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp => src/server/scripts/outland/coilfang_resevoir/underbog/boss_hungarfen.cpp rename : src/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp => src/server/scripts/outland/coilfang_resevoir/underbog/boss_the_black_stalker.cpp rename : src/scripts/outland/gruuls_lair/boss_gruul.cpp => src/server/scripts/outland/gruuls_lair/boss_gruul.cpp rename : src/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp => src/server/scripts/outland/gruuls_lair/boss_high_king_maulgar.cpp rename : src/scripts/outland/gruuls_lair/gruuls_lair.h => src/server/scripts/outland/gruuls_lair/gruuls_lair.h rename : src/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp => src/server/scripts/outland/gruuls_lair/instance_gruuls_lair.cpp rename : src/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h => src/server/scripts/outland/hellfire_citadel/blood_furnace/blood_furnace.h rename : src/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp => src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_broggok.cpp rename : src/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp => src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_kelidan_the_breaker.cpp rename : src/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp => src/server/scripts/outland/hellfire_citadel/blood_furnace/boss_the_maker.cpp rename : src/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp => src/server/scripts/outland/hellfire_citadel/blood_furnace/instance_blood_furnace.cpp rename : src/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp => src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_omor_the_unscarred.cpp rename : src/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp => src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_vazruden_the_herald.cpp rename : src/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp => src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/boss_watchkeeper_gargolmar.cpp rename : src/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h => src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/hellfire_ramparts.h rename : src/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp => src/server/scripts/outland/hellfire_citadel/hellfire_ramparts/instance_hellfire_ramparts.cpp rename : src/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp => src/server/scripts/outland/hellfire_citadel/magtheridons_lair/boss_magtheridon.cpp rename : src/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp => src/server/scripts/outland/hellfire_citadel/magtheridons_lair/instance_magtheridons_lair.cpp rename : src/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h => src/server/scripts/outland/hellfire_citadel/magtheridons_lair/magtheridons_lair.h rename : src/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp => src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_nethekurse.cpp rename : src/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp => src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warbringer_omrogg.cpp rename : src/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp => src/server/scripts/outland/hellfire_citadel/shattered_halls/boss_warchief_kargath_bladefist.cpp rename : src/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp => src/server/scripts/outland/hellfire_citadel/shattered_halls/instance_shattered_halls.cpp rename : src/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h => src/server/scripts/outland/hellfire_citadel/shattered_halls/shattered_halls.h rename : src/scripts/outland/hellfire_peninsula.cpp => src/server/scripts/outland/hellfire_peninsula.cpp rename : src/scripts/outland/nagrand.cpp => src/server/scripts/outland/nagrand.cpp rename : src/scripts/outland/netherstorm.cpp => src/server/scripts/outland/netherstorm.cpp rename : src/scripts/outland/shadowmoon_valley.cpp => src/server/scripts/outland/shadowmoon_valley.cpp rename : src/scripts/outland/shattrath_city.cpp => src/server/scripts/outland/shattrath_city.cpp rename : src/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp => src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.cpp rename : src/scripts/outland/tempest_keep/arcatraz/arcatraz.h => src/server/scripts/outland/tempest_keep/arcatraz/arcatraz.h rename : src/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp => src/server/scripts/outland/tempest_keep/arcatraz/boss_harbinger_skyriss.cpp rename : src/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp => src/server/scripts/outland/tempest_keep/arcatraz/instance_arcatraz.cpp rename : src/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp => src/server/scripts/outland/tempest_keep/botanica/boss_high_botanist_freywinn.cpp rename : src/scripts/outland/tempest_keep/botanica/boss_laj.cpp => src/server/scripts/outland/tempest_keep/botanica/boss_laj.cpp rename : src/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp => src/server/scripts/outland/tempest_keep/botanica/boss_warp_splinter.cpp rename : src/scripts/outland/tempest_keep/the_eye/boss_alar.cpp => src/server/scripts/outland/tempest_keep/the_eye/boss_alar.cpp rename : src/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp => src/server/scripts/outland/tempest_keep/the_eye/boss_astromancer.cpp rename : src/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp => src/server/scripts/outland/tempest_keep/the_eye/boss_kaelthas.cpp rename : src/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp => src/server/scripts/outland/tempest_keep/the_eye/boss_void_reaver.cpp rename : src/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp => src/server/scripts/outland/tempest_keep/the_eye/instance_the_eye.cpp rename : src/scripts/outland/tempest_keep/the_eye/the_eye.cpp => src/server/scripts/outland/tempest_keep/the_eye/the_eye.cpp rename : src/scripts/outland/tempest_keep/the_eye/the_eye.h => src/server/scripts/outland/tempest_keep/the_eye/the_eye.h rename : src/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp => src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_gyrokill.cpp rename : src/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp => src/server/scripts/outland/tempest_keep/the_mechanar/boss_gatewatcher_ironhand.cpp rename : src/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp => src/server/scripts/outland/tempest_keep/the_mechanar/boss_nethermancer_sepethrea.cpp rename : src/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp => src/server/scripts/outland/tempest_keep/the_mechanar/boss_pathaleon_the_calculator.cpp rename : src/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp => src/server/scripts/outland/tempest_keep/the_mechanar/instance_mechanar.cpp rename : src/scripts/outland/tempest_keep/the_mechanar/mechanar.h => src/server/scripts/outland/tempest_keep/the_mechanar/mechanar.h rename : src/scripts/outland/terokkar_forest.cpp => src/server/scripts/outland/terokkar_forest.cpp rename : src/scripts/outland/zangarmarsh.cpp => src/server/scripts/outland/zangarmarsh.cpp rename : src/scripts/world/areatrigger_scripts.cpp => src/server/scripts/world/areatrigger_scripts.cpp rename : src/scripts/world/boss_emeriss.cpp => src/server/scripts/world/boss_emeriss.cpp rename : src/scripts/world/boss_lethon.cpp => src/server/scripts/world/boss_lethon.cpp rename : src/scripts/world/boss_taerar.cpp => src/server/scripts/world/boss_taerar.cpp rename : src/scripts/world/boss_ysondre.cpp => src/server/scripts/world/boss_ysondre.cpp rename : src/scripts/world/go_scripts.cpp => src/server/scripts/world/go_scripts.cpp rename : src/scripts/world/guards.cpp => src/server/scripts/world/guards.cpp rename : src/scripts/world/item_scripts.cpp => src/server/scripts/world/item_scripts.cpp rename : src/scripts/world/mob_generic_creature.cpp => src/server/scripts/world/mob_generic_creature.cpp rename : src/scripts/world/npc_innkeeper.cpp => src/server/scripts/world/npc_innkeeper.cpp rename : src/scripts/world/npc_professions.cpp => src/server/scripts/world/npc_professions.cpp rename : src/scripts/world/npc_taxi.cpp => src/server/scripts/world/npc_taxi.cpp rename : src/scripts/world/npcs_special.cpp => src/server/scripts/world/npcs_special.cpp rename : src/shared/Auth/AuthCrypt.cpp => src/server/shared/Auth/AuthCrypt.cpp rename : src/shared/Auth/AuthCrypt.h => src/server/shared/Auth/AuthCrypt.h rename : src/shared/Auth/BigNumber.cpp => src/server/shared/Auth/BigNumber.cpp rename : src/shared/Auth/BigNumber.h => src/server/shared/Auth/BigNumber.h rename : src/shared/Auth/CMakeLists.txt => src/server/shared/Auth/CMakeLists.txt rename : src/shared/Auth/Hmac.cpp => src/server/shared/Auth/Hmac.cpp rename : src/shared/Auth/Hmac.h => src/server/shared/Auth/Hmac.h rename : src/shared/Auth/SARC4.cpp => src/server/shared/Auth/SARC4.cpp rename : src/shared/Auth/SARC4.h => src/server/shared/Auth/SARC4.h rename : src/shared/Auth/Sha1.cpp => src/server/shared/Auth/Sha1.cpp rename : src/shared/Auth/Sha1.h => src/server/shared/Auth/Sha1.h rename : src/shared/Auth/md5.c => src/server/shared/Auth/md5.c rename : src/shared/Auth/md5.h => src/server/shared/Auth/md5.h rename : src/shared/ByteBuffer.h => src/server/shared/ByteBuffer.h rename : src/shared/CMakeLists.txt => src/server/shared/CMakeLists.txt rename : src/shared/Common.cpp => src/server/shared/Common.cpp rename : src/shared/Common.h => src/server/shared/Common.h rename : src/shared/Config/CMakeLists.txt => src/server/shared/Config/CMakeLists.txt rename : src/shared/Config/Config.cpp => src/server/shared/Config/Config.cpp rename : src/shared/Config/Config.h => src/server/shared/Config/Config.h rename : src/shared/Config/ConfigEnv.h => src/server/shared/Config/ConfigEnv.h rename : src/shared/Config/ConfigLibrary.vcproj => src/server/shared/Config/ConfigLibrary.vcproj rename : src/shared/Config/dotconfpp/dotconfpp.cpp => src/server/shared/Config/dotconfpp/dotconfpp.cpp rename : src/shared/Config/dotconfpp/dotconfpp.h => src/server/shared/Config/dotconfpp/dotconfpp.h rename : src/shared/Config/dotconfpp/mempool.cpp => src/server/shared/Config/dotconfpp/mempool.cpp rename : src/shared/Config/dotconfpp/mempool.h => src/server/shared/Config/dotconfpp/mempool.h rename : src/shared/Database/CMakeLists.txt => src/server/shared/Database/CMakeLists.txt rename : src/shared/Database/DBCFileLoader.cpp => src/server/shared/Database/DBCFileLoader.cpp rename : src/shared/Database/DBCFileLoader.h => src/server/shared/Database/DBCFileLoader.h rename : src/shared/Database/DBCStore.h => src/server/shared/Database/DBCStore.h rename : src/shared/Database/Database.cpp => src/server/shared/Database/Database.cpp rename : src/shared/Database/Database.h => src/server/shared/Database/Database.h rename : src/shared/Database/DatabaseEnv.h => src/server/shared/Database/DatabaseEnv.h rename : src/shared/Database/DatabaseImpl.h => src/server/shared/Database/DatabaseImpl.h rename : src/shared/Database/Field.cpp => src/server/shared/Database/Field.cpp rename : src/shared/Database/Field.h => src/server/shared/Database/Field.h rename : src/shared/Database/QueryResult.cpp => src/server/shared/Database/QueryResult.cpp rename : src/shared/Database/QueryResult.h => src/server/shared/Database/QueryResult.h rename : src/shared/Database/SQLStorage.cpp => src/server/shared/Database/SQLStorage.cpp rename : src/shared/Database/SQLStorage.h => src/server/shared/Database/SQLStorage.h rename : src/shared/Database/SQLStorageImpl.h => src/server/shared/Database/SQLStorageImpl.h rename : src/shared/Database/SqlDelayThread.cpp => src/server/shared/Database/SqlDelayThread.cpp rename : src/shared/Database/SqlDelayThread.h => src/server/shared/Database/SqlDelayThread.h rename : src/shared/Database/SqlOperations.cpp => src/server/shared/Database/SqlOperations.cpp rename : src/shared/Database/SqlOperations.h => src/server/shared/Database/SqlOperations.h rename : src/shared/DelayExecutor.cpp => src/server/shared/DelayExecutor.cpp rename : src/shared/DelayExecutor.h => src/server/shared/DelayExecutor.h rename : src/shared/Errors.h => src/server/shared/Errors.h rename : src/shared/LockedQueue.h => src/server/shared/LockedQueue.h rename : src/shared/Log.cpp => src/server/shared/Log.cpp rename : src/shared/Log.h => src/server/shared/Log.h rename : src/shared/MemoryLeaks.cpp => src/server/shared/MemoryLeaks.cpp rename : src/shared/MemoryLeaks.h => src/server/shared/MemoryLeaks.h rename : src/shared/PacketLog.cpp => src/server/shared/PacketLog.cpp rename : src/shared/PacketLog.h => src/server/shared/PacketLog.h rename : src/shared/ProgressBar.cpp => src/server/shared/ProgressBar.cpp rename : src/shared/ProgressBar.h => src/server/shared/ProgressBar.h rename : src/shared/ServiceWin32.cpp => src/server/shared/ServiceWin32.cpp rename : src/shared/ServiceWin32.h => src/server/shared/ServiceWin32.h rename : src/shared/SignalHandler.h => src/server/shared/SignalHandler.h rename : src/shared/SystemConfig.h => src/server/shared/SystemConfig.h rename : src/shared/Threading.cpp => src/server/shared/Threading.cpp rename : src/shared/Threading.h => src/server/shared/Threading.h rename : src/shared/Timer.h => src/server/shared/Timer.h rename : src/shared/Util.cpp => src/server/shared/Util.cpp rename : src/shared/Util.h => src/server/shared/Util.h rename : src/shared/WheatyExceptionReport.cpp => src/server/shared/WheatyExceptionReport.cpp rename : src/shared/WheatyExceptionReport.h => src/server/shared/WheatyExceptionReport.h rename : src/shared/WorldPacket.h => src/server/shared/WorldPacket.h rename : src/shared/vmap/BIH.cpp => src/server/shared/vmap/BIH.cpp rename : src/shared/vmap/BIH.h => src/server/shared/vmap/BIH.h rename : src/shared/vmap/CMakeLists.txt => src/server/shared/vmap/CMakeLists.txt rename : src/shared/vmap/IVMapManager.h => src/server/shared/vmap/IVMapManager.h rename : src/shared/vmap/MapTree.cpp => src/server/shared/vmap/MapTree.cpp rename : src/shared/vmap/MapTree.h => src/server/shared/vmap/MapTree.h rename : src/shared/vmap/ModelInstance.cpp => src/server/shared/vmap/ModelInstance.cpp rename : src/shared/vmap/ModelInstance.h => src/server/shared/vmap/ModelInstance.h rename : src/shared/vmap/TileAssembler.cpp => src/server/shared/vmap/TileAssembler.cpp rename : src/shared/vmap/TileAssembler.h => src/server/shared/vmap/TileAssembler.h rename : src/shared/vmap/VMapDefinitions.h => src/server/shared/vmap/VMapDefinitions.h rename : src/shared/vmap/VMapFactory.cpp => src/server/shared/vmap/VMapFactory.cpp rename : src/shared/vmap/VMapFactory.h => src/server/shared/vmap/VMapFactory.h rename : src/shared/vmap/VMapManager2.cpp => src/server/shared/vmap/VMapManager2.cpp rename : src/shared/vmap/VMapManager2.h => src/server/shared/vmap/VMapManager2.h rename : src/shared/vmap/VMapTools.h => src/server/shared/vmap/VMapTools.h rename : src/shared/vmap/WorldModel.cpp => src/server/shared/vmap/WorldModel.cpp rename : src/shared/vmap/WorldModel.h => src/server/shared/vmap/WorldModel.h rename : src/trinitycore/CMakeLists.txt => src/server/trinitycore/CMakeLists.txt rename : src/trinitycore/CliRunnable.cpp => src/server/trinitycore/CliRunnable.cpp rename : src/trinitycore/CliRunnable.h => src/server/trinitycore/CliRunnable.h rename : src/trinitycore/Main.cpp => src/server/trinitycore/Main.cpp rename : src/trinitycore/Master.cpp => src/server/trinitycore/Master.cpp rename : src/trinitycore/Master.h => src/server/trinitycore/Master.h rename : src/trinitycore/RASocket.cpp => src/server/trinitycore/RASocket.cpp rename : src/trinitycore/RASocket.h => src/server/trinitycore/RASocket.h rename : src/trinitycore/TrinityCore.ico => src/server/trinitycore/TrinityCore.ico rename : src/trinitycore/TrinityCore.rc => src/server/trinitycore/TrinityCore.rc rename : src/trinitycore/WorldRunnable.cpp => src/server/trinitycore/WorldRunnable.cpp rename : src/trinitycore/WorldRunnable.h => src/server/trinitycore/WorldRunnable.h rename : src/trinitycore/resource.h => src/server/trinitycore/resource.h rename : src/trinitycore/trinitycore.conf.dist => src/server/trinitycore/trinitycore.conf.dist rename : src/trinityrealm/AuthCodes.cpp => src/server/trinityrealm/AuthCodes.cpp rename : src/trinityrealm/AuthCodes.h => src/server/trinityrealm/AuthCodes.h rename : src/trinityrealm/AuthSocket.cpp => src/server/trinityrealm/AuthSocket.cpp rename : src/trinityrealm/AuthSocket.h => src/server/trinityrealm/AuthSocket.h rename : src/trinityrealm/CMakeLists.txt => src/server/trinityrealm/CMakeLists.txt rename : src/trinityrealm/Main.cpp => src/server/trinityrealm/Main.cpp rename : src/trinityrealm/RealmAcceptor.h => src/server/trinityrealm/RealmAcceptor.h rename : src/trinityrealm/RealmList.cpp => src/server/trinityrealm/RealmList.cpp rename : src/trinityrealm/RealmList.h => src/server/trinityrealm/RealmList.h rename : src/trinityrealm/RealmSocket.cpp => src/server/trinityrealm/RealmSocket.cpp rename : src/trinityrealm/RealmSocket.h => src/server/trinityrealm/RealmSocket.h rename : src/trinityrealm/TrinityRealm.ico => src/server/trinityrealm/TrinityRealm.ico rename : src/trinityrealm/TrinityRealm.rc => src/server/trinityrealm/TrinityRealm.rc rename : src/trinityrealm/resource.h => src/server/trinityrealm/resource.h rename : src/trinityrealm/trinityrealm.conf.dist => src/server/trinityrealm/trinityrealm.conf.dist
Diffstat (limited to 'src/server/shared')
-rw-r--r--src/server/shared/Auth/AuthCrypt.cpp81
-rw-r--r--src/server/shared/Auth/AuthCrypt.h47
-rw-r--r--src/server/shared/Auth/BigNumber.cpp201
-rw-r--r--src/server/shared/Auth/BigNumber.h96
-rw-r--r--src/server/shared/Auth/CMakeLists.txt27
-rw-r--r--src/server/shared/Auth/Hmac.cpp62
-rw-r--r--src/server/shared/Auth/Hmac.h49
-rw-r--r--src/server/shared/Auth/SARC4.cpp52
-rw-r--r--src/server/shared/Auth/SARC4.h36
-rw-r--r--src/server/shared/Auth/Sha1.cpp69
-rw-r--r--src/server/shared/Auth/Sha1.h53
-rw-r--r--src/server/shared/Auth/md5.c385
-rw-r--r--src/server/shared/Auth/md5.h92
-rw-r--r--src/server/shared/ByteBuffer.h601
-rw-r--r--src/server/shared/CMakeLists.txt42
-rw-r--r--src/server/shared/Common.cpp43
-rw-r--r--src/server/shared/Common.h216
-rw-r--r--src/server/shared/Config/CMakeLists.txt22
-rw-r--r--src/server/shared/Config/Config.cpp105
-rw-r--r--src/server/shared/Config/Config.h53
-rw-r--r--src/server/shared/Config/ConfigEnv.h30
-rw-r--r--src/server/shared/Config/ConfigLibrary.vcproj137
-rw-r--r--src/server/shared/Config/dotconfpp/dotconfpp.cpp599
-rw-r--r--src/server/shared/Config/dotconfpp/dotconfpp.h97
-rw-r--r--src/server/shared/Config/dotconfpp/mempool.cpp100
-rw-r--r--src/server/shared/Config/dotconfpp/mempool.h46
-rw-r--r--src/server/shared/Database/CMakeLists.txt30
-rw-r--r--src/server/shared/Database/DBCFileLoader.cpp270
-rw-r--r--src/server/shared/Database/DBCFileLoader.h110
-rw-r--r--src/server/shared/Database/DBCStore.h265
-rw-r--r--src/server/shared/Database/Database.cpp657
-rw-r--r--src/server/shared/Database/Database.h155
-rw-r--r--src/server/shared/Database/DatabaseEnv.h43
-rw-r--r--src/server/shared/Database/DatabaseImpl.h234
-rw-r--r--src/server/shared/Database/Field.cpp77
-rw-r--r--src/server/shared/Database/Field.h89
-rw-r--r--src/server/shared/Database/QueryResult.cpp105
-rw-r--r--src/server/shared/Database/QueryResult.h102
-rw-r--r--src/server/shared/Database/SQLStorage.cpp77
-rw-r--r--src/server/shared/Database/SQLStorage.h118
-rw-r--r--src/server/shared/Database/SQLStorageImpl.h210
-rw-r--r--src/server/shared/Database/SqlDelayThread.cpp61
-rw-r--r--src/server/shared/Database/SqlDelayThread.h50
-rw-r--r--src/server/shared/Database/SqlOperations.cpp209
-rw-r--r--src/server/shared/Database/SqlOperations.h168
-rw-r--r--src/server/shared/DelayExecutor.cpp111
-rw-r--r--src/server/shared/DelayExecutor.h37
-rw-r--r--src/server/shared/Errors.h48
-rw-r--r--src/server/shared/LockedQueue.h139
-rw-r--r--src/server/shared/Log.cpp1005
-rw-r--r--src/server/shared/Log.h190
-rw-r--r--src/server/shared/MemoryLeaks.cpp32
-rw-r--r--src/server/shared/MemoryLeaks.h48
-rw-r--r--src/server/shared/PacketLog.cpp160
-rw-r--r--src/server/shared/PacketLog.h49
-rw-r--r--src/server/shared/ProgressBar.cpp85
-rw-r--r--src/server/shared/ProgressBar.h42
-rw-r--r--src/server/shared/ServiceWin32.cpp263
-rw-r--r--src/server/shared/ServiceWin32.h31
-rw-r--r--src/server/shared/SignalHandler.h43
-rw-r--r--src/server/shared/SystemConfig.h54
-rw-r--r--src/server/shared/Threading.cpp232
-rw-r--r--src/server/shared/Threading.h108
-rw-r--r--src/server/shared/Timer.h215
-rw-r--r--src/server/shared/Util.cpp468
-rw-r--r--src/server/shared/Util.h536
-rw-r--r--src/server/shared/WheatyExceptionReport.cpp1013
-rw-r--r--src/server/shared/WheatyExceptionReport.h118
-rw-r--r--src/server/shared/WorldPacket.h54
-rw-r--r--src/server/shared/vmap/BIH.cpp304
-rw-r--r--src/server/shared/vmap/BIH.h391
-rw-r--r--src/server/shared/vmap/CMakeLists.txt30
-rw-r--r--src/server/shared/vmap/IVMapManager.h106
-rw-r--r--src/server/shared/vmap/MapTree.cpp450
-rw-r--r--src/server/shared/vmap/MapTree.h97
-rw-r--r--src/server/shared/vmap/ModelInstance.cpp219
-rw-r--r--src/server/shared/vmap/ModelInstance.h81
-rw-r--r--src/server/shared/vmap/TileAssembler.cpp494
-rw-r--r--src/server/shared/vmap/TileAssembler.h89
-rw-r--r--src/server/shared/vmap/VMapDefinitions.h42
-rw-r--r--src/server/shared/vmap/VMapFactory.cpp136
-rw-r--r--src/server/shared/vmap/VMapFactory.h43
-rw-r--r--src/server/shared/vmap/VMapManager2.cpp336
-rw-r--r--src/server/shared/vmap/VMapManager2.h114
-rw-r--r--src/server/shared/vmap/VMapTools.h150
-rw-r--r--src/server/shared/vmap/WorldModel.cpp535
-rw-r--r--src/server/shared/vmap/WorldModel.h123
87 files changed, 15192 insertions, 0 deletions
diff --git a/src/server/shared/Auth/AuthCrypt.cpp b/src/server/shared/Auth/AuthCrypt.cpp
new file mode 100644
index 00000000000..b34b922b16a
--- /dev/null
+++ b/src/server/shared/Auth/AuthCrypt.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "AuthCrypt.h"
+#include "Hmac.h"
+#include "Log.h"
+#include "BigNumber.h"
+
+AuthCrypt::AuthCrypt() : _clientDecrypt(SHA_DIGEST_LENGTH), _serverEncrypt(SHA_DIGEST_LENGTH)
+{
+ _initialized = false;
+}
+
+AuthCrypt::~AuthCrypt()
+{
+
+}
+
+void AuthCrypt::Init(BigNumber *K)
+{
+ uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
+ HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey);
+ uint8 *encryptHash = serverEncryptHmac.ComputeHash(K);
+
+ uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
+ HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey);
+ uint8 *decryptHash = clientDecryptHmac.ComputeHash(K);
+
+ //SARC4 _serverDecrypt(encryptHash);
+ _clientDecrypt.Init(decryptHash);
+ _serverEncrypt.Init(encryptHash);
+ //SARC4 _clientEncrypt(decryptHash);
+
+ uint8 syncBuf[1024];
+
+ memset(syncBuf, 0, 1024);
+
+ _serverEncrypt.UpdateData(1024, syncBuf);
+ //_clientEncrypt.UpdateData(1024, syncBuf);
+
+ memset(syncBuf, 0, 1024);
+
+ //_serverDecrypt.UpdateData(1024, syncBuf);
+ _clientDecrypt.UpdateData(1024, syncBuf);
+
+ _initialized = true;
+}
+
+void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
+{
+ if (!_initialized)
+ return;
+
+ _clientDecrypt.UpdateData(len, data);
+}
+
+void AuthCrypt::EncryptSend(uint8 *data, size_t len)
+{
+ if (!_initialized)
+ return;
+
+ _serverEncrypt.UpdateData(len, data);
+}
+
diff --git a/src/server/shared/Auth/AuthCrypt.h b/src/server/shared/Auth/AuthCrypt.h
new file mode 100644
index 00000000000..6695dc580cc
--- /dev/null
+++ b/src/server/shared/Auth/AuthCrypt.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AUTHCRYPT_H
+#define _AUTHCRYPT_H
+
+#include <Common.h>
+#include "SARC4.h"
+
+class BigNumber;
+
+class AuthCrypt
+{
+ public:
+ AuthCrypt();
+ ~AuthCrypt();
+
+ void Init(BigNumber *K);
+ void DecryptRecv(uint8 *, size_t);
+ void EncryptSend(uint8 *, size_t);
+
+ bool IsInitialized() { return _initialized; }
+
+ private:
+ SARC4 _clientDecrypt;
+ SARC4 _serverEncrypt;
+ bool _initialized;
+};
+#endif
+
diff --git a/src/server/shared/Auth/BigNumber.cpp b/src/server/shared/Auth/BigNumber.cpp
new file mode 100644
index 00000000000..64e9ef21ccc
--- /dev/null
+++ b/src/server/shared/Auth/BigNumber.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Auth/BigNumber.h"
+#include <openssl/bn.h>
+#include <algorithm>
+
+BigNumber::BigNumber()
+{
+ _bn = BN_new();
+ _array = NULL;
+}
+
+BigNumber::BigNumber(const BigNumber &bn)
+{
+ _bn = BN_dup(bn._bn);
+ _array = NULL;
+}
+
+BigNumber::BigNumber(uint32 val)
+{
+ _bn = BN_new();
+ BN_set_word(_bn, val);
+ _array = NULL;
+}
+
+BigNumber::~BigNumber()
+{
+ BN_free(_bn);
+ if(_array) delete[] _array;
+}
+
+void BigNumber::SetDword(uint32 val)
+{
+ BN_set_word(_bn, val);
+}
+
+void BigNumber::SetQword(uint64 val)
+{
+ BN_add_word(_bn, (uint32)(val >> 32));
+ BN_lshift(_bn, _bn, 32);
+ BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF));
+}
+
+void BigNumber::SetBinary(const uint8 *bytes, int len)
+{
+ uint8 t[1000];
+ for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i];
+ BN_bin2bn(t, len, _bn);
+}
+
+void BigNumber::SetHexStr(const char *str)
+{
+ BN_hex2bn(&_bn, str);
+}
+
+void BigNumber::SetRand(int numbits)
+{
+ BN_rand(_bn, numbits, 0, 1);
+}
+
+BigNumber BigNumber::operator=(const BigNumber &bn)
+{
+ BN_copy(_bn, bn._bn);
+ return *this;
+}
+
+BigNumber BigNumber::operator+=(const BigNumber &bn)
+{
+ BN_add(_bn, _bn, bn._bn);
+ return *this;
+}
+
+BigNumber BigNumber::operator-=(const BigNumber &bn)
+{
+ BN_sub(_bn, _bn, bn._bn);
+ return *this;
+}
+
+BigNumber BigNumber::operator*=(const BigNumber &bn)
+{
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ BN_mul(_bn, _bn, bn._bn, bnctx);
+ BN_CTX_free(bnctx);
+
+ return *this;
+}
+
+BigNumber BigNumber::operator/=(const BigNumber &bn)
+{
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ BN_div(_bn, NULL, _bn, bn._bn, bnctx);
+ BN_CTX_free(bnctx);
+
+ return *this;
+}
+
+BigNumber BigNumber::operator%=(const BigNumber &bn)
+{
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ BN_mod(_bn, _bn, bn._bn, bnctx);
+ BN_CTX_free(bnctx);
+
+ return *this;
+}
+
+BigNumber BigNumber::Exp(const BigNumber &bn)
+{
+ BigNumber ret;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ BN_exp(ret._bn, _bn, bn._bn, bnctx);
+ BN_CTX_free(bnctx);
+
+ return ret;
+}
+
+BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2)
+{
+ BigNumber ret;
+ BN_CTX *bnctx;
+
+ bnctx = BN_CTX_new();
+ BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
+ BN_CTX_free(bnctx);
+
+ return ret;
+}
+
+int BigNumber::GetNumBytes(void)
+{
+ return BN_num_bytes(_bn);
+}
+
+uint32 BigNumber::AsDword()
+{
+ return (uint32)BN_get_word(_bn);
+}
+
+bool BigNumber::isZero() const
+{
+ return BN_is_zero(_bn)!=0;
+}
+
+uint8 *BigNumber::AsByteArray(int minSize, bool reverse)
+{
+ int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();
+
+ if (_array)
+ {
+ delete[] _array;
+ _array = NULL;
+ }
+ _array = new uint8[length];
+
+ // If we need more bytes than length of BigNumber set the rest to 0
+ if (length > GetNumBytes())
+ memset((void*)_array, 0, length);
+
+ BN_bn2bin(_bn, (unsigned char *)_array);
+
+ if (reverse)
+ std::reverse(_array, _array + length);
+
+ return _array;
+}
+
+const char *BigNumber::AsHexStr()
+{
+ return BN_bn2hex(_bn);
+}
+
+const char *BigNumber::AsDecStr()
+{
+ return BN_bn2dec(_bn);
+}
+
diff --git a/src/server/shared/Auth/BigNumber.h b/src/server/shared/Auth/BigNumber.h
new file mode 100644
index 00000000000..1dd43c83fc7
--- /dev/null
+++ b/src/server/shared/Auth/BigNumber.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AUTH_BIGNUMBER_H
+#define _AUTH_BIGNUMBER_H
+
+#include "Common.h"
+
+struct bignum_st;
+
+class BigNumber
+{
+ public:
+ BigNumber();
+ BigNumber(const BigNumber &bn);
+ BigNumber(uint32);
+ ~BigNumber();
+
+ void SetDword(uint32);
+ void SetQword(uint64);
+ void SetBinary(const uint8 *bytes, int len);
+ void SetHexStr(const char *str);
+
+ void SetRand(int numbits);
+
+ BigNumber operator=(const BigNumber &bn);
+
+ BigNumber operator+=(const BigNumber &bn);
+ BigNumber operator+(const BigNumber &bn)
+ {
+ BigNumber t(*this);
+ return t += bn;
+ }
+ BigNumber operator-=(const BigNumber &bn);
+ BigNumber operator-(const BigNumber &bn)
+ {
+ BigNumber t(*this);
+ return t -= bn;
+ }
+ BigNumber operator*=(const BigNumber &bn);
+ BigNumber operator*(const BigNumber &bn)
+ {
+ BigNumber t(*this);
+ return t *= bn;
+ }
+ BigNumber operator/=(const BigNumber &bn);
+ BigNumber operator/(const BigNumber &bn)
+ {
+ BigNumber t(*this);
+ return t /= bn;
+ }
+ BigNumber operator%=(const BigNumber &bn);
+ BigNumber operator%(const BigNumber &bn)
+ {
+ BigNumber t(*this);
+ return t %= bn;
+ }
+
+ bool isZero() const;
+
+ BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2);
+ BigNumber Exp(const BigNumber &);
+
+ int GetNumBytes(void);
+
+ struct bignum_st *BN() { return _bn; }
+
+ uint32 AsDword();
+ uint8* AsByteArray(int minSize = 0, bool reverse = true);
+
+ const char *AsHexStr();
+ const char *AsDecStr();
+
+ private:
+ struct bignum_st *_bn;
+ uint8 *_array;
+};
+#endif
+
diff --git a/src/server/shared/Auth/CMakeLists.txt b/src/server/shared/Auth/CMakeLists.txt
new file mode 100644
index 00000000000..c843a6b0f35
--- /dev/null
+++ b/src/server/shared/Auth/CMakeLists.txt
@@ -0,0 +1,27 @@
+
+########### next target ###############
+
+SET(trinityauth_STAT_SRCS
+ AuthCrypt.cpp
+ AuthCrypt.h
+ BigNumber.cpp
+ BigNumber.h
+ Hmac.cpp
+ Hmac.h
+ Sha1.cpp
+ Sha1.h
+ md5.c
+ md5.h
+ SARC4.cpp
+ SARC4.h
+)
+
+include_directories(
+ ${ACE_INCLUDE_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/src/shared
+ ${CMAKE_SOURCE_DIR}/src/framework
+ ${MYSQL_INCLUDE_DIR}
+)
+
+add_library(trinityauth STATIC ${trinityauth_STAT_SRCS})
diff --git a/src/server/shared/Auth/Hmac.cpp b/src/server/shared/Auth/Hmac.cpp
new file mode 100644
index 00000000000..a30f1b2d1e2
--- /dev/null
+++ b/src/server/shared/Auth/Hmac.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Auth/Hmac.h"
+#include "BigNumber.h"
+
+HmacHash::HmacHash(uint32 len, uint8 *seed)
+{
+ HMAC_CTX_init(&m_ctx);
+ HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL);
+}
+
+HmacHash::~HmacHash()
+{
+ HMAC_CTX_cleanup(&m_ctx);
+}
+
+void HmacHash::UpdateBigNumber(BigNumber *bn)
+{
+ UpdateData(bn->AsByteArray(), bn->GetNumBytes());
+}
+
+void HmacHash::UpdateData(const uint8 *data, int length)
+{
+ HMAC_Update(&m_ctx, data, length);
+}
+
+void HmacHash::UpdateData(const std::string &str)
+{
+ UpdateData((uint8 const*)str.c_str(), str.length());
+}
+
+void HmacHash::Finalize()
+{
+ uint32 length = 0;
+ HMAC_Final(&m_ctx, (uint8*)m_digest, &length);
+ ASSERT(length == SHA_DIGEST_LENGTH)
+}
+
+uint8 *HmacHash::ComputeHash(BigNumber *bn)
+{
+ HMAC_Update(&m_ctx, bn->AsByteArray(), bn->GetNumBytes());
+ Finalize();
+ return (uint8*)m_digest;
+}
diff --git a/src/server/shared/Auth/Hmac.h b/src/server/shared/Auth/Hmac.h
new file mode 100644
index 00000000000..845d6e84802
--- /dev/null
+++ b/src/server/shared/Auth/Hmac.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AUTH_HMAC_H
+#define _AUTH_HMAC_H
+
+#include "Common.h"
+#include <openssl/hmac.h>
+#include <openssl/sha.h>
+
+class BigNumber;
+
+#define SEED_KEY_SIZE 16
+
+class HmacHash
+{
+ public:
+ HmacHash(uint32 len, uint8 *seed);
+ ~HmacHash();
+ void UpdateBigNumber(BigNumber *bn);
+ void UpdateData(const uint8 *data, int length);
+ void UpdateData(const std::string &str);
+ void Finalize();
+ uint8 *ComputeHash(BigNumber *bn);
+ uint8 *GetDigest() { return (uint8*)m_digest; }
+ int GetLength() { return SHA_DIGEST_LENGTH; }
+ private:
+ HMAC_CTX m_ctx;
+ uint8 m_digest[SHA_DIGEST_LENGTH];
+};
+#endif
+
diff --git a/src/server/shared/Auth/SARC4.cpp b/src/server/shared/Auth/SARC4.cpp
new file mode 100644
index 00000000000..80cad4991e9
--- /dev/null
+++ b/src/server/shared/Auth/SARC4.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Auth/SARC4.h"
+#include <openssl/sha.h>
+
+SARC4::SARC4(uint8 len)
+{
+ EVP_CIPHER_CTX_init(&m_ctx);
+ EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL);
+ EVP_CIPHER_CTX_set_key_length(&m_ctx, len);
+}
+
+SARC4::SARC4(uint8 *seed, uint8 len)
+{
+ EVP_CIPHER_CTX_init(&m_ctx);
+ EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL);
+ EVP_CIPHER_CTX_set_key_length(&m_ctx, len);
+ EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL);
+}
+
+SARC4::~SARC4()
+{
+ EVP_CIPHER_CTX_cleanup(&m_ctx);
+}
+
+void SARC4::Init(uint8 *seed)
+{
+ EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL);
+}
+
+void SARC4::UpdateData(int len, uint8 *data)
+{
+ int outlen = 0;
+ EVP_EncryptUpdate(&m_ctx, data, &outlen, data, len);
+ EVP_EncryptFinal_ex(&m_ctx, data, &outlen);
+}
diff --git a/src/server/shared/Auth/SARC4.h b/src/server/shared/Auth/SARC4.h
new file mode 100644
index 00000000000..2e408627fc8
--- /dev/null
+++ b/src/server/shared/Auth/SARC4.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AUTH_SARC4_H
+#define _AUTH_SARC4_H
+
+#include "Common.h"
+#include <openssl/evp.h>
+
+class SARC4
+{
+ public:
+ SARC4(uint8 len);
+ SARC4(uint8 *seed, uint8 len);
+ ~SARC4();
+ void Init(uint8 *seed);
+ void UpdateData(int len, uint8 *data);
+ private:
+ EVP_CIPHER_CTX m_ctx;
+};
+#endif
diff --git a/src/server/shared/Auth/Sha1.cpp b/src/server/shared/Auth/Sha1.cpp
new file mode 100644
index 00000000000..b63deb2c5f3
--- /dev/null
+++ b/src/server/shared/Auth/Sha1.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Auth/Sha1.h"
+#include "Auth/BigNumber.h"
+#include <stdarg.h>
+
+Sha1Hash::Sha1Hash()
+{
+ SHA1_Init(&mC);
+}
+
+Sha1Hash::~Sha1Hash()
+{
+ SHA1_Init(&mC);
+}
+
+void Sha1Hash::UpdateData(const uint8 *dta, int len)
+{
+ SHA1_Update(&mC, dta, len);
+}
+
+void Sha1Hash::UpdateData(const std::string &str)
+{
+ UpdateData((uint8 const*)str.c_str(), str.length());
+}
+
+void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...)
+{
+ va_list v;
+ BigNumber *bn;
+
+ va_start(v, bn0);
+ bn = bn0;
+ while (bn)
+ {
+ UpdateData(bn->AsByteArray(), bn->GetNumBytes());
+ bn = va_arg(v, BigNumber *);
+ }
+ va_end(v);
+}
+
+void Sha1Hash::Initialize()
+{
+ SHA1_Init(&mC);
+}
+
+void Sha1Hash::Finalize(void)
+{
+ SHA1_Final(mDigest, &mC);
+}
+
diff --git a/src/server/shared/Auth/Sha1.h b/src/server/shared/Auth/Sha1.h
new file mode 100644
index 00000000000..2d7f361ae9a
--- /dev/null
+++ b/src/server/shared/Auth/Sha1.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _AUTH_SHA1_H
+#define _AUTH_SHA1_H
+
+#include "Common.h"
+#include <openssl/sha.h>
+#include <openssl/crypto.h>
+
+class BigNumber;
+
+class Sha1Hash
+{
+ public:
+ Sha1Hash();
+ ~Sha1Hash();
+
+ void UpdateFinalizeBigNumbers(BigNumber *bn0, ...);
+ void UpdateBigNumbers(BigNumber *bn0, ...);
+
+ void UpdateData(const uint8 *dta, int len);
+ void UpdateData(const std::string &str);
+
+ void Initialize();
+ void Finalize();
+
+ uint8 *GetDigest(void) { return mDigest; };
+ int GetLength(void) { return SHA_DIGEST_LENGTH; };
+
+ private:
+ SHA_CTX mC;
+ uint8 mDigest[SHA_DIGEST_LENGTH];
+};
+#endif
+
diff --git a/src/server/shared/Auth/md5.c b/src/server/shared/Auth/md5.c
new file mode 100644
index 00000000000..3e9735e2dbb
--- /dev/null
+++ b/src/server/shared/Auth/md5.c
@@ -0,0 +1,385 @@
+/*
+ Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+L. Peter Deutsch
+ghost@aladdin.com
+
+*/
+/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+The original and principal author of md5.c is L. Peter Deutsch
+<ghost@aladdin.com>. Other authors are noted in the change history
+that follows (in reverse chronological order):
+
+2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+either statically or dynamically; added missing #include <string.h>
+in library.
+2002-03-11 lpd Corrected argument list for main(), and added int return
+type, in test program and T value program.
+2002-02-21 lpd Added missing #include <stdio.h> in test program.
+2000-07-03 lpd Patched to eliminate warnings about "constant is
+unsigned in ANSI C, signed in traditional"; made test program
+self-checking.
+1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+1999-05-03 lpd Original version.
+*/
+
+#include "md5.h"
+#include <string.h>
+
+#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+# define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3 0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6 0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9 0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13 0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16 0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19 0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22 0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25 0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28 0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31 0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35 0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38 0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41 0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44 0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47 0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50 0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53 0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57 0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60 0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63 0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+ md5_word_t
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
+ md5_word_t t;
+ #if BYTE_ORDER > 0
+ /* Define storage only for big-endian CPUs. */
+ md5_word_t X[16];
+ #else
+ /* Define storage for little-endian or both types of CPUs. */
+ md5_word_t xbuf[16];
+ const md5_word_t *X;
+ #endif
+
+ {
+ #if BYTE_ORDER == 0
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+ #endif
+ #if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3))
+ {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ }
+ else
+ {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
+ #endif
+ #if BYTE_ORDER == 0
+ else /* dynamic big-endian */
+ #endif
+ #if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
+
+ # if BYTE_ORDER == 0
+ X = xbuf; /* (dynamic only) */
+ # else
+ # define xbuf X /* (static only) */
+ # endif
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
+ #endif
+ }
+
+ #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+ /* Round 1. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+ #define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+ #define SET(a, b, c, d, k, s, Ti)\
+ t = a + F(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 7, T1);
+ SET(d, a, b, c, 1, 12, T2);
+ SET(c, d, a, b, 2, 17, T3);
+ SET(b, c, d, a, 3, 22, T4);
+ SET(a, b, c, d, 4, 7, T5);
+ SET(d, a, b, c, 5, 12, T6);
+ SET(c, d, a, b, 6, 17, T7);
+ SET(b, c, d, a, 7, 22, T8);
+ SET(a, b, c, d, 8, 7, T9);
+ SET(d, a, b, c, 9, 12, T10);
+ SET(c, d, a, b, 10, 17, T11);
+ SET(b, c, d, a, 11, 22, T12);
+ SET(a, b, c, d, 12, 7, T13);
+ SET(d, a, b, c, 13, 12, T14);
+ SET(c, d, a, b, 14, 17, T15);
+ SET(b, c, d, a, 15, 22, T16);
+ #undef SET
+
+ /* Round 2. */
+ /* Let [abcd k s i] denote the operation
+ a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+ #define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+ #define SET(a, b, c, d, k, s, Ti)\
+ t = a + G(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 1, 5, T17);
+ SET(d, a, b, c, 6, 9, T18);
+ SET(c, d, a, b, 11, 14, T19);
+ SET(b, c, d, a, 0, 20, T20);
+ SET(a, b, c, d, 5, 5, T21);
+ SET(d, a, b, c, 10, 9, T22);
+ SET(c, d, a, b, 15, 14, T23);
+ SET(b, c, d, a, 4, 20, T24);
+ SET(a, b, c, d, 9, 5, T25);
+ SET(d, a, b, c, 14, 9, T26);
+ SET(c, d, a, b, 3, 14, T27);
+ SET(b, c, d, a, 8, 20, T28);
+ SET(a, b, c, d, 13, 5, T29);
+ SET(d, a, b, c, 2, 9, T30);
+ SET(c, d, a, b, 7, 14, T31);
+ SET(b, c, d, a, 12, 20, T32);
+ #undef SET
+
+ /* Round 3. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+ #define H(x, y, z) ((x) ^ (y) ^ (z))
+ #define SET(a, b, c, d, k, s, Ti)\
+ t = a + H(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 5, 4, T33);
+ SET(d, a, b, c, 8, 11, T34);
+ SET(c, d, a, b, 11, 16, T35);
+ SET(b, c, d, a, 14, 23, T36);
+ SET(a, b, c, d, 1, 4, T37);
+ SET(d, a, b, c, 4, 11, T38);
+ SET(c, d, a, b, 7, 16, T39);
+ SET(b, c, d, a, 10, 23, T40);
+ SET(a, b, c, d, 13, 4, T41);
+ SET(d, a, b, c, 0, 11, T42);
+ SET(c, d, a, b, 3, 16, T43);
+ SET(b, c, d, a, 6, 23, T44);
+ SET(a, b, c, d, 9, 4, T45);
+ SET(d, a, b, c, 12, 11, T46);
+ SET(c, d, a, b, 15, 16, T47);
+ SET(b, c, d, a, 2, 23, T48);
+ #undef SET
+
+ /* Round 4. */
+ /* Let [abcd k s t] denote the operation
+ a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+ #define I(x, y, z) ((y) ^ ((x) | ~(z)))
+ #define SET(a, b, c, d, k, s, Ti)\
+ t = a + I(b,c,d) + X[k] + Ti;\
+ a = ROTATE_LEFT(t, s) + b
+ /* Do the following 16 operations. */
+ SET(a, b, c, d, 0, 6, T49);
+ SET(d, a, b, c, 7, 10, T50);
+ SET(c, d, a, b, 14, 15, T51);
+ SET(b, c, d, a, 5, 21, T52);
+ SET(a, b, c, d, 12, 6, T53);
+ SET(d, a, b, c, 3, 10, T54);
+ SET(c, d, a, b, 10, 15, T55);
+ SET(b, c, d, a, 1, 21, T56);
+ SET(a, b, c, d, 8, 6, T57);
+ SET(d, a, b, c, 15, 10, T58);
+ SET(c, d, a, b, 6, 15, T59);
+ SET(b, c, d, a, 13, 21, T60);
+ SET(a, b, c, d, 4, 6, T61);
+ SET(d, a, b, c, 11, 10, T62);
+ SET(c, d, a, b, 2, 15, T63);
+ SET(b, c, d, a, 9, 21, T64);
+ #undef SET
+
+ /* Then perform the following additions. (That is increment each
+ of the four registers by the value it had before this block
+ was started.) */
+ pms->abcd[0] += a;
+ pms->abcd[1] += b;
+ pms->abcd[2] += c;
+ pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+ pms->count[0] = pms->count[1] = 0;
+ pms->abcd[0] = 0x67452301;
+ pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+ pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+ pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+ const md5_byte_t *p = data;
+ int left = nbytes;
+ int offset = (pms->count[0] >> 3) & 63;
+ md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+ if (nbytes <= 0)
+ return;
+
+ /* Update the message length. */
+ pms->count[1] += nbytes >> 29;
+ pms->count[0] += nbits;
+ if (pms->count[0] < nbits)
+ ++pms->count[1];
+
+ /* Process an initial partial block. */
+ if (offset)
+ {
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
+ }
+
+ /* Process full blocks. */
+ for (; left >= 64; p += 64, left -= 64)
+ md5_process(pms, p);
+
+ /* Process a final partial block. */
+ if (left)
+ memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+ static const md5_byte_t pad[64] =
+ {
+ 0x80, 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
+ };
+ md5_byte_t data[8];
+ int i;
+
+ /* Save the length before padding. */
+ for (i = 0; i < 8; ++i)
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ /* Pad to 56 bytes mod 64. */
+ md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+ /* Append the length. */
+ md5_append(pms, data, 8);
+ for (i = 0; i < 16; ++i)
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/src/server/shared/Auth/md5.h b/src/server/shared/Auth/md5.h
new file mode 100644
index 00000000000..0463051b6a6
--- /dev/null
+++ b/src/server/shared/Auth/md5.h
@@ -0,0 +1,92 @@
+/*
+ Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+1. The origin of this software must not be misrepresented; you must not
+claim that you wrote the original software. If you use this software
+in a product, an acknowledgment in the product documentation would be
+appreciated but is not required.
+2. Altered source versions must be plainly marked as such, and must not be
+misrepresented as being the original software.
+3. This notice may not be removed or altered from any source distribution.
+
+L. Peter Deutsch
+ghost@aladdin.com
+
+*/
+/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
+/*
+ Independent implementation of MD5 (RFC 1321).
+
+ This code implements the MD5 Algorithm defined in RFC 1321, whose
+ text is available at
+ http://www.ietf.org/rfc/rfc1321.txt
+ The code is derived from the text of the RFC, including the test suite
+ (section A.5) but excluding the rest of Appendix A. It does not include
+ any code or documentation that is identified in the RFC as being
+ copyrighted.
+
+The original and principal author of md5.h is L. Peter Deutsch
+<ghost@aladdin.com>. Other authors are noted in the change history
+that follows (in reverse chronological order):
+
+2002-04-13 lpd Removed support for non-ANSI compilers; removed
+references to Ghostscript; clarified derivation from RFC 1321;
+now handles byte order either statically or dynamically.
+1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+added conditionalization for C++ compilation from Martin
+Purschke <purschke@bnl.gov>.
+1999-05-03 lpd Original version.
+*/
+
+#ifndef md5_INCLUDED
+# define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s
+{
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C"
+{
+ #endif
+
+ /* Initialize the algorithm. */
+ void md5_init(md5_state_t *pms);
+
+ /* Append a string to the message. */
+ void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+ /* Finish the message and return the digest. */
+ void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+ #ifdef __cplusplus
+} /* end extern "C" */
+#endif
+#endif /* md5_INCLUDED */
+
diff --git a/src/server/shared/ByteBuffer.h b/src/server/shared/ByteBuffer.h
new file mode 100644
index 00000000000..ba0240fb58b
--- /dev/null
+++ b/src/server/shared/ByteBuffer.h
@@ -0,0 +1,601 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _BYTEBUFFER_H
+#define _BYTEBUFFER_H
+
+#include "Common.h"
+#include "Errors.h"
+#include "Log.h"
+#include "Utilities/ByteConverter.h"
+
+class ByteBufferException
+{
+ public:
+ ByteBufferException(bool _add, size_t _pos, size_t _esize, size_t _size)
+ : add(_add), pos(_pos), esize(_esize), size(_size)
+ {
+ PrintPosError();
+ }
+
+ void PrintPosError() const
+ {
+ sLog.outError("ERROR: Attempted to %s in ByteBuffer (pos: " SIZEFMTD " size: "SIZEFMTD") value with size: " SIZEFMTD,
+ (add ? "put" : "get"), pos, size, esize);
+ }
+ private:
+ bool add;
+ size_t pos;
+ size_t esize;
+ size_t size;
+};
+
+class ByteBuffer
+{
+ public:
+ const static size_t DEFAULT_SIZE = 0x1000;
+
+ // constructor
+ ByteBuffer(): _rpos(0), _wpos(0)
+ {
+ _storage.reserve(DEFAULT_SIZE);
+ }
+
+ // constructor
+ ByteBuffer(size_t res): _rpos(0), _wpos(0)
+ {
+ _storage.reserve(res);
+ }
+
+ // copy constructor
+ ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { }
+
+ void clear()
+ {
+ _storage.clear();
+ _rpos = _wpos = 0;
+ }
+
+ template <typename T> void append(T value)
+ {
+ EndianConvert(value);
+ append((uint8 *)&value, sizeof(value));
+ }
+
+ template <typename T> void put(size_t pos,T value)
+ {
+ EndianConvert(value);
+ put(pos,(uint8 *)&value,sizeof(value));
+ }
+
+ ByteBuffer &operator<<(uint8 value)
+ {
+ append<uint8>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(uint16 value)
+ {
+ append<uint16>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(uint32 value)
+ {
+ append<uint32>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(uint64 value)
+ {
+ append<uint64>(value);
+ return *this;
+ }
+
+ // signed as in 2e complement
+ ByteBuffer &operator<<(int8 value)
+ {
+ append<int8>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(int16 value)
+ {
+ append<int16>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(int32 value)
+ {
+ append<int32>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(int64 value)
+ {
+ append<int64>(value);
+ return *this;
+ }
+
+ // floating points
+ ByteBuffer &operator<<(float value)
+ {
+ append<float>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(double value)
+ {
+ append<double>(value);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(const std::string &value)
+ {
+ append((uint8 const *)value.c_str(), value.length());
+ append((uint8)0);
+ return *this;
+ }
+
+ ByteBuffer &operator<<(const char *str)
+ {
+ append((uint8 const *)str, str ? strlen(str) : 0);
+ append((uint8)0);
+ return *this;
+ }
+
+ ByteBuffer &operator>>(bool &value)
+ {
+ value = read<char>() > 0 ? true : false;
+ return *this;
+ }
+
+ ByteBuffer &operator>>(uint8 &value)
+ {
+ value = read<uint8>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(uint16 &value)
+ {
+ value = read<uint16>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(uint32 &value)
+ {
+ value = read<uint32>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(uint64 &value)
+ {
+ value = read<uint64>();
+ return *this;
+ }
+
+ //signed as in 2e complement
+ ByteBuffer &operator>>(int8 &value)
+ {
+ value = read<int8>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(int16 &value)
+ {
+ value = read<int16>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(int32 &value)
+ {
+ value = read<int32>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(int64 &value)
+ {
+ value = read<int64>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(float &value)
+ {
+ value = read<float>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(double &value)
+ {
+ value = read<double>();
+ return *this;
+ }
+
+ ByteBuffer &operator>>(std::string& value)
+ {
+ value.clear();
+ while (rpos() < size()) // prevent crash at wrong string format in packet
+ {
+ char c = read<char>();
+ if (c == 0)
+ break;
+ value += c;
+ }
+ return *this;
+ }
+
+ uint8 operator[](size_t pos) const
+ {
+ return read<uint8>(pos);
+ }
+
+ size_t rpos() const { return _rpos; }
+
+ size_t rpos(size_t rpos_)
+ {
+ _rpos = rpos_;
+ return _rpos;
+ }
+
+ size_t wpos() const { return _wpos; }
+
+ size_t wpos(size_t wpos_)
+ {
+ _wpos = wpos_;
+ return _wpos;
+ }
+
+ template<typename T>
+ void read_skip() { read_skip(sizeof(T)); }
+
+ void read_skip(size_t skip)
+ {
+ if(_rpos + skip > size())
+ throw ByteBufferException(false, _rpos, skip, size());
+ _rpos += skip;
+ }
+
+ template <typename T> T read()
+ {
+ T r = read<T>(_rpos);
+ _rpos += sizeof(T);
+ return r;
+ }
+
+ template <typename T> T read(size_t pos) const
+ {
+ if(pos + sizeof(T) > size())
+ throw ByteBufferException(false, pos, sizeof(T), size());
+ T val = *((T const*)&_storage[pos]);
+ EndianConvert(val);
+ return val;
+ }
+
+ void read(uint8 *dest, size_t len)
+ {
+ if(_rpos + len > size())
+ throw ByteBufferException(false, _rpos, len, size());
+ memcpy(dest, &_storage[_rpos], len);
+ _rpos += len;
+ }
+
+ bool readPackGUID(uint64& guid)
+ {
+ if(rpos() + 1 > size())
+ return false;
+
+ guid = 0;
+
+ uint8 guidmark = 0;
+ (*this) >> guidmark;
+
+ for (int i = 0; i < 8; ++i)
+ {
+ if(guidmark & (uint8(1) << i))
+ {
+ if(rpos() + 1 > size())
+ return false;
+
+ uint8 bit;
+ (*this) >> bit;
+ guid |= (uint64(bit) << (i * 8));
+ }
+ }
+
+ return true;
+ }
+
+ const uint8 *contents() const { return &_storage[0]; }
+
+ size_t size() const { return _storage.size(); }
+ bool empty() const { return _storage.empty(); }
+
+ void resize(size_t newsize)
+ {
+ _storage.resize(newsize);
+ _rpos = 0;
+ _wpos = size();
+ }
+
+ void reserve(size_t ressize)
+ {
+ if (ressize > size())
+ _storage.reserve(ressize);
+ }
+
+ void append(const std::string& str)
+ {
+ append((uint8 const*)str.c_str(), str.size() + 1);
+ }
+
+ void append(const char *src, size_t cnt)
+ {
+ return append((const uint8 *)src, cnt);
+ }
+
+ template<class T> void append(const T *src, size_t cnt)
+ {
+ return append((const uint8 *)src, cnt * sizeof(T));
+ }
+
+ void append(const uint8 *src, size_t cnt)
+ {
+ if (!cnt)
+ return;
+
+ ASSERT(size() < 10000000);
+
+ if (_storage.size() < _wpos + cnt)
+ _storage.resize(_wpos + cnt);
+ memcpy(&_storage[_wpos], src, cnt);
+ _wpos += cnt;
+ }
+
+ void append(const ByteBuffer& buffer)
+ {
+ if(buffer.wpos())
+ append(buffer.contents(), buffer.wpos());
+ }
+
+ // can be used in SMSG_MONSTER_MOVE opcode
+ void appendPackXYZ(float x, float y, float z)
+ {
+ uint32 packed = 0;
+ packed |= ((int)(x / 0.25f) & 0x7FF);
+ packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
+ packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
+ *this << packed;
+ }
+
+ void appendPackGUID(uint64 guid)
+ {
+ uint8 packGUID[8+1];
+ packGUID[0] = 0;
+ size_t size = 1;
+ for(uint8 i = 0;guid != 0;++i)
+ {
+ if(guid & 0xFF)
+ {
+ packGUID[0] |= uint8(1 << i);
+ packGUID[size] = uint8(guid & 0xFF);
+ ++size;
+ }
+
+ guid >>= 8;
+ }
+ append(packGUID, size);
+ }
+
+ void put(size_t pos, const uint8 *src, size_t cnt)
+ {
+ if(pos + cnt > size())
+ throw ByteBufferException(true, pos, cnt, size());
+ memcpy(&_storage[pos], src, cnt);
+ }
+
+ void print_storage() const
+ {
+ if(!sLog.IsOutDebug()) // optimize disabled debug output
+ return;
+
+ sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
+ for (uint32 i = 0; i < size(); ++i)
+ sLog.outDebugInLine("%u - ", read<uint8>(i) );
+ sLog.outDebug(" ");
+ }
+
+ void textlike() const
+ {
+ if(!sLog.IsOutDebug()) // optimize disabled debug output
+ return;
+
+ sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
+ for (uint32 i = 0; i < size(); ++i)
+ sLog.outDebugInLine("%c", read<uint8>(i) );
+ sLog.outDebug(" ");
+ }
+
+ void hexlike() const
+ {
+ if(!sLog.IsOutDebug()) // optimize disabled debug output
+ return;
+
+ uint32 j = 1, k = 1;
+ sLog.outDebug("STORAGE_SIZE: %lu", (unsigned long)size() );
+
+ for (uint32 i = 0; i < size(); ++i)
+ {
+ if ((i == (j * 8)) && ((i != (k * 16))))
+ {
+ if (read<uint8>(i) < 0x10)
+ {
+ sLog.outDebugInLine("| 0%X ", read<uint8>(i) );
+ }
+ else
+ {
+ sLog.outDebugInLine("| %X ", read<uint8>(i) );
+ }
+ ++j;
+ }
+ else if (i == (k * 16))
+ {
+ if (read<uint8>(i) < 0x10)
+ {
+ sLog.outDebugInLine("\n");
+
+ sLog.outDebugInLine("0%X ", read<uint8>(i) );
+ }
+ else
+ {
+ sLog.outDebugInLine("\n");
+
+ sLog.outDebugInLine("%X ", read<uint8>(i) );
+ }
+
+ ++k;
+ ++j;
+ }
+ else
+ {
+ if (read<uint8>(i) < 0x10)
+ {
+ sLog.outDebugInLine("0%X ", read<uint8>(i) );
+ }
+ else
+ {
+ sLog.outDebugInLine("%X ", read<uint8>(i) );
+ }
+ }
+ }
+ sLog.outDebugInLine("\n");
+ }
+
+ protected:
+ size_t _rpos, _wpos;
+ std::vector<uint8> _storage;
+};
+
+template <typename T>
+inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
+{
+ b << (uint32)v.size();
+ for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
+ {
+ b << *i;
+ }
+ return b;
+}
+
+template <typename T>
+inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
+{
+ uint32 vsize;
+ b >> vsize;
+ v.clear();
+ while(vsize--)
+ {
+ T t;
+ b >> t;
+ v.push_back(t);
+ }
+ return b;
+}
+
+template <typename T>
+inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
+{
+ b << (uint32)v.size();
+ for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
+ {
+ b << *i;
+ }
+ return b;
+}
+
+template <typename T>
+inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
+{
+ uint32 vsize;
+ b >> vsize;
+ v.clear();
+ while(vsize--)
+ {
+ T t;
+ b >> t;
+ v.push_back(t);
+ }
+ return b;
+}
+
+template <typename K, typename V>
+inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
+{
+ b << (uint32)m.size();
+ for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
+ {
+ b << i->first << i->second;
+ }
+ return b;
+}
+
+template <typename K, typename V>
+inline ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
+{
+ uint32 msize;
+ b >> msize;
+ m.clear();
+ while(msize--)
+ {
+ K k;
+ V v;
+ b >> k >> v;
+ m.insert(make_pair(k, v));
+ }
+ return b;
+}
+
+// TODO: Make a ByteBuffer.cpp and move all this inlining to it.
+template<> inline std::string ByteBuffer::read<std::string>()
+{
+ std::string tmp;
+ *this >> tmp;
+ return tmp;
+}
+
+template<>
+inline void ByteBuffer::read_skip<char*>()
+{
+ std::string temp;
+ *this >> temp;
+}
+
+template<>
+inline void ByteBuffer::read_skip<char const*>()
+{
+ read_skip<char*>();
+}
+
+template<>
+inline void ByteBuffer::read_skip<std::string>()
+{
+ read_skip<char*>();
+}
+#endif
+
diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt
new file mode 100644
index 00000000000..d00f8b83fb8
--- /dev/null
+++ b/src/server/shared/CMakeLists.txt
@@ -0,0 +1,42 @@
+add_subdirectory(vmap)
+add_subdirectory(Auth)
+add_subdirectory(Config)
+add_subdirectory(Database)
+
+########### next target ###############
+
+SET(shared_STAT_SRCS
+ ByteBuffer.h
+ Common.cpp
+ Common.h
+ DelayExecutor.cpp
+ DelayExecutor.h
+ Errors.h
+ Log.cpp
+ Log.h
+ ProgressBar.cpp
+ ProgressBar.h
+ SignalHandler.h
+ Threading.cpp
+ Timer.h
+ Util.cpp
+ Util.h
+ WorldPacket.h
+ SystemConfig.h
+)
+
+include_directories(
+ ${ACE_INCLUDE_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/dep/include
+ ${CMAKE_SOURCE_DIR}/dep/include/sockets
+ ${CMAKE_SOURCE_DIR}/src/framework
+ ${CMAKE_SOURCE_DIR}/src/shared
+ ${MYSQL_INCLUDE_DIR}
+)
+
+add_library(shared STATIC ${shared_STAT_SRCS})
+target_link_libraries(
+shared
+${ACE_LIBRARY}
+)
diff --git a/src/server/shared/Common.cpp b/src/server/shared/Common.cpp
new file mode 100644
index 00000000000..49a45d67131
--- /dev/null
+++ b/src/server/shared/Common.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+
+char const* localeNames[MAX_LOCALE] = {
+ "enUS",
+ "koKR",
+ "frFR",
+ "deDE",
+ "zhCN",
+ "zhTW",
+ "esES",
+ "esMX",
+ "ruRU"
+};
+
+LocaleConstant GetLocaleByName(const std::string& name)
+{
+ for (uint32 i = 0; i < MAX_LOCALE; ++i)
+ if(name==localeNames[i])
+ return LocaleConstant(i);
+
+ return LOCALE_enUS; // including enGB case
+}
+
diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h
new file mode 100644
index 00000000000..4a6aac43390
--- /dev/null
+++ b/src/server/shared/Common.h
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITYCORE_COMMON_H
+#define TRINITYCORE_COMMON_H
+
+// config.h needs to be included 1st
+// TODO this thingy looks like hack ,but its not, need to
+// make separate header however, because It makes mess here.
+#ifdef HAVE_CONFIG_H
+// Remove Some things that we will define
+// This is in case including another config.h
+// before trinity config.h
+#ifdef PACKAGE
+#undef PACKAGE
+#endif //PACKAGE
+#ifdef PACKAGE_BUGREPORT
+#undef PACKAGE_BUGREPORT
+#endif //PACKAGE_BUGREPORT
+#ifdef PACKAGE_NAME
+#undef PACKAGE_NAME
+#endif //PACKAGE_NAME
+#ifdef PACKAGE_STRING
+#undef PACKAGE_STRING
+#endif //PACKAGE_STRING
+#ifdef PACKAGE_TARNAME
+#undef PACKAGE_TARNAME
+#endif //PACKAGE_TARNAME
+#ifdef PACKAGE_VERSION
+#undef PACKAGE_VERSION
+#endif //PACKAGE_VERSION
+#ifdef VERSION
+#undef VERSION
+#endif //VERSION
+# include "config.h"
+#undef PACKAGE
+#undef PACKAGE_BUGREPORT
+#undef PACKAGE_NAME
+#undef PACKAGE_STRING
+#undef PACKAGE_TARNAME
+#undef PACKAGE_VERSION
+#undef VERSION
+#endif //HAVE_CONFIG_H
+
+#include "Platform/Define.h"
+
+#if COMPILER == COMPILER_MICROSOFT
+# pragma warning(disable:4996) // 'function': was declared deprecated
+#ifndef __SHOW_STUPID_WARNINGS__
+# pragma warning(disable:4005) // 'identifier' : macro redefinition
+# pragma warning(disable:4018) // 'expression' : signed/unsigned mismatch
+# pragma warning(disable:4244) // 'argument' : conversion from 'type1' to 'type2', possible loss of data
+# pragma warning(disable:4267) // 'var' : conversion from 'size_t' to 'type', possible loss of data
+# pragma warning(disable:4305) // 'identifier' : truncation from 'type1' to 'type2'
+# pragma warning(disable:4311) // 'variable' : pointer truncation from 'type' to 'type'
+# pragma warning(disable:4355) // 'this' : used in base member initializer list
+# pragma warning(disable:4800) // 'type' : forcing value to bool 'true' or 'false' (performance warning)
+# pragma warning(disable:4522) //warning when class has 2 constructors
+#endif // __SHOW_STUPID_WARNINGS__
+#endif // __GNUC__
+
+#include "Utilities/UnorderedMap.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <math.h>
+#include <errno.h>
+#include <signal.h>
+#include <assert.h>
+
+#if PLATFORM == PLATFORM_WINDOWS
+#define STRCASECMP stricmp
+#else
+#define STRCASECMP strcasecmp
+#endif
+
+#include <set>
+#include <list>
+#include <string>
+#include <map>
+#include <queue>
+#include <sstream>
+#include <algorithm>
+
+#include "LockedQueue.h"
+#include "Threading.h"
+
+#include <ace/Basic_Types.h>
+#include <ace/Guard_T.h>
+#include <ace/RW_Thread_Mutex.h>
+#include <ace/Thread_Mutex.h>
+
+#if PLATFORM == PLATFORM_WINDOWS
+# define FD_SETSIZE 4096
+# include <ace/config-all.h>
+// XP winver - needed to compile with standard leak check in MemoryLeaks.h
+// uncomment later if needed
+//#define _WIN32_WINNT 0x0501
+# include <ws2tcpip.h>
+//#undef WIN32_WINNT
+#else
+# include <sys/types.h>
+# include <sys/ioctl.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <unistd.h>
+# include <netdb.h>
+#endif
+
+#if COMPILER == COMPILER_MICROSOFT
+
+#include <float.h>
+
+#define I32FMT "%08I32X"
+#define I64FMT "%016I64X"
+#define snprintf _snprintf
+#define atoll __atoi64
+#define vsnprintf _vsnprintf
+#define strdup _strdup
+#define finite(X) _finite(X)
+
+#else
+
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+#define I32FMT "%08X"
+#define I64FMT "%016llX"
+
+#endif
+
+#define UI64FMTD ACE_UINT64_FORMAT_SPECIFIER
+#define UI64LIT(N) ACE_UINT64_LITERAL(N)
+
+#define SI64FMTD ACE_INT64_FORMAT_SPECIFIER
+#define SI64LIT(N) ACE_INT64_LITERAL(N)
+
+#define SIZEFMTD ACE_SIZE_T_FORMAT_SPECIFIER
+
+inline float finiteAlways(float f) { return finite(f) ? f : 0.0f; }
+
+#define atol(a) strtoul( a, NULL, 10)
+
+#define STRINGIZE(a) #a
+
+enum TimeConstants
+{
+ MINUTE = 60,
+ HOUR = MINUTE*60,
+ DAY = HOUR*24,
+ WEEK = DAY*7,
+ MONTH = DAY*30,
+ YEAR = MONTH*12,
+ IN_MILISECONDS = 1000
+};
+
+enum AccountTypes
+{
+ SEC_PLAYER = 0,
+ SEC_MODERATOR = 1,
+ SEC_GAMEMASTER = 2,
+ SEC_ADMINISTRATOR = 3,
+ SEC_CONSOLE = 4 // must be always last in list, accounts must have less security level always also
+};
+
+enum LocaleConstant
+{
+ LOCALE_enUS = 0,
+ LOCALE_koKR = 1,
+ LOCALE_frFR = 2,
+ LOCALE_deDE = 3,
+ LOCALE_zhCN = 4,
+ LOCALE_zhTW = 5,
+ LOCALE_esES = 6,
+ LOCALE_esMX = 7,
+ LOCALE_ruRU = 8
+};
+
+const uint8 MAX_LOCALE = 9;
+
+extern char const* localeNames[MAX_LOCALE];
+
+LocaleConstant GetLocaleByName(const std::string& name);
+
+// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms)
+#ifdef max
+#undef max
+#endif
+
+#ifdef min
+#undef min
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#endif
+
diff --git a/src/server/shared/Config/CMakeLists.txt b/src/server/shared/Config/CMakeLists.txt
new file mode 100644
index 00000000000..98065034f08
--- /dev/null
+++ b/src/server/shared/Config/CMakeLists.txt
@@ -0,0 +1,22 @@
+
+########### next target ###############
+
+SET(trinityconfig_STAT_SRCS
+ dotconfpp/dotconfpp.cpp
+ dotconfpp/dotconfpp.h
+ dotconfpp/mempool.cpp
+ dotconfpp/mempool.h
+ Config.cpp
+ Config.h
+ ConfigEnv.h
+)
+
+include_directories(
+ ${ACE_INCLUDE_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/src/shared
+ ${CMAKE_SOURCE_DIR}/src/framework
+)
+
+add_library(trinityconfig STATIC ${trinityconfig_STAT_SRCS})
+
diff --git a/src/server/shared/Config/Config.cpp b/src/server/shared/Config/Config.cpp
new file mode 100644
index 00000000000..39830104a7c
--- /dev/null
+++ b/src/server/shared/Config/Config.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ConfigEnv.h"
+#include "Policies/SingletonImp.h"
+
+INSTANTIATE_SINGLETON_1(Config);
+
+Config::Config() : mIgnoreCase(true), mConf(NULL)
+{
+}
+
+Config::~Config()
+{
+ delete mConf;
+}
+
+bool Config::SetSource(const char *file, bool ignorecase)
+{
+ mIgnoreCase = ignorecase;
+ mFilename = file;
+
+ return Reload();
+}
+
+bool Config::Reload()
+{
+ delete mConf;
+
+ mConf = new DOTCONFDocument(mIgnoreCase ?
+ DOTCONFDocument::CASEINSENSETIVE :
+ DOTCONFDocument::CASESENSETIVE);
+
+ if (mConf->setContent(mFilename.c_str()) == -1)
+ {
+ delete mConf;
+ mConf = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+std::string Config::GetStringDefault(const char * name, std::string def)
+{
+ if(!mConf)
+ return std::string(def);
+ const DOTCONFDocumentNode * node = mConf->findNode(name);
+ if(!node || !node->getValue())
+ return std::string(def);
+ return std::string(node->getValue());
+};
+
+bool Config::GetBoolDefault(const char * name, const bool def)
+{
+ if(!mConf)
+ return false;
+ const DOTCONFDocumentNode * node = mConf->findNode(name);
+ if(!node || !node->getValue())
+ return def;
+ const char * str = node->getValue();
+ if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 ||
+ strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 ||
+ strcmp(str, "1") == 0)
+ return true;
+ else
+ return false;
+};
+
+int32 Config::GetIntDefault(const char * name, const int32 def)
+{
+ if(!mConf)
+ return def;
+ const DOTCONFDocumentNode * node = mConf->findNode(name);
+ if(!node || !node->getValue())
+ return def;
+ return atoi(node->getValue());
+};
+
+float Config::GetFloatDefault(const char * name, const float def)
+{
+ if(!mConf)
+ return def;
+ const DOTCONFDocumentNode * node = mConf->findNode(name);
+ if(!node || !node->getValue())
+ return def;
+ return atof(node->getValue());
+};
diff --git a/src/server/shared/Config/Config.h b/src/server/shared/Config/Config.h
new file mode 100644
index 00000000000..ccc76073e46
--- /dev/null
+++ b/src/server/shared/Config/Config.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef CONFIG_H
+#define CONFIG_H
+
+#include <Policies/Singleton.h>
+#include "Platform/Define.h"
+
+class DOTCONFDocument;
+
+class Config
+{
+ public:
+ Config();
+ ~Config();
+
+ bool SetSource(const char *file, bool ignorecase = true);
+ bool Reload();
+
+ std::string GetStringDefault(const char * name, std::string def);
+ bool GetBoolDefault(const char * name, const bool def);
+ int32 GetIntDefault(const char * name, const int32 def);
+ float GetFloatDefault(const char * name, const float def);
+
+ std::string GetFilename() const { return mFilename; }
+ private:
+ std::string mFilename;
+ bool mIgnoreCase;
+ DOTCONFDocument *mConf;
+};
+
+#define sConfig Trinity::Singleton<Config>::Instance()
+
+#endif
+
diff --git a/src/server/shared/Config/ConfigEnv.h b/src/server/shared/Config/ConfigEnv.h
new file mode 100644
index 00000000000..16e596fd2da
--- /dev/null
+++ b/src/server/shared/Config/ConfigEnv.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if !defined(CONFIGENVIRONMENT_H)
+
+#define CONFIGENVIRONMENT_H
+
+#include "Common.h"
+#include "dotconfpp/dotconfpp.h"
+#include "Config.h"
+
+#endif
+
diff --git a/src/server/shared/Config/ConfigLibrary.vcproj b/src/server/shared/Config/ConfigLibrary.vcproj
new file mode 100644
index 00000000000..a8f1fc322e7
--- /dev/null
+++ b/src/server/shared/Config/ConfigLibrary.vcproj
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="ConfigLibrary"
+ ProjectGUID="{C849D54F-32A6-4025-95BE-E64D1CF0686E}"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/ConfigLibrary.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=""
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="$(OutDir)/ConfigLibrary.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\Config.cpp">
+ </File>
+ <File
+ RelativePath=".\dotconfpp\dotconfpp.cpp">
+ </File>
+ <File
+ RelativePath=".\dotconfpp\mempool.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath=".\Config.h">
+ </File>
+ <File
+ RelativePath=".\ConfigEnv.h">
+ </File>
+ <File
+ RelativePath=".\dotconfpp\dotconfpp.h">
+ </File>
+ <File
+ RelativePath=".\dotconfpp\mempool.h">
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/src/server/shared/Config/dotconfpp/dotconfpp.cpp b/src/server/shared/Config/dotconfpp/dotconfpp.cpp
new file mode 100644
index 00000000000..8760b118e38
--- /dev/null
+++ b/src/server/shared/Config/dotconfpp/dotconfpp.cpp
@@ -0,0 +1,599 @@
+
+#include "Common.h"
+
+#include "dotconfpp.h"
+
+#ifdef WIN32
+#define PATH_MAX _MAX_PATH
+#define strcasecmp stricmp
+#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH)
+#include <io.h>
+#else
+#include <unistd.h>
+#include <limits.h>
+#include <stdint.h>
+#include <strings.h>
+#endif
+
+#if !defined(R_OK)
+#define R_OK 04
+#endif
+
+DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL),
+ values(NULL), valuesCount(0),
+ name(NULL), lineNum(0), fileName(NULL), closed(true)
+{
+}
+
+DOTCONFDocumentNode::~DOTCONFDocumentNode()
+{
+ free(name);
+ if(values != NULL){
+ for (int i = 0 ; i < valuesCount; i++){
+ free(values[i]);
+ }
+ free(values);
+ }
+}
+
+void DOTCONFDocumentNode::pushValue(char * _value)
+{
+ ++valuesCount;
+ values = (char**)realloc(values, valuesCount*sizeof(char*));
+ values[valuesCount-1] = strdup(_value);
+}
+
+const char* DOTCONFDocumentNode::getValue(int index) const
+{
+ if(index >= valuesCount){
+ return NULL;
+ }
+ return values[index];
+}
+
+DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity):
+ mempool(NULL),
+ curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL)
+{
+ if(caseSensitivity == CASESENSETIVE){
+ cmp_func = strcmp;
+ } else {
+ cmp_func = strcasecmp;
+ }
+
+ mempool = new AsyncDNSMemPool(1024);
+ mempool->initialize();
+}
+
+DOTCONFDocument::~DOTCONFDocument()
+{
+ for (std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i != nodeTree.end(); ++i){
+ delete(*i);
+ }
+ for (std::list<char*>::iterator i = requiredOptions.begin(); i != requiredOptions.end(); ++i){
+ free(*i);
+ }
+ for (std::list<char*>::iterator i = processedFiles.begin(); i != processedFiles.end(); ++i){
+ free(*i);
+ }
+ free(fileName);
+ delete mempool;
+}
+
+int DOTCONFDocument::cleanupLine(char * line)
+{
+ char * start = line;
+ char * bg = line;
+ bool multiline = false;
+ bool concat = false;
+ char * word = NULL;
+
+ if(!words.empty() && quoted)
+ concat = true;
+
+ while(*line){
+ if((*line == '#' || *line == ';') && !quoted){
+ *bg = 0;
+ if(strlen(start)){
+
+ if(concat){
+ word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
+ strcpy(word, words.back());
+ strcat(word, start);
+ words.pop_back();
+ concat = false;
+ } else {
+ word = mempool->strdup(start);
+ }
+ words.push_back(word);
+ }
+ break;
+ }
+ if(*line == '=' && !quoted){
+ *line = ' ';continue;
+ }
+
+ // Allowing \" in there causes problems with directory paths
+ // like "C:\TrinIty\"
+ //if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){
+ if(*line == '\\' && (*(line+1) == '\'')) {
+ *bg++ = *(line+1);
+ line+=2; continue;
+ }
+ if(*line == '\\' && *(line+1) == 'n'){
+ *bg++ = '\n';
+ line+=2; continue;
+ }
+ if(*line == '\\' && *(line+1) == 'r'){
+ *bg++ = '\r';
+ line+=2; continue;
+ }
+ if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){
+ *bg = 0;
+ if(strlen(start)){
+
+ if(concat){
+ word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
+ strcpy(word, words.back());
+ strcat(word, start);
+ words.pop_back();
+ concat = false;
+ } else {
+ word = mempool->strdup(start);
+ }
+ words.push_back(word);
+ }
+ multiline = true;
+ break;
+ }
+ if(*line == '"' || *line == '\''){
+ quoted = !quoted;
+ ++line; continue;
+ }
+ if(isspace((unsigned char)*line) && !quoted){
+ *bg++ = 0;
+ if(strlen(start)){
+
+ if(concat){
+ word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
+ strcpy(word, words.back());
+ strcat(word, start);
+ words.pop_back();
+ concat = false;
+ } else {
+ word = mempool->strdup(start);
+ }
+ words.push_back(word);
+ }
+ start = bg;
+ while(isspace((unsigned char)*++line)) {}
+
+ continue;
+ }
+ *bg++ = *line++;
+ }
+
+ if(quoted && !multiline){
+ error(curLine, fileName, "unterminated quote");
+ return -1;
+ }
+
+ return multiline?1:0;
+}
+
+int DOTCONFDocument::parseLine()
+{
+ char * word = NULL;
+ char * nodeName = NULL;
+ char * nodeValue = NULL;
+ DOTCONFDocumentNode * tagNode = NULL;
+ bool newNode = false;
+
+ for (std::list<char*>::iterator i = words.begin(); i != words.end(); ++i) {
+ word = *i;
+
+ if(*word == '<'){
+ newNode = true;
+ }
+
+ if(newNode){
+ nodeValue = NULL;
+ nodeName = NULL;
+ newNode = false;
+ }
+
+ size_t wordLen = strlen(word);
+ if(word[wordLen-1] == '>'){
+ word[wordLen-1] = 0;
+ newNode = true;
+ }
+
+ if(nodeName == NULL){
+ nodeName = word;
+ bool closed = true;
+ if(*nodeName == '<'){
+ if(*(nodeName+1) != '/'){
+ ++nodeName;
+ closed = false;
+ } else {
+ nodeName+=2;
+ std::list<DOTCONFDocumentNode*>::reverse_iterator itr=nodeTree.rbegin();
+ for (; itr!=nodeTree.rend(); ++itr){
+ if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){
+ (*itr)->closed = true;
+ curParent = (*itr)->parentNode;
+ curPrev = *itr;
+ break;
+ }
+ }
+ if(itr==nodeTree.rend()){
+ error(curLine, fileName, "not matched closing tag </%s>", nodeName);
+ return -1;
+ }
+ continue;
+ }
+ }
+ tagNode = new DOTCONFDocumentNode;
+ tagNode->name = strdup(nodeName);
+ tagNode->document = this;
+ tagNode->fileName = processedFiles.back();
+ tagNode->lineNum = curLine;
+ tagNode->closed = closed;
+ if(!nodeTree.empty()){
+ DOTCONFDocumentNode * prev = nodeTree.back();
+ if(prev->closed){
+
+ curPrev->nextNode = tagNode;
+ tagNode->previousNode = curPrev;
+ tagNode->parentNode = curParent;
+
+ } else {
+ prev->childNode = tagNode;
+ tagNode->parentNode = prev;
+ curParent = prev;
+ }
+ }
+ nodeTree.push_back(tagNode);
+ curPrev = tagNode;
+ } else {
+ nodeValue = word;
+ tagNode->pushValue(nodeValue);
+ }
+ }
+
+ return 0;
+}
+int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent)
+{
+ char str[512];
+ int ret = 0;
+ curLine = 0;
+ curParent = _parent;
+
+ quoted = false;
+ size_t slen = 0;
+
+ while(fgets(str, 511, file)){
+ ++curLine;
+ slen = strlen(str);
+ if( slen >= 510 ){
+ error(curLine, fileName, "warning: line too long");
+ }
+ if(str[slen-1] != '\n'){
+ str[slen] = '\n';
+ str[slen+1] = 0;
+ }
+ if((ret = cleanupLine(str)) == -1){
+ break;
+ }
+ if(ret == 0){
+ if(!words.empty()){
+ ret = parseLine();
+ mempool->free();
+ words.clear();
+ if(ret == -1){
+ break;
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+
+int DOTCONFDocument::checkConfig(const std::list<DOTCONFDocumentNode*>::iterator & from)
+{
+ int ret = 0;
+
+ DOTCONFDocumentNode * tagNode = NULL;
+ int vi = 0;
+ for (std::list<DOTCONFDocumentNode*>::iterator i = from; i != nodeTree.end(); ++i){
+ tagNode = *i;
+ if(!tagNode->closed){
+ error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name);
+ ret = -1;
+ break;
+ }
+ vi = 0;
+ while( vi < tagNode->valuesCount ){
+
+ if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){
+ ret = macroSubstitute(tagNode, vi );
+ mempool->free();
+ if(ret == -1){
+ break;
+ }
+ }
+ ++vi;
+ }
+ if(ret == -1){
+ break;
+ }
+ }
+
+ return ret;
+}
+
+int DOTCONFDocument::setContent(const char * _fileName)
+{
+ int ret = 0;
+ char realpathBuf[PATH_MAX];
+
+ if(realpath(_fileName, realpathBuf) == NULL){
+ error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno));
+ return -1;
+ }
+
+ fileName = strdup(realpathBuf);
+
+ processedFiles.push_back(strdup(realpathBuf));
+
+ if(( file = fopen(fileName, "r")) == NULL){
+ error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno));
+ return -1;
+ }
+ // Try read utf8 header and skip it if exist
+ uint32 utf8header = 0;
+ fgets((char*)&utf8header, 4, file); // Try read header
+ if (utf8header!=0x00BFBBEF) // If not exist
+ fseek(file, 0, SEEK_SET); // Reset read position
+
+ ret = parseFile();
+
+ (void) fclose(file);
+
+ if(!ret){
+
+ if( (ret = checkConfig(nodeTree.begin())) == -1){
+ return -1;
+ }
+
+ std::list<DOTCONFDocumentNode*>::iterator from;
+ DOTCONFDocumentNode * tagNode = NULL;
+ int vi = 0;
+ for (std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){
+ tagNode = *i;
+ if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){
+ vi = 0;
+ while( vi < tagNode->valuesCount ){
+ if(access(tagNode->values[vi], R_OK) == -1){
+ error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno));
+ return -1;
+ }
+ if(realpath(tagNode->values[vi], realpathBuf) == NULL){
+ error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno));
+ return -1;
+ }
+
+ bool processed = false;
+ for (std::list<char*>::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); ++itInode){
+ if(!strcmp(*itInode, realpathBuf)){
+ processed = true;
+ break;
+ }
+ }
+ if(processed){
+ break;
+ }
+
+ processedFiles.push_back(strdup(realpathBuf));
+
+ file = fopen(tagNode->values[vi], "r");
+ if(file == NULL){
+ error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno));
+ return -1;
+ }
+
+ fileName = strdup(realpathBuf);
+ from = nodeTree.end(); --from;
+
+ ret = parseFile();
+ (void) fclose(file);
+ if(ret == -1)
+ return -1;
+ if(checkConfig(++from) == -1){
+ return -1;
+ }
+ ++vi;
+ }
+ }
+ }
+
+ if(!requiredOptions.empty())
+ ret = checkRequiredOptions();
+ }
+
+ return ret;
+}
+
+int DOTCONFDocument::checkRequiredOptions()
+{
+ for (std::list<char*>::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ++ci){
+ bool matched = false;
+ for (std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i!=nodeTree.end(); ++i){
+ if(!cmp_func((*i)->name, *ci)){
+ matched = true;
+ break;
+ }
+ }
+ if(!matched){
+ error(0, NULL, "required option '%s' not specified", *ci);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...)
+{
+ va_list args;
+ va_start(args, fmt);
+
+ size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50;
+ char * buf = (char*)mempool->alloc(len);
+
+ if(lineNum)
+ (void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt);
+ else
+ (void) snprintf(buf, len, "DOTCONF++: %s\n", fmt);
+
+ (void) vfprintf(stderr, buf, args);
+
+ va_end(args);
+}
+
+char * DOTCONFDocument::getSubstitution(char * macro, int lineNum)
+{
+ char * buf = NULL;
+ char * variable = macro+2;
+
+ char * endBr = strchr(macro, '}');
+
+ if(!endBr){
+ error(lineNum, fileName, "unterminated '{'");
+ return NULL;
+ }
+ *endBr = 0;
+
+ char * defaultValue = strchr(variable, ':');
+
+ if(defaultValue){
+ *defaultValue++ = 0;
+ if(*defaultValue != '-'){
+ error(lineNum, fileName, "incorrect macro substitution syntax");
+ return NULL;
+ }
+ ++defaultValue;
+ if(*defaultValue == '"' || *defaultValue == '\''){
+ ++defaultValue;
+ defaultValue[strlen(defaultValue)-1] = 0;
+ }
+ } else {
+ defaultValue = NULL;
+ }
+
+ char * subs = getenv(variable);
+ if( subs ){
+ buf = mempool->strdup(subs);
+ } else {
+ std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin();
+ DOTCONFDocumentNode * tagNode = NULL;
+ for (; i!=nodeTree.end(); i++){
+ tagNode = *i;
+ if(!cmp_func(tagNode->name, variable)){
+ if(tagNode->valuesCount != 0){
+ buf = mempool->strdup(tagNode->values[0]);
+ break;
+ }
+ }
+ }
+ if( i == nodeTree.end() ){
+ if( defaultValue ){
+ buf = mempool->strdup(defaultValue);
+ } else {
+ error(lineNum, fileName, "substitution not found and default value not given");
+ return NULL;
+ }
+ }
+ }
+ return buf;
+}
+
+int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex)
+{
+ int ret = 0;
+ char * macro = tagNode->values[valueIndex];
+ size_t valueLen = strlen(tagNode->values[valueIndex])+1;
+ char * value = (char*)mempool->alloc(valueLen);
+ char * v = value;
+ char * subs = NULL;
+
+ while(*macro){
+ if(*macro == '$' && *(macro+1) == '{'){
+ char * m = strchr(macro, '}');
+ subs = getSubstitution(macro, tagNode->lineNum);
+ if(subs == NULL){
+ ret = -1;
+ break;
+ }
+ macro = m + 1;
+ *v = 0;
+ v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen);
+ strcpy(v, value);
+ value = strcat(v, subs);
+ v = value + strlen(value);
+ continue;
+ }
+ *v++ = *macro++;
+ }
+ *v = 0;
+
+ free(tagNode->values[valueIndex]);
+ tagNode->values[valueIndex] = strdup(value);
+ return ret;
+}
+
+const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const
+{
+ if ( !nodeTree.empty() ) {
+ return *nodeTree.begin();
+ } else {
+ return NULL;
+ }
+}
+
+const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const
+{
+
+ std::list<DOTCONFDocumentNode*>::const_iterator i = nodeTree.begin();
+
+ if(startNode == NULL)
+ startNode = parentNode;
+
+ if(startNode != NULL){
+ while( i != nodeTree.end() && (*i) != startNode ){
+ ++i;
+ }
+ if( i != nodeTree.end() ) ++i;
+ }
+
+ for (; i!=nodeTree.end(); ++i){
+
+ if((*i)->parentNode != parentNode){
+ continue;
+ }
+ if(!cmp_func(nodeName, (*i)->name)){
+ return *i;
+ }
+ }
+ return NULL;
+}
+
+void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames)
+{
+ while(*requiredOptionNames){
+ requiredOptions.push_back(strdup( *requiredOptionNames ));
+ ++requiredOptionNames;
+ }
+}
+
diff --git a/src/server/shared/Config/dotconfpp/dotconfpp.h b/src/server/shared/Config/dotconfpp/dotconfpp.h
new file mode 100644
index 00000000000..554b152f693
--- /dev/null
+++ b/src/server/shared/Config/dotconfpp/dotconfpp.h
@@ -0,0 +1,97 @@
+
+
+#ifndef DOTCONFPP_H
+#define DOTCONFPP_H
+
+#include <list>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "mempool.h"
+
+class DOTCONFDocument;
+
+class DOTCONFDocumentNode
+{
+friend class DOTCONFDocument;
+private:
+ DOTCONFDocumentNode * previousNode;
+ DOTCONFDocumentNode * nextNode;
+ DOTCONFDocumentNode * parentNode;
+ DOTCONFDocumentNode * childNode;
+ char ** values;
+ int valuesCount;
+ char * name;
+ const DOTCONFDocument * document;
+ int lineNum;
+ char * fileName;
+ bool closed;
+
+ void pushValue(char * _value);
+
+public:
+ DOTCONFDocumentNode();
+ ~DOTCONFDocumentNode();
+
+ const char * getConfigurationFileName()const { return fileName; }
+ int getConfigurationLineNumber() const { return lineNum; }
+
+ const DOTCONFDocumentNode * getNextNode() const { return nextNode; }
+ const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; }
+ const DOTCONFDocumentNode * getParentNode() const { return parentNode; }
+ const DOTCONFDocumentNode * getChildNode() const { return childNode; }
+ const char* getValue(int index = 0) const;
+ const char * getName() const { return name; }
+ const DOTCONFDocument * getDocument() const { return document; }
+};
+
+class DOTCONFDocument
+{
+public:
+ enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE };
+protected:
+ AsyncDNSMemPool * mempool;
+private:
+ DOTCONFDocumentNode * curParent;
+ DOTCONFDocumentNode * curPrev;
+ int curLine;
+ bool quoted;
+ std::list<DOTCONFDocumentNode*> nodeTree;
+ std::list<char*> requiredOptions;
+ std::list<char*> processedFiles;
+ FILE * file;
+ char * fileName;
+ std::list<char*> words;
+ int (*cmp_func)(const char *, const char *);
+
+ int checkRequiredOptions();
+ int parseLine();
+ int parseFile(DOTCONFDocumentNode * _parent = NULL);
+ int checkConfig(const std::list<DOTCONFDocumentNode*>::iterator & from);
+ int cleanupLine(char * line);
+ char * getSubstitution(char * macro, int lineNum);
+ int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex);
+
+protected:
+ virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5);
+
+public:
+ DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE);
+ virtual ~DOTCONFDocument();
+
+ int setContent(const char * _fileName);
+
+ void setRequiredOptionNames(const char ** requiredOptionNames);
+ const DOTCONFDocumentNode * getFirstNode() const;
+ const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const;
+};
+
+#endif
+
diff --git a/src/server/shared/Config/dotconfpp/mempool.cpp b/src/server/shared/Config/dotconfpp/mempool.cpp
new file mode 100644
index 00000000000..a23e33808bd
--- /dev/null
+++ b/src/server/shared/Config/dotconfpp/mempool.cpp
@@ -0,0 +1,100 @@
+
+
+#include "mempool.h"
+
+AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size):
+ pool(NULL), pos(0), size(_size)
+{
+ pool = ::malloc(size);
+}
+
+AsyncDNSMemPool::PoolChunk::~PoolChunk()
+{
+ ::free(pool);
+}
+
+AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize):
+ chunks(NULL), chunksCount(0), defaultSize(_defaultSize),
+ poolUsage(0), poolUsageCounter(0)
+{
+}
+
+AsyncDNSMemPool::~AsyncDNSMemPool()
+{
+ for (size_t i = 0; i<chunksCount; ++i){
+ delete chunks[i];
+ }
+ ::free(chunks);
+}
+
+int AsyncDNSMemPool::initialize()
+{
+ chunksCount = 1;
+ chunks = (PoolChunk**)::malloc(sizeof(PoolChunk*));
+ if(chunks == NULL)
+ return -1;
+
+ chunks[chunksCount-1] = new PoolChunk(defaultSize);
+
+ return 0;
+}
+
+void AsyncDNSMemPool::addNewChunk(size_t size)
+{
+ ++chunksCount;
+ chunks = (PoolChunk**)::realloc(chunks, chunksCount*sizeof(PoolChunk*));
+ if(size <= defaultSize)
+ chunks[chunksCount-1] = new PoolChunk(defaultSize);
+ else
+ chunks[chunksCount-1] = new PoolChunk(size);
+}
+
+void * AsyncDNSMemPool::alloc(size_t size)
+{
+ PoolChunk * chunk = NULL;
+ for (size_t i = 0; i<chunksCount; ++i){
+ chunk = chunks[i];
+ if((chunk->size - chunk->pos) >= size){
+ chunk->pos += size;
+ return ((char*)chunk->pool) + chunk->pos - size;
+ }
+ }
+ addNewChunk(size);
+ chunks[chunksCount-1]->pos = size;
+ return chunks[chunksCount-1]->pool;
+}
+
+void AsyncDNSMemPool::free()
+{
+ size_t pu = 0;
+ size_t psz = 0;
+ ++poolUsageCounter;
+
+ for (size_t i = 0; i<chunksCount; ++i){
+ pu += chunks[i]->pos;
+ psz += chunks[i]->size;
+ chunks[i]->pos = 0;
+ }
+ poolUsage=(poolUsage>pu)?poolUsage:pu;
+
+ if(poolUsageCounter >= 10 && chunksCount > 1){
+ psz -= chunks[chunksCount-1]->size;
+ if(poolUsage < psz){
+ --chunksCount;
+ delete chunks[chunksCount];
+ }
+ poolUsage = 0;
+ poolUsageCounter = 0;
+ }
+}
+
+void * AsyncDNSMemPool::calloc(size_t size)
+{
+ return ::memset(this->alloc(size), 0, size);
+}
+
+char * AsyncDNSMemPool::strdup(const char *str)
+{
+ return ::strcpy((char*)this->alloc(strlen(str)+1), str);
+}
+
diff --git a/src/server/shared/Config/dotconfpp/mempool.h b/src/server/shared/Config/dotconfpp/mempool.h
new file mode 100644
index 00000000000..185b50798e1
--- /dev/null
+++ b/src/server/shared/Config/dotconfpp/mempool.h
@@ -0,0 +1,46 @@
+
+
+#ifndef ASYNC_DNS_MEMPOOL_H
+#define ASYNC_DNS_MEMPOOL_H
+
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#undef free
+#undef calloc
+#undef strdup
+
+class AsyncDNSMemPool
+{
+private:
+ struct PoolChunk {
+ void * pool;
+ size_t pos;
+ size_t size;
+
+ PoolChunk(size_t _size);
+ ~PoolChunk();
+ };
+ PoolChunk ** chunks;
+ size_t chunksCount;
+ size_t defaultSize;
+
+ size_t poolUsage;
+ size_t poolUsageCounter;
+
+ void addNewChunk(size_t size);
+
+public:
+ AsyncDNSMemPool(size_t _defaultSize = 4096);
+ virtual ~AsyncDNSMemPool();
+
+ int initialize();
+ void free();
+ void * alloc(size_t size);
+ void * calloc(size_t size);
+ char * strdup(const char *str);
+};
+
+#endif
+
diff --git a/src/server/shared/Database/CMakeLists.txt b/src/server/shared/Database/CMakeLists.txt
new file mode 100644
index 00000000000..405a5f89a57
--- /dev/null
+++ b/src/server/shared/Database/CMakeLists.txt
@@ -0,0 +1,30 @@
+SET(trinitydatabase_STAT_SRCS
+ DBCFileLoader.cpp
+ DBCFileLoader.h
+ DBCStore.h
+ Database.cpp
+ Database.h
+ DatabaseEnv.h
+ DatabaseImpl.h
+ Field.cpp
+ Field.h
+ QueryResult.cpp
+ QueryResult.h
+ SQLStorage.cpp
+ SQLStorage.h
+ SqlDelayThread.cpp
+ SqlDelayThread.h
+ SqlOperations.cpp
+ SqlOperations.h
+)
+
+include_directories(
+ ${ACE_INCLUDE_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${CMAKE_SOURCE_DIR}/src/shared
+ ${CMAKE_SOURCE_DIR}/src/shared/Database
+ ${CMAKE_SOURCE_DIR}/src/framework
+ ${MYSQL_INCLUDE_DIR}
+)
+
+add_library(trinitydatabase STATIC ${trinitydatabase_STAT_SRCS})
diff --git a/src/server/shared/Database/DBCFileLoader.cpp b/src/server/shared/Database/DBCFileLoader.cpp
new file mode 100644
index 00000000000..bad87a36fce
--- /dev/null
+++ b/src/server/shared/Database/DBCFileLoader.cpp
@@ -0,0 +1,270 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "DBCFileLoader.h"
+
+DBCFileLoader::DBCFileLoader()
+{
+ data = NULL;
+ fieldsOffset = NULL;
+}
+
+bool DBCFileLoader::Load(const char *filename, const char *fmt)
+{
+ uint32 header;
+ if (data)
+ {
+ delete [] data;
+ data = NULL;
+ }
+
+ FILE * f = fopen(filename,"rb");
+ if (!f)
+ return false;
+
+ if (fread(&header,4,1,f)!=1) // Number of records
+ return false;
+
+ EndianConvert(header);
+
+ if (header!=0x43424457)
+ return false; //'WDBC'
+
+ if (fread(&recordCount,4,1,f)!=1) // Number of records
+ return false;
+
+ EndianConvert(recordCount);
+
+ if (fread(&fieldCount,4,1,f)!=1) // Number of fields
+ return false;
+
+ EndianConvert(fieldCount);
+
+ if (fread(&recordSize,4,1,f)!=1) // Size of a record
+ return false;
+
+ EndianConvert(recordSize);
+
+ if (fread(&stringSize,4,1,f)!=1) // String size
+ return false;
+
+ EndianConvert(stringSize);
+
+ fieldsOffset = new uint32[fieldCount];
+ fieldsOffset[0] = 0;
+ for (uint32 i = 1; i < fieldCount; i++)
+ {
+ fieldsOffset[i] = fieldsOffset[i - 1];
+ if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
+ fieldsOffset[i] += 1;
+ else // 4 byte fields (int32/float/strings)
+ fieldsOffset[i] += 4;
+ }
+
+ data = new unsigned char[recordSize*recordCount+stringSize];
+ stringTable = data + recordSize*recordCount;
+
+ if (fread(data,recordSize*recordCount+stringSize,1,f)!=1)
+ return false;
+
+ fclose(f);
+
+ return true;
+}
+
+DBCFileLoader::~DBCFileLoader()
+{
+ if (data)
+ delete [] data;
+
+ if (fieldsOffset)
+ delete [] fieldsOffset;
+}
+
+DBCFileLoader::Record DBCFileLoader::getRecord(size_t id)
+{
+ assert(data);
+ return Record(*this, data + id*recordSize);
+}
+
+uint32 DBCFileLoader::GetFormatRecordSize(const char * format,int32* index_pos)
+{
+ uint32 recordsize = 0;
+ int32 i = -1;
+ for (uint32 x=0; format[x]; ++x)
+ {
+ switch(format[x])
+ {
+ case FT_FLOAT:
+ case FT_INT:
+ recordsize+=4;
+ break;
+ case FT_STRING:
+ recordsize+=sizeof(char*);
+ break;
+ case FT_SORT:
+ i=x;
+ break;
+ case FT_IND:
+ i=x;
+ recordsize+=4;
+ break;
+ case FT_BYTE:
+ recordsize += 1;
+ break;
+ }
+ }
+
+ if (index_pos)
+ *index_pos = i;
+
+ return recordsize;
+}
+
+char* DBCFileLoader::AutoProduceData(const char* format, uint32& records, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable)
+{
+ /*
+ format STRING, NA, FLOAT,NA,INT <=>
+ struct{
+ char* field0,
+ float field1,
+ int field2
+ }entry;
+
+ this func will generate entry[rows] data;
+ */
+
+ typedef char * ptr;
+ if (strlen(format)!=fieldCount)
+ return NULL;
+
+ //get struct size and index pos
+ int32 i;
+ uint32 recordsize=GetFormatRecordSize(format,&i);
+
+ if (i>=0)
+ {
+ uint32 maxi=0;
+ //find max index
+ for (uint32 y=0; y<recordCount; y++)
+ {
+ uint32 ind=getRecord(y).getUInt (i);
+ if(ind>maxi)maxi=ind;
+ }
+
+ // If higher index avalible from sql - use it instead of dbcs
+ if (sqlHighestIndex > maxi)
+ maxi = sqlHighestIndex;
+
+ ++maxi;
+ records=maxi;
+ indexTable=new ptr[maxi];
+ memset(indexTable,0,maxi*sizeof(ptr));
+ }
+ else
+ {
+ records = recordCount + sqlRecordCount;
+ indexTable = new ptr[recordCount+ sqlRecordCount];
+ }
+
+ char* dataTable= new char[(recordCount + sqlRecordCount)*recordsize];
+
+ uint32 offset=0;
+
+ for (uint32 y =0; y<recordCount; ++y)
+ {
+ if(i>=0)
+ indexTable[getRecord(y).getUInt(i)]=&dataTable[offset];
+ else
+ indexTable[y]=&dataTable[offset];
+
+ for (uint32 x=0; x<fieldCount; x++)
+ {
+ switch(format[x])
+ {
+ case FT_FLOAT:
+ *((float*)(&dataTable[offset]))=getRecord(y).getFloat(x);
+ offset+=4;
+ break;
+ case FT_IND:
+ case FT_INT:
+ *((uint32*)(&dataTable[offset]))=getRecord(y).getUInt(x);
+ offset+=4;
+ break;
+ case FT_BYTE:
+ *((uint8*)(&dataTable[offset]))=getRecord(y).getUInt8(x);
+ offset+=1;
+ break;
+ case FT_STRING:
+ *((char**)(&dataTable[offset]))=NULL; // will be replaces non-empty or "" strings in AutoProduceStrings
+ offset+=sizeof(char*);
+ break;
+ }
+ }
+ }
+
+ sqlDataTable = dataTable + offset;
+
+ return dataTable;
+}
+
+char* DBCFileLoader::AutoProduceStrings(const char* format, char* dataTable)
+{
+ if (strlen(format)!=fieldCount)
+ return NULL;
+
+ char* stringPool= new char[stringSize];
+ memcpy(stringPool,stringTable,stringSize);
+
+ uint32 offset=0;
+
+ for (uint32 y =0; y<recordCount; y++)
+ {
+ for (uint32 x=0; x<fieldCount; x++)
+ switch(format[x])
+ {
+ case FT_FLOAT:
+ case FT_IND:
+ case FT_INT:
+ offset+=4;
+ break;
+ case FT_BYTE:
+ offset+=1;
+ break;
+ case FT_STRING:
+ // fill only not filled entries
+ char** slot = (char**)(&dataTable[offset]);
+ if(!*slot || !**slot)
+ {
+ const char * st = getRecord(y).getString(x);
+ *slot=stringPool+(st-(const char*)stringTable);
+ }
+ offset+=sizeof(char*);
+ break;
+ }
+ }
+
+ return stringPool;
+}
+
diff --git a/src/server/shared/Database/DBCFileLoader.h b/src/server/shared/Database/DBCFileLoader.h
new file mode 100644
index 00000000000..a97ab4d60fa
--- /dev/null
+++ b/src/server/shared/Database/DBCFileLoader.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DBC_FILE_LOADER_H
+#define DBC_FILE_LOADER_H
+#include "Platform/Define.h"
+#include "Utilities/ByteConverter.h"
+#include <cassert>
+
+enum
+{
+ FT_NA='x', //not used or unknown, 4 byte size
+ FT_NA_BYTE='X', //not used or unknown, byte
+ FT_STRING='s', //char*
+ FT_FLOAT='f', //float
+ FT_INT='i', //uint32
+ FT_BYTE='b', //uint8
+ FT_SORT='d', //sorted by this field, field is not included
+ FT_IND='n', //the same,but parsed to data
+ FT_LOGIC='l', //Logical (boolean)
+ FT_SQL_PRESENT='p', //Used in sql format to mark column present in sql dbc
+ FT_SQL_ABSENT='a' //Used in sql format to mark column absent in sql dbc
+};
+
+class DBCFileLoader
+{
+ public:
+ DBCFileLoader();
+ ~DBCFileLoader();
+
+ bool Load(const char *filename, const char *fmt);
+
+ class Record
+ {
+ public:
+ float getFloat(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ float val = *reinterpret_cast<float*>(offset+file.GetOffset(field));
+ EndianConvert(val);
+ return val;
+ }
+ uint32 getUInt(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field));
+ EndianConvert(val);
+ return val;
+ }
+ uint8 getUInt8(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ return *reinterpret_cast<uint8*>(offset+file.GetOffset(field));
+ }
+
+ const char *getString(size_t field) const
+ {
+ assert(field < file.fieldCount);
+ size_t stringOffset = getUInt(field);
+ assert(stringOffset < file.stringSize);
+ return reinterpret_cast<char*>(file.stringTable + stringOffset);
+ }
+
+ private:
+ Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) {}
+ unsigned char *offset;
+ DBCFileLoader &file;
+
+ friend class DBCFileLoader;
+
+ };
+
+ // Get record by id
+ Record getRecord(size_t id);
+ /// Get begin iterator over records
+
+ uint32 GetNumRows() const { return recordCount; }
+ uint32 GetRowSize() const { return recordSize; }
+ uint32 GetCols() const { return fieldCount; }
+ uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; }
+ bool IsLoaded() { return data != NULL; }
+ char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable, uint32 sqlRecordCount, uint32 sqlHighestIndex, char *& sqlDataTable);
+ char* AutoProduceStrings(const char* fmt, char* dataTable);
+ static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL);
+ private:
+
+ uint32 recordSize;
+ uint32 recordCount;
+ uint32 fieldCount;
+ uint32 stringSize;
+ uint32 *fieldsOffset;
+ unsigned char *data;
+ unsigned char *stringTable;
+};
+#endif
diff --git a/src/server/shared/Database/DBCStore.h b/src/server/shared/Database/DBCStore.h
new file mode 100644
index 00000000000..61e2f7a6d06
--- /dev/null
+++ b/src/server/shared/Database/DBCStore.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DBCSTORE_H
+#define DBCSTORE_H
+
+#include "DBCFileLoader.h"
+#include "Log.h"
+
+struct SqlDbc
+{
+ const std::string * formatString;
+ const std::string * indexName;
+ std::string sqlTableName;
+ int32 indexPos;
+ int32 sqlIndexPos;
+ SqlDbc(const std::string * _filename, const std::string * _format, const std::string * _idname, const char * fmt)
+ :formatString(_format),sqlIndexPos(0), indexName (_idname)
+ {
+ // Convert dbc file name to sql table name
+ sqlTableName = *_filename;
+ for (uint32 i = 0; i< sqlTableName.size(); ++i)
+ {
+ if (isalpha(sqlTableName[i]))
+ sqlTableName[i] = tolower(sqlTableName[i]);
+ else if (sqlTableName[i] == '.')
+ sqlTableName[i] = '_';
+ }
+
+ // Get sql index position
+ DBCFileLoader::GetFormatRecordSize(fmt, &indexPos);
+ if (indexPos>=0)
+ {
+ for (int32 x=0; x < formatString->size(); x++)
+ {
+ // Count only fields present in sql
+ if ((*formatString)[x] == FT_SQL_PRESENT)
+ {
+ if (x == indexPos)
+ break;
+ ++sqlIndexPos;
+ }
+ }
+ }
+ }
+};
+
+template<class T>
+class DBCStorage
+{
+ typedef std::list<char*> StringPoolList;
+ public:
+ explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { }
+ ~DBCStorage() { Clear(); }
+
+ T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; }
+ uint32 GetNumRows() const { return nCount; }
+ char const* GetFormat() const { return fmt; }
+ uint32 GetFieldCount() const { return fieldCount; }
+
+ bool Load(char const* fn, SqlDbc * sql)
+ {
+ DBCFileLoader dbc;
+ // Check if load was sucessful, only then continue
+ if (!dbc.Load(fn, fmt))
+ return false;
+
+ uint32 sqlRecordCount = 0;
+ uint32 sqlHighestIndex = 0;
+ Field *fields = NULL;
+ QueryResult_AutoPtr result = QueryResult_AutoPtr(NULL);
+ // Load data from sql
+ if (sql)
+ {
+ std::string query = "SELECT * FROM " + sql->sqlTableName;
+ if (sql->indexPos >= 0)
+ query +=" ORDER BY + " + *sql->indexName + " DESC";
+ query += ";";
+
+ result = WorldDatabase.Query(query.c_str());
+ if (result)
+ {
+ sqlRecordCount = result->GetRowCount();
+ if (sql->indexPos >= 0)
+ {
+ fields = result->Fetch();
+ sqlHighestIndex = fields[sql->sqlIndexPos].GetUInt32();
+ }
+ // Check if sql index pos is valid
+ if (int32(result->GetFieldCount()-1) < sql->sqlIndexPos)
+ {
+ sLog.outError("Invalid index pos for dbc:'%s'", sql->sqlTableName.c_str());
+ return false;
+ }
+ }
+ }
+ char * sqlDataTable;
+ fieldCount = dbc.GetCols();
+ m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable, sqlRecordCount, sqlHighestIndex, sqlDataTable);
+
+ m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
+
+ // Insert sql data into arrays
+ if (result)
+ {
+ if (indexTable)
+ {
+ uint32 offset = 0;
+ uint32 rowIndex = dbc.GetNumRows();
+ do
+ {
+ if (!fields)
+ fields = result->Fetch();
+
+ if(sql->indexPos >= 0)
+ {
+ uint32 id = fields[sql->sqlIndexPos].GetUInt32();
+ if (indexTable[id])
+ {
+ sLog.outError("Index %d already exists in dbc:'%s'", id, sql->sqlTableName.c_str());
+ return false;
+ }
+ indexTable[id]=(T*)&sqlDataTable[offset];
+ }
+ else
+ indexTable[rowIndex]=(T*)&sqlDataTable[offset];
+ uint32 columnNumber = 0;
+ uint32 sqlColumnNumber = 0;
+
+ for (; columnNumber < sql->formatString->size(); ++columnNumber)
+ {
+ if ((*sql->formatString)[columnNumber] == FT_SQL_ABSENT)
+ {
+ switch(fmt[columnNumber])
+ {
+ case FT_FLOAT:
+ *((float*)(&sqlDataTable[offset]))= 0.0f;
+ offset+=4;
+ break;
+ case FT_IND:
+ case FT_INT:
+ *((uint32*)(&sqlDataTable[offset]))=uint32(0);
+ offset+=4;
+ break;
+ case FT_BYTE:
+ *((uint8*)(&sqlDataTable[offset]))=uint8(0);
+ offset+=1;
+ break;
+ case FT_STRING:
+ // Beginning of the pool - empty string
+ *((char**)(&sqlDataTable[offset]))=m_stringPoolList.back();
+ offset+=sizeof(char*);
+ break;
+ }
+ }
+ else if ((*sql->formatString)[columnNumber] == FT_SQL_PRESENT)
+ {
+ bool validSqlColumn = true;
+ switch(fmt[columnNumber])
+ {
+ case FT_FLOAT:
+ *((float*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetFloat();
+ offset+=4;
+ break;
+ case FT_IND:
+ case FT_INT:
+ *((uint32*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt32();
+ offset+=4;
+ break;
+ case FT_BYTE:
+ *((uint8*)(&sqlDataTable[offset]))=fields[sqlColumnNumber].GetUInt8();
+ offset+=1;
+ break;
+ case FT_STRING:
+ sLog.outError("Unsupported data type in table '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
+ return false;
+ case FT_SORT:
+ break;
+ default:
+ validSqlColumn = false;
+ }
+ if (validSqlColumn && (columnNumber != (sql->formatString->size()-1)))
+ sqlColumnNumber++;
+ }
+ else
+ {
+ sLog.outError("Incorrect sql format string '%s' at char %d", sql->sqlTableName.c_str(), columnNumber);
+ return false;
+ }
+ }
+ if (sqlColumnNumber != (result->GetFieldCount()-1))
+ {
+ sLog.outError("SQL and DBC format strings are not matching for table: '%s'", sql->sqlTableName.c_str());
+ return false;
+ }
+
+ fields = NULL;
+ ++rowIndex;
+ }while (result->NextRow());
+ }
+ }
+
+ // error in dbc file at loading if NULL
+ return indexTable!=NULL;
+ }
+
+ bool LoadStringsFrom(char const* fn)
+ {
+ // DBC must be already loaded using Load
+ if(!indexTable)
+ return false;
+
+ DBCFileLoader dbc;
+ // Check if load was successful, only then continue
+ if(!dbc.Load(fn, fmt))
+ return false;
+
+ m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
+
+ return true;
+ }
+
+ void Clear()
+ {
+ if (!indexTable)
+ return;
+
+ delete[] ((char*)indexTable);
+ indexTable = NULL;
+ delete[] ((char*)m_dataTable);
+ m_dataTable = NULL;
+
+ while(!m_stringPoolList.empty())
+ {
+ delete[] m_stringPoolList.front();
+ m_stringPoolList.pop_front();
+ }
+ nCount = 0;
+ }
+
+ private:
+ char const* fmt;
+ uint32 nCount;
+ uint32 fieldCount;
+ T** indexTable;
+ T* m_dataTable;
+ StringPoolList m_stringPoolList;
+};
+
+#endif
diff --git a/src/server/shared/Database/Database.cpp b/src/server/shared/Database/Database.cpp
new file mode 100644
index 00000000000..379388d7997
--- /dev/null
+++ b/src/server/shared/Database/Database.cpp
@@ -0,0 +1,657 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DatabaseEnv.h"
+#include "Config/ConfigEnv.h"
+
+#include "Common.h"
+#include "../../game/UpdateFields.h"
+
+#include "Util.h"
+#include "Policies/SingletonImp.h"
+#include "Platform/Define.h"
+#include "Threading.h"
+#include "Database/SqlDelayThread.h"
+#include "Database/SqlOperations.h"
+#include "Timer.h"
+
+
+#include <ctime>
+#include <iostream>
+#include <fstream>
+
+size_t Database::db_count = 0;
+
+Database::Database() : mMysql(NULL)
+{
+ // before first connection
+ if (db_count++ == 0)
+ {
+ // Mysql Library Init
+ mysql_library_init(-1, NULL, NULL);
+
+ if (!mysql_thread_safe())
+ {
+ sLog.outError("FATAL ERROR: Used MySQL library isn't thread-safe.");
+ exit(1);
+ }
+ }
+}
+
+Database::~Database()
+{
+ if (m_delayThread)
+ HaltDelayThread();
+
+ if (mMysql)
+ mysql_close(mMysql);
+
+ // Free Mysql library pointers for last ~DB
+ if (--db_count == 0)
+ mysql_library_end();
+}
+
+bool Database::Initialize(const char *infoString)
+{
+ // Enable logging of SQL commands (usally only GM commands)
+ // (See method: PExecuteLog)
+ m_logSQL = sConfig.GetBoolDefault("LogSQL", false);
+ m_logsDir = sConfig.GetStringDefault("LogsDir","");
+ if (!m_logsDir.empty())
+ {
+ if ((m_logsDir.at(m_logsDir.length()-1)!='/') && (m_logsDir.at(m_logsDir.length()-1)!='\\'))
+ m_logsDir.append("/");
+ }
+
+ tranThread = NULL;
+ MYSQL *mysqlInit;
+ mysqlInit = mysql_init(NULL);
+ if (!mysqlInit)
+ {
+ sLog.outError("Could not initialize Mysql connection");
+ return false;
+ }
+
+ InitDelayThread();
+
+ Tokens tokens = StrSplit(infoString, ";");
+
+ Tokens::iterator iter;
+
+ std::string host, port_or_socket, user, password, database;
+ int port;
+ char const* unix_socket;
+
+ iter = tokens.begin();
+
+ if (iter != tokens.end())
+ host = *iter++;
+ if (iter != tokens.end())
+ port_or_socket = *iter++;
+ if (iter != tokens.end())
+ user = *iter++;
+ if (iter != tokens.end())
+ password = *iter++;
+ if (iter != tokens.end())
+ database = *iter++;
+
+ mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");
+ #ifdef WIN32
+ if (host==".") // named pipe use option (Windows)
+ {
+ unsigned int opt = MYSQL_PROTOCOL_PIPE;
+ mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt);
+ port = 0;
+ unix_socket = 0;
+ }
+ else // generic case
+ {
+ port = atoi(port_or_socket.c_str());
+ unix_socket = 0;
+ }
+ #else
+ if (host==".") // socket use option (Unix/Linux)
+ {
+ unsigned int opt = MYSQL_PROTOCOL_SOCKET;
+ mysql_options(mysqlInit, MYSQL_OPT_PROTOCOL, (char const*)&opt);
+ host = "localhost";
+ port = 0;
+ unix_socket = port_or_socket.c_str();
+ }
+ else // generic case
+ {
+ port = atoi(port_or_socket.c_str());
+ unix_socket = 0;
+ }
+ #endif
+
+ mMysql = mysql_real_connect(mysqlInit, host.c_str(), user.c_str(),
+ password.c_str(), database.c_str(), port, unix_socket, 0);
+
+ if (mMysql)
+ {
+ sLog.outDetail("Connected to MySQL database at %s", host.c_str());
+ sLog.outString("MySQL client library: %s", mysql_get_client_info());
+ sLog.outString("MySQL server ver: %s ", mysql_get_server_info( mMysql));
+
+ if (!mysql_autocommit(mMysql, 1))
+ sLog.outDetail("AUTOCOMMIT SUCCESSFULLY SET TO 1");
+ else
+ sLog.outDetail("AUTOCOMMIT NOT SET TO 1");
+
+ // set connection properties to UTF8 to properly handle locales for different
+ // server configs - core sends data in UTF8, so MySQL must expect UTF8 too
+ PExecute("SET NAMES `utf8`");
+ PExecute("SET CHARACTER SET `utf8`");
+
+ #if MYSQL_VERSION_ID >= 50003
+ my_bool my_true = (my_bool)1;
+ if (mysql_options(mMysql, MYSQL_OPT_RECONNECT, &my_true))
+ sLog.outDetail("Failed to turn on MYSQL_OPT_RECONNECT.");
+ else
+ sLog.outDetail("Successfully turned on MYSQL_OPT_RECONNECT.");
+ #else
+ #warning "Your mySQL client lib version does not support reconnecting after a timeout.\nIf this causes you any trouble we advice you to upgrade your mySQL client libs to at least mySQL 5.0.13 to resolve this problem."
+ #endif
+ return true;
+ }
+ else
+ {
+ sLog.outError("Could not connect to MySQL database at %s: %s\n", host.c_str(),mysql_error(mysqlInit));
+ mysql_close(mysqlInit);
+ return false;
+ }
+}
+
+void Database::ThreadStart()
+{
+ mysql_thread_init();
+}
+
+void Database::ThreadEnd()
+{
+ mysql_thread_end();
+}
+
+void Database::escape_string(std::string& str)
+{
+ if (str.empty())
+ return;
+
+ char* buf = new char[str.size()*2+1];
+ escape_string(buf,str.c_str(),str.size());
+ str = buf;
+ delete[] buf;
+}
+
+unsigned long Database::escape_string(char *to, const char *from, unsigned long length)
+{
+ if (!mMysql || !to || !from || !length)
+ return 0;
+
+ return(mysql_real_escape_string(mMysql, to, from, length));
+}
+
+
+bool Database::PExecuteLog(const char * format,...)
+{
+ if (!format)
+ return false;
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
+ va_end(ap);
+
+ if (res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return false;
+ }
+
+ if (m_logSQL)
+ {
+ time_t curr;
+ tm local;
+ time(&curr); // get current time_t value
+ local=*(localtime(&curr)); // dereference and assign
+ char fName[128];
+ sprintf(fName, "%04d-%02d-%02d_logSQL.sql", local.tm_year+1900, local.tm_mon+1, local.tm_mday);
+
+ FILE* log_file;
+ std::string logsDir_fname = m_logsDir+fName;
+ log_file = fopen(logsDir_fname.c_str(), "a");
+ if (log_file)
+ {
+ fprintf(log_file, "%s;\n", szQuery);
+ fclose(log_file);
+ }
+ else
+ {
+ // The file could not be opened
+ sLog.outError("SQL-Logging is disabled - Log file for the SQL commands could not be openend: %s",fName);
+ }
+ }
+
+ return Execute(szQuery);
+}
+
+void Database::SetResultQueue(SqlResultQueue * queue)
+{
+ m_queryQueues[ACE_Based::Thread::current()] = queue;
+}
+
+bool Database::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount)
+{
+ if (!mMysql)
+ return 0;
+
+ {
+ // guarded block for thread-safe mySQL request
+ ACE_Guard<ACE_Thread_Mutex> query_connection_guard(mMutex);
+ #ifdef TRINITY_DEBUG
+ uint32 _s = getMSTime();
+ #endif
+ if (mysql_query(mMysql, sql))
+ {
+ sLog.outErrorDb("SQL: %s", sql);
+ sLog.outErrorDb("query ERROR: %s", mysql_error(mMysql));
+ return false;
+ }
+ else
+ {
+ #ifdef TRINITY_DEBUG
+ sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql );
+ #endif
+ }
+
+ *pResult = mysql_store_result(mMysql);
+ *pRowCount = mysql_affected_rows(mMysql);
+ *pFieldCount = mysql_field_count(mMysql);
+ }
+
+ if (!*pResult )
+ return false;
+
+ if (!*pRowCount)
+ {
+ mysql_free_result(*pResult);
+ return false;
+ }
+
+ *pFields = mysql_fetch_fields(*pResult);
+ return true;
+}
+
+QueryResult_AutoPtr Database::Query(const char *sql)
+{
+ MYSQL_RES *result = NULL;
+ MYSQL_FIELD *fields = NULL;
+ uint64 rowCount = 0;
+ uint32 fieldCount = 0;
+
+ if (!_Query(sql, &result, &fields, &rowCount, &fieldCount))
+ return QueryResult_AutoPtr(NULL);
+
+ QueryResult *queryResult = new QueryResult(result, fields, rowCount, fieldCount);
+
+ queryResult->NextRow();
+
+ return QueryResult_AutoPtr(queryResult);
+}
+
+QueryResult_AutoPtr Database::PQuery(const char *format,...)
+{
+ if (!format)
+ return QueryResult_AutoPtr(NULL);
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
+ va_end(ap);
+
+ if (res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return QueryResult_AutoPtr(NULL);
+ }
+
+ return Query(szQuery);
+}
+
+QueryNamedResult* Database::QueryNamed(const char *sql)
+{
+ MYSQL_RES *result = NULL;
+ MYSQL_FIELD *fields = NULL;
+ uint64 rowCount = 0;
+ uint32 fieldCount = 0;
+
+ if (!_Query(sql, &result, &fields, &rowCount, &fieldCount))
+ return NULL;
+
+ QueryFieldNames names(fieldCount);
+ for (uint32 i = 0; i < fieldCount; i++)
+ names[i] = fields[i].name;
+
+ QueryResult *queryResult = new QueryResult(result, fields, rowCount, fieldCount);
+
+ queryResult->NextRow();
+
+ return new QueryNamedResult(queryResult, names);
+}
+
+QueryNamedResult* Database::PQueryNamed(const char *format,...)
+{
+ if (!format)
+ return NULL;
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
+ va_end(ap);
+
+ if (res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return false;
+ }
+
+ return QueryNamed(szQuery);
+}
+
+bool Database::Execute(const char *sql)
+{
+ if (!mMysql)
+ return false;
+
+ // don't use queued execution if it has not been initialized
+ if (!m_threadBody)
+ return DirectExecute(sql);
+
+ nMutex.acquire();
+ tranThread = ACE_Based::Thread::current(); // owner of this transaction
+ TransactionQueues::iterator i = m_tranQueues.find(tranThread);
+ if (i != m_tranQueues.end() && i->second != NULL)
+ i->second->DelayExecute(sql); // Statement for transaction
+ else
+ m_threadBody->Delay(new SqlStatement(sql)); // Simple sql statement
+
+ nMutex.release();
+ return true;
+}
+
+bool Database::PExecute(const char * format,...)
+{
+ if (!format)
+ return false;
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
+ va_end(ap);
+
+ if (res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return false;
+ }
+
+ return Execute(szQuery);
+}
+
+bool Database::_UpdateDataBlobValue(const uint32 guid, const uint32 field, const int32 value)
+{
+ return PExecute(
+ "UPDATE characters SET data="
+ "CONCAT(SUBSTRING_INDEX(`data`,' ',%u),' ',"
+ "GREATEST(SUBSTRING_INDEX(SUBSTRING_INDEX(`data`,' ',%u),' ',-1)+%i,0),"
+ "' ',SUBSTRING_INDEX(`data`,' ',%i)) WHERE guid=%u",
+ field, field+1, value, -int32(PLAYER_END-field), guid);
+}
+
+bool Database::_SetDataBlobValue(const uint32 guid, const uint32 field, const uint32 value)
+{
+ return PExecute(
+ "UPDATE characters SET data="
+ "CONCAT(SUBSTRING_INDEX(`data`,' ',%u),' ',"
+ "%u,' ',SUBSTRING_INDEX(`data`,' ',%i)) WHERE guid=%u",
+ field, value, -int32(PLAYER_END-field), guid);
+}
+
+bool Database::DirectExecute(const char* sql)
+{
+ if (!mMysql)
+ return false;
+
+ {
+ // guarded block for thread-safe mySQL request
+ ACE_Guard<ACE_Thread_Mutex> query_connection_guard(mMutex);
+
+ #ifdef TRINITY_DEBUG
+ uint32 _s = getMSTime();
+ #endif
+ if (mysql_query(mMysql, sql))
+ {
+ sLog.outErrorDb("SQL: %s", sql);
+ sLog.outErrorDb("SQL ERROR: %s", mysql_error(mMysql));
+ return false;
+ }
+ else
+ {
+ #ifdef TRINITY_DEBUG
+ sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql);
+ #endif
+ }
+ }
+
+ return true;
+}
+
+bool Database::DirectPExecute(const char * format,...)
+{
+ if (!format)
+ return false;
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
+ va_end(ap);
+
+ if (res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return false;
+ }
+
+ return DirectExecute(szQuery);
+}
+
+bool Database::CheckRequiredField(char const* table_name, char const* required_name)
+{
+ // check required field
+ QueryResult_AutoPtr result = PQuery("SELECT %s FROM %s LIMIT 1",required_name,table_name);
+ if (result)
+ return true;
+
+ // check fail, prepare readabale error message
+
+ // search current required_* field in DB
+ QueryNamedResult* result2 = PQueryNamed("SELECT * FROM %s LIMIT 1",table_name);
+ if (result2)
+ {
+ QueryFieldNames const& namesMap = result2->GetFieldNames();
+ std::string reqName;
+ for (QueryFieldNames::const_iterator itr = namesMap.begin(); itr != namesMap.end(); ++itr)
+ {
+ if (itr->substr(0,9)=="required_")
+ {
+ reqName = *itr;
+ break;
+ }
+ }
+
+ delete result2;
+
+ if (!reqName.empty())
+ sLog.outErrorDb("Table `%s` have field `%s` but expected `%s`! Not all sql updates applied?",table_name,reqName.c_str(),required_name);
+ else
+ sLog.outErrorDb("Table `%s` not have required_* field but expected `%s`! Not all sql updates applied?",table_name,required_name);
+ }
+ else
+ sLog.outErrorDb("Table `%s` fields list query fail but expected have `%s`! No records in `%s`?",table_name,required_name,table_name);
+
+ return false;
+}
+
+bool Database::_TransactionCmd(const char *sql)
+{
+ if (mysql_query(mMysql, sql))
+ {
+ sLog.outError("SQL: %s", sql);
+ sLog.outError("SQL ERROR: %s", mysql_error(mMysql));
+ return false;
+ }
+ else
+ DEBUG_LOG("SQL: %s", sql);
+
+ return true;
+}
+
+bool Database::BeginTransaction()
+{
+ if (!mMysql)
+ return false;
+
+ // don't use queued execution if it has not been initialized
+ if (!m_threadBody)
+ {
+ if (tranThread == ACE_Based::Thread::current())
+ return false; // huh? this thread already started transaction
+
+ mMutex.acquire();
+ if (!_TransactionCmd("START TRANSACTION"))
+ {
+ mMutex.release(); // can't start transaction
+ return false;
+ }
+ return true; // transaction started
+ }
+
+ nMutex.acquire();
+ tranThread = ACE_Based::Thread::current(); // owner of this transaction
+ TransactionQueues::iterator i = m_tranQueues.find(tranThread);
+ if (i != m_tranQueues.end() && i->second != NULL)
+ // If for thread exists queue and also contains transaction
+ // delete that transaction (not allow trans in trans)
+ delete i->second;
+
+ m_tranQueues[tranThread] = new SqlTransaction();
+ nMutex.release();
+ return true;
+}
+
+bool Database::CommitTransaction()
+{
+ if (!mMysql)
+ return false;
+
+ bool _res = false;
+
+ // don't use queued execution if it has not been initialized
+ if (!m_threadBody)
+ {
+ if (tranThread != ACE_Based::Thread::current())
+ return false;
+
+ _res = _TransactionCmd("COMMIT");
+ tranThread = NULL;
+ mMutex.release();
+ return _res;
+ }
+
+ nMutex.acquire();
+ tranThread = ACE_Based::Thread::current();
+ TransactionQueues::iterator i = m_tranQueues.find(tranThread);
+ if (i != m_tranQueues.end() && i->second != NULL)
+ {
+ m_threadBody->Delay(i->second);
+ m_tranQueues.erase(i);
+ _res = true;
+ }
+ nMutex.release();
+ return _res;
+}
+
+bool Database::RollbackTransaction()
+{
+ if (!mMysql)
+ return false;
+
+ // don't use queued execution if it has not been initialized
+ if (!m_threadBody)
+ {
+ if (tranThread != ACE_Based::Thread::current())
+ return false;
+
+ bool _res = _TransactionCmd("ROLLBACK");
+ tranThread = NULL;
+ mMutex.release();
+ return _res;
+ }
+
+ nMutex.acquire();
+ tranThread = ACE_Based::Thread::current();
+ TransactionQueues::iterator i = m_tranQueues.find(tranThread);
+ if (i != m_tranQueues.end() && i->second != NULL)
+ {
+ delete i->second;
+ i->second = NULL;
+ m_tranQueues.erase(i);
+ }
+ nMutex.release();
+ return true;
+}
+
+void Database::InitDelayThread()
+{
+ assert(!m_delayThread);
+
+ //New delay thread for delay execute
+ m_threadBody = new SqlDelayThread(this); // will deleted at m_delayThread delete
+ m_delayThread = new ACE_Based::Thread(m_threadBody);
+}
+
+void Database::HaltDelayThread()
+{
+ if (!m_threadBody || !m_delayThread)
+ return;
+
+ m_threadBody->Stop(); //Stop event
+ m_delayThread->wait(); //Wait for flush to DB
+ delete m_delayThread; //This also deletes m_threadBody
+ m_delayThread = NULL;
+ m_threadBody = NULL;
+}
+
diff --git a/src/server/shared/Database/Database.h b/src/server/shared/Database/Database.h
new file mode 100644
index 00000000000..4ad5d29c993
--- /dev/null
+++ b/src/server/shared/Database/Database.h
@@ -0,0 +1,155 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef DATABASE_H
+#define DATABASE_H
+
+#include "Threading.h"
+#include "Utilities/UnorderedMap.h"
+#include "Database/SqlDelayThread.h"
+#include "Policies/Singleton.h"
+#include "ace/Thread_Mutex.h"
+#include "ace/Guard_T.h"
+
+#ifdef WIN32
+#define FD_SETSIZE 1024
+#include <winsock2.h>
+#include <mysql/mysql.h>
+#else
+#include <mysql.h>
+#endif
+
+class SqlTransaction;
+class SqlResultQueue;
+class SqlQueryHolder;
+
+typedef UNORDERED_MAP<ACE_Based::Thread* , SqlTransaction*> TransactionQueues;
+typedef UNORDERED_MAP<ACE_Based::Thread* , SqlResultQueue*> QueryQueues;
+
+#define MAX_QUERY_LEN 32*1024
+
+class Database
+{
+ protected:
+ TransactionQueues m_tranQueues; ///< Transaction queues from diff. threads
+ QueryQueues m_queryQueues; ///< Query queues from diff threads
+ SqlDelayThread* m_threadBody; ///< Pointer to delay sql executer (owned by m_delayThread)
+ ACE_Based::Thread* m_delayThread; ///< Pointer to executer thread
+
+ public:
+
+ Database();
+ ~Database();
+
+ /*! infoString should be formated like hostname;username;password;database. */
+ bool Initialize(const char *infoString);
+
+ void InitDelayThread();
+ void HaltDelayThread();
+
+ QueryResult_AutoPtr Query(const char *sql);
+ QueryResult_AutoPtr PQuery(const char *format,...) ATTR_PRINTF(2,3);
+ QueryNamedResult* QueryNamed(const char *sql);
+ QueryNamedResult* PQueryNamed(const char *format,...) ATTR_PRINTF(2,3);
+
+ /// Async queries and query holders, implemented in DatabaseImpl.h
+
+ // Query / member
+ template<class Class>
+ bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql);
+ template<class Class, typename ParamType1>
+ bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql);
+ template<class Class, typename ParamType1, typename ParamType2>
+ bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql);
+ template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+ bool AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
+ // Query / static
+ template<typename ParamType1>
+ bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql);
+ template<typename ParamType1, typename ParamType2>
+ bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql);
+ template<typename ParamType1, typename ParamType2, typename ParamType3>
+ bool AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql);
+ // PQuery / member
+ template<class Class>
+ bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...) ATTR_PRINTF(4,5);
+ template<class Class, typename ParamType1>
+ bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
+ template<class Class, typename ParamType1, typename ParamType2>
+ bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(6,7);
+ template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+ bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(7,8);
+ // PQuery / static
+ template<typename ParamType1>
+ bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(4,5);
+ template<typename ParamType1, typename ParamType2>
+ bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...) ATTR_PRINTF(5,6);
+ template<typename ParamType1, typename ParamType2, typename ParamType3>
+ bool AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...) ATTR_PRINTF(6,7);
+ template<class Class>
+ // QueryHolder
+ bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*), SqlQueryHolder *holder);
+ template<class Class, typename ParamType1>
+ bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1);
+
+ bool Execute(const char *sql);
+ bool PExecute(const char *format,...) ATTR_PRINTF(2,3);
+ bool DirectExecute(const char* sql);
+ bool DirectPExecute(const char *format,...) ATTR_PRINTF(2,3);
+
+ bool _UpdateDataBlobValue(const uint32 guid, const uint32 field, const int32 value);
+ bool _SetDataBlobValue(const uint32 guid, const uint32 field, const uint32 value);
+
+ // Writes SQL commands to a LOG file (see Trinityd.conf "LogSQL")
+ bool PExecuteLog(const char *format,...) ATTR_PRINTF(2,3);
+
+ bool BeginTransaction();
+ bool CommitTransaction();
+ bool RollbackTransaction();
+
+ operator bool () const { return mMysql != NULL; }
+ unsigned long escape_string(char *to, const char *from, unsigned long length);
+ void escape_string(std::string& str);
+
+ void ThreadStart();
+ void ThreadEnd();
+
+ // sets the result queue of the current thread, be careful what thread you call this from
+ void SetResultQueue(SqlResultQueue * queue);
+
+ bool CheckRequiredField(char const* table_name, char const* required_name);
+
+ private:
+ bool m_logSQL;
+ std::string m_logsDir;
+ ACE_Thread_Mutex mMutex; // For thread safe operations between core and mySQL server
+ ACE_Thread_Mutex nMutex; // For thread safe operations on m_transQueues
+
+ ACE_Based::Thread * tranThread;
+
+ MYSQL *mMysql;
+
+ static size_t db_count;
+
+ bool _TransactionCmd(const char *sql);
+ bool _Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount);
+};
+#endif
+
diff --git a/src/server/shared/Database/DatabaseEnv.h b/src/server/shared/Database/DatabaseEnv.h
new file mode 100644
index 00000000000..69236b076e9
--- /dev/null
+++ b/src/server/shared/Database/DatabaseEnv.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if !defined(DATABASEENV_H)
+#define DATABASEENV_H
+
+#include "Common.h"
+#include "Log.h"
+#include "Errors.h"
+
+#include "Database/Field.h"
+#include "Database/QueryResult.h"
+
+#include "Database/Database.h"
+typedef Database DatabaseType;
+#define _LIKE_ "LIKE"
+#define _TABLE_SIM_ "`"
+#define _CONCAT3_(A,B,C) "CONCAT( " A " , " B " , " C " )"
+#define _OFFSET_ "LIMIT %d,1"
+
+extern DatabaseType WorldDatabase;
+extern DatabaseType CharacterDatabase;
+extern DatabaseType LoginDatabase;
+
+#endif
+
diff --git a/src/server/shared/Database/DatabaseImpl.h b/src/server/shared/Database/DatabaseImpl.h
new file mode 100644
index 00000000000..f0ba9c84a30
--- /dev/null
+++ b/src/server/shared/Database/DatabaseImpl.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include "Database/Database.h"
+#include "Database/SqlOperations.h"
+
+
+/// Function body definitions for the template function members of the Database class
+
+
+#define ASYNC_QUERY_BODY(sql, queue_itr) \
+ if (!sql) return false; \
+ \
+ QueryQueues::iterator queue_itr; \
+ \
+ { \
+ ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
+ queue_itr = m_queryQueues.find(queryThread); \
+ if (queue_itr == m_queryQueues.end()) return false; \
+ }
+
+
+#define ASYNC_PQUERY_BODY(format, szQuery) \
+ if(!format) return false; \
+ \
+ char szQuery [MAX_QUERY_LEN]; \
+ \
+ { \
+ va_list ap; \
+ \
+ va_start(ap, format); \
+ int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap ); \
+ va_end(ap); \
+ \
+ if(res==-1) \
+ { \
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format); \
+ return false; \
+ } \
+ }
+
+
+#define ASYNC_DELAYHOLDER_BODY(holder, queue_itr) \
+ if (!holder) return false; \
+ \
+ QueryQueues::iterator queue_itr; \
+ \
+ { \
+ ACE_Based::Thread * queryThread = ACE_Based::Thread::current(); \
+ queue_itr = m_queryQueues.find(queryThread); \
+ if (queue_itr == m_queryQueues.end()) return false; \
+ }
+
+
+// -- Query / member --
+
+
+template<class Class>
+bool
+Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class>(object, method), itr->second));
+}
+
+
+template<class Class, typename ParamType1>
+bool
+Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, param1), itr->second));
+}
+
+
+template<class Class, typename ParamType1, typename ParamType2>
+bool
+Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2>(object, method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second));
+}
+
+
+template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+bool
+Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::QueryCallback<Class, ParamType1, ParamType2, ParamType3>(object, method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second));
+}
+
+
+// -- Query / static --
+
+
+template<typename ParamType1>
+bool
+Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1>(method, (QueryResult_AutoPtr)NULL, param1), itr->second));
+}
+
+
+template<typename ParamType1, typename ParamType2>
+bool
+Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1, ParamType2>(method, (QueryResult_AutoPtr)NULL, param1, param2), itr->second));
+}
+
+
+template<typename ParamType1, typename ParamType2, typename ParamType3>
+bool
+Database::AsyncQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *sql)
+{
+ ASYNC_QUERY_BODY(sql, itr)
+ return m_threadBody->Delay(new SqlQuery(sql, new Trinity::SQueryCallback<ParamType1, ParamType2, ParamType3>(method, (QueryResult_AutoPtr)NULL, param1, param2, param3), itr->second));
+}
+
+
+// -- PQuery / member --
+
+
+template<class Class>
+bool
+Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr), const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(object, method, szQuery);
+}
+
+
+template<class Class, typename ParamType1>
+bool
+Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(object, method, param1, szQuery);
+}
+
+
+template<class Class, typename ParamType1, typename ParamType2>
+bool
+Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(object, method, param1, param2, szQuery);
+}
+
+
+template<class Class, typename ParamType1, typename ParamType2, typename ParamType3>
+bool
+Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(object, method, param1, param2, param3, szQuery);
+}
+
+
+// -- PQuery / static --
+
+
+template<typename ParamType1>
+bool
+Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1), ParamType1 param1, const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(method, param1, szQuery);
+}
+
+
+template<typename ParamType1, typename ParamType2>
+bool
+Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2), ParamType1 param1, ParamType2 param2, const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(method, param1, param2, szQuery);
+}
+
+
+template<typename ParamType1, typename ParamType2, typename ParamType3>
+bool
+Database::AsyncPQuery(void (*method)(QueryResult_AutoPtr, ParamType1, ParamType2, ParamType3), ParamType1 param1, ParamType2 param2, ParamType3 param3, const char *format,...)
+{
+ ASYNC_PQUERY_BODY(format, szQuery)
+ return AsyncQuery(method, param1, param2, param3, szQuery);
+}
+
+
+// -- QueryHolder --
+
+
+template<class Class>
+bool
+Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*), SqlQueryHolder *holder)
+{
+ ASYNC_DELAYHOLDER_BODY(holder, itr)
+ return holder->Execute(new Trinity::QueryCallback<Class, SqlQueryHolder*>(object, method, (QueryResult_AutoPtr)NULL, holder), m_threadBody, itr->second);
+}
+
+
+template<class Class, typename ParamType1>
+bool
+Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult_AutoPtr, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1)
+{
+ ASYNC_DELAYHOLDER_BODY(holder, itr)
+ return holder->Execute(new Trinity::QueryCallback<Class, SqlQueryHolder*, ParamType1>(object, method, (QueryResult_AutoPtr)NULL, holder, param1), m_threadBody, itr->second);
+}
+
+
+#undef ASYNC_QUERY_BODY
+#undef ASYNC_PQUERY_BODY
+#undef ASYNC_DELAYHOLDER_BODY
diff --git a/src/server/shared/Database/Field.cpp b/src/server/shared/Database/Field.cpp
new file mode 100644
index 00000000000..191a2884aac
--- /dev/null
+++ b/src/server/shared/Database/Field.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DatabaseEnv.h"
+
+Field::Field() :
+mValue(NULL), mType(DB_TYPE_UNKNOWN)
+{
+}
+
+Field::Field(Field &f)
+{
+ const char *value;
+
+ value = f.GetString();
+
+ if (value)
+ {
+ mValue = new char[strlen(value) + 1];
+ if (mValue)
+ strcpy(mValue, value);
+ }
+ else
+ mValue = NULL;
+
+ mType = f.GetType();
+}
+
+Field::Field(const char *value, enum Field::DataTypes type) :
+mType(type)
+{
+ if (value)
+ {
+ mValue = new char[strlen(value) + 1];
+ if (mValue)
+ strcpy(mValue, value);
+ }
+ else
+ mValue = NULL;
+}
+
+Field::~Field()
+{
+ if (mValue)
+ delete [] mValue;
+}
+
+void Field::SetValue(const char *value)
+{
+ if (mValue)
+ delete [] mValue;
+
+ if (value)
+ {
+ mValue = new char[strlen(value) + 1];
+ strcpy(mValue, value);
+ }
+ else
+ mValue = NULL;
+}
diff --git a/src/server/shared/Database/Field.h b/src/server/shared/Database/Field.h
new file mode 100644
index 00000000000..8d149858a42
--- /dev/null
+++ b/src/server/shared/Database/Field.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if !defined(FIELD_H)
+#define FIELD_H
+
+class Field
+{
+ public:
+
+ enum DataTypes
+ {
+ DB_TYPE_UNKNOWN = 0x00,
+ DB_TYPE_STRING = 0x01,
+ DB_TYPE_INTEGER = 0x02,
+ DB_TYPE_FLOAT = 0x03,
+ DB_TYPE_BOOL = 0x04
+ };
+
+ Field();
+ Field(Field &f);
+ Field(const char *value, enum DataTypes type);
+
+ ~Field();
+
+ enum DataTypes GetType() const { return mType; }
+
+ const char *GetString() const { return mValue; }
+ std::string GetCppString() const
+ {
+ return mValue ? mValue : ""; // std::string s = 0 have undefine result in C++
+ }
+ float GetFloat() const { return mValue ? static_cast<float>(atof(mValue)) : 0.0f; }
+ bool GetBool() const { return mValue ? atoi(mValue) > 0 : false; }
+ int32 GetInt32() const { return mValue ? static_cast<int32>(atol(mValue)) : int32(0); }
+ uint8 GetUInt8() const { return mValue ? static_cast<uint8>(atol(mValue)) : uint8(0); }
+ uint16 GetUInt16() const { return mValue ? static_cast<uint16>(atol(mValue)) : uint16(0); }
+ int16 GetInt16() const { return mValue ? static_cast<int16>(atol(mValue)) : int16(0); }
+ uint32 GetUInt32() const { return mValue ? static_cast<uint32>(atol(mValue)) : uint32(0); }
+ uint64 GetUInt64() const
+ {
+ if(mValue)
+ {
+ uint64 value;
+ sscanf(mValue,UI64FMTD,&value);
+ return value;
+ }
+ else
+ return 0;
+ }
+ uint64 GetInt64() const
+ {
+ if(mValue)
+ {
+ int64 value;
+ sscanf(mValue,SI64FMTD,&value);
+ return value;
+ }
+ else
+ return 0;
+ }
+
+ void SetType(enum DataTypes type) { mType = type; }
+
+ void SetValue(const char *value);
+
+ private:
+ char *mValue;
+ enum DataTypes mType;
+};
+#endif
+
diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/shared/Database/QueryResult.cpp
new file mode 100644
index 00000000000..8b0c437b066
--- /dev/null
+++ b/src/server/shared/Database/QueryResult.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "DatabaseEnv.h"
+
+QueryResult::QueryResult(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount)
+: mResult(result)
+, mFieldCount(fieldCount)
+, mRowCount(rowCount)
+{
+ mCurrentRow = new Field[mFieldCount];
+ ASSERT(mCurrentRow);
+
+ for (uint32 i = 0; i < mFieldCount; i++)
+ mCurrentRow[i].SetType(ConvertNativeType(fields[i].type));
+}
+
+QueryResult::~QueryResult()
+{
+ EndQuery();
+}
+
+bool QueryResult::NextRow()
+{
+ MYSQL_ROW row;
+
+ if (!mResult)
+ return false;
+
+ row = mysql_fetch_row(mResult);
+ if (!row)
+ {
+ EndQuery();
+ return false;
+ }
+
+ for (uint32 i = 0; i < mFieldCount; i++)
+ mCurrentRow[i].SetValue(row[i]);
+
+ return true;
+}
+
+void QueryResult::EndQuery()
+{
+ if (mCurrentRow)
+ {
+ delete [] mCurrentRow;
+ mCurrentRow = 0;
+ }
+
+ if (mResult)
+ {
+ mysql_free_result(mResult);
+ mResult = 0;
+ }
+}
+
+enum Field::DataTypes QueryResult::ConvertNativeType(enum_field_types mysqlType) const
+{
+ switch (mysqlType)
+ {
+ case FIELD_TYPE_TIMESTAMP:
+ case FIELD_TYPE_DATE:
+ case FIELD_TYPE_TIME:
+ case FIELD_TYPE_DATETIME:
+ case FIELD_TYPE_YEAR:
+ case FIELD_TYPE_STRING:
+ case FIELD_TYPE_VAR_STRING:
+ case FIELD_TYPE_BLOB:
+ case FIELD_TYPE_SET:
+ case FIELD_TYPE_NULL:
+ return Field::DB_TYPE_STRING;
+ case FIELD_TYPE_TINY:
+
+ case FIELD_TYPE_SHORT:
+ case FIELD_TYPE_LONG:
+ case FIELD_TYPE_INT24:
+ case FIELD_TYPE_LONGLONG:
+ case FIELD_TYPE_ENUM:
+ return Field::DB_TYPE_INTEGER;
+ case FIELD_TYPE_DECIMAL:
+ case FIELD_TYPE_FLOAT:
+ case FIELD_TYPE_DOUBLE:
+ return Field::DB_TYPE_FLOAT;
+ default:
+ return Field::DB_TYPE_UNKNOWN;
+ }
+}
diff --git a/src/server/shared/Database/QueryResult.h b/src/server/shared/Database/QueryResult.h
new file mode 100644
index 00000000000..4eec9915362
--- /dev/null
+++ b/src/server/shared/Database/QueryResult.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#if !defined(QUERYRESULT_H)
+#define QUERYRESULT_H
+
+#include <ace/Refcounted_Auto_Ptr.h>
+#include <ace/Null_Mutex.h>
+
+#include "Field.h"
+
+#ifdef WIN32
+#define FD_SETSIZE 1024
+#include <winsock2.h>
+#include <mysql/mysql.h>
+#else
+#include <mysql.h>
+#endif
+
+class QueryResult
+{
+ public:
+ QueryResult(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount);
+ ~QueryResult();
+
+ bool NextRow();
+
+ Field *Fetch() const { return mCurrentRow; }
+
+ const Field & operator [] (int index) const { return mCurrentRow[index]; }
+
+ uint32 GetFieldCount() const { return mFieldCount; }
+ uint64 GetRowCount() const { return mRowCount; }
+
+ protected:
+ Field *mCurrentRow;
+ uint32 mFieldCount;
+ uint64 mRowCount;
+
+ private:
+ enum Field::DataTypes ConvertNativeType(enum_field_types mysqlType) const;
+ void EndQuery();
+ MYSQL_RES *mResult;
+
+};
+
+typedef ACE_Refcounted_Auto_Ptr<QueryResult, ACE_Null_Mutex> QueryResult_AutoPtr;
+
+typedef std::vector<std::string> QueryFieldNames;
+
+class QueryNamedResult
+{
+ public:
+ explicit QueryNamedResult(QueryResult* query, QueryFieldNames const& names) : mQuery(query), mFieldNames(names) {}
+ ~QueryNamedResult() { delete mQuery; }
+
+ // compatible interface with QueryResult
+ bool NextRow() { return mQuery->NextRow(); }
+ Field *Fetch() const { return mQuery->Fetch(); }
+ uint32 GetFieldCount() const { return mQuery->GetFieldCount(); }
+ uint64 GetRowCount() const { return mQuery->GetRowCount(); }
+ Field const& operator[] (int index) const { return (*mQuery)[index]; }
+
+ // named access
+ Field const& operator[] (const std::string &name) const { return mQuery->Fetch()[GetField_idx(name)]; }
+ QueryFieldNames const& GetFieldNames() const { return mFieldNames; }
+
+ uint32 GetField_idx(const std::string &name) const
+ {
+ for (size_t idx = 0; idx < mFieldNames.size(); ++idx)
+ {
+ if(mFieldNames[idx] == name)
+ return idx;
+ }
+ ASSERT(false && "unknown field name");
+ return uint32(-1);
+ }
+
+ protected:
+ QueryResult *mQuery;
+ QueryFieldNames mFieldNames;
+};
+
+#endif
+
diff --git a/src/server/shared/Database/SQLStorage.cpp b/src/server/shared/Database/SQLStorage.cpp
new file mode 100644
index 00000000000..f42c31b2fea
--- /dev/null
+++ b/src/server/shared/Database/SQLStorage.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "SQLStorage.h"
+#include "SQLStorageImpl.h"
+
+extern Database WorldDatabase;
+
+const char CreatureInfosrcfmt[]="iiiiiiiiiisssiiiiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifffliiiiiiiliiisi";
+const char CreatureInfodstfmt[]="iiiiiiiiiisssibbiiiifffiffiifiiiiiiiiiiffiiiiiiiiiiiiiiiiiiiiiiiisiifffliiiiiiiliiiii";
+const char CreatureDataAddonInfofmt[]="iiiiiis";
+const char CreatureModelfmt[]="iffbi";
+const char CreatureInfoAddonInfofmt[]="iiiiiis";
+const char EquipmentInfofmt[]="iiii";
+const char GameObjectInfosrcfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiisi";
+const char GameObjectInfodstfmt[]="iiissssiifiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii";
+const char ItemPrototypesrcfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiisiiiii";
+const char ItemPrototypedstfmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifiiiiiiiii";
+const char PageTextfmt[]="isii";
+const char InstanceTemplatesrcfmt[]="iiiffffsb";
+const char InstanceTemplatedstfmt[]="iiiffffib";
+
+SQLStorage sCreatureStorage(CreatureInfosrcfmt, CreatureInfodstfmt, "entry","creature_template");
+SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");
+SQLStorage sCreatureModelStorage(CreatureModelfmt,"modelid","creature_model_info");
+SQLStorage sCreatureInfoAddonStorage(CreatureInfoAddonInfofmt,"entry","creature_template_addon");
+SQLStorage sEquipmentStorage(EquipmentInfofmt,"entry","creature_equip_template");
+SQLStorage sGOStorage(GameObjectInfosrcfmt, GameObjectInfodstfmt, "entry","gameobject_template");
+SQLStorage sItemStorage(ItemPrototypesrcfmt, ItemPrototypedstfmt, "entry","item_template");
+SQLStorage sPageTextStore(PageTextfmt,"entry","page_text");
+SQLStorage sInstanceTemplate(InstanceTemplatesrcfmt, InstanceTemplatedstfmt, "map","instance_template");
+
+void SQLStorage::Free ()
+{
+ uint32 offset=0;
+ for (uint32 x=0; x<iNumFields; x++)
+ if (dst_format[x]==FT_STRING)
+ {
+ for (uint32 y=0; y<MaxEntry; y++)
+ if(pIndex[y])
+ delete [] *(char**)((char*)(pIndex[y])+offset);
+
+ offset += sizeof(char*);
+ }
+ else if (dst_format[x]==FT_LOGIC)
+ offset += sizeof(bool);
+ else if (dst_format[x]==FT_BYTE)
+ offset += sizeof(char);
+ else
+ offset += 4;
+
+ delete [] pIndex;
+ delete [] data;
+}
+
+void SQLStorage::Load()
+{
+ SQLStorageLoader loader;
+ loader.Load(*this);
+}
diff --git a/src/server/shared/Database/SQLStorage.h b/src/server/shared/Database/SQLStorage.h
new file mode 100644
index 00000000000..931c46b1995
--- /dev/null
+++ b/src/server/shared/Database/SQLStorage.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef SQLSTORAGE_H
+#define SQLSTORAGE_H
+
+#include "Common.h"
+#include "Database/DatabaseEnv.h"
+
+class SQLStorage
+{
+ template<class T>
+ friend struct SQLStorageLoaderBase;
+
+ public:
+
+ SQLStorage(const char* fmt, const char * _entry_field, const char * sqlname)
+ {
+ src_format = fmt;
+ dst_format = fmt;
+ init(_entry_field, sqlname);
+ }
+
+ SQLStorage(const char* src_fmt, const char* dst_fmt, const char * _entry_field, const char * sqlname)
+ {
+ src_format = src_fmt;
+ dst_format = dst_fmt;
+ init(_entry_field, sqlname);
+ }
+
+ ~SQLStorage()
+ {
+ Free();
+ }
+
+ template<class T>
+ T const* LookupEntry(uint32 id) const
+ {
+ if( id == 0 )
+ return NULL;
+ if(id >= MaxEntry)
+ return NULL;
+ return reinterpret_cast<T const*>(pIndex[id]);
+ }
+
+ uint32 RecordCount;
+ uint32 MaxEntry;
+ uint32 iNumFields;
+
+ char const* GetTableName() const { return table; }
+
+ void Load();
+ void Free();
+
+ private:
+ void init(const char * _entry_field, const char * sqlname)
+ {
+ entry_field = _entry_field;
+ table=sqlname;
+ data=NULL;
+ pIndex=NULL;
+ iNumFields = strlen(src_format);
+ MaxEntry = 0;
+ }
+
+ char** pIndex;
+
+ char *data;
+ const char *src_format;
+ const char *dst_format;
+ const char *table;
+ const char *entry_field;
+ //bool HasString;
+};
+
+template <class T>
+struct SQLStorageLoaderBase
+{
+ public:
+ void Load(SQLStorage &storage);
+
+ template<class S, class D>
+ void convert(uint32 field_pos, S src, D &dst);
+ template<class S>
+ void convert_to_str(uint32 field_pos, S src, char * & dst);
+ template<class D>
+ void convert_from_str(uint32 field_pos, char * src, D& dst);
+ void convert_str_to_str(uint32 field_pos, char *src, char *&dst);
+
+ private:
+ template<class V>
+ void storeValue(V value, SQLStorage &store, char *p, int x, uint32 &offset);
+ void storeValue(char * value, SQLStorage &store, char *p, int x, uint32 &offset);
+};
+
+struct SQLStorageLoader : public SQLStorageLoaderBase<SQLStorageLoader>
+{
+};
+
+#endif
+
diff --git a/src/server/shared/Database/SQLStorageImpl.h b/src/server/shared/Database/SQLStorageImpl.h
new file mode 100644
index 00000000000..c74be48c34c
--- /dev/null
+++ b/src/server/shared/Database/SQLStorageImpl.h
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ProgressBar.h"
+#include "Log.h"
+#include "DBCFileLoader.h"
+
+template<class T>
+template<class S, class D>
+void SQLStorageLoaderBase<T>::convert(uint32 /*field_pos*/, S src, D &dst)
+{
+ dst = D(src);
+}
+
+template<class T>
+void SQLStorageLoaderBase<T>::convert_str_to_str(uint32 /*field_pos*/, char *src, char *&dst)
+{
+ if(!src)
+ {
+ dst = new char[1];
+ *dst = 0;
+ }
+ else
+ {
+ uint32 l = strlen(src) + 1;
+ dst = new char[l];
+ memcpy(dst, src, l);
+ }
+}
+
+template<class T>
+template<class S>
+void SQLStorageLoaderBase<T>::convert_to_str(uint32 /*field_pos*/, S /*src*/, char * & dst)
+{
+ dst = new char[1];
+ *dst = 0;
+}
+
+template<class T>
+template<class D>
+void SQLStorageLoaderBase<T>::convert_from_str(uint32 /*field_pos*/, char * /*src*/, D& dst)
+{
+ dst = 0;
+}
+
+template<class T>
+template<class V>
+void SQLStorageLoaderBase<T>::storeValue(V value, SQLStorage &store, char *p, int x, uint32 &offset)
+{
+ T * subclass = (static_cast<T*>(this));
+ switch(store.dst_format[x])
+ {
+ case FT_LOGIC:
+ subclass->convert(x, value, *((bool*)(&p[offset])) );
+ offset+=sizeof(bool);
+ break;
+ case FT_BYTE:
+ subclass->convert(x, value, *((char*)(&p[offset])) );
+ offset+=sizeof(char);
+ break;
+ case FT_INT:
+ subclass->convert(x, value, *((uint32*)(&p[offset])) );
+ offset+=sizeof(uint32);
+ break;
+ case FT_FLOAT:
+ subclass->convert(x, value, *((float*)(&p[offset])) );
+ offset+=sizeof(float);
+ break;
+ case FT_STRING:
+ subclass->convert_to_str(x, value, *((char**)(&p[offset])) );
+ offset+=sizeof(char*);
+ break;
+ }
+}
+
+template<class T>
+void SQLStorageLoaderBase<T>::storeValue(char * value, SQLStorage &store, char *p, int x, uint32 &offset)
+{
+ T * subclass = (static_cast<T*>(this));
+ switch(store.dst_format[x])
+ {
+ case FT_LOGIC:
+ subclass->convert_from_str(x, value, *((bool*)(&p[offset])) );
+ offset+=sizeof(bool);
+ break;
+ case FT_BYTE:
+ subclass->convert_from_str(x, value, *((char*)(&p[offset])) );
+ offset+=sizeof(char);
+ break;
+ case FT_INT:
+ subclass->convert_from_str(x, value, *((uint32*)(&p[offset])) );
+ offset+=sizeof(uint32);
+ break;
+ case FT_FLOAT:
+ subclass->convert_from_str(x, value, *((float*)(&p[offset])) );
+ offset+=sizeof(float);
+ break;
+ case FT_STRING:
+ subclass->convert_str_to_str(x, value, *((char**)(&p[offset])) );
+ offset+=sizeof(char*);
+ break;
+ }
+}
+
+template<class T>
+void SQLStorageLoaderBase<T>::Load(SQLStorage &store)
+{
+ uint32 maxi;
+ Field *fields;
+ QueryResult_AutoPtr result = WorldDatabase.PQuery("SELECT MAX(%s) FROM %s", store.entry_field, store.table);
+ if(!result)
+ {
+ sLog.outError("Error loading %s table (not exist?)\n", store.table);
+ exit(1); // Stop server at loading non exited table or not accessable table
+ }
+
+ maxi = (*result)[0].GetUInt32()+1;
+
+ result = WorldDatabase.PQuery("SELECT COUNT(*) FROM %s", store.table);
+ if(result)
+ {
+ fields = result->Fetch();
+ store.RecordCount = fields[0].GetUInt32();
+ }
+ else
+ store.RecordCount = 0;
+
+ result = WorldDatabase.PQuery("SELECT * FROM %s", store.table);
+
+ if(!result)
+ {
+ sLog.outError("%s table is empty!\n", store.table);
+ store.RecordCount = 0;
+ return;
+ }
+
+ uint32 recordsize = 0;
+ uint32 offset = 0;
+
+ if(store.iNumFields != result->GetFieldCount())
+ {
+ store.RecordCount = 0;
+ sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n", store.table, store.iNumFields);
+ exit(1); // Stop server at loading broken or non-compatible table.
+ }
+
+ //get struct size
+ uint32 sc=0;
+ uint32 bo=0;
+ uint32 bb=0;
+ for (uint32 x=0; x< store.iNumFields; x++)
+ if(store.dst_format[x]==FT_STRING)
+ ++sc;
+ else if (store.dst_format[x]==FT_LOGIC)
+ ++bo;
+ else if (store.dst_format[x]==FT_BYTE)
+ ++bb;
+ recordsize=(store.iNumFields-sc-bo-bb)*4+sc*sizeof(char*)+bo*sizeof(bool)+bb*sizeof(char);
+
+ char** newIndex=new char*[maxi];
+ memset(newIndex,0,maxi*sizeof(char*));
+
+ char * _data= new char[store.RecordCount *recordsize];
+ uint32 count=0;
+ barGoLink bar( store.RecordCount );
+ do
+ {
+ fields = result->Fetch();
+ bar.step();
+ char *p=(char*)&_data[recordsize*count];
+ newIndex[fields[0].GetUInt32()]=p;
+
+ offset=0;
+ for (uint32 x = 0; x < store.iNumFields; x++)
+ switch(store.src_format[x])
+ {
+ case FT_LOGIC:
+ storeValue((bool)(fields[x].GetUInt32() > 0), store, p, x, offset); break;
+ case FT_BYTE:
+ storeValue((char)fields[x].GetUInt8(), store, p, x, offset); break;
+ case FT_INT:
+ storeValue((uint32)fields[x].GetUInt32(), store, p, x, offset); break;
+ case FT_FLOAT:
+ storeValue((float)fields[x].GetFloat(), store, p, x, offset); break;
+ case FT_STRING:
+ storeValue((char*)fields[x].GetString(), store, p, x, offset); break;
+ }
+ ++count;
+ }while( result->NextRow() );
+
+ store.pIndex = newIndex;
+ store.MaxEntry = maxi;
+ store.data = _data;
+}
+
diff --git a/src/server/shared/Database/SqlDelayThread.cpp b/src/server/shared/Database/SqlDelayThread.cpp
new file mode 100644
index 00000000000..43de3c63ffc
--- /dev/null
+++ b/src/server/shared/Database/SqlDelayThread.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Database/SqlDelayThread.h"
+#include "Database/SqlOperations.h"
+#include "DatabaseEnv.h"
+
+SqlDelayThread::SqlDelayThread(Database* db) : m_dbEngine(db), m_running(true)
+{
+}
+
+void SqlDelayThread::run()
+{
+ mysql_thread_init();
+
+ SqlAsyncTask * s = NULL;
+
+ ACE_Time_Value _time(2);
+ while (m_running)
+ {
+ // if the running state gets turned off while sleeping
+ // empty the queue before exiting
+ s = dynamic_cast<SqlAsyncTask*> (m_sqlQueue.dequeue());
+ if (s)
+ {
+ s->call();
+ delete s;
+ }
+ }
+
+ mysql_thread_end();
+}
+
+void SqlDelayThread::Stop()
+{
+ m_running = false;
+ m_sqlQueue.queue()->deactivate();
+}
+
+bool SqlDelayThread::Delay(SqlOperation* sql)
+{
+ int res = m_sqlQueue.enqueue(new SqlAsyncTask(m_dbEngine, sql));
+ return (res != -1);
+}
diff --git a/src/server/shared/Database/SqlDelayThread.h b/src/server/shared/Database/SqlDelayThread.h
new file mode 100644
index 00000000000..d603813c8fa
--- /dev/null
+++ b/src/server/shared/Database/SqlDelayThread.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __SQLDELAYTHREAD_H
+#define __SQLDELAYTHREAD_H
+
+#include "ace/Thread_Mutex.h"
+#include "ace/Activation_Queue.h"
+#include "Threading.h"
+
+class Database;
+class SqlOperation;
+
+class SqlDelayThread : public ACE_Based::Runnable
+{
+ typedef ACE_Activation_Queue SqlQueue;
+
+ private:
+ SqlQueue m_sqlQueue; ///< Queue of SQL statements
+ Database* m_dbEngine; ///< Pointer to used Database engine
+ volatile bool m_running;
+
+ SqlDelayThread();
+ public:
+ SqlDelayThread(Database* db);
+
+ ///< Put sql statement to delay queue
+ bool Delay(SqlOperation* sql);
+
+ void Stop(); ///< Stop event
+ virtual void run(); ///< Main Thread loop
+};
+#endif //__SQLDELAYTHREAD_H
diff --git a/src/server/shared/Database/SqlOperations.cpp b/src/server/shared/Database/SqlOperations.cpp
new file mode 100644
index 00000000000..785c5cb84e7
--- /dev/null
+++ b/src/server/shared/Database/SqlOperations.cpp
@@ -0,0 +1,209 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "SqlOperations.h"
+#include "SqlDelayThread.h"
+#include "DatabaseEnv.h"
+#include "DatabaseImpl.h"
+
+/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
+
+void SqlStatement::Execute(Database *db)
+{
+ /// just do it
+ db->DirectExecute(m_sql);
+}
+
+void SqlTransaction::Execute(Database *db)
+{
+ const char* sql;
+
+ m_Mutex.acquire();
+ if (m_queue.empty())
+ {
+ m_Mutex.release();
+ return;
+ }
+
+ db->DirectExecute("START TRANSACTION");
+ while (!m_queue.empty())
+ {
+ sql = m_queue.front();
+
+ if (!db->DirectExecute(sql))
+ {
+ free((void*)const_cast<char*>(sql));
+ m_queue.pop();
+ db->DirectExecute("ROLLBACK");
+ while (!m_queue.empty())
+ {
+ free((void*)const_cast<char*>(m_queue.front()));
+ m_queue.pop();
+ }
+ m_Mutex.release();
+ return;
+ }
+
+ free((void*)const_cast<char*>(sql));
+ m_queue.pop();
+ }
+
+ db->DirectExecute("COMMIT");
+ m_Mutex.release();
+}
+
+/// ---- ASYNC QUERIES ----
+
+void SqlQuery::Execute(Database *db)
+{
+ if (!m_callback || !m_queue)
+ return;
+
+ /// execute the query and store the result in the callback
+ m_callback->SetResult(db->Query(m_sql));
+ /// add the callback to the sql result queue of the thread it originated from
+ m_queue->add(m_callback);
+}
+
+void SqlResultQueue::Update()
+{
+ /// execute the callbacks waiting in the synchronization queue
+ Trinity::IQueryCallback* callback;
+ while (next(callback))
+ {
+ callback->Execute();
+ delete callback;
+ }
+}
+
+bool SqlQueryHolder::Execute(Trinity::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue)
+{
+ if (!callback || !thread || !queue)
+ return false;
+
+ /// delay the execution of the queries, sync them with the delay thread
+ /// which will in turn resync on execution (via the queue) and call back
+ SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue);
+ thread->Delay(holderEx);
+ return true;
+}
+
+bool SqlQueryHolder::SetQuery(size_t index, const char *sql)
+{
+ if (m_queries.size() <= index)
+ {
+ sLog.outError("Query index (%u) out of range (size: %u) for query: %s",index,(uint32)m_queries.size(),sql);
+ return false;
+ }
+
+ if (m_queries[index].first != NULL)
+ {
+ sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",
+ index,m_queries[index].first,sql);
+ return false;
+ }
+
+ /// not executed yet, just stored (it's not called a holder for nothing)
+ m_queries[index] = SqlResultPair(strdup(sql), QueryResult_AutoPtr(NULL));
+ return true;
+}
+
+bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...)
+{
+ if (!format)
+ {
+ sLog.outError("Query (index: %u) is empty.",index);
+ return false;
+ }
+
+ va_list ap;
+ char szQuery [MAX_QUERY_LEN];
+ va_start(ap, format);
+ int res = vsnprintf(szQuery, MAX_QUERY_LEN, format, ap);
+ va_end(ap);
+
+ if (res==-1)
+ {
+ sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
+ return false;
+ }
+
+ return SetQuery(index,szQuery);
+}
+
+QueryResult_AutoPtr SqlQueryHolder::GetResult(size_t index)
+{
+ if (index < m_queries.size())
+ {
+ /// the query strings are freed on the first GetResult or in the destructor
+ if (m_queries[index].first != NULL)
+ {
+ free((void*)(const_cast<char*>(m_queries[index].first)));
+ m_queries[index].first = NULL;
+ }
+ /// when you get a result aways remember to delete it!
+ return m_queries[index].second;
+ }
+ else
+ return QueryResult_AutoPtr(NULL);
+}
+
+void SqlQueryHolder::SetResult(size_t index, QueryResult_AutoPtr result)
+{
+ /// store the result in the holder
+ if (index < m_queries.size())
+ m_queries[index].second = result;
+}
+
+SqlQueryHolder::~SqlQueryHolder()
+{
+ for (size_t i = 0; i < m_queries.size(); i++)
+ {
+ /// if the result was never used, free the resources
+ /// results used already (getresult called) are expected to be deleted
+ if (m_queries[i].first != NULL)
+ free((void*)(const_cast<char*>(m_queries[i].first)));
+ }
+}
+
+void SqlQueryHolder::SetSize(size_t size)
+{
+ /// to optimize push_back, reserve the number of queries about to be executed
+ m_queries.resize(size);
+}
+
+void SqlQueryHolderEx::Execute(Database *db)
+{
+ if (!m_holder || !m_callback || !m_queue)
+ return;
+
+ /// we can do this, we are friends
+ std::vector<SqlQueryHolder::SqlResultPair> &queries = m_holder->m_queries;
+
+ for (size_t i = 0; i < queries.size(); i++)
+ {
+ /// execute all queries in the holder and pass the results
+ char const *sql = queries[i].first;
+ if(sql) m_holder->SetResult(i, db->Query(sql));
+ }
+
+ /// sync with the caller thread
+ m_queue->add(m_callback);
+}
diff --git a/src/server/shared/Database/SqlOperations.h b/src/server/shared/Database/SqlOperations.h
new file mode 100644
index 00000000000..f2e09c0c921
--- /dev/null
+++ b/src/server/shared/Database/SqlOperations.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef __SQLOPERATIONS_H
+#define __SQLOPERATIONS_H
+
+#include "Common.h"
+
+#include "ace/Thread_Mutex.h"
+#include "ace/Method_Request.h"
+#include "LockedQueue.h"
+#include <queue>
+#include "Utilities/Callback.h"
+#include "QueryResult.h"
+
+/// ---- BASE ---
+
+class Database;
+class SqlDelayThread;
+
+class SqlOperation
+{
+ public:
+ virtual void OnRemove() { delete this; }
+ virtual void Execute(Database *db) = 0;
+ virtual ~SqlOperation() {}
+};
+
+/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
+
+class SqlStatement : public SqlOperation
+{
+ private:
+ const char *m_sql;
+ public:
+ SqlStatement(const char *sql) : m_sql(strdup(sql)){}
+ ~SqlStatement() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
+ void Execute(Database *db);
+};
+
+class SqlTransaction : public SqlOperation
+{
+ private:
+ std::queue<const char*> m_queue;
+ ACE_Thread_Mutex m_Mutex;
+ public:
+ SqlTransaction() {}
+ void DelayExecute(const char *sql)
+ {
+ m_Mutex.acquire();
+ char* _sql = strdup(sql);
+ if (_sql)
+ m_queue.push(_sql);
+ m_Mutex.release();
+ }
+ void Execute(Database *db);
+};
+
+/// ---- ASYNC QUERIES ----
+
+class SqlQuery; /// contains a single async query
+class QueryResult; /// the result of one
+class SqlResultQueue; /// queue for thread sync
+class SqlQueryHolder; /// groups several async quries
+class SqlQueryHolderEx; /// points to a holder, added to the delay thread
+
+class SqlResultQueue : public ACE_Based::LockedQueue<Trinity::IQueryCallback* , ACE_Thread_Mutex>
+{
+ public:
+ SqlResultQueue() {}
+ void Update();
+};
+
+class SqlQuery : public SqlOperation
+{
+ private:
+ const char *m_sql;
+ Trinity::IQueryCallback * m_callback;
+ SqlResultQueue * m_queue;
+ public:
+ SqlQuery(const char *sql, Trinity::IQueryCallback * callback, SqlResultQueue * queue)
+ : m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {}
+ ~SqlQuery() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
+ void Execute(Database *db);
+};
+
+class SqlQueryHolder
+{
+ friend class SqlQueryHolderEx;
+ private:
+ typedef std::pair<const char*, QueryResult_AutoPtr> SqlResultPair;
+ std::vector<SqlResultPair> m_queries;
+ public:
+ SqlQueryHolder() {}
+ ~SqlQueryHolder();
+ bool SetQuery(size_t index, const char *sql);
+ bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4);
+ void SetSize(size_t size);
+ QueryResult_AutoPtr GetResult(size_t index);
+ void SetResult(size_t index, QueryResult_AutoPtr result);
+ bool Execute(Trinity::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue);
+};
+
+class SqlQueryHolderEx : public SqlOperation
+{
+ private:
+ SqlQueryHolder * m_holder;
+ Trinity::IQueryCallback * m_callback;
+ SqlResultQueue * m_queue;
+ public:
+ SqlQueryHolderEx(SqlQueryHolder *holder, Trinity::IQueryCallback * callback, SqlResultQueue * queue)
+ : m_holder(holder), m_callback(callback), m_queue(queue) {}
+ void Execute(Database *db);
+};
+
+class SqlAsyncTask : public ACE_Method_Request
+{
+public:
+ SqlAsyncTask(Database * db, SqlOperation * op) : m_db(db), m_op(op){}
+ ~SqlAsyncTask()
+ {
+ if (!m_op)
+ return;
+
+ delete m_op;
+ m_op = NULL;
+ }
+
+ int call()
+ {
+ if (m_db == NULL || m_op == NULL)
+ return -1;
+
+ try
+ {
+ m_op->Execute(m_db);
+ }
+ catch(...)
+ {
+ return -1;
+ }
+
+ return 0;
+ }
+
+private:
+ Database * m_db;
+ SqlOperation * m_op;
+};
+#endif //__SQLOPERATIONS_H
+
diff --git a/src/server/shared/DelayExecutor.cpp b/src/server/shared/DelayExecutor.cpp
new file mode 100644
index 00000000000..9a718823232
--- /dev/null
+++ b/src/server/shared/DelayExecutor.cpp
@@ -0,0 +1,111 @@
+#include <ace/Singleton.h>
+#include <ace/Thread_Mutex.h>
+#include <ace/Log_Msg.h>
+
+#include "DelayExecutor.h"
+
+DelayExecutor* DelayExecutor::instance()
+{
+ return ACE_Singleton<DelayExecutor, ACE_Thread_Mutex>::instance();
+}
+
+DelayExecutor::DelayExecutor()
+ : activated_(false), pre_svc_hook_(0), post_svc_hook_(0)
+{
+}
+
+DelayExecutor::~DelayExecutor()
+{
+ if (pre_svc_hook_)
+ delete pre_svc_hook_;
+
+ if (post_svc_hook_)
+ delete post_svc_hook_;
+
+ deactivate();
+}
+
+int DelayExecutor::deactivate()
+{
+ if (!activated())
+ return -1;
+
+ activated(false);
+ queue_.queue()->deactivate();
+ wait();
+
+ return 0;
+}
+
+int DelayExecutor::svc()
+{
+ if (pre_svc_hook_)
+ pre_svc_hook_->call();
+
+ for (;;)
+ {
+ ACE_Method_Request* rq = queue_.dequeue();
+
+ if (!rq)
+ break;
+
+ rq->call();
+ delete rq;
+ }
+
+ if (post_svc_hook_)
+ post_svc_hook_->call();
+
+ return 0;
+}
+
+int DelayExecutor::activate(int num_threads, ACE_Method_Request* pre_svc_hook, ACE_Method_Request* post_svc_hook)
+{
+ if (activated())
+ return -1;
+
+ if (num_threads < 1)
+ return -1;
+
+ if (pre_svc_hook_)
+ delete pre_svc_hook_;
+
+ if (post_svc_hook_)
+ delete post_svc_hook_;
+
+ pre_svc_hook_ = pre_svc_hook;
+ post_svc_hook_ = post_svc_hook;
+
+ queue_.queue()->activate();
+
+ if (ACE_Task_Base::activate(THR_NEW_LWP | THR_JOINABLE | THR_INHERIT_SCHED, num_threads) == -1)
+ return -1;
+
+ activated(true);
+
+ return true;
+}
+
+int DelayExecutor::execute(ACE_Method_Request* new_req)
+{
+ if (new_req == NULL)
+ return -1;
+
+ if (queue_.enqueue(new_req, (ACE_Time_Value*)&ACE_Time_Value::zero) == -1)
+ {
+ delete new_req;
+ ACE_ERROR_RETURN((LM_ERROR, ACE_TEXT("(%t) %p\n"), ACE_TEXT("DelayExecutor::execute enqueue")), -1);
+ }
+
+ return 0;
+}
+
+bool DelayExecutor::activated()
+{
+ return activated_;
+}
+
+void DelayExecutor::activated(bool s)
+{
+ activated_ = s;
+}
diff --git a/src/server/shared/DelayExecutor.h b/src/server/shared/DelayExecutor.h
new file mode 100644
index 00000000000..664d8ca78a2
--- /dev/null
+++ b/src/server/shared/DelayExecutor.h
@@ -0,0 +1,37 @@
+#ifndef _M_DELAY_EXECUTOR_H
+#define _M_DELAY_EXECUTOR_H
+
+#include <ace/Task.h>
+#include <ace/Activation_Queue.h>
+#include <ace/Method_Request.h>
+
+class DelayExecutor : protected ACE_Task_Base
+{
+ public:
+
+ DelayExecutor();
+ virtual ~DelayExecutor();
+
+ static DelayExecutor* instance();
+
+ int execute(ACE_Method_Request* new_req);
+
+ int activate(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL);
+
+ int deactivate();
+
+ bool activated();
+
+ virtual int svc();
+
+ private:
+
+ ACE_Activation_Queue queue_;
+ ACE_Method_Request* pre_svc_hook_;
+ ACE_Method_Request* post_svc_hook_;
+ bool activated_;
+
+ void activated(bool s);
+};
+
+#endif // _M_DELAY_EXECUTOR_H
diff --git a/src/server/shared/Errors.h b/src/server/shared/Errors.h
new file mode 100644
index 00000000000..15c6b1414ed
--- /dev/null
+++ b/src/server/shared/Errors.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITYCORE_ERRORS_H
+#define TRINITYCORE_ERRORS_H
+
+#include "Common.h"
+
+#if PLATFORM != PLATFORM_WINDOWS
+#ifndef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#endif
+
+#ifdef HAVE_ACE_STACK_TRACE_H
+#include "ace/Stack_Trace.h"
+#endif
+
+#ifdef HAVE_ACE_STACK_TRACE_H // old versions ACE not have Stack_Trace.h but used at some oS for better compatibility
+#define WPAssert( assertion ) { if (!(assertion)) { ACE_Stack_Trace st; fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n%s\n", __FILE__, __LINE__,__FUNCTION__, #assertion, st.c_str()); assert( #assertion &&0 ); } }
+#else
+#define WPAssert( assertion ) { if (!(assertion)) { fprintf( stderr, "\n%s:%i in %s ASSERTION FAILED2:\n %s\n", __FILE__, __LINE__,__FUNCTION__, #assertion); assert( #assertion &&0 ); } }
+#endif
+#define WPError( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%\n%s:%i in %s ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( false ); }
+#define WPWarning( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s WARNING:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); }
+
+#define WPFatal( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "\n%s:%i in %s FATAL ERROR:\n %s\n", __FILE__, __LINE__, __FUNCTION__, (char *)errmsg ); assert( #assertion &&0 ); abort(); }
+
+#define ASSERT WPAssert
+#endif
+
diff --git a/src/server/shared/LockedQueue.h b/src/server/shared/LockedQueue.h
new file mode 100644
index 00000000000..9f8afae6c14
--- /dev/null
+++ b/src/server/shared/LockedQueue.h
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef LOCKEDQUEUE_H
+#define LOCKEDQUEUE_H
+
+#include <ace/Guard_T.h>
+#include <ace/Thread_Mutex.h>
+#include <deque>
+#include <assert.h>
+#include "Errors.h"
+
+namespace ACE_Based
+{
+ template <class T, class LockType, typename StorageType=std::deque<T> >
+ class LockedQueue
+ {
+ //! Lock access to the queue.
+ LockType _lock;
+
+ //! Storage backing the queue.
+ StorageType _queue;
+
+ //! Cancellation flag.
+ volatile bool _canceled;
+
+ public:
+
+ //! Create a LockedQueue.
+ LockedQueue()
+ : _canceled(false)
+ {
+ }
+
+ //! Destroy a LockedQueue.
+ virtual ~LockedQueue()
+ {
+ }
+
+ //! Adds an item to the queue.
+ void add(const T& item)
+ {
+ lock();
+
+ //ASSERT(!this->_canceled);
+ // throw Cancellation_Exception();
+
+ _queue.push_back(item);
+
+ unlock();
+ }
+
+ //! Gets the next result in the queue, if any.
+ bool next(T& result)
+ {
+ // ACE_Guard<LockType> g(this->_lock);
+ ACE_GUARD_RETURN (LockType, g, this->_lock, false);
+
+ if (_queue.empty())
+ return false;
+
+ //ASSERT (!_queue.empty() || !this->_canceled);
+ // throw Cancellation_Exception();
+ result = _queue.front();
+ _queue.pop_front();
+
+ return true;
+ }
+
+ //! Peeks at the top of the queue. Remember to unlock after use.
+ T& peek()
+ {
+ lock();
+
+ T& result = _queue.front();
+
+ return result;
+ }
+
+ //! Cancels the queue.
+ void cancel()
+ {
+ lock();
+
+ _canceled = true;
+
+ unlock();
+ }
+
+ //! Checks if the queue is cancelled.
+ bool cancelled()
+ {
+ ACE_Guard<LockType> g(this->_lock);
+ return _canceled;
+ }
+
+ //! Locks the queue for access.
+ void lock()
+ {
+ this->_lock.acquire();
+ }
+
+ //! Unlocks the queue.
+ void unlock()
+ {
+ this->_lock.release();
+ }
+
+ ///! Calls pop_front of the queue
+ void pop_front()
+ {
+ ACE_GUARD (LockType, g, this->_lock);
+ _queue.pop_front();
+ }
+
+ ///! Checks if we're empty or not with locks held
+ bool empty()
+ {
+ ACE_GUARD_RETURN (LockType, g, this->_lock, false);
+ return _queue.empty();
+ }
+ };
+}
+#endif
diff --git a/src/server/shared/Log.cpp b/src/server/shared/Log.cpp
new file mode 100644
index 00000000000..187b9eaa79b
--- /dev/null
+++ b/src/server/shared/Log.cpp
@@ -0,0 +1,1005 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "Log.h"
+#include "Policies/SingletonImp.h"
+#include "Config/ConfigEnv.h"
+#include "Util.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+INSTANTIATE_SINGLETON_1( Log );
+
+Log::Log() :
+ raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL),
+ dberLogfile(NULL), chatLogfile(NULL), m_gmlog_per_account(false),
+ m_enableLogDBLater(false), m_enableLogDB(false), m_colored(false),
+ arenaLogFile(NULL)
+{
+ Initialize();
+}
+
+Log::~Log()
+{
+ if( logfile != NULL )
+ fclose(logfile);
+ logfile = NULL;
+
+ if( gmLogfile != NULL )
+ fclose(gmLogfile);
+ gmLogfile = NULL;
+
+ if (charLogfile != NULL)
+ fclose(charLogfile);
+ charLogfile = NULL;
+
+ if( dberLogfile != NULL )
+ fclose(dberLogfile);
+ dberLogfile = NULL;
+
+ if (raLogfile != NULL)
+ fclose(raLogfile);
+ raLogfile = NULL;
+
+ if (chatLogfile != NULL)
+ fclose(chatLogfile);
+ chatLogfile = NULL;
+
+ if (arenaLogFile != NULL)
+ fclose(arenaLogFile);
+ arenaLogFile = NULL;
+}
+
+void Log::SetLogLevel(char *Level)
+{
+ int32 NewLevel =atoi((char*)Level);
+ if ( NewLevel <0 )
+ NewLevel = 0;
+ m_logLevel = NewLevel;
+
+ outString( "LogLevel is %u",m_logLevel );
+}
+
+void Log::SetLogFileLevel(char *Level)
+{
+ int32 NewLevel =atoi((char*)Level);
+ if ( NewLevel <0 )
+ NewLevel = 0;
+ m_logFileLevel = NewLevel;
+
+ outString( "LogFileLevel is %u",m_logFileLevel );
+}
+
+void Log::SetDBLogLevel(char *Level)
+{
+ int32 NewLevel = atoi((char*)Level);
+ if ( NewLevel < 0 )
+ NewLevel = 0;
+ m_dbLogLevel = NewLevel;
+
+ outString( "DBLogLevel is %u",m_dbLogLevel );
+}
+
+void Log::Initialize()
+{
+ /// Check whether we'll log GM commands/RA events/character outputs/chat stuffs
+ m_dbChar = sConfig.GetBoolDefault("LogDB.Char", false);
+ m_dbRA = sConfig.GetBoolDefault("LogDB.RA", false);
+ m_dbGM = sConfig.GetBoolDefault("LogDB.GM", false);
+ m_dbChat = sConfig.GetBoolDefault("LogDB.Chat", false);
+
+ /// Realm must be 0 by default
+ SetRealmID(0);
+
+ /// Common log files data
+ m_logsDir = sConfig.GetStringDefault("LogsDir","");
+ if (!m_logsDir.empty())
+ if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\'))
+ m_logsDir.append("/");
+
+ m_logsTimestamp = "_" + GetTimestampStr();
+
+ /// Open specific log files
+ logfile = openLogFile("LogFile","LogTimestamp","w");
+ InitColors(sConfig.GetStringDefault("LogColors", ""));
+
+ m_gmlog_per_account = sConfig.GetBoolDefault("GmLogPerAccount",false);
+ if(!m_gmlog_per_account)
+ gmLogfile = openLogFile("GMLogFile","GmLogTimestamp","a");
+ else
+ {
+ // GM log settings for per account case
+ m_gmlog_filename_format = sConfig.GetStringDefault("GMLogFile", "");
+ if(!m_gmlog_filename_format.empty())
+ {
+ bool m_gmlog_timestamp = sConfig.GetBoolDefault("GmLogTimestamp",false);
+
+ size_t dot_pos = m_gmlog_filename_format.find_last_of(".");
+ if(dot_pos!=m_gmlog_filename_format.npos)
+ {
+ if(m_gmlog_timestamp)
+ m_gmlog_filename_format.insert(dot_pos,m_logsTimestamp);
+
+ m_gmlog_filename_format.insert(dot_pos,"_#%u");
+ }
+ else
+ {
+ m_gmlog_filename_format += "_#%u";
+
+ if(m_gmlog_timestamp)
+ m_gmlog_filename_format += m_logsTimestamp;
+ }
+
+ m_gmlog_filename_format = m_logsDir + m_gmlog_filename_format;
+ }
+ }
+
+ charLogfile = openLogFile("CharLogFile","CharLogTimestamp","a");
+
+ dberLogfile = openLogFile("DBErrorLogFile",NULL,"a");
+ raLogfile = openLogFile("RaLogFile",NULL,"a");
+ chatLogfile = openLogFile("ChatLogFile","ChatLogTimestamp","a");
+ arenaLogFile = openLogFile("ArenaLogFile",NULL,"a");
+
+ // Main log file settings
+ m_logLevel = sConfig.GetIntDefault("LogLevel", LOGL_NORMAL);
+ m_logFileLevel = sConfig.GetIntDefault("LogFileLevel", LOGL_NORMAL);
+ m_dbLogLevel = sConfig.GetIntDefault("DBLogLevel", LOGL_NORMAL);
+
+ m_logFilter = 0;
+
+ if(sConfig.GetBoolDefault("LogFilter_TransportMoves", true))
+ m_logFilter |= LOG_FILTER_TRANSPORT_MOVES;
+ if(sConfig.GetBoolDefault("LogFilter_CreatureMoves", true))
+ m_logFilter |= LOG_FILTER_CREATURE_MOVES;
+ if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true))
+ m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES;
+ if(sConfig.GetBoolDefault("LogFilter_AchievementUpdates", true))
+ m_logFilter |= LOG_FILTER_ACHIEVEMENT_UPDATES;
+
+ // Char log settings
+ m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false);
+ m_charLog_Dump_Separate = sConfig.GetBoolDefault("CharLogDump.Separate", false);
+ if (m_charLog_Dump_Separate)
+ {
+ m_dumpsDir = sConfig.GetStringDefault("CharLogDump.SeparateDir", "");
+ if (!m_dumpsDir.empty())
+ if ((m_dumpsDir.at(m_dumpsDir.length() - 1) != '/') && (m_dumpsDir.at(m_dumpsDir.length() - 1) != '\\'))
+ m_dumpsDir.append("/");
+ }
+}
+
+FILE* Log::openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode)
+{
+ std::string logfn=sConfig.GetStringDefault(configFileName, "");
+ if(logfn.empty())
+ return NULL;
+
+ if(configTimeStampFlag && sConfig.GetBoolDefault(configTimeStampFlag,false))
+ {
+ size_t dot_pos = logfn.find_last_of(".");
+ if(dot_pos!=logfn.npos)
+ logfn.insert(dot_pos,m_logsTimestamp);
+ else
+ logfn += m_logsTimestamp;
+ }
+
+ return fopen((m_logsDir+logfn).c_str(), mode);
+}
+
+FILE* Log::openGmlogPerAccount(uint32 account)
+{
+ if(m_gmlog_filename_format.empty())
+ return NULL;
+
+ char namebuf[TRINITY_PATH_MAX];
+ snprintf(namebuf,TRINITY_PATH_MAX,m_gmlog_filename_format.c_str(),account);
+ return fopen(namebuf, "a");
+}
+
+void Log::outTimestamp(FILE* file)
+{
+ time_t t = time(NULL);
+ tm* aTm = localtime(&t);
+ // YYYY year
+ // MM month (2 digits 01-12)
+ // DD day (2 digits 01-31)
+ // HH hour (2 digits 00-23)
+ // MM minutes (2 digits 00-59)
+ // SS seconds (2 digits 00-59)
+ fprintf(file,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
+}
+
+void Log::InitColors(const std::string& str)
+{
+ if(str.empty())
+ {
+ m_colored = false;
+ return;
+ }
+
+ int color[4];
+
+ std::istringstream ss(str);
+
+ for (uint8 i = 0; i < LogLevels; ++i)
+ {
+ ss >> color[i];
+
+ if(!ss)
+ return;
+
+ if(color[i] < 0 || color[i] >= Colors)
+ return;
+ }
+
+ for (uint8 i = 0; i < LogLevels; ++i)
+ m_colors[i] = ColorTypes(color[i]);
+
+ m_colored = true;
+}
+
+void Log::SetColor(bool stdout_stream, ColorTypes color)
+{
+ #if PLATFORM == PLATFORM_WINDOWS
+ static WORD WinColorFG[Colors] =
+ {
+ 0, // BLACK
+ FOREGROUND_RED, // RED
+ FOREGROUND_GREEN, // GREEN
+ FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
+ FOREGROUND_BLUE, // BLUE
+ FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA
+ FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE
+ // YELLOW
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+ // RED_BOLD
+ FOREGROUND_RED | FOREGROUND_INTENSITY,
+ // GREEN_BOLD
+ FOREGROUND_GREEN | FOREGROUND_INTENSITY,
+ FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
+ // MAGENTA_BOLD
+ FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
+ // CYAN_BOLD
+ FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
+ // WHITE_BOLD
+ FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
+ };
+
+ HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
+ SetConsoleTextAttribute(hConsole, WinColorFG[color]);
+ #else
+ enum ANSITextAttr
+ {
+ TA_NORMAL=0,
+ TA_BOLD=1,
+ TA_BLINK=5,
+ TA_REVERSE=7
+ };
+
+ enum ANSIFgTextAttr
+ {
+ FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
+ FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
+ };
+
+ enum ANSIBgTextAttr
+ {
+ BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
+ BG_MAGENTA, BG_CYAN, BG_WHITE
+ };
+
+ static uint8 UnixColorFG[Colors] =
+ {
+ FG_BLACK, // BLACK
+ FG_RED, // RED
+ FG_GREEN, // GREEN
+ FG_BROWN, // BROWN
+ FG_BLUE, // BLUE
+ FG_MAGENTA, // MAGENTA
+ FG_CYAN, // CYAN
+ FG_WHITE, // WHITE
+ FG_YELLOW, // YELLOW
+ FG_RED, // LRED
+ FG_GREEN, // LGREEN
+ FG_BLUE, // LBLUE
+ FG_MAGENTA, // LMAGENTA
+ FG_CYAN, // LCYAN
+ FG_WHITE // LWHITE
+ };
+
+ fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : ""));
+ #endif
+}
+
+void Log::ResetColor(bool stdout_stream)
+{
+ #if PLATFORM == PLATFORM_WINDOWS
+ HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
+ SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED );
+ #else
+ fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m");
+ #endif
+}
+
+std::string Log::GetTimestampStr()
+{
+ time_t t = time(NULL);
+ tm* aTm = localtime(&t);
+ // YYYY year
+ // MM month (2 digits 01-12)
+ // DD day (2 digits 01-31)
+ // HH hour (2 digits 00-23)
+ // MM minutes (2 digits 00-59)
+ // SS seconds (2 digits 00-59)
+ char buf[20];
+ snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
+ return std::string(buf);
+}
+
+void Log::outDB(LogTypes type, const char * str)
+{
+ if (!str || type >= MAX_LOG_TYPES)
+ return;
+
+ std::string new_str(str);
+ if (new_str.empty())
+ return;
+ LoginDatabase.escape_string(new_str);
+
+ LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) "
+ "VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, type, new_str.c_str());
+}
+
+void Log::outString(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB)
+ {
+ // we don't want empty strings in the DB
+ std::string s(str);
+ if (s.empty() || s == " ")
+ return;
+
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_STRING, nnew_str);
+ va_end(ap2);
+ }
+
+ if (m_colored)
+ SetColor(true,m_colors[LOGL_NORMAL]);
+
+ va_list ap;
+
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(true);
+
+ printf("\n");
+ if(logfile)
+ {
+ outTimestamp(logfile);
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ fprintf(logfile, "\n");
+ va_end(ap);
+
+ fflush(logfile);
+ }
+ fflush(stdout);
+}
+
+void Log::outString()
+{
+ printf("\n");
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ fprintf(logfile, "\n");
+ fflush(logfile);
+ }
+ fflush(stdout);
+}
+
+void Log::outCrash(const char * err, ...)
+{
+ if (!err)
+ return;
+
+ if (m_enableLogDB)
+ {
+ va_list ap2;
+ va_start(ap2, err);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2);
+ outDB(LOG_TYPE_CRASH, nnew_str);
+ va_end(ap2);
+ }
+
+ if (m_colored)
+ SetColor(false,LRED);
+
+ va_list ap;
+
+ va_start(ap, err);
+ vutf8printf(stdout, err, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(false);
+
+ fprintf(stderr, "\n");
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ fprintf(logfile, "CRASH ALERT: ");
+
+ va_start(ap, err);
+ vfprintf(logfile, err, ap);
+ va_end(ap);
+
+ fprintf(logfile, "\n");
+ fflush(logfile);
+ }
+ fflush(stderr);
+}
+
+void Log::outError(const char * err, ...)
+{
+ if (!err)
+ return;
+
+ if (m_enableLogDB)
+ {
+ va_list ap2;
+ va_start(ap2, err);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, err, ap2);
+ outDB(LOG_TYPE_ERROR, nnew_str);
+ va_end(ap2);
+ }
+
+ if (m_colored)
+ SetColor(false,LRED);
+
+ va_list ap;
+
+ va_start(ap, err);
+ vutf8printf(stderr, err, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(false);
+
+ fprintf( stderr, "\n");
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ fprintf(logfile, "ERROR: ");
+
+ va_start(ap, err);
+ vfprintf(logfile, err, ap);
+ va_end(ap);
+
+ fprintf(logfile, "\n");
+ fflush(logfile);
+ }
+ fflush(stderr);
+}
+
+void Log::outArena(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (arenaLogFile)
+ {
+ va_list ap;
+ outTimestamp(arenaLogFile);
+ va_start(ap, str);
+ vfprintf(arenaLogFile, str, ap);
+ fprintf(arenaLogFile, "\n");
+ va_end(ap);
+ fflush(arenaLogFile);
+ }
+ fflush(stdout);
+}
+
+void Log::outErrorDb(const char * err, ...)
+{
+ if (!err)
+ return;
+
+ if (m_colored)
+ SetColor(false,LRED);
+
+ va_list ap;
+
+ va_start(ap, err);
+ vutf8printf(stderr, err, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(false);
+
+ fprintf( stderr, "\n" );
+
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ fprintf(logfile, "ERROR: " );
+
+ va_start(ap, err);
+ vfprintf(logfile, err, ap);
+ va_end(ap);
+
+ fprintf(logfile, "\n" );
+ fflush(logfile);
+ }
+
+ if (dberLogfile)
+ {
+ outTimestamp(dberLogfile);
+ va_start(ap, err);
+ vfprintf(dberLogfile, err, ap);
+ va_end(ap);
+
+ fprintf(dberLogfile, "\n" );
+ fflush(dberLogfile);
+ }
+ fflush(stderr);
+}
+
+void Log::outBasic(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB && m_dbLogLevel > LOGL_NORMAL)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_BASIC, nnew_str);
+ va_end(ap2);
+ }
+
+ if (m_logLevel > LOGL_NORMAL)
+ {
+ if (m_colored)
+ SetColor(true,m_colors[LOGL_BASIC]);
+
+ va_list ap;
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(true);
+
+ printf("\n");
+
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ fprintf(logfile, "\n" );
+ va_end(ap);
+ fflush(logfile);
+ }
+ }
+ fflush(stdout);
+}
+
+void Log::outDetail(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB && m_dbLogLevel > LOGL_BASIC)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_DETAIL, nnew_str);
+ va_end(ap2);
+ }
+
+ if (m_logLevel > LOGL_BASIC)
+ {
+ if (m_colored)
+ SetColor(true,m_colors[LOGL_DETAIL]);
+
+ va_list ap;
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(true);
+
+ printf("\n");
+
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ va_end(ap);
+
+ fprintf(logfile, "\n");
+ fflush(logfile);
+ }
+ }
+
+ fflush(stdout);
+}
+
+void Log::outDebugInLine(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_logLevel > LOGL_DETAIL)
+ {
+ va_list ap;
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ //if(m_colored)
+ // ResetColor(true);
+
+ if (logfile)
+ {
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ va_end(ap);
+ }
+ }
+}
+
+void Log::outDebug(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB && m_dbLogLevel > LOGL_DETAIL)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_DEBUG, nnew_str);
+ va_end(ap2);
+ }
+
+ if( m_logLevel > LOGL_DETAIL )
+ {
+ if (m_colored)
+ SetColor(true,m_colors[LOGL_DEBUG]);
+
+ va_list ap;
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ if(m_colored)
+ ResetColor(true);
+
+ printf( "\n" );
+
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ va_end(ap);
+
+ fprintf(logfile, "\n" );
+ fflush(logfile);
+ }
+ }
+ fflush(stdout);
+}
+
+void Log::outStringInLine(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ va_list ap;
+
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ if (logfile)
+ {
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ va_end(ap);
+ }
+}
+
+void Log::outCommand(uint32 account, const char * str, ...)
+{
+ if (!str)
+ return;
+
+ // TODO: support accountid
+ if (m_enableLogDB && m_dbGM)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_GM, nnew_str);
+ va_end(ap2);
+ }
+
+ if (m_logLevel > LOGL_NORMAL)
+ {
+ if (m_colored)
+ SetColor(true,m_colors[LOGL_BASIC]);
+
+ va_list ap;
+ va_start(ap, str);
+ vutf8printf(stdout, str, &ap);
+ va_end(ap);
+
+ if (m_colored)
+ ResetColor(true);
+
+ printf("\n");
+
+ if (logfile)
+ {
+ outTimestamp(logfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(logfile, str, ap);
+ fprintf(logfile, "\n" );
+ va_end(ap);
+ fflush(logfile);
+ }
+ }
+
+ if (m_gmlog_per_account)
+ {
+ if (FILE* per_file = openGmlogPerAccount (account))
+ {
+ outTimestamp(per_file);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(per_file, str, ap);
+ fprintf(per_file, "\n" );
+ va_end(ap);
+ fclose(per_file);
+ }
+ }
+ else if (gmLogfile)
+ {
+ outTimestamp(gmLogfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(gmLogfile, str, ap);
+ fprintf(gmLogfile, "\n" );
+ va_end(ap);
+ fflush(gmLogfile);
+ }
+
+ fflush(stdout);
+}
+
+void Log::outChar(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB && m_dbChar)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_CHAR, nnew_str);
+ va_end(ap2);
+ }
+
+ if (charLogfile)
+ {
+ outTimestamp(charLogfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(charLogfile, str, ap);
+ fprintf(charLogfile, "\n" );
+ va_end(ap);
+ fflush(charLogfile);
+ }
+}
+
+void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name)
+{
+ FILE *file = NULL;
+ if (m_charLog_Dump_Separate)
+ {
+ char fileName[29]; // Max length: name(12) + guid(11) + _.log (5) + \0
+ snprintf(fileName, 29, "%d_%s.log", guid, name);
+ std::string sFileName(m_dumpsDir);
+ sFileName.append(fileName);
+ file = fopen((m_logsDir + sFileName).c_str(), "w");
+ }
+ else
+ file = charLogfile;
+ if (file)
+ {
+ fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",
+ account_id, guid, name, str);
+ fflush(file);
+ if (m_charLog_Dump_Separate)
+ fclose(file);
+ }
+}
+
+void Log::outRemote(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB && m_dbRA)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_RA, nnew_str);
+ va_end(ap2);
+ }
+
+ if (raLogfile)
+ {
+ outTimestamp(raLogfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(raLogfile, str, ap);
+ fprintf(raLogfile, "\n" );
+ va_end(ap);
+ fflush(raLogfile);
+ }
+ fflush(stdout);
+}
+
+void Log::outChat(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ if (m_enableLogDB && m_dbChat)
+ {
+ va_list ap2;
+ va_start(ap2, str);
+ char nnew_str[MAX_QUERY_LEN];
+ vsnprintf(nnew_str, MAX_QUERY_LEN, str, ap2);
+ outDB(LOG_TYPE_CHAT, nnew_str);
+ va_end(ap2);
+ }
+
+ if (chatLogfile)
+ {
+ outTimestamp(chatLogfile);
+ va_list ap;
+ va_start(ap, str);
+ vfprintf(chatLogfile, str, ap);
+ fprintf(chatLogfile, "\n" );
+ fflush(chatLogfile);
+ va_end(ap);
+ }
+ fflush(stdout);
+}
+
+void outstring_log(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ char buf[256];
+ va_list ap;
+ va_start(ap, str);
+ vsnprintf(buf,256, str, ap);
+ va_end(ap);
+
+ Trinity::Singleton<Log>::Instance().outString(buf);
+}
+
+void detail_log(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ char buf[256];
+ va_list ap;
+ va_start(ap, str);
+ vsnprintf(buf,256, str, ap);
+ va_end(ap);
+
+ Trinity::Singleton<Log>::Instance().outDetail(buf);
+}
+
+void debug_log(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ char buf[256];
+ va_list ap;
+ va_start(ap, str);
+ vsnprintf(buf,256, str, ap);
+ va_end(ap);
+
+ Trinity::Singleton<Log>::Instance().outDebug(buf);
+}
+
+void error_log(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ char buf[256];
+ va_list ap;
+ va_start(ap, str);
+ vsnprintf(buf,256, str, ap);
+ va_end(ap);
+
+ Trinity::Singleton<Log>::Instance().outError(buf);
+}
+
+void error_db_log(const char * str, ...)
+{
+ if (!str)
+ return;
+
+ char buf[256];
+ va_list ap;
+ va_start(ap, str);
+ vsnprintf(buf,256, str, ap);
+ va_end(ap);
+
+ Trinity::Singleton<Log>::Instance().outErrorDb(buf);
+}
+
diff --git a/src/server/shared/Log.h b/src/server/shared/Log.h
new file mode 100644
index 00000000000..deb6c55e4e0
--- /dev/null
+++ b/src/server/shared/Log.h
@@ -0,0 +1,190 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITYCORE_LOG_H
+#define TRINITYCORE_LOG_H
+
+#include "Common.h"
+#include "Policies/Singleton.h"
+#include "Database/DatabaseEnv.h"
+
+class Config;
+
+enum LogFilters
+{
+ LOG_FILTER_TRANSPORT_MOVES = 1,
+ LOG_FILTER_CREATURE_MOVES = 2,
+ LOG_FILTER_VISIBILITY_CHANGES = 4,
+ LOG_FILTER_ACHIEVEMENT_UPDATES = 8
+};
+
+enum LogTypes
+{
+ LOG_TYPE_STRING = 0,
+ LOG_TYPE_ERROR = 1,
+ LOG_TYPE_BASIC = 2,
+ LOG_TYPE_DETAIL = 3,
+ LOG_TYPE_DEBUG = 4,
+ LOG_TYPE_CHAR = 5,
+ LOG_TYPE_WORLD = 6,
+ LOG_TYPE_RA = 7,
+ LOG_TYPE_GM = 8,
+ LOG_TYPE_CRASH = 9,
+ LOG_TYPE_CHAT = 10,
+ MAX_LOG_TYPES
+};
+
+enum LogLevel
+{
+ LOGL_NORMAL = 0,
+ LOGL_BASIC,
+ LOGL_DETAIL,
+ LOGL_DEBUG
+};
+
+const int LogLevels = int(LOGL_DEBUG)+1;
+
+enum ColorTypes
+{
+ BLACK,
+ RED,
+ GREEN,
+ BROWN,
+ BLUE,
+ MAGENTA,
+ CYAN,
+ GREY,
+ YELLOW,
+ LRED,
+ LGREEN,
+ LBLUE,
+ LMAGENTA,
+ LCYAN,
+ WHITE
+};
+
+const int Colors = int(WHITE)+1;
+
+class Log : public Trinity::Singleton<Log, Trinity::ClassLevelLockable<Log, ACE_Thread_Mutex> >
+{
+ friend class Trinity::OperatorNew<Log>;
+ Log();
+ ~Log();
+
+ public:
+ void Initialize();
+
+ void InitColors(const std::string& init_str);
+ void SetColor(bool stdout_stream, ColorTypes color);
+ void ResetColor(bool stdout_stream);
+
+ void outDB( LogTypes type, const char * str );
+ void outString( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outString( );
+ void outStringInLine( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outError( const char * err, ... ) ATTR_PRINTF(2,3);
+ void outCrash( const char * err, ... ) ATTR_PRINTF(2,3);
+ void outBasic( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outDetail( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outDebug( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outDebugInLine( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outErrorDb( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outChar( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outCommand( uint32 account, const char * str, ...) ATTR_PRINTF(3,4);
+ void outRemote( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outChat( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outArena( const char * str, ... ) ATTR_PRINTF(2,3);
+ void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name );
+
+ static void outTimestamp(FILE* file);
+ static std::string GetTimestampStr();
+
+ void SetLogLevel(char * Level);
+ void SetLogFileLevel(char * Level);
+ void SetDBLogLevel(char * Level);
+ void SetRealmID(uint32 id) { realm = id; }
+
+ uint32 getLogFilter() const { return m_logFilter; }
+ bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
+ bool IsOutCharDump() const { return m_charLog_Dump; }
+
+ bool GetLogDB() { return m_enableLogDB; }
+ bool GetLogDBLater() { return m_enableLogDBLater; }
+ void SetLogDB(bool enable) { m_enableLogDB = enable; }
+ void SetLogDBLater(bool value) { m_enableLogDBLater = value; }
+ private:
+ FILE* openLogFile(char const* configFileName,char const* configTimeStampFlag, char const* mode);
+ FILE* openGmlogPerAccount(uint32 account);
+
+ FILE* raLogfile;
+ FILE* logfile;
+ FILE* gmLogfile;
+ FILE* charLogfile;
+ FILE* dberLogfile;
+ FILE* chatLogfile;
+ FILE* arenaLogFile;
+
+ // cache values for after initilization use (like gm log per account case)
+ std::string m_logsDir;
+ std::string m_logsTimestamp;
+
+ // gm log control
+ bool m_gmlog_per_account;
+ std::string m_gmlog_filename_format;
+
+ bool m_enableLogDBLater;
+ bool m_enableLogDB;
+ uint32 realm;
+
+ // log coloring
+ bool m_colored;
+ ColorTypes m_colors[4];
+
+ // log levels:
+ // 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug
+ uint8 m_dbLogLevel;
+ uint8 m_logLevel;
+ uint8 m_logFileLevel;
+ uint8 m_logFilter;
+ bool m_dbChar;
+ bool m_dbRA;
+ bool m_dbGM;
+ bool m_dbChat;
+ bool m_charLog_Dump;
+ bool m_charLog_Dump_Separate;
+ std::string m_dumpsDir;
+};
+
+#define sLog Trinity::Singleton<Log>::Instance()
+
+#ifdef TRINITY_DEBUG
+#define DEBUG_LOG Trinity::Singleton<Log>::Instance().outDebug
+#else
+#define DEBUG_LOG
+#endif
+
+// primary for script library
+void outstring_log(const char * str, ...) ATTR_PRINTF(1,2);
+void detail_log(const char * str, ...) ATTR_PRINTF(1,2);
+void debug_log(const char * str, ...) ATTR_PRINTF(1,2);
+void error_log(const char * str, ...) ATTR_PRINTF(1,2);
+void error_db_log(const char * str, ...) ATTR_PRINTF(1,2);
+#endif
+
diff --git a/src/server/shared/MemoryLeaks.cpp b/src/server/shared/MemoryLeaks.cpp
new file mode 100644
index 00000000000..ef7e36c3b57
--- /dev/null
+++ b/src/server/shared/MemoryLeaks.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "MemoryLeaks.h"
+#include "Policies/SingletonImp.h"
+
+INSTANTIATE_SINGLETON_1( MemoryManager ) ;
+
+MemoryManager::MemoryManager( )
+{
+ #if COMPILER == MICROSOFT
+ // standard leak check initialization
+ //_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
+ // uncomment to disable Visual Leak Detector from code
+ //VLDDisable();
+ #endif
+}
diff --git a/src/server/shared/MemoryLeaks.h b/src/server/shared/MemoryLeaks.h
new file mode 100644
index 00000000000..c8b8fb8e1b1
--- /dev/null
+++ b/src/server/shared/MemoryLeaks.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITYSERVER_MEMORY_H
+#define TRINITYSERVER_MEMORY_H
+
+#include "Platform/CompilerDefs.h"
+
+#if COMPILER == COMPILER_MICROSOFT
+
+#ifndef _WIN64
+// Visual Leak Detector support enabled
+//#include <vld/vld.h>
+// standard Visual Studio leak check disabled,
+//# define _CRTDBG_MAP_ALLOC
+//# include <stdlib.h>
+//# include <crtdbg.h>
+#else
+//# define _CRTDBG_MAP_ALLOC
+//# include <stdlib.h>
+//# include <crtdbg.h>
+#endif
+
+#endif
+
+
+#include "Policies/Singleton.h"
+
+struct MemoryManager : public Trinity::Singleton < MemoryManager >
+{
+ MemoryManager();
+};
+#endif
diff --git a/src/server/shared/PacketLog.cpp b/src/server/shared/PacketLog.cpp
new file mode 100644
index 00000000000..4e5cad69605
--- /dev/null
+++ b/src/server/shared/PacketLog.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Common.h"
+#include "PacketLog.h"
+#include "Config/ConfigEnv.h"
+#include "Policies/SingletonImpl.h"
+
+#include <ctype.h>
+
+INSTANTIATE_SINGLETON_1( PacketLog );
+
+PacketLog::PacketLog()
+{
+
+ if (sConfig.GetBoolDefault("LogRealm", false))
+ {
+ FILE *pFile = fopen("realm.log", "w+");
+ fclose(pFile);
+ }
+
+ if (sConfig.GetBoolDefault("LogWorld", false))
+ {
+ FILE *pFile = fopen("world.log", "w+");
+ fclose(pFile);
+ }
+}
+
+PacketLog::~PacketLog()
+{
+}
+
+char PacketLog::makehexchar(int i)
+{
+ return (i<=9) ? '0'+i : 'A'+(i-10);
+}
+
+int PacketLog::hextoint(char c)
+{
+ c = toupper(c);
+ return (c > '9' ? c - 'A' + 10 : c - '0');
+}
+
+void PacketLog::HexDump(const unsigned char* data, size_t length, const char* file)
+{
+ FILE *pFile;
+ pFile = fopen(file, "a");
+
+ const int char_offset = 16*3 + 2;
+ const int line_size = 16*3 + 16 + 3;
+ char line[line_size+1];
+
+ fprintf(pFile,"OFFSET 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF\n");
+ fprintf(pFile,"--------------------------------------------------------------------------\n");
+
+ line[char_offset - 1] = ' ';
+ line[char_offset - 2] = ' ';
+
+ for (size_t i=0; i<length; )
+ {
+ int bi=0;
+ int ci=0;
+
+ int start_i = i;
+
+ for (int line_i=0; i < length && line_i < 16; i++, line_i++)
+ {
+ line[bi++] = makehexchar(*data>>4);
+ line[bi++] = makehexchar(*data & 0x0f);
+ line[bi++] = ' ';
+ line[char_offset+(ci++)]=(isprint(*data) ? *data : '.');
+ ++data;
+ }
+
+ while (bi<16*3)
+ {
+ line[bi++]=' ';
+ }
+
+ line[char_offset+(ci++)]='\n';
+ line[char_offset+ci]=0;
+
+ fprintf(pFile,"%06X %s", start_i, line);
+ }
+ fprintf(pFile, "\n\n");
+ fclose(pFile);
+}
+
+void PacketLog::HexDump(const char *data, size_t length, const char* file)
+{
+ HexDump((unsigned char *)data, length, file);
+}
+
+void PacketLog::HexDumpStr(const char *msg, const char *data, size_t len, const char* file)
+{
+ FILE *pFile;
+ pFile = fopen(file, "a");
+ fprintf(pFile,"%s\n", msg);
+ fclose(pFile);
+
+ HexDump(data, len, file);
+}
+
+void PacketLog::RealmHexDump(RealmPacket* data, uint32 socket, bool direction)
+{
+ if (!sConfig.GetBoolDefault("LogRealm", false))
+ return;
+
+ FILE *pFile;
+ pFile = fopen("realm.log", "a");
+
+ uint16 len = data->size() + 2;
+ uint8 opcode = data->GetOpcode();
+ if (direction)
+ fprintf(pFile, "SERVER:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.2X\nDATA:\n", socket, len, opcode);
+ else
+ fprintf(pFile, "CLIENT:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.2X\nDATA:\n", socket, len, opcode);
+
+ fclose(pFile);
+ HexDump((char *)data->contents(), data->size(), "realm.log");
+
+}
+
+void PacketLog::WorldHexDump(WorldPacket* data, uint32 socket, bool direction)
+{
+ if (!sConfig.GetBoolDefault("LogWorld", false))
+ return;
+
+ FILE *pFile;
+ pFile = fopen("world.log", "a");
+
+ uint16 len = data->size();
+ uint16 opcode = data->GetOpcode();
+ if (direction)
+ fprintf(pFile, "SERVER:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.4X\nDATA:\n", socket, len, opcode);
+ else
+ fprintf(pFile, "CLIENT:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.4X\nDATA:\n", socket, len, opcode);
+
+ fclose(pFile);
+ HexDump((char *)data->contents(), data->size(), "world.log");
+
+}
+
diff --git a/src/server/shared/PacketLog.h b/src/server/shared/PacketLog.h
new file mode 100644
index 00000000000..462cc1eed51
--- /dev/null
+++ b/src/server/shared/PacketLog.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITYCORE_PACKETLOG_H
+#define TRINITYCORE_PACKETLOG_H
+
+#include "Common.h"
+#include "Policies/Singleton.h"
+#include "RealmPacket.h"
+#include "WorldPacket.h"
+
+class PacketLog
+{
+ public:
+ PacketLog();
+ ~PacketLog();
+
+ int hextoint(char c);
+ char makehexchar(int i);
+
+ void HexDump(const unsigned char* data, size_t length, const char* file);
+ void HexDump(const char *data, size_t length, const char* file);
+ void HexDumpStr(const char *msg, const char *data, size_t len, const char* file);
+
+ void RealmHexDump(RealmPacket * data, uint32 socket, bool direction);
+
+ void WorldHexDump(WorldPacket * data, uint32 socket, bool direction);
+};
+
+#define sPacketLog Trinity::Singleton<PacketLog>::Instance()
+#endif
+
diff --git a/src/server/shared/ProgressBar.cpp b/src/server/shared/ProgressBar.cpp
new file mode 100644
index 00000000000..c24d9f86f6b
--- /dev/null
+++ b/src/server/shared/ProgressBar.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <stdio.h>
+
+#include "ProgressBar.h"
+
+char const* const barGoLink::empty = " ";
+#ifdef _WIN32
+char const* const barGoLink::full = "\x3D";
+#else
+char const* const barGoLink::full = "*";
+#endif
+
+barGoLink::~barGoLink()
+{
+ printf( "\n" );
+ fflush(stdout);
+}
+
+barGoLink::barGoLink( int row_count )
+{
+ rec_no = 0;
+ rec_pos = 0;
+ indic_len = 50;
+ num_rec = row_count;
+ #ifdef _WIN32
+ printf( "\x3D" );
+ #else
+ printf( "[" );
+ #endif
+ for (int i = 0; i < indic_len; i++ ) printf( empty );
+ #ifdef _WIN32
+ printf( "\x3D 0%%\r\x3D" );
+ #else
+ printf( "] 0%%\r[" );
+ #endif
+ fflush(stdout);
+}
+
+void barGoLink::step( void )
+{
+ int i, n;
+
+ if ( num_rec == 0 ) return;
+ ++rec_no;
+ n = rec_no * indic_len / num_rec;
+ if ( n != rec_pos )
+ {
+ #ifdef _WIN32
+ printf( "\r\x3D" );
+ #else
+ printf( "\r[" );
+ #endif
+ for (i = 0; i < n; i++ ) printf( full );
+ for (; i < indic_len; i++ ) printf( empty );
+ float percent = (((float)n/(float)indic_len)*100);
+ #ifdef _WIN32
+ printf( "\x3D %i%% \r\x3D", (int)percent);
+ #else
+ printf( "] %i%% \r[", (int)percent);
+ #endif
+ fflush(stdout);
+
+ rec_pos = n;
+ }
+}
+
diff --git a/src/server/shared/ProgressBar.h b/src/server/shared/ProgressBar.h
new file mode 100644
index 00000000000..e7565590278
--- /dev/null
+++ b/src/server/shared/ProgressBar.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef TRINITYCORE_PROGRESSBAR_H
+#define TRINITYCORE_PROGRESSBAR_H
+
+#include "Platform/Define.h"
+
+class barGoLink
+{
+ static char const * const empty;
+ static char const * const full;
+
+ int rec_no;
+ int rec_pos;
+ int num_rec;
+ int indic_len;
+
+ public:
+
+ void step( void );
+ barGoLink( int );
+ ~barGoLink();
+};
+#endif
+
diff --git a/src/server/shared/ServiceWin32.cpp b/src/server/shared/ServiceWin32.cpp
new file mode 100644
index 00000000000..2c1df2ff483
--- /dev/null
+++ b/src/server/shared/ServiceWin32.cpp
@@ -0,0 +1,263 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef WIN32
+
+#include "Common.h"
+#include "Log.h"
+#include <cstring>
+#include <windows.h>
+#include <winsvc.h>
+
+#if !defined(WINADVAPI)
+#if !defined(_ADVAPI32_)
+#define WINADVAPI DECLSPEC_IMPORT
+#else
+#define WINADVAPI
+#endif
+#endif
+
+extern int main(int argc, char ** argv);
+extern char serviceLongName[];
+extern char serviceName[];
+extern char serviceDescription[];
+
+extern int m_ServiceStatus;
+
+SERVICE_STATUS serviceStatus;
+
+SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
+
+typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
+
+bool WinServiceInstall()
+{
+ CSD_T ChangeService_Config2;
+ HMODULE advapi32;
+ SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
+
+ if (serviceControlManager)
+ {
+ char path[_MAX_PATH + 10];
+ if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
+ {
+ SC_HANDLE service;
+ std::strcat(path, " --service");
+ service = CreateService(serviceControlManager,
+ serviceName, // name of service
+ serviceLongName, // service name to display
+ SERVICE_ALL_ACCESS, // desired access
+ // service type
+ SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
+ SERVICE_AUTO_START, // start type
+ SERVICE_ERROR_IGNORE, // error control type
+ path, // service's binary
+ 0, // no load ordering group
+ 0, // no tag identifier
+ 0, // no dependencies
+ 0, // LocalSystem account
+ 0); // no password
+ if (service)
+ {
+ advapi32 = GetModuleHandle("ADVAPI32.DLL");
+ if(!advapi32)
+ {
+ CloseServiceHandle(service);
+ CloseServiceHandle(serviceControlManager);
+ return false;
+ }
+
+ ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
+ if (!ChangeService_Config2)
+ {
+ CloseServiceHandle(service);
+ CloseServiceHandle(serviceControlManager);
+ return false;
+ }
+
+ SERVICE_DESCRIPTION sdBuf;
+ sdBuf.lpDescription = serviceDescription;
+ ChangeService_Config2(
+ service, // handle to service
+ SERVICE_CONFIG_DESCRIPTION, // change: description
+ &sdBuf); // new data
+
+ SC_ACTION _action[1];
+ _action[0].Type = SC_ACTION_RESTART;
+ _action[0].Delay = 10000;
+ SERVICE_FAILURE_ACTIONS sfa;
+ ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
+ sfa.lpsaActions = _action;
+ sfa.cActions = 1;
+ sfa.dwResetPeriod =INFINITE;
+ ChangeService_Config2(
+ service, // handle to service
+ SERVICE_CONFIG_FAILURE_ACTIONS, // information level
+ &sfa); // new data
+
+ CloseServiceHandle(service);
+
+ }
+ }
+ CloseServiceHandle(serviceControlManager);
+ }
+ return true;
+}
+
+bool WinServiceUninstall()
+{
+ SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
+
+ if (serviceControlManager)
+ {
+ SC_HANDLE service = OpenService(serviceControlManager,
+ serviceName, SERVICE_QUERY_STATUS | DELETE);
+ if (service)
+ {
+ SERVICE_STATUS serviceStatus2;
+ if (QueryServiceStatus(service, &serviceStatus2))
+ {
+ if (serviceStatus2.dwCurrentState == SERVICE_STOPPED)
+ DeleteService(service);
+ }
+ CloseServiceHandle(service);
+ }
+
+ CloseServiceHandle(serviceControlManager);
+ }
+ return true;
+}
+
+void WINAPI ServiceControlHandler(DWORD controlCode)
+{
+ switch (controlCode)
+ {
+ case SERVICE_CONTROL_INTERROGATE:
+ break;
+
+ case SERVICE_CONTROL_SHUTDOWN:
+ case SERVICE_CONTROL_STOP:
+ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+
+ m_ServiceStatus = 0;
+ return;
+
+ case SERVICE_CONTROL_PAUSE:
+ m_ServiceStatus = 2;
+ serviceStatus.dwCurrentState = SERVICE_PAUSED;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+ break;
+
+ case SERVICE_CONTROL_CONTINUE:
+ serviceStatus.dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+ m_ServiceStatus = 1;
+ break;
+
+ default:
+ if ( controlCode >= 128 && controlCode <= 255 )
+ // user defined control code
+ break;
+ else
+ // unrecognized control code
+ break;
+ }
+
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+}
+
+void WINAPI ServiceMain(DWORD argc, char *argv[])
+{
+ // initialise service status
+ serviceStatus.dwServiceType = SERVICE_WIN32;
+ serviceStatus.dwCurrentState = SERVICE_START_PENDING;
+ serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
+ serviceStatus.dwWin32ExitCode = NO_ERROR;
+ serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
+ serviceStatus.dwCheckPoint = 0;
+ serviceStatus.dwWaitHint = 0;
+
+ serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
+
+ if ( serviceStatusHandle )
+ {
+ char path[_MAX_PATH + 1];
+ unsigned int i, last_slash = 0;
+
+ GetModuleFileName(0, path, sizeof(path)/sizeof(path[0]));
+
+ for (i = 0; i < std::strlen(path); i++)
+ {
+ if (path[i] == '\\') last_slash = i;
+ }
+
+ path[last_slash] = 0;
+
+ // service is starting
+ serviceStatus.dwCurrentState = SERVICE_START_PENDING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+
+ // do initialisation here
+ SetCurrentDirectory(path);
+
+ // running
+ serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ serviceStatus.dwCurrentState = SERVICE_RUNNING;
+ SetServiceStatus( serviceStatusHandle, &serviceStatus );
+
+ ////////////////////////
+ // service main cycle //
+ ////////////////////////
+
+ m_ServiceStatus = 1;
+ argc = 1;
+ main(argc , argv);
+
+ // service was stopped
+ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+
+ // do cleanup here
+
+ // service is now stopped
+ serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
+ serviceStatus.dwCurrentState = SERVICE_STOPPED;
+ SetServiceStatus(serviceStatusHandle, &serviceStatus);
+ }
+}
+
+bool WinServiceRun()
+{
+ SERVICE_TABLE_ENTRY serviceTable[] =
+ {
+ { serviceName, ServiceMain },
+ { 0, 0 }
+ };
+
+ if (!StartServiceCtrlDispatcher(serviceTable))
+ {
+ sLog.outError("StartService Failed. Error [%u]", ::GetLastError());
+ return false;
+ }
+ return true;
+}
+#endif
+
diff --git a/src/server/shared/ServiceWin32.h b/src/server/shared/ServiceWin32.h
new file mode 100644
index 00000000000..ddac785a0fb
--- /dev/null
+++ b/src/server/shared/ServiceWin32.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifdef WIN32
+#ifndef _WIN32_SERVICE_
+#define _WIN32_SERVICE_
+
+bool WinServiceInstall();
+bool WinServiceUninstall();
+bool WinServiceRun();
+
+#endif // _WIN32_SERVICE_
+#endif // WIN32
+
diff --git a/src/server/shared/SignalHandler.h b/src/server/shared/SignalHandler.h
new file mode 100644
index 00000000000..0c4d8143c41
--- /dev/null
+++ b/src/server/shared/SignalHandler.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __SIGNAL_HANDLER_H__
+#define __SIGNAL_HANDLER_H__
+
+#include <ace/Event_Handler.h>
+
+namespace Trinity
+{
+
+/// Handle termination signals
+class SignalHandler : public ACE_Event_Handler
+{
+ public:
+ int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL)
+ {
+ HandleSignal(SigNum);
+ return 0;
+ }
+ virtual void HandleSignal(int SigNum) {};
+};
+
+}
+
+#endif /* __SIGNAL_HANDLER_H__ */
diff --git a/src/server/shared/SystemConfig.h b/src/server/shared/SystemConfig.h
new file mode 100644
index 00000000000..ac531cbbc94
--- /dev/null
+++ b/src/server/shared/SystemConfig.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+// THIS FILE IS DEPRECATED
+
+#ifndef TRINITY_SYSTEMCONFIG_H
+#define TRINITY_SYSTEMCONFIG_H
+
+#include "Platform/Define.h"
+#include "revision.h"
+
+#define _PACKAGENAME "TrinityCore "
+#define _CODENAME "LONG_COLD_WINTER"
+
+#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
+# define _ENDIAN_STRING "big-endian"
+#else
+# define _ENDIAN_STRING "little-endian"
+#endif
+
+#if PLATFORM == PLATFORM_WINDOWS
+# ifdef _WIN64
+# define _FULLVERSION _PACKAGENAME "Rev: " _REVISION " " _BUILD_DIRECTIVE " Hash: " _HASH " (Win64," _ENDIAN_STRING ")"
+# else
+# define _FULLVERSION _PACKAGENAME "Rev: " _REVISION " " _BUILD_DIRECTIVE " Hash: " _HASH " (Win32," _ENDIAN_STRING ")"
+# endif
+#else
+# define _FULLVERSION _PACKAGENAME "Rev: " _REVISION " " _BUILD_DIRECTIVE " Hash: " _HASH " (Unix," _ENDIAN_STRING ")"
+#endif
+
+#define DEFAULT_PLAYER_LIMIT 100
+#define DEFAULT_WORLDSERVER_PORT 8085 //8129
+#define DEFAULT_REALMSERVER_PORT 3724
+#define DEFAULT_SOCKET_SELECT_TIME 10000
+#endif
+
diff --git a/src/server/shared/Threading.cpp b/src/server/shared/Threading.cpp
new file mode 100644
index 00000000000..3938286dbdb
--- /dev/null
+++ b/src/server/shared/Threading.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (C) 2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Threading.h"
+#include "Errors.h"
+#include <ace/OS_NS_unistd.h>
+#include <ace/Sched_Params.h>
+#include <vector>
+
+using namespace ACE_Based;
+
+ThreadPriority::ThreadPriority()
+{
+ for (int i = Idle; i < MAXPRIORITYNUM; ++i)
+ m_priority[i] = ACE_THR_PRI_OTHER_DEF;
+
+ m_priority[Idle] = ACE_Sched_Params::priority_min(ACE_SCHED_OTHER);
+ m_priority[Realtime] = ACE_Sched_Params::priority_max(ACE_SCHED_OTHER);
+
+ std::vector<int> _tmp;
+
+ ACE_Sched_Params::Policy _policy = ACE_SCHED_OTHER;
+ ACE_Sched_Priority_Iterator pr_iter(_policy);
+
+ while (pr_iter.more())
+ {
+ _tmp.push_back(pr_iter.priority());
+ pr_iter.next();
+ }
+
+ ASSERT (!_tmp.empty());
+
+ if(_tmp.size() >= MAXPRIORITYNUM)
+ {
+ const size_t max_pos = _tmp.size();
+ size_t min_pos = 1;
+ size_t norm_pos = 0;
+ for (size_t i = 0; i < max_pos; ++i)
+ {
+ if(_tmp[i] == ACE_THR_PRI_OTHER_DEF)
+ {
+ norm_pos = i + 1;
+ break;
+ }
+ }
+
+ //since we have only 7(seven) values in enum Priority
+ //and 3 we know already (Idle, Normal, Realtime) so
+ //we need to split each list [Idle...Normal] and [Normal...Realtime]
+ //into ¹ piesces
+ const size_t _divider = 4;
+ size_t _div = (norm_pos - min_pos) / _divider;
+ if(_div == 0)
+ _div = 1;
+
+ min_pos = (norm_pos - 1);
+
+ m_priority[Low] = _tmp[min_pos -= _div];
+ m_priority[Lowest] = _tmp[min_pos -= _div ];
+
+ _div = (max_pos - norm_pos) / _divider;
+ if(_div == 0)
+ _div = 1;
+
+ min_pos = norm_pos - 1;
+
+ m_priority[High] = _tmp[min_pos += _div];
+ m_priority[Highest] = _tmp[min_pos += _div];
+ }
+}
+
+int ThreadPriority::getPriority(Priority p) const
+{
+ if(p < Idle)
+ p = Idle;
+
+ if(p > Realtime)
+ p = Realtime;
+
+ return m_priority[p];
+}
+
+#define THREADFLAG (THR_NEW_LWP | THR_SCHED_DEFAULT| THR_JOINABLE)
+
+Thread::Thread() : m_task(0), m_iThreadId(0), m_hThreadHandle(0)
+{
+
+}
+
+Thread::Thread(Runnable* instance) : m_task(instance), m_iThreadId(0), m_hThreadHandle(0)
+{
+ // register reference to m_task to prevent it deeltion until destructor
+ if (m_task)
+ m_task->incReference();
+
+ bool _start = start();
+ ASSERT (_start);
+}
+
+Thread::~Thread()
+{
+ //Wait();
+
+ // deleted runnable object (if no other references)
+ if (m_task)
+ m_task->decReference();
+}
+
+//initialize Thread's class static member
+Thread::ThreadStorage Thread::m_ThreadStorage;
+ThreadPriority Thread::m_TpEnum;
+
+bool Thread::start()
+{
+ if (m_task == 0 || m_iThreadId != 0)
+ return false;
+
+ bool res = (ACE_Thread::spawn(&Thread::ThreadTask, (void*)m_task, THREADFLAG, &m_iThreadId, &m_hThreadHandle) == 0);
+
+ if (res)
+ m_task->incReference();
+
+ return res;
+}
+
+bool Thread::wait()
+{
+ if (!m_hThreadHandle || !m_task)
+ return false;
+
+ ACE_THR_FUNC_RETURN _value = ACE_THR_FUNC_RETURN(-1);
+ int _res = ACE_Thread::join(m_hThreadHandle, &_value);
+
+ m_iThreadId = 0;
+ m_hThreadHandle = 0;
+
+ return (_res == 0);
+}
+
+void Thread::destroy()
+{
+ if (!m_iThreadId || !m_task)
+ return;
+
+ if (ACE_Thread::kill(m_iThreadId, -1) != 0)
+ return;
+
+ m_iThreadId = 0;
+ m_hThreadHandle = 0;
+
+ // reference set at ACE_Thread::spawn
+ m_task->decReference();
+}
+
+void Thread::suspend()
+{
+ ACE_Thread::suspend(m_hThreadHandle);
+}
+
+void Thread::resume()
+{
+ ACE_Thread::resume(m_hThreadHandle);
+}
+
+ACE_THR_FUNC_RETURN Thread::ThreadTask(void * param)
+{
+ Runnable * _task = (Runnable*)param;
+ _task->run();
+
+ // task execution complete, free referecne added at
+ _task->decReference();
+
+ return (ACE_THR_FUNC_RETURN)0;
+}
+
+ACE_thread_t Thread::currentId()
+{
+ return ACE_Thread::self();
+}
+
+ACE_hthread_t Thread::currentHandle()
+{
+ ACE_hthread_t _handle;
+ ACE_Thread::self(_handle);
+
+ return _handle;
+}
+
+Thread * Thread::current()
+{
+ Thread * _thread = m_ThreadStorage.ts_object();
+ if(!_thread)
+ {
+ _thread = new Thread();
+ _thread->m_iThreadId = Thread::currentId();
+ _thread->m_hThreadHandle = Thread::currentHandle();
+
+ Thread * _oldValue = m_ThreadStorage.ts_object(_thread);
+ if(_oldValue)
+ delete _oldValue;
+ }
+
+ return _thread;
+}
+
+void Thread::setPriority(Priority type)
+{
+ int _priority = m_TpEnum.getPriority(type);
+ int _ok = ACE_Thread::setprio(m_hThreadHandle, _priority);
+ //remove this ASSERT in case you don't want to know is thread priority change was successful or not
+ ASSERT (_ok == 0);
+}
+
+void Thread::Sleep(unsigned long msecs)
+{
+ ACE_OS::sleep(ACE_Time_Value(0, 1000 * msecs));
+}
diff --git a/src/server/shared/Threading.h b/src/server/shared/Threading.h
new file mode 100644
index 00000000000..fa046117c6e
--- /dev/null
+++ b/src/server/shared/Threading.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2009 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef THREADING_H
+#define THREADING_H
+
+#include <ace/Thread.h>
+#include <ace/TSS_T.h>
+#include "ace/Atomic_Op.h"
+#include <assert.h>
+
+namespace ACE_Based
+{
+
+ class Runnable
+ {
+ public:
+ virtual ~Runnable() {}
+ virtual void run() = 0;
+
+ void incReference() { ++m_refs; }
+ void decReference()
+ {
+ if(!--m_refs)
+ delete this;
+ }
+ private:
+ ACE_Atomic_Op<ACE_Thread_Mutex, long> m_refs;
+ };
+
+ enum Priority
+ {
+ Idle,
+ Lowest,
+ Low,
+ Normal,
+ High,
+ Highest,
+ Realtime,
+ };
+
+#define MAXPRIORITYNUM (Realtime + 1)
+
+ class ThreadPriority
+ {
+ public:
+ ThreadPriority();
+ int getPriority(Priority p) const;
+
+ private:
+ int m_priority[MAXPRIORITYNUM];
+ };
+
+ class Thread
+ {
+ public:
+ Thread();
+ explicit Thread(Runnable* instance);
+ ~Thread();
+
+ bool start();
+ bool wait();
+ void destroy();
+
+ void suspend();
+ void resume();
+
+ void setPriority(Priority type);
+
+ static void Sleep(unsigned long msecs);
+ static ACE_thread_t currentId();
+ static ACE_hthread_t currentHandle();
+ static Thread * current();
+
+ private:
+ Thread(const Thread&);
+ Thread& operator=(const Thread&);
+
+ static ACE_THR_FUNC_RETURN ThreadTask(void * param);
+
+ ACE_thread_t m_iThreadId;
+ ACE_hthread_t m_hThreadHandle;
+ Runnable * m_task;
+
+ typedef ACE_TSS<Thread> ThreadStorage;
+ //global object - container for Thread class representation of every thread
+ static ThreadStorage m_ThreadStorage;
+ //use this object to determine current OS thread priority values mapped to enum Priority{}
+ static ThreadPriority m_TpEnum;
+ };
+
+}
+#endif
diff --git a/src/server/shared/Timer.h b/src/server/shared/Timer.h
new file mode 100644
index 00000000000..3e0a369b655
--- /dev/null
+++ b/src/server/shared/Timer.h
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITY_TIMER_H
+#define TRINITY_TIMER_H
+
+#include "Platform/CompilerDefs.h"
+
+#if PLATFORM == PLATFORM_WINDOWS
+# include <ace/config-all.h>
+# include <mmsystem.h>
+# include <time.h>
+#else
+# if defined(__APPLE_CC__)
+# include <time.h>
+# endif
+# include <sys/time.h>
+# include <sys/timeb.h>
+#endif
+
+#if PLATFORM == PLATFORM_WINDOWS
+inline uint32 getMSTime() { return GetTickCount(); }
+#else
+inline uint32 getMSTime()
+{
+ struct timeval tv;
+ struct timezone tz;
+ gettimeofday( &tv, &tz );
+ return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+}
+#endif
+
+inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
+{
+ // getMSTime() have limited data range and this is case when it overflow in this tick
+ if (oldMSTime > newMSTime)
+ return (0xFFFFFFFF - oldMSTime) + newMSTime;
+ else
+ return newMSTime - oldMSTime;
+}
+
+struct IntervalTimer
+{
+ public:
+
+ IntervalTimer()
+ : _interval(0), _current(0)
+ {
+ }
+
+ void Update(time_t diff)
+ {
+ _current += diff;
+ if (_current < 0)
+ _current = 0;
+ }
+
+ bool Passed()
+ {
+ return _current >= _interval;
+ }
+
+ void Reset()
+ {
+ if (_current >= _interval)
+ _current -= _interval;
+ }
+
+ void SetCurrent(time_t current)
+ {
+ _current = current;
+ }
+
+ void SetInterval(time_t interval)
+ {
+ _interval = interval;
+ }
+
+ time_t GetInterval() const
+ {
+ return _interval;
+ }
+
+ time_t GetCurrent() const
+ {
+ return _current;
+ }
+
+ private:
+
+ time_t _interval;
+ time_t _current;
+};
+
+struct TimeTracker
+{
+ public:
+
+ TimeTracker(time_t expiry)
+ : i_expiryTime(expiry)
+ {
+ }
+
+ void Update(time_t diff)
+ {
+ i_expiryTime -= diff;
+ }
+
+ bool Passed() const
+ {
+ return i_expiryTime <= 0;
+ }
+
+ void Reset(time_t interval)
+ {
+ i_expiryTime = interval;
+ }
+
+ time_t GetExpiry() const
+ {
+ return i_expiryTime;
+ }
+
+ private:
+
+ time_t i_expiryTime;
+};
+
+struct TimeTrackerSmall
+{
+ public:
+
+ TimeTrackerSmall(uint32 expiry)
+ : i_expiryTime(expiry)
+ {
+ }
+
+ void Update(int32 diff)
+ {
+ i_expiryTime -= diff;
+ }
+
+ bool Passed() const
+ {
+ return i_expiryTime <= 0;
+ }
+
+ void Reset(uint32 interval)
+ {
+ i_expiryTime = interval;
+ }
+
+ int32 GetExpiry() const
+ {
+ return i_expiryTime;
+ }
+
+ private:
+
+ int32 i_expiryTime;
+};
+
+struct PeriodicTimer
+{
+ public:
+
+ PeriodicTimer(int32 period, int32 start_time)
+ : i_expireTime(start_time), i_period(period)
+ {
+ }
+
+ bool Update(const uint32 &diff)
+ {
+ if ((i_expireTime -= diff) > 0)
+ return false;
+
+ i_expireTime += i_period > diff ? i_period : diff;
+ return true;
+ }
+
+ void SetPeriodic(int32 period, int32 start_time)
+ {
+ i_expireTime = start_time;
+ i_period = period;
+ }
+
+ // Tracker interface
+ void TUpdate(int32 diff) { i_expireTime -= diff; }
+ bool TPassed() const { return i_expireTime <= 0; }
+ void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; }
+
+ private:
+
+ int32 i_period;
+ int32 i_expireTime;
+};
+
+#endif
diff --git a/src/server/shared/Util.cpp b/src/server/shared/Util.cpp
new file mode 100644
index 00000000000..a3c017fdbfd
--- /dev/null
+++ b/src/server/shared/Util.cpp
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "Util.h"
+
+#include "sockets/socket_include.h"
+#include "utf8cpp/utf8.h"
+#include "mersennetwister/MersenneTwister.h"
+#include <ace/TSS_T.h>
+
+typedef ACE_TSS<MTRand> MTRandTSS;
+static MTRandTSS mtRand;
+
+int32 irand (int32 min, int32 max)
+{
+ return int32 (mtRand->randInt (max - min)) + min;
+}
+
+uint32 urand (uint32 min, uint32 max)
+{
+ return mtRand->randInt (max - min) + min;
+}
+
+int32 rand32 ()
+{
+ return mtRand->randInt ();
+}
+
+double rand_norm(void)
+{
+ return mtRand->randExc ();
+}
+
+double rand_chance (void)
+{
+ return mtRand->randExc (100.0);
+}
+
+Tokens StrSplit(const std::string &src, const std::string &sep)
+{
+ Tokens r;
+ std::string s;
+ for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
+ {
+ if (sep.find(*i) != std::string::npos)
+ {
+ if (s.length()) r.push_back(s);
+ s = "";
+ }
+ else
+ {
+ s += *i;
+ }
+ }
+ if (s.length()) r.push_back(s);
+ return r;
+}
+
+void stripLineInvisibleChars(std::string &str)
+{
+ static std::string invChars = " \t\7\n";
+
+ size_t wpos = 0;
+
+ bool space = false;
+ for (size_t pos = 0; pos < str.size(); ++pos)
+ {
+ if(invChars.find(str[pos])!=std::string::npos)
+ {
+ if(!space)
+ {
+ str[wpos++] = ' ';
+ space = true;
+ }
+ }
+ else
+ {
+ if(wpos!=pos)
+ str[wpos++] = str[pos];
+ else
+ ++wpos;
+ space = false;
+ }
+ }
+
+ if(wpos < str.size())
+ str.erase(wpos,str.size());
+ if(str.find("|TInterface")!=std::string::npos)
+ str.clear();
+
+}
+
+std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
+{
+ uint32 secs = timeInSecs % MINUTE;
+ uint32 minutes = timeInSecs % HOUR / MINUTE;
+ uint32 hours = timeInSecs % DAY / HOUR;
+ uint32 days = timeInSecs / DAY;
+
+ std::ostringstream ss;
+ if(days)
+ ss << days << (shortText ? "d" : " Day(s) ");
+ if(hours || hoursOnly)
+ ss << hours << (shortText ? "h" : " Hour(s) ");
+ if(!hoursOnly)
+ {
+ if(minutes)
+ ss << minutes << (shortText ? "m" : " Minute(s) ");
+ if(secs || (!days && !hours && !minutes) )
+ ss << secs << (shortText ? "s" : " Second(s).");
+ }
+
+ return ss.str();
+}
+
+uint32 TimeStringToSecs(const std::string& timestring)
+{
+ uint32 secs = 0;
+ uint32 buffer = 0;
+ uint32 multiplier = 0;
+
+ for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); itr++ )
+ {
+ if(isdigit(*itr))
+ {
+ buffer*=10;
+ buffer+= (*itr)-'0';
+ }
+ else
+ {
+ switch(*itr)
+ {
+ case 'd': multiplier = DAY; break;
+ case 'h': multiplier = HOUR; break;
+ case 'm': multiplier = MINUTE; break;
+ case 's': multiplier = 1; break;
+ default : return 0; //bad format
+ }
+ buffer*=multiplier;
+ secs+=buffer;
+ buffer=0;
+ }
+ }
+
+ return secs;
+}
+
+std::string TimeToTimestampStr(time_t t)
+{
+ tm* aTm = localtime(&t);
+ // YYYY year
+ // MM month (2 digits 01-12)
+ // DD day (2 digits 01-31)
+ // HH hour (2 digits 00-23)
+ // MM minutes (2 digits 00-59)
+ // SS seconds (2 digits 00-59)
+ char buf[20];
+ snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
+ return std::string(buf);
+}
+
+/// Check if the string is a valid ip address representation
+bool IsIPAddress(char const* ipaddress)
+{
+ if(!ipaddress)
+ return false;
+
+ // Let the big boys do it.
+ // Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD)
+ return inet_addr(ipaddress) != INADDR_NONE;
+}
+
+/// create PID file
+uint32 CreatePIDFile(const std::string& filename)
+{
+ FILE * pid_file = fopen (filename.c_str(), "w" );
+ if (pid_file == NULL)
+ return 0;
+
+#ifdef WIN32
+ DWORD pid = GetCurrentProcessId();
+#else
+ pid_t pid = getpid();
+#endif
+
+ fprintf(pid_file, "%d", pid );
+ fclose(pid_file);
+
+ return (uint32)pid;
+}
+
+size_t utf8length(std::string& utf8str)
+{
+ try
+ {
+ return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
+ }
+ catch(std::exception)
+ {
+ utf8str = "";
+ return 0;
+ }
+}
+
+void utf8truncate(std::string& utf8str,size_t len)
+{
+ try
+ {
+ size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
+ if(wlen <= len)
+ return;
+
+ std::wstring wstr;
+ wstr.resize(wlen);
+ utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
+ wstr.resize(len);
+ char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]);
+ utf8str.resize(oend-(&utf8str[0])); // remove unused tail
+ }
+ catch(std::exception)
+ {
+ utf8str = "";
+ }
+}
+
+bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
+{
+ try
+ {
+ size_t len = utf8::distance(utf8str,utf8str+csize);
+ if(len > wsize)
+ {
+ if(wsize > 0)
+ wstr[0] = L'\0';
+ wsize = 0;
+ return false;
+ }
+
+ wsize = len;
+ utf8::utf8to16(utf8str,utf8str+csize,wstr);
+ wstr[len] = L'\0';
+ }
+ catch(std::exception)
+ {
+ if(wsize > 0)
+ wstr[0] = L'\0';
+ wsize = 0;
+ return false;
+ }
+
+ return true;
+}
+
+bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
+{
+ try
+ {
+ size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
+ wstr.resize(len);
+
+ utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
+ }
+ catch(std::exception)
+ {
+ wstr = L"";
+ return false;
+ }
+
+ return true;
+}
+
+bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
+{
+ try
+ {
+ std::string utf8str2;
+ utf8str2.resize(size*4); // allocate for most long case
+
+ char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]);
+ utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
+ utf8str = utf8str2;
+ }
+ catch(std::exception)
+ {
+ utf8str = "";
+ return false;
+ }
+
+ return true;
+}
+
+bool WStrToUtf8(std::wstring wstr, std::string& utf8str)
+{
+ try
+ {
+ std::string utf8str2;
+ utf8str2.resize(wstr.size()*4); // allocate for most long case
+
+ char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]);
+ utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
+ utf8str = utf8str2;
+ }
+ catch(std::exception)
+ {
+ utf8str = "";
+ return false;
+ }
+
+ return true;
+}
+
+typedef wchar_t const* const* wstrlist;
+
+std::wstring GetMainPartOfName(std::wstring wname, uint32 declension)
+{
+ // supported only Cyrillic cases
+ if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5)
+ return wname;
+
+ // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
+
+ static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)};
+ static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)};
+ static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)};
+ static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)};
+ static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)};
+ static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)};
+ static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)};
+ static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)};
+ static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)};
+ static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)};
+ static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)};
+ static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)};
+ static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)};
+ static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)};
+ static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)};
+ static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)};
+
+ static wchar_t const* const dropEnds[6][8] = {
+ { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL },
+ { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL },
+ { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL },
+ { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL },
+ { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL },
+ { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL }
+ };
+
+ for (wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr)
+ {
+ size_t len = size_t((*itr)[-1]); // get length from string size field
+
+ if(wname.substr(wname.size()-len,len)==*itr)
+ return wname.substr(0,wname.size()-len);
+ }
+
+ return wname;
+}
+
+bool utf8ToConsole(const std::string& utf8str, std::string& conStr)
+{
+#if PLATFORM == PLATFORM_WINDOWS
+ std::wstring wstr;
+ if(!Utf8toWStr(utf8str,wstr))
+ return false;
+
+ conStr.resize(wstr.size());
+ CharToOemBuffW(&wstr[0],&conStr[0],wstr.size());
+#else
+ // not implemented yet
+ conStr = utf8str;
+#endif
+
+ return true;
+}
+
+bool consoleToUtf8(const std::string& conStr,std::string& utf8str)
+{
+#if PLATFORM == PLATFORM_WINDOWS
+ std::wstring wstr;
+ wstr.resize(conStr.size());
+ OemToCharBuffW(&conStr[0],&wstr[0],conStr.size());
+
+ return WStrToUtf8(wstr,utf8str);
+#else
+ // not implemented yet
+ utf8str = conStr;
+ return true;
+#endif
+}
+
+bool Utf8FitTo(const std::string& str, std::wstring search)
+{
+ std::wstring temp;
+
+ if(!Utf8toWStr(str,temp))
+ return false;
+
+ // converting to lower case
+ wstrToLower( temp );
+
+ if(temp.find(search) == std::wstring::npos)
+ return false;
+
+ return true;
+}
+
+void utf8printf(FILE *out, const char *str, ...)
+{
+ va_list ap;
+ va_start(ap, str);
+ vutf8printf(out, str, &ap);
+ va_end(ap);
+}
+
+void vutf8printf(FILE *out, const char *str, va_list* ap)
+{
+#if PLATFORM == PLATFORM_WINDOWS
+ char temp_buf[32*1024];
+ wchar_t wtemp_buf[32*1024];
+
+ size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap);
+
+ size_t wtemp_len = 32*1024-1;
+ Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
+
+ CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1);
+ fprintf(out, temp_buf);
+#else
+ vfprintf(out, str, *ap);
+#endif
+}
+
+void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result)
+{
+ std::ostringstream ss;
+ for (uint32 i=0; i<arrayLen; ++i)
+ {
+ for (uint8 j=0; j<2; ++j)
+ {
+ unsigned char nibble = 0x0F & (bytes[i]>>((1-j)*4));
+ char encodedNibble;
+ if(nibble < 0x0A)
+ encodedNibble = '0'+nibble;
+ else
+ encodedNibble = 'A'+nibble-0x0A;
+ ss << encodedNibble;
+ }
+ }
+ result = ss.str();
+}
+
diff --git a/src/server/shared/Util.h b/src/server/shared/Util.h
new file mode 100644
index 00000000000..4f997725d25
--- /dev/null
+++ b/src/server/shared/Util.h
@@ -0,0 +1,536 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#include "Common.h"
+
+#include <string>
+#include <vector>
+
+typedef std::vector<std::string> Tokens;
+
+Tokens StrSplit(const std::string &src, const std::string &sep);
+
+void stripLineInvisibleChars(std::string &src);
+
+std::string secsToTimeString(uint32 timeInSecs, bool shortText = false, bool hoursOnly = false);
+uint32 TimeStringToSecs(const std::string& timestring);
+std::string TimeToTimestampStr(time_t t);
+
+inline uint32 secsToTimeBitFields(time_t secs)
+{
+ tm* lt = localtime(&secs);
+ return (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min;
+}
+
+/* Return a random number in the range min..max; (max-min) must be smaller than 32768. */
+ int32 irand(int32 min, int32 max);
+
+/* Return a random number in the range min..max (inclusive). For reliable results, the difference
+* between max and min should be less than RAND32_MAX. */
+ uint32 urand(uint32 min, uint32 max);
+
+/* Return a random number in the range 0 .. RAND32_MAX. */
+ int32 rand32();
+
+/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits.
+ * A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits).
+ * With an FPU, there is usually no difference in performance between float and double. */
+ double rand_norm(void);
+
+/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits.
+ * A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits).
+ * With an FPU, there is usually no difference in performance between float and double. */
+ double rand_chance(void);
+
+/* Return true if a random roll fits in the specified chance (range 0-100). */
+inline bool roll_chance_f(float chance)
+{
+ return chance > rand_chance();
+}
+
+/* Return true if a random roll fits in the specified chance (range 0-100). */
+inline bool roll_chance_i(int chance)
+{
+ return chance > irand(0, 99);
+}
+
+inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply)
+{
+ int32 cur = var;
+ cur += (apply ? val : -val);
+ if(cur < 0)
+ cur = 0;
+ var = cur;
+}
+
+inline void ApplyModFloatVar(float& var, float val, bool apply)
+{
+ var += (apply ? val : -val);
+ if(var < 0)
+ var = 0;
+}
+
+inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
+{
+ if (val == -100.0f) // prevent set var to zero
+ val = -99.99f;
+ var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val));
+}
+
+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);
+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 wstr, std::string& utf8str);
+// size==real string size
+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);
+
+inline bool isBasicLatinCharacter(wchar_t wchar)
+{
+ if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z
+ return true;
+ if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z
+ return true;
+ return false;
+}
+
+inline bool isExtendedLatinCharacter(wchar_t wchar)
+{
+ if(isBasicLatinCharacter(wchar))
+ return true;
+ if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS
+ return true;
+ if(wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN
+ return true;
+ if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
+ return true;
+ if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS
+ return true;
+ if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN
+ return true;
+ if(wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK
+ return true;
+ if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S
+ return true;
+ return false;
+}
+
+inline bool isCyrillicCharacter(wchar_t wchar)
+{
+ if(wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA
+ return true;
+ if(wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO
+ return true;
+ return false;
+}
+
+inline bool isEastAsianCharacter(wchar_t wchar)
+{
+ if(wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo
+ return true;
+ if(wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana
+ return true;
+ if(wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo
+ return true;
+ if(wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext.
+ return true;
+ if(wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A
+ return true;
+ if(wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs
+ return true;
+ if(wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables
+ return true;
+ if(wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms
+ return true;
+ return false;
+}
+
+inline bool isNumeric(wchar_t wchar)
+{
+ return (wchar >= L'0' && wchar <=L'9');
+}
+
+inline bool isNumeric(char c)
+{
+ return (c >= '0' && c <='9');
+}
+
+inline bool isNumericOrSpace(wchar_t wchar)
+{
+ return isNumeric(wchar) || wchar == L' ';
+}
+
+inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace)
+{
+ for (size_t i = 0; i < wstr.size(); ++i)
+ if(!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
+ return false;
+ return true;
+}
+
+inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace)
+{
+ for (size_t i = 0; i < wstr.size(); ++i)
+ if(!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
+ return false;
+ return true;
+}
+
+inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace)
+{
+ for (size_t i = 0; i < wstr.size(); ++i)
+ if(!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
+ return false;
+ return true;
+}
+
+inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace)
+{
+ for (size_t i = 0; i < wstr.size(); ++i)
+ if(!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
+ return false;
+ return true;
+}
+
+inline wchar_t wcharToUpper(wchar_t wchar)
+{
+ if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z
+ return wchar_t(uint16(wchar)-0x0020);
+ if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
+ return wchar_t(0x1E9E);
+ if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS
+ return wchar_t(uint16(wchar)-0x0020);
+ if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN
+ return wchar_t(uint16(wchar)-0x0020);
+ if(wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1)
+ {
+ if(wchar % 2 == 1)
+ return wchar_t(uint16(wchar)-0x0001);
+ }
+ if(wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA
+ return wchar_t(uint16(wchar)-0x0020);
+ if(wchar == 0x0451) // CYRILLIC SMALL LETTER IO
+ return wchar_t(0x0401);
+
+ return wchar;
+}
+
+inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar)
+{
+ return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar;
+}
+
+inline wchar_t wcharToLower(wchar_t wchar)
+{
+ if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z
+ return wchar_t(uint16(wchar)+0x0020);
+ if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS
+ return wchar_t(uint16(wchar)+0x0020);
+ if(wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN
+ return wchar_t(uint16(wchar)+0x0020);
+ if(wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0)
+ {
+ if(wchar % 2 == 0)
+ return wchar_t(uint16(wchar)+0x0001);
+ }
+ if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S
+ return wchar_t(0x00DF);
+ if(wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO
+ return wchar_t(0x0451);
+ if(wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA
+ return wchar_t(uint16(wchar)+0x0020);
+
+ return wchar;
+}
+
+inline void wstrToUpper(std::wstring& str)
+{
+ std::transform( str.begin(), str.end(), str.begin(), wcharToUpper );
+}
+
+inline void wstrToLower(std::wstring& str)
+{
+ std::transform( str.begin(), str.end(), str.begin(), wcharToLower );
+}
+
+std::wstring GetMainPartOfName(std::wstring 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 search);
+void utf8printf(FILE *out, const char *str, ...);
+void vutf8printf(FILE *out, const char *str, va_list* ap);
+
+bool IsIPAddress(char const* ipaddress);
+uint32 CreatePIDFile(const std::string& filename);
+
+void hexEncodeByteArray(uint8* bytes, uint32 arrayLen, std::string& result);
+#endif
+
+//handler for operations on large flags
+#ifndef _FLAG96
+#define _FLAG96
+
+#ifndef PAIR64_HIPART
+#define PAIR64_HIPART(x) (uint32)((uint64(x) >> 32) & UI64LIT(0x00000000FFFFFFFF))
+#define PAIR64_LOPART(x) (uint32)(uint64(x) & UI64LIT(0x00000000FFFFFFFF))
+#endif
+
+class flag96
+{
+private:
+ uint32 part[3];
+public:
+ flag96(uint32 p1=0,uint32 p2=0,uint32 p3=0)
+ {
+ part[0]=p1;
+ part[1]=p2;
+ part[2]=p3;
+ }
+
+ flag96(uint64 p1, uint32 p2)
+ {
+ part[0]=PAIR64_LOPART(p1);
+ part[1]=PAIR64_HIPART(p1);
+ part[2]=p2;
+ }
+
+ inline bool IsEqual(uint32 p1=0, uint32 p2=0, uint32 p3=0) const
+ {
+ return (
+ part[0]==p1 &&
+ part[1]==p2 &&
+ part[2]==p3);
+ };
+
+ inline bool HasFlag(uint32 p1=0, uint32 p2=0, uint32 p3=0) const
+ {
+ return (
+ part[0]&p1 ||
+ part[1]&p2 ||
+ part[2]&p3);
+ };
+
+ inline void Set(uint32 p1=0, uint32 p2=0, uint32 p3=0)
+ {
+ part[0]=p1;
+ part[1]=p2;
+ part[2]=p3;
+ };
+
+ template<class type>
+ inline bool operator < (type & right)
+ {
+ for (uint8 i=3; i > 0; --i)
+ {
+ if (part[i-1]<right.part[i-1])
+ return 1;
+ else if (part[i-1]>right.part[i-1])
+ return 0;
+ }
+ return 0;
+ };
+
+ template<class type>
+ inline bool operator < (type & right) const
+ {
+ for (uint8 i = 3; i > 0; --i)
+ {
+ if (part[i-1]<right.part[i-1])
+ return 1;
+ else if (part[i-1]>right.part[i-1])
+ return 0;
+ }
+ return 0;
+ };
+
+ template<class type>
+ inline bool operator != (type & right)
+ {
+ if (part[0]!=right.part[0]
+ || part[1]!=right.part[1]
+ || part[2]!=right.part[2])
+ return true;
+ return false;
+ }
+
+ template<class type>
+ inline bool operator != (type & right) const
+ {
+ if (part[0]!=right.part[0]
+ || part[1]!=right.part[1]
+ || part[2]!=right.part[2])
+ return true;
+ return false;
+ };
+
+ template<class type>
+ inline bool operator == (type & right)
+ {
+ if (part[0]!=right.part[0]
+ || part[1]!=right.part[1]
+ || part[2]!=right.part[2])
+ return false;
+ return true;
+ };
+
+ template<class type>
+ inline bool operator == (type & right) const
+ {
+ if (part[0]!=right.part[0]
+ || part[1]!=right.part[1]
+ || part[2]!=right.part[2])
+ return false;
+ return true;
+ };
+
+ template<class type>
+ inline void operator = (type & right)
+ {
+ part[0]=right.part[0];
+ part[1]=right.part[1];
+ part[2]=right.part[2];
+ };
+
+ template<class type>
+ inline flag96 operator & (type & right)
+ {
+ flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]);
+ return
+ ret;
+ };
+ template<class type>
+ inline flag96 operator & (type & right) const
+ {
+ flag96 ret(part[0] & right.part[0],part[1] & right.part[1],part[2] & right.part[2]);
+ return
+ ret;
+ };
+
+ template<class type>
+ inline void operator &= (type & right)
+ {
+ *this=*this & right;
+ };
+
+ template<class type>
+ inline flag96 operator | (type & right)
+ {
+ flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]);
+ return
+ ret;
+ };
+
+ template<class type>
+ inline flag96 operator | (type & right) const
+ {
+ flag96 ret(part[0] | right.part[0],part[1] | right.part[1],part[2] | right.part[2]);
+ return
+ ret;
+ };
+
+ template<class type>
+ inline void operator |= (type & right)
+ {
+ *this=*this | right;
+ };
+
+ inline void operator ~ ()
+ {
+ part[2]=~part[2];
+ part[1]=~part[1];
+ part[0]=~part[0];
+ };
+
+ template<class type>
+ inline flag96 operator ^ (type & right)
+ {
+ flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]);
+ return
+ ret;
+ };
+
+ template<class type>
+ inline flag96 operator ^ (type & right) const
+ {
+ flag96 ret(part[0] ^ right.part[0],part[1] ^ right.part[1],part[2] ^ right.part[2]);
+ return
+ ret;
+ };
+
+ template<class type>
+ inline void operator ^= (type & right)
+ {
+ *this=*this^right;
+ };
+
+ inline operator bool() const
+ {
+ return(
+ part[0] != 0 ||
+ part[1] != 0 ||
+ part[2] != 0);
+ };
+
+ inline operator bool()
+ {
+ return(
+ part[0] != 0 ||
+ part[1] != 0 ||
+ part[2] != 0);
+ };
+
+ inline bool operator ! () const
+ {
+ return(
+ part[0] == 0 &&
+ part[1] == 0 &&
+ part[2] == 0);
+ };
+
+ inline bool operator ! ()
+ {
+ return(
+ part[0] == 0 &&
+ part[1] == 0 &&
+ part[2] == 0);
+ };
+
+ inline uint32 & operator[](uint8 el)
+ {
+ return (part[el]);
+ };
+
+ inline const uint32 & operator[](uint8 el) const
+ {
+ return (part[el]);
+ };
+};
+#endif
diff --git a/src/server/shared/WheatyExceptionReport.cpp b/src/server/shared/WheatyExceptionReport.cpp
new file mode 100644
index 00000000000..8fb5d5e2d2a
--- /dev/null
+++ b/src/server/shared/WheatyExceptionReport.cpp
@@ -0,0 +1,1013 @@
+//==========================================
+// Matt Pietrek
+// MSDN Magazine, 2002
+// FILE: WheatyExceptionReport.CPP
+//==========================================
+#define WIN32_LEAN_AND_MEAN
+#pragma warning(disable:4996)
+#pragma warning(disable:4312)
+#pragma warning(disable:4311)
+#include <windows.h>
+#include <tlhelp32.h>
+#include <stdio.h>
+#include <tchar.h>
+#define _NO_CVCONST_H
+#include <dbghelp.h>
+#include "WheatyExceptionReport.h"
+#include "SystemConfig.h"
+#include "revision.h"
+#define CrashFolder _T("Crashes")
+//#pragma comment(linker, "/defaultlib:dbghelp.lib")
+
+inline LPTSTR ErrorMessage(DWORD dw)
+{
+ LPVOID lpMsgBuf;
+ FormatMessage(
+ FORMAT_MESSAGE_ALLOCATE_BUFFER |
+ FORMAT_MESSAGE_FROM_SYSTEM,
+ NULL,
+ dw,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+ (LPTSTR) &lpMsgBuf,
+ 0, NULL);
+ return (LPTSTR)lpMsgBuf;
+}
+
+//============================== Global Variables =============================
+
+//
+// Declare the static variables of the WheatyExceptionReport class
+//
+TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH];
+LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter;
+HANDLE WheatyExceptionReport::m_hReportFile;
+HANDLE WheatyExceptionReport::m_hProcess;
+
+// Declare global instance of class
+WheatyExceptionReport g_WheatyExceptionReport;
+
+//============================== Class Methods =============================
+
+WheatyExceptionReport::WheatyExceptionReport() // Constructor
+{
+ // Install the unhandled exception filter function
+ m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter);
+ m_hProcess = GetCurrentProcess();
+}
+
+//============
+// Destructor
+//============
+WheatyExceptionReport::~WheatyExceptionReport()
+{
+ if (m_previousFilter)
+ SetUnhandledExceptionFilter(m_previousFilter);
+}
+
+//===========================================================
+// Entry point where control comes on an unhandled exception
+//===========================================================
+LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
+PEXCEPTION_POINTERS pExceptionInfo)
+{
+ TCHAR module_folder_name[MAX_PATH];
+ GetModuleFileName(0, module_folder_name, MAX_PATH);
+ TCHAR* pos = _tcsrchr(module_folder_name, '\\');
+ if (!pos)
+ return 0;
+ pos[0] = '\0';
+ ++pos;
+
+ TCHAR crash_folder_path[MAX_PATH];
+ sprintf(crash_folder_path, "%s\\%s", module_folder_name, CrashFolder);
+ if (!CreateDirectory(crash_folder_path, NULL))
+ {
+ if (GetLastError() != ERROR_ALREADY_EXISTS)
+ return 0;
+ }
+
+ SYSTEMTIME systime;
+ GetLocalTime(&systime);
+ sprintf(m_szLogFileName, "%s\\%s_[%u-%u_%u-%u-%u].txt",
+ crash_folder_path, pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
+
+ m_hReportFile = CreateFile(m_szLogFileName,
+ GENERIC_WRITE,
+ 0,
+ 0,
+ OPEN_ALWAYS,
+ FILE_FLAG_WRITE_THROUGH,
+ 0);
+
+ if (m_hReportFile)
+ {
+ SetFilePointer(m_hReportFile, 0, 0, FILE_END);
+
+ GenerateExceptionReport(pExceptionInfo);
+
+ CloseHandle(m_hReportFile);
+ m_hReportFile = 0;
+ }
+
+ if (m_previousFilter)
+ return m_previousFilter(pExceptionInfo);
+ else
+ return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/;
+}
+
+BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount)
+{
+ if (!sProcessorName)
+ return FALSE;
+
+ HKEY hKey;
+ LONG lRet;
+ lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
+ 0, KEY_QUERY_VALUE, &hKey);
+ if (lRet != ERROR_SUCCESS)
+ return FALSE;
+ TCHAR szTmp[2048];
+ DWORD cntBytes = sizeof(szTmp);
+ lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL,
+ (LPBYTE)szTmp, &cntBytes);
+ if (lRet != ERROR_SUCCESS)
+ return FALSE;
+ ::RegCloseKey(hKey);
+ sProcessorName[0] = '\0';
+ // Skip spaces
+ TCHAR* psz = szTmp;
+ while (iswspace(*psz))
+ ++psz;
+ _tcsncpy(sProcessorName, psz, maxcount);
+ return TRUE;
+}
+
+BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
+{
+ // Try calling GetVersionEx using the OSVERSIONINFOEX structure.
+ // If that fails, try using the OSVERSIONINFO structure.
+ OSVERSIONINFOEX osvi = { 0 };
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
+ BOOL bOsVersionInfoEx;
+ bOsVersionInfoEx = ::GetVersionEx((LPOSVERSIONINFO)(&osvi));
+ if (!bOsVersionInfoEx)
+ {
+ osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+ if (!::GetVersionEx((OSVERSIONINFO*)&osvi))
+ return FALSE;
+ }
+ *szVersion = _T('\0');
+ TCHAR wszTmp[128];
+ switch (osvi.dwPlatformId)
+ {
+ // Windows NT product family.
+ case VER_PLATFORM_WIN32_NT:
+ // Test for the specific product family.
+ if (osvi.dwMajorVersion == 6)
+ _tcsncat(szVersion, _T("Windows Vista or Windows Server 2008 "), cntMax);
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
+ _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax);
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
+ _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax);
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
+ _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax);
+ if (osvi.dwMajorVersion <= 4)
+ _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax);
+
+ // Test for specific product on Windows NT 4.0 SP6 and later.
+ if (bOsVersionInfoEx)
+ {
+ // Test for the workstation type.
+ #if WINVER < 0x0500
+ if (osvi.wReserved[1] == VER_NT_WORKSTATION)
+ #else
+ if (osvi.wProductType == VER_NT_WORKSTATION)
+ #endif // WINVER < 0x0500
+ {
+ if (osvi.dwMajorVersion == 4)
+ _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax);
+ #if WINVER < 0x0500
+ else if (osvi.wReserved[0] & VER_SUITE_PERSONAL)
+ #else
+ else if (osvi.wSuiteMask & VER_SUITE_PERSONAL)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Home Edition "), cntMax);
+ #if WINVER < 0x0500
+ else if (osvi.wReserved[0] & VER_SUITE_EMBEDDEDNT)
+ #else
+ else if (osvi.wSuiteMask & VER_SUITE_EMBEDDEDNT)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Embedded "), cntMax);
+ else
+ _tcsncat(szVersion, _T("Professional "), cntMax);
+ }
+ // Test for the server type.
+ #if WINVER < 0x0500
+ else if (osvi.wReserved[1] == VER_NT_SERVER)
+ #else
+ else if (osvi.wProductType == VER_NT_SERVER)
+ #endif // WINVER < 0x0500
+ {
+ if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
+ {
+ #if WINVER < 0x0500
+ if (osvi.wReserved[0] & VER_SUITE_DATACENTER)
+ #else
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Datacenter Edition "), cntMax);
+ #if WINVER < 0x0500
+ else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE)
+ #else
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Enterprise Edition "), cntMax);
+ #if WINVER < 0x0500
+ else if (osvi.wReserved[0] == VER_SUITE_BLADE)
+ #else
+ else if (osvi.wSuiteMask == VER_SUITE_BLADE)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Web Edition "), cntMax);
+ else
+ _tcsncat(szVersion, _T("Standard Edition "), cntMax);
+ }
+ else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
+ {
+ #if WINVER < 0x0500
+ if (osvi.wReserved[0] & VER_SUITE_DATACENTER)
+ #else
+ if (osvi.wSuiteMask & VER_SUITE_DATACENTER)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Datacenter Server "), cntMax);
+ #if WINVER < 0x0500
+ else if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE)
+ #else
+ else if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Advanced Server "), cntMax);
+ else
+ _tcsncat(szVersion, _T("Server "), cntMax);
+ }
+ else // Windows NT 4.0
+ {
+ #if WINVER < 0x0500
+ if (osvi.wReserved[0] & VER_SUITE_ENTERPRISE)
+ #else
+ if (osvi.wSuiteMask & VER_SUITE_ENTERPRISE)
+ #endif // WINVER < 0x0500
+ _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax);
+ else
+ _tcsncat(szVersion, _T("Server 4.0 "), cntMax);
+ }
+ }
+ }
+ // Display service pack (if any) and build number.
+ if (osvi.dwMajorVersion == 4 && _tcsicmp(osvi.szCSDVersion, _T("Service Pack 6")) == 0)
+ {
+ HKEY hKey;
+ LONG lRet;
+
+ // Test for SP6 versus SP6a.
+ lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey);
+ if (lRet == ERROR_SUCCESS)
+ {
+ _stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"),
+ osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
+ _tcsncat(szVersion, wszTmp, cntMax);
+ }
+ else // Windows NT 4.0 prior to SP6a
+ {
+ _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
+ osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
+ _tcsncat(szVersion, wszTmp, cntMax);
+ }
+ ::RegCloseKey(hKey);
+ }
+ else // Windows NT 3.51 and earlier or Windows 2000 and later
+ {
+ if (!_tcslen(osvi.szCSDVersion))
+ _stprintf(wszTmp, _T("(Version %d.%d, Build %d)"),
+ osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
+ else
+ _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
+ osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
+ _tcsncat(szVersion, wszTmp, cntMax);
+ }
+ break;
+ default:
+ _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
+ osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
+ _tcsncat(szVersion, wszTmp, cntMax);
+ break;
+ }
+
+ return TRUE;
+}
+
+void WheatyExceptionReport::PrintSystemInfo()
+{
+ SYSTEM_INFO SystemInfo;
+ ::GetSystemInfo(&SystemInfo);
+
+ MEMORYSTATUS MemoryStatus;
+ MemoryStatus.dwLength = sizeof (MEMORYSTATUS);
+ ::GlobalMemoryStatus(&MemoryStatus);
+ TCHAR sString[1024];
+ _tprintf(_T("//=====================================================\r\n"));
+ if (_GetProcessorName(sString, countof(sString)))
+ _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
+ sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400);
+ else
+ _tprintf(_T("*** Hardware ***\r\nProcessor: <unknown>\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"),
+ SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400);
+
+ if (_GetWindowsVersion(sString, countof(sString)))
+ _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString);
+ else
+ _tprintf(_T("\r\n*** Operation System:\r\n<unknown>\r\n"));
+}
+
+//===========================================================================
+void WheatyExceptionReport::printTracesForAllThreads()
+{
+ HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
+ THREADENTRY32 te32;
+
+ DWORD dwOwnerPID = GetCurrentProcessId();
+ m_hProcess = GetCurrentProcess();
+ // Take a snapshot of all running threads
+ hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
+ if (hThreadSnap == INVALID_HANDLE_VALUE)
+ return;
+
+ // Fill in the size of the structure before using it.
+ te32.dwSize = sizeof(THREADENTRY32);
+
+ // Retrieve information about the first thread,
+ // and exit if unsuccessful
+ if (!Thread32First(hThreadSnap, &te32))
+ {
+ CloseHandle(hThreadSnap); // Must clean up the
+ // snapshot object!
+ return;
+ }
+
+ // Now walk the thread list of the system,
+ // and display information about each thread
+ // associated with the specified process
+ do
+ {
+ if (te32.th32OwnerProcessID == dwOwnerPID)
+ {
+ CONTEXT context;
+ context.ContextFlags = 0xffffffff;
+ HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION,false, te32.th32ThreadID);
+ if (threadHandle && GetThreadContext(threadHandle, &context))
+ {
+ WriteStackDetails(&context, false, threadHandle);
+ }
+ CloseHandle(threadHandle);
+ }
+ } while(Thread32Next(hThreadSnap, &te32));
+
+// Don't forget to clean up the snapshot object.
+ CloseHandle(hThreadSnap);
+}
+
+//===========================================================================
+// Open the report file, and write the desired information to it. Called by
+// WheatyUnhandledExceptionFilter
+//===========================================================================
+void WheatyExceptionReport::GenerateExceptionReport(
+PEXCEPTION_POINTERS pExceptionInfo)
+{
+ SYSTEMTIME systime;
+ GetLocalTime(&systime);
+
+ // Start out with a banner
+ _tprintf(_T("Revision: %s\r\n"), _FULLVERSION);
+ _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute);
+ PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord;
+
+ PrintSystemInfo();
+ // First print information about the type of fault
+ _tprintf(_T("\r\n//=====================================================\r\n"));
+ _tprintf(_T("Exception code: %08X %s\r\n"),
+ pExceptionRecord->ExceptionCode,
+ GetExceptionString(pExceptionRecord->ExceptionCode));
+
+ // Now print information about where the fault occured
+ TCHAR szFaultingModule[MAX_PATH];
+ DWORD section;
+ DWORD_PTR offset;
+ GetLogicalAddress(pExceptionRecord->ExceptionAddress,
+ szFaultingModule,
+ sizeof(szFaultingModule),
+ section, offset);
+
+#ifdef _M_IX86
+ _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"),
+ pExceptionRecord->ExceptionAddress,
+ section, offset, szFaultingModule);
+#endif
+#ifdef _M_X64
+ _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"),
+ pExceptionRecord->ExceptionAddress,
+ section, offset, szFaultingModule);
+#endif
+
+ PCONTEXT pCtx = pExceptionInfo->ContextRecord;
+
+ // Show the registers
+ #ifdef _M_IX86 // X86 Only!
+ _tprintf(_T("\r\nRegisters:\r\n"));
+
+ _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n")
+ ,pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx,
+ pCtx->Esi, pCtx->Edi);
+
+ _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip);
+ _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"),
+ pCtx->SegSs, pCtx->Esp, pCtx->Ebp);
+ _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
+ _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+ #endif
+
+ #ifdef _M_X64
+ _tprintf(_T("\r\nRegisters:\r\n"));
+ _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n")
+ _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n")
+ ,pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx,
+ pCtx->Rsi, pCtx->Rdi ,pCtx->R9,pCtx->R10,pCtx->R11,pCtx->R12,pCtx->R13,pCtx->R14,pCtx->R15);
+ _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip);
+ _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"),
+ pCtx->SegSs, pCtx->Rsp, pCtx->Rbp);
+ _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"),
+ pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs);
+ _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags);
+ #endif
+
+ SymSetOptions(SYMOPT_DEFERRED_LOADS);
+
+ // Initialize DbgHelp
+ if (!SymInitialize(GetCurrentProcess(), 0, TRUE))
+ {
+ _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"),
+ ErrorMessage(GetLastError()));
+ }
+
+ CONTEXT trashableContext = *pCtx;
+
+ WriteStackDetails(&trashableContext, false, NULL);
+ printTracesForAllThreads();
+
+// #ifdef _M_IX86 // X86 Only!
+
+ _tprintf(_T("========================\r\n"));
+ _tprintf(_T("Local Variables And Parameters\r\n"));
+
+ trashableContext = *pCtx;
+ WriteStackDetails(&trashableContext, true, NULL);
+
+ _tprintf(_T("========================\r\n"));
+ _tprintf(_T("Global Variables\r\n"));
+
+ SymEnumSymbols(GetCurrentProcess(),
+ (DWORD64)GetModuleHandle(szFaultingModule),
+ 0, EnumerateSymbolsCallback, 0);
+ // #endif // X86 Only!
+
+ SymCleanup(GetCurrentProcess());
+
+ _tprintf(_T("\r\n"));
+}
+
+//======================================================================
+// Given an exception code, returns a pointer to a static string with a
+// description of the exception
+//======================================================================
+LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
+{
+ #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x);
+
+ switch (dwCode)
+ {
+ EXCEPTION(ACCESS_VIOLATION)
+ EXCEPTION(DATATYPE_MISALIGNMENT)
+ EXCEPTION(BREAKPOINT)
+ EXCEPTION(SINGLE_STEP)
+ EXCEPTION(ARRAY_BOUNDS_EXCEEDED)
+ EXCEPTION(FLT_DENORMAL_OPERAND)
+ EXCEPTION(FLT_DIVIDE_BY_ZERO)
+ EXCEPTION(FLT_INEXACT_RESULT)
+ EXCEPTION(FLT_INVALID_OPERATION)
+ EXCEPTION(FLT_OVERFLOW)
+ EXCEPTION(FLT_STACK_CHECK)
+ EXCEPTION(FLT_UNDERFLOW)
+ EXCEPTION(INT_DIVIDE_BY_ZERO)
+ EXCEPTION(INT_OVERFLOW)
+ EXCEPTION(PRIV_INSTRUCTION)
+ EXCEPTION(IN_PAGE_ERROR)
+ EXCEPTION(ILLEGAL_INSTRUCTION)
+ EXCEPTION(NONCONTINUABLE_EXCEPTION)
+ EXCEPTION(STACK_OVERFLOW)
+ EXCEPTION(INVALID_DISPOSITION)
+ EXCEPTION(GUARD_PAGE)
+ EXCEPTION(INVALID_HANDLE)
+ }
+
+ // If not one of the "known" exceptions, try to get the string
+ // from NTDLL.DLL's message table.
+
+ static TCHAR szBuffer[512] = { 0 };
+
+ FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
+ GetModuleHandle(_T("NTDLL.DLL")),
+ dwCode, 0, szBuffer, sizeof(szBuffer), 0);
+
+ return szBuffer;
+}
+
+//=============================================================================
+// Given a linear address, locates the module, section, and offset containing
+// that address.
+//
+// Note: the szModule paramater buffer is an output buffer of length specified
+// by the len parameter (in characters!)
+//=============================================================================
+BOOL WheatyExceptionReport::GetLogicalAddress(
+PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
+{
+ MEMORY_BASIC_INFORMATION mbi;
+
+ if (!VirtualQuery(addr, &mbi, sizeof(mbi)))
+ return FALSE;
+
+ DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase;
+
+ if (!GetModuleFileName((HMODULE)hMod, szModule, len))
+ return FALSE;
+
+ // Point to the DOS header in memory
+ PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod;
+
+ // From the DOS header, find the NT (PE) header
+ PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew));
+
+ PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr);
+
+ DWORD_PTR rva = (DWORD_PTR)addr - hMod; // RVA is offset from module load address
+
+ // Iterate through the section table, looking for the one that encompasses
+ // the linear address.
+ for (unsigned i = 0;
+ i < pNtHdr->FileHeader.NumberOfSections;
+ i++, pSection++)
+ {
+ DWORD_PTR sectionStart = pSection->VirtualAddress;
+ DWORD_PTR sectionEnd = sectionStart
+ + DWORD_PTR(max(pSection->SizeOfRawData, pSection->Misc.VirtualSize));
+
+ // Is the address in this section???
+ if ((rva >= sectionStart) && (rva <= sectionEnd))
+ {
+ // Yes, address is in the section. Calculate section and offset,
+ // and store in the "section" & "offset" params, which were
+ // passed by reference.
+ section = i+1;
+ offset = rva - sectionStart;
+ return TRUE;
+ }
+ }
+
+ return FALSE; // Should never get here!
+}
+
+// It contains SYMBOL_INFO structure plus additional
+// space for the name of the symbol
+struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE
+{
+ CSymbolInfoPackage()
+ {
+ si.SizeOfStruct = sizeof(SYMBOL_INFO);
+ si.MaxNameLen = sizeof(name);
+ }
+};
+
+//============================================================
+// Walks the stack, and writes the results to the report file
+//============================================================
+void WheatyExceptionReport::WriteStackDetails(
+PCONTEXT pContext,
+bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output
+{
+ _tprintf(_T("\r\nCall stack:\r\n"));
+
+ _tprintf(_T("Address Frame Function SourceFile\r\n"));
+
+ DWORD dwMachineType = 0;
+ // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag
+
+ STACKFRAME64 sf;
+ memset(&sf, 0, sizeof(sf));
+
+ #ifdef _M_IX86
+ // Initialize the STACKFRAME structure for the first call. This is only
+ // necessary for Intel CPUs, and isn't mentioned in the documentation.
+ sf.AddrPC.Offset = pContext->Eip;
+ sf.AddrPC.Mode = AddrModeFlat;
+ sf.AddrStack.Offset = pContext->Esp;
+ sf.AddrStack.Mode = AddrModeFlat;
+ sf.AddrFrame.Offset = pContext->Ebp;
+ sf.AddrFrame.Mode = AddrModeFlat;
+
+ dwMachineType = IMAGE_FILE_MACHINE_I386;
+ #endif
+
+#ifdef _M_X64
+ sf.AddrPC.Offset = pContext->Rip;
+ sf.AddrPC.Mode = AddrModeFlat;
+ sf.AddrStack.Offset = pContext->Rsp;
+ sf.AddrStack.Mode = AddrModeFlat;
+ sf.AddrFrame.Offset = pContext->Rbp;
+ sf.AddrFrame.Mode = AddrModeFlat;
+ dwMachineType = IMAGE_FILE_MACHINE_AMD64;
+#endif
+
+ while (1)
+ {
+ // Get the next stack frame
+ if (! StackWalk64(dwMachineType,
+ m_hProcess,
+ pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(),
+ &sf,
+ pContext,
+ 0,
+ SymFunctionTableAccess64,
+ SymGetModuleBase64,
+ 0))
+ break;
+ if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure
+ break; // the frame is OK. Bail if not.
+#ifdef _M_IX86
+ _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
+#endif
+#ifdef _M_X64
+ _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset);
+#endif
+
+ DWORD64 symDisplacement = 0; // Displacement of the input address,
+ // relative to the start of the symbol
+
+ // Get the name of the function for this stack frame entry
+ CSymbolInfoPackage sip;
+ if (SymFromAddr(
+ m_hProcess, // Process handle of the current process
+ sf.AddrPC.Offset, // Symbol address
+ &symDisplacement, // Address of the variable that will receive the displacement
+ &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object)
+ {
+ _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement);
+
+ }
+ else // No symbol found. Print out the logical address instead.
+ {
+ TCHAR szModule[MAX_PATH] = _T("");
+ DWORD section = 0;
+ DWORD_PTR offset = 0;
+
+ GetLogicalAddress((PVOID)sf.AddrPC.Offset,
+ szModule, sizeof(szModule), section, offset);
+#ifdef _M_IX86
+ _tprintf(_T("%04X:%08X %s"), section, offset, szModule);
+#endif
+#ifdef _M_X64
+ _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule);
+#endif
+ }
+
+ // Get the source line for this stack frame entry
+ IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE) };
+ DWORD dwLineDisplacement;
+ if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset,
+ &dwLineDisplacement, &lineInfo))
+ {
+ _tprintf(_T(" %s line %u"),lineInfo.FileName,lineInfo.LineNumber);
+ }
+
+ _tprintf(_T("\r\n"));
+
+ // Write out the variables, if desired
+ if (bWriteVariables)
+ {
+ // Use SymSetContext to get just the locals/params for this frame
+ IMAGEHLP_STACK_FRAME imagehlpStackFrame;
+ imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset;
+ SymSetContext(m_hProcess, &imagehlpStackFrame, 0);
+
+ // Enumerate the locals/parameters
+ SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf);
+
+ _tprintf(_T("\r\n"));
+ }
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// The function invoked by SymEnumSymbols
+//////////////////////////////////////////////////////////////////////////////
+
+BOOL CALLBACK
+WheatyExceptionReport::EnumerateSymbolsCallback(
+PSYMBOL_INFO pSymInfo,
+ULONG SymbolSize,
+PVOID UserContext)
+{
+
+ char szBuffer[2048];
+
+ __try
+ {
+ if (FormatSymbolValue(pSymInfo, (STACKFRAME*)UserContext,
+ szBuffer, sizeof(szBuffer)))
+ _tprintf(_T("\t%s\r\n"), szBuffer);
+ }
+ __except(1)
+ {
+ _tprintf(_T("punting on symbol %s\r\n"), pSymInfo->Name);
+ }
+
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Given a SYMBOL_INFO representing a particular variable, displays its
+// contents. If it's a user defined type, display the members and their
+// values.
+//////////////////////////////////////////////////////////////////////////////
+bool WheatyExceptionReport::FormatSymbolValue(
+PSYMBOL_INFO pSym,
+STACKFRAME * sf,
+char * pszBuffer,
+unsigned cbBuffer)
+{
+ char * pszCurrBuffer = pszBuffer;
+
+ // Indicate if the variable is a local or parameter
+ if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "Parameter ");
+ else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "Local ");
+
+ // If it's a function, don't do anything.
+ if (pSym->Tag == 5) // SymTagFunction from CVCONST.H from the DIA SDK
+ return false;
+
+ DWORD_PTR pVariable = 0; // Will point to the variable's data in memory
+
+ if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
+ {
+ // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1)
+ { // This may change!!!
+ pVariable = sf->AddrFrame.Offset;
+ pVariable += (DWORD_PTR)pSym->Address;
+ }
+ // else
+ // return false;
+ }
+ else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER)
+ {
+ return false; // Don't try to report register variable
+ }
+ else
+ {
+ pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable
+ }
+
+ // Determine if the variable is a user defined type (UDT). IF so, bHandled
+ // will return true.
+ bool bHandled;
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer,pSym->ModBase, pSym->TypeIndex,
+ 0, pVariable, bHandled, pSym->Name);
+
+ if (!bHandled)
+ {
+ // The symbol wasn't a UDT, so do basic, stupid formatting of the
+ // variable. Based on the size, we're assuming it's a char, WORD, or
+ // DWORD.
+ BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase);
+ pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]);
+
+ // Emit the variable name
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", pSym->Name);
+
+ pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType, pSym->Size,
+ (PVOID)pVariable);
+ }
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// If it's a user defined type (UDT), recurse through its members until we're
+// at fundamental types. When he hit fundamental types, return
+// bHandled = false, so that FormatSymbolValue() will format them.
+//////////////////////////////////////////////////////////////////////////////
+char * WheatyExceptionReport::DumpTypeIndex(
+char * pszCurrBuffer,
+DWORD64 modBase,
+DWORD dwTypeIndex,
+unsigned nestingLevel,
+DWORD_PTR offset,
+bool & bHandled,
+char* Name)
+{
+ bHandled = false;
+
+ // Get the name of the symbol. This will either be a Type name (if a UDT),
+ // or the structure member name.
+ WCHAR * pwszTypeName;
+ if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME,
+ &pwszTypeName))
+ {
+ pszCurrBuffer += sprintf(pszCurrBuffer, " %ls", pwszTypeName);
+ LocalFree(pwszTypeName);
+ }
+
+ // Determine how many children this type has.
+ DWORD dwChildrenCount = 0;
+ SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT,
+ &dwChildrenCount);
+
+ if (!dwChildrenCount) // If no children, we're done
+ return pszCurrBuffer;
+
+ // Prepare to get an array of "TypeIds", representing each of the children.
+ // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a
+ // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this.
+ struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
+ {
+ ULONG MoreChildIds[1024];
+ FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);}
+ } children;
+
+ children.Count = dwChildrenCount;
+ children.Start= 0;
+
+ // Get the array of TypeIds, one for each child type
+ if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN,
+ &children))
+ {
+ return pszCurrBuffer;
+ }
+
+ // Append a line feed
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n");
+
+ // Iterate through each of the children
+ for (unsigned i = 0; i < dwChildrenCount; i++)
+ {
+ // Add appropriate indentation level (since this routine is recursive)
+ for (unsigned j = 0; j <= nestingLevel+1; j++)
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\t");
+
+ // Recurse for each of the child types
+ bool bHandled2;
+ BasicType basicType = GetBasicType(children.ChildId[i], modBase);
+ pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]);
+
+ pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase,
+ children.ChildId[i], nestingLevel+1,
+ offset, bHandled2, ""/*Name */);
+
+ // If the child wasn't a UDT, format it appropriately
+ if (!bHandled2)
+ {
+ // Get the offset of the child member, relative to its parent
+ DWORD dwMemberOffset;
+ SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
+ TI_GET_OFFSET, &dwMemberOffset);
+
+ // Get the real "TypeId" of the child. We need this for the
+ // SymGetTypeInfo(TI_GET_TYPEID) call below.
+ DWORD typeId;
+ SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
+ TI_GET_TYPEID, &typeId);
+
+ // Get the size of the child member
+ ULONG64 length;
+ SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH,&length);
+
+ // Calculate the address of the member
+ DWORD_PTR dwFinalOffset = offset + dwMemberOffset;
+
+ // BasicType basicType = GetBasicType(children.ChildId[i], modBase);
+ //
+ // pszCurrBuffer += sprintf(pszCurrBuffer, rgBaseType[basicType]);
+ //
+ // Emit the variable name
+ // pszCurrBuffer += sprintf(pszCurrBuffer, "\'%s\'", Name);
+
+ pszCurrBuffer = FormatOutputValue(pszCurrBuffer, basicType,
+ length, (PVOID)dwFinalOffset);
+
+ pszCurrBuffer += sprintf(pszCurrBuffer, "\r\n");
+ }
+ }
+
+ bHandled = true;
+ return pszCurrBuffer;
+}
+
+char * WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer,
+BasicType basicType,
+DWORD64 length,
+PVOID pAddress)
+{
+ // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!)
+ if (length == 1)
+ pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PBYTE)pAddress);
+ else if (length == 2)
+ pszCurrBuffer += sprintf(pszCurrBuffer, " = %X", *(PWORD)pAddress);
+ else if (length == 4)
+ {
+ if (basicType == btFloat)
+ {
+ pszCurrBuffer += sprintf(pszCurrBuffer," = %f", *(PFLOAT)pAddress);
+ }
+ else if (basicType == btChar)
+ {
+ if (!IsBadStringPtr(*(PSTR*)pAddress, 32))
+ {
+ pszCurrBuffer += sprintf(pszCurrBuffer, " = \"%.31s\"",
+ *(PDWORD)pAddress);
+ }
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer, " = %X",
+ *(PDWORD)pAddress);
+ }
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer," = %X", *(PDWORD)pAddress);
+ }
+ else if (length == 8)
+ {
+ if (basicType == btFloat)
+ {
+ pszCurrBuffer += sprintf(pszCurrBuffer, " = %lf",
+ *(double *)pAddress);
+ }
+ else
+ pszCurrBuffer += sprintf(pszCurrBuffer, " = %I64X",
+ *(DWORD64*)pAddress);
+ }
+
+ return pszCurrBuffer;
+}
+
+BasicType
+WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
+{
+ BasicType basicType;
+ if (SymGetTypeInfo(m_hProcess, modBase, typeIndex,
+ TI_GET_BASETYPE, &basicType))
+ {
+ return basicType;
+ }
+
+ // Get the real "TypeId" of the child. We need this for the
+ // SymGetTypeInfo(TI_GET_TYPEID) call below.
+ DWORD typeId;
+ if (SymGetTypeInfo(m_hProcess,modBase, typeIndex, TI_GET_TYPEID, &typeId))
+ {
+ if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE,
+ &basicType))
+ {
+ return basicType;
+ }
+ }
+
+ return btNoType;
+}
+
+//============================================================================
+// Helper function that writes to the report file, and allows the user to use
+// printf style formating
+//============================================================================
+int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...)
+{
+ TCHAR szBuff[1024];
+ int retValue;
+ DWORD cbWritten;
+ va_list argptr;
+
+ va_start(argptr, format);
+ retValue = vsprintf(szBuff, format, argptr);
+ va_end(argptr);
+
+ WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0);
+
+ return retValue;
+}
+
diff --git a/src/server/shared/WheatyExceptionReport.h b/src/server/shared/WheatyExceptionReport.h
new file mode 100644
index 00000000000..33fb4bc5b0e
--- /dev/null
+++ b/src/server/shared/WheatyExceptionReport.h
@@ -0,0 +1,118 @@
+#ifndef _WHEATYEXCEPTIONREPORT_
+#define _WHEATYEXCEPTIONREPORT_
+
+#include <dbghelp.h>
+
+#if _MSC_VER < 1400
+# define countof(array) (sizeof(array) / sizeof(array[0]))
+#else
+# include <stdlib.h>
+# define countof _countof
+#endif // _MSC_VER < 1400
+
+enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
+{
+ btNoType = 0,
+ btVoid = 1,
+ btChar = 2,
+ btWChar = 3,
+ btInt = 6,
+ btUInt = 7,
+ btFloat = 8,
+ btBCD = 9,
+ btBool = 10,
+ btLong = 13,
+ btULong = 14,
+ btCurrency = 25,
+ btDate = 26,
+ btVariant = 27,
+ btComplex = 28,
+ btBit = 29,
+ btBSTR = 30,
+ btHresult = 31
+};
+
+const char* const rgBaseType[] =
+{
+ " <user defined> ", // btNoType = 0,
+ " void ", // btVoid = 1,
+ " char* ", // btChar = 2,
+ " wchar_t* ", // btWChar = 3,
+ " signed char ",
+ " unsigned char ",
+ " int ", // btInt = 6,
+ " unsigned int ", // btUInt = 7,
+ " float ", // btFloat = 8,
+ " <BCD> ", // btBCD = 9,
+ " bool ", // btBool = 10,
+ " short ",
+ " unsigned short ",
+ " long ", // btLong = 13,
+ " unsigned long ", // btULong = 14,
+ " __int8 ",
+ " __int16 ",
+ " __int32 ",
+ " __int64 ",
+ " __int128 ",
+ " unsigned __int8 ",
+ " unsigned __int16 ",
+ " unsigned __int32 ",
+ " unsigned __int64 ",
+ " unsigned __int128 ",
+ " <currency> ", // btCurrency = 25,
+ " <date> ", // btDate = 26,
+ " VARIANT ", // btVariant = 27,
+ " <complex> ", // btComplex = 28,
+ " <bit> ", // btBit = 29,
+ " BSTR ", // btBSTR = 30,
+ " HRESULT " // btHresult = 31
+};
+
+class WheatyExceptionReport
+{
+ public:
+
+ WheatyExceptionReport();
+ ~WheatyExceptionReport();
+
+ // entry point where control comes on an unhandled exception
+ static LONG WINAPI WheatyUnhandledExceptionFilter(
+ PEXCEPTION_POINTERS pExceptionInfo);
+
+ static void printTracesForAllThreads();
+ private:
+ // where report info is extracted and generated
+ static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
+ static void PrintSystemInfo();
+ static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
+ static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
+
+ // Helper functions
+ static LPTSTR GetExceptionString(DWORD dwCode);
+ static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
+ DWORD& section, DWORD_PTR& offset);
+
+ static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
+
+ static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID);
+
+ static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer);
+
+ static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & , char*);
+
+ static char * FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress);
+
+ static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
+
+ static int __cdecl _tprintf(const TCHAR * format, ...);
+
+ // Variables used by the class
+ static TCHAR m_szLogFileName[MAX_PATH];
+ static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
+ static HANDLE m_hReportFile;
+ static HANDLE m_hProcess;
+};
+
+extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class
+#endif //WheatyExceptionReport
+
diff --git a/src/server/shared/WorldPacket.h b/src/server/shared/WorldPacket.h
new file mode 100644
index 00000000000..d708959f91d
--- /dev/null
+++ b/src/server/shared/WorldPacket.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
+ *
+ * Copyright (C) 2008-2010 Trinity <http://www.trinitycore.org/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef TRINITYCORE_WORLDPACKET_H
+#define TRINITYCORE_WORLDPACKET_H
+
+#include "Common.h"
+#include "ByteBuffer.h"
+
+class WorldPacket : public ByteBuffer
+{
+ public:
+ // just container for later use
+ WorldPacket() : ByteBuffer(0), m_opcode(0)
+ {
+ }
+ explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { }
+ // copy constructor
+ WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
+ {
+ }
+
+ void Initialize(uint16 opcode, size_t newres=200)
+ {
+ clear();
+ _storage.reserve(newres);
+ m_opcode = opcode;
+ }
+
+ uint16 GetOpcode() const { return m_opcode; }
+ void SetOpcode(uint16 opcode) { m_opcode = opcode; }
+
+ protected:
+ uint16 m_opcode;
+};
+#endif
+
diff --git a/src/server/shared/vmap/BIH.cpp b/src/server/shared/vmap/BIH.cpp
new file mode 100644
index 00000000000..4bd6b3c701e
--- /dev/null
+++ b/src/server/shared/vmap/BIH.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "BIH.h"
+
+void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats)
+{
+ // create space for the first node
+ tempTree.push_back(3 << 30); // dummy leaf
+ tempTree.insert(tempTree.end(), 2, 0);
+ //tempTree.add(0);
+
+ // seed bbox
+ AABound gridBox = { bounds.low(), bounds.high() };
+ AABound nodeBox = gridBox;
+ // seed subdivide function
+ subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats);
+}
+
+void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats)
+{
+ if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE)
+ {
+ // write leaf node
+ stats.updateLeaf(depth, right - left + 1);
+ createNode(tempTree, nodeIndex, left, right);
+ return;
+ }
+ // calculate extents
+ int axis = -1, prevAxis, rightOrig;
+ float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan();
+ float split = G3D::fnan(), prevSplit;
+ bool wasLeft = true;
+ while (true)
+ {
+ prevAxis = axis;
+ prevSplit = split;
+ // perform quick consistency checks
+ Vector3 d( gridBox.hi - gridBox.lo );
+ if (d.x < 0 || d.y < 0 || d.z < 0)
+ throw std::logic_error("negative node extents");
+ for (int i = 0; i < 3; i++)
+ {
+ if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i])
+ {
+ //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1);
+ throw std::logic_error("invalid node overlap");
+ }
+ }
+ // find longest axis
+ axis = d.primaryAxis();
+ split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]);
+ // partition L/R subsets
+ clipL = -G3D::inf();
+ clipR = G3D::inf();
+ rightOrig = right; // save this for later
+ float nodeL = G3D::inf();
+ float nodeR = -G3D::inf();
+ for (int i = left; i <= right;)
+ {
+ int obj = dat.indices[i];
+ float minb = dat.primBound[obj].low()[axis];
+ float maxb = dat.primBound[obj].high()[axis];
+ float center = (minb + maxb) * 0.5f;
+ if (center <= split)
+ {
+ // stay left
+ i++;
+ if (clipL < maxb)
+ clipL = maxb;
+ }
+ else
+ {
+ // move to the right most
+ int t = dat.indices[i];
+ dat.indices[i] = dat.indices[right];
+ dat.indices[right] = t;
+ right--;
+ if (clipR > minb)
+ clipR = minb;
+ }
+ nodeL = std::min(nodeL, minb);
+ nodeR = std::max(nodeR, maxb);
+ }
+ // check for empty space
+ if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis])
+ {
+ float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis];
+ float nodeNewW = nodeR - nodeL;
+ // node box is too big compare to space occupied by primitives?
+ if (1.3f * nodeNewW < nodeBoxW)
+ {
+ stats.updateBVH2();
+ int nextIndex = tempTree.size();
+ // allocate child
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ // write bvh2 clip node
+ stats.updateInner();
+ tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex;
+ tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL);
+ tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR);
+ // update nodebox and recurse
+ nodeBox.lo[axis] = nodeL;
+ nodeBox.hi[axis] = nodeR;
+ subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats);
+ return;
+ }
+ }
+ // ensure we are making progress in the subdivision
+ if (right == rightOrig)
+ {
+ // all left
+ if (prevAxis == axis && prevSplit == split) {
+ // we are stuck here - create a leaf
+ stats.updateLeaf(depth, right - left + 1);
+ createNode(tempTree, nodeIndex, left, right);
+ return;
+ }
+ if (clipL <= split) {
+ // keep looping on left half
+ gridBox.hi[axis] = split;
+ prevClip = clipL;
+ wasLeft = true;
+ continue;
+ }
+ gridBox.hi[axis] = split;
+ prevClip = G3D::fnan();
+ }
+ else if (left > right)
+ {
+ // all right
+ if (prevAxis == axis && prevSplit == split) {
+ // we are stuck here - create a leaf
+ stats.updateLeaf(depth, right - left + 1);
+ createNode(tempTree, nodeIndex, left, right);
+ return;
+ }
+ right = rightOrig;
+ if (clipR >= split) {
+ // keep looping on right half
+ gridBox.lo[axis] = split;
+ prevClip = clipR;
+ wasLeft = false;
+ continue;
+ }
+ gridBox.lo[axis] = split;
+ prevClip = G3D::fnan();
+ }
+ else
+ {
+ // we are actually splitting stuff
+ if (prevAxis != -1 && !isnan(prevClip))
+ {
+ // second time through - lets create the previous split
+ // since it produced empty space
+ int nextIndex = tempTree.size();
+ // allocate child node
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ if (wasLeft) {
+ // create a node with a left child
+ // write leaf node
+ stats.updateInner();
+ tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex;
+ tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip);
+ tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf());
+ } else {
+ // create a node with a right child
+ // write leaf node
+ stats.updateInner();
+ tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3);
+ tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::inf());
+ tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip);
+ }
+ // count stats for the unused leaf
+ depth++;
+ stats.updateLeaf(depth, 0);
+ // now we keep going as we are, with a new nodeIndex:
+ nodeIndex = nextIndex;
+ }
+ break;
+ }
+ }
+ // compute index of child nodes
+ int nextIndex = tempTree.size();
+ // allocate left node
+ int nl = right - left + 1;
+ int nr = rightOrig - (right + 1) + 1;
+ if (nl > 0) {
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ } else
+ nextIndex -= 3;
+ // allocate right node
+ if (nr > 0) {
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ tempTree.push_back(0);
+ }
+ // write leaf node
+ stats.updateInner();
+ tempTree[nodeIndex + 0] = (axis << 30) | nextIndex;
+ tempTree[nodeIndex + 1] = floatToRawIntBits(clipL);
+ tempTree[nodeIndex + 2] = floatToRawIntBits(clipR);
+ // prepare L/R child boxes
+ AABound gridBoxL(gridBox), gridBoxR(gridBox);
+ AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox);
+ gridBoxL.hi[axis] = gridBoxR.lo[axis] = split;
+ nodeBoxL.hi[axis] = clipL;
+ nodeBoxR.lo[axis] = clipR;
+ // recurse
+ if (nl > 0)
+ subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats);
+ else
+ stats.updateLeaf(depth + 1, 0);
+ if (nr > 0)
+ subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats);
+ else
+ stats.updateLeaf(depth + 1, 0);
+}
+
+bool BIH::writeToFile(FILE *wf) const
+{
+ uint32 treeSize = tree.size();
+ uint32 check=0, count=0;
+ check += fwrite(&bounds.low(), sizeof(float), 3, wf);
+ check += fwrite(&bounds.high(), sizeof(float), 3, wf);
+ check += fwrite(&treeSize, sizeof(uint32), 1, wf);
+ check += fwrite(&tree[0], sizeof(uint32), treeSize, wf);
+ count = objects.size();
+ check += fwrite(&count, sizeof(uint32), 1, wf);
+ check += fwrite(&objects[0], sizeof(uint32), count, wf);
+ return check == (3 + 3 + 2 + treeSize + count);
+}
+
+bool BIH::readFromFile(FILE *rf)
+{
+ uint32 treeSize;
+ Vector3 lo, hi;
+ uint32 check=0, count=0;
+ check += fread(&lo, sizeof(float), 3, rf);
+ check += fread(&hi, sizeof(float), 3, rf);
+ bounds = AABox(lo, hi);
+ check += fread(&treeSize, sizeof(uint32), 1, rf);
+ tree.resize(treeSize);
+ check += fread(&tree[0], sizeof(uint32), treeSize, rf);
+ check += fread(&count, sizeof(uint32), 1, rf);
+ objects.resize(count); // = new uint32[nObjects];
+ check += fread(&objects[0], sizeof(uint32), count, rf);
+ return check == (3 + 3 + 2 + treeSize + count);
+}
+
+void BIH::BuildStats::updateLeaf(int depth, int n)
+{
+ numLeaves++;
+ minDepth = std::min(depth, minDepth);
+ maxDepth = std::max(depth, maxDepth);
+ sumDepth += depth;
+ minObjects = std::min(n, minObjects);
+ maxObjects = std::max(n, maxObjects);
+ sumObjects += n;
+ int nl = std::min(n, 5);
+ ++numLeavesN[nl];
+}
+
+void BIH::BuildStats::printStats()
+{
+ printf("Tree stats:\n");
+ printf(" * Nodes: %d\n", numNodes);
+ printf(" * Leaves: %d\n", numLeaves);
+ printf(" * Objects: min %d\n", minObjects);
+ printf(" avg %.2f\n", (float) sumObjects / numLeaves);
+ printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0]));
+ printf(" max %d\n", maxObjects);
+ printf(" * Depth: min %d\n", minDepth);
+ printf(" avg %.2f\n", (float) sumDepth / numLeaves);
+ printf(" max %d\n", maxDepth);
+ printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves);
+ printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves);
+ printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves);
+ printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves);
+ printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves);
+ printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves);
+ printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2));
+}
diff --git a/src/server/shared/vmap/BIH.h b/src/server/shared/vmap/BIH.h
new file mode 100644
index 00000000000..15ae90c23eb
--- /dev/null
+++ b/src/server/shared/vmap/BIH.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _BIH_H
+#define _BIH_H
+
+#include <G3D/Vector3.h>
+#include <G3D/Ray.h>
+#include <G3D/AABox.h>
+
+#include <Platform/Define.h>
+
+#include <stdexcept>
+#include <vector>
+#include <algorithm>
+#include <limits>
+#include <cmath>
+
+#define MAX_STACK_SIZE 64
+
+#ifdef _MSC_VER
+ #define isnan(x) _isnan(x)
+#endif
+
+using G3D::Vector3;
+using G3D::AABox;
+using G3D::Ray;
+
+static inline uint32 floatToRawIntBits(float f)
+{
+ union
+ {
+ uint32 ival;
+ float fval;
+ } temp;
+ temp.fval=f;
+ return temp.ival;
+}
+
+static inline float intBitsToFloat(uint32 i)
+{
+ union
+ {
+ uint32 ival;
+ float fval;
+ } temp;
+ temp.ival=i;
+ return temp.fval;
+}
+
+struct AABound
+{
+ Vector3 lo, hi;
+};
+
+/** Bounding Interval Hierarchy Class.
+ Building and Ray-Intersection functions based on BIH from
+ Sunflow, a Java Raytracer, released under MIT/X11 License
+ http://sunflow.sourceforge.net/
+ Copyright (c) 2003-2007 Christopher Kulla
+*/
+
+class BIH
+{
+ public:
+ BIH() {};
+ template< class T, class BoundsFunc >
+ void build(const std::vector<T> &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false)
+ {
+ if(primitives.size() == 0)
+ return;
+ buildData dat;
+ dat.maxPrims = leafSize;
+ dat.numPrims = primitives.size();
+ dat.indices = new uint32[dat.numPrims];
+ dat.primBound = new AABox[dat.numPrims];
+ getBounds(primitives[0], bounds);
+ for (uint32 i=0; i<dat.numPrims; ++i)
+ {
+ dat.indices[i] = i;
+ AABox tb;
+ getBounds(primitives[i], dat.primBound[i]);
+ bounds.merge(dat.primBound[i]);
+ }
+ std::vector<uint32> tempTree;
+ BuildStats stats;
+ buildHierarchy(tempTree, dat, stats);
+ if (printStats)
+ stats.printStats();
+
+ objects.resize(dat.numPrims);
+ for (uint32 i=0; i<dat.numPrims; ++i)
+ objects[i] = dat.indices[i];
+ //nObjects = dat.numPrims;
+ tree = tempTree;
+ delete[] dat.primBound;
+ delete[] dat.indices;
+ }
+ uint32 primCount() { return objects.size(); }
+
+ template<typename RayCallback>
+ void intersectRay(const Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const
+ {
+ float intervalMin = 0.f;
+ float intervalMax = maxDist;
+ Vector3 org = r.origin();
+ Vector3 dir = r.direction();
+ Vector3 invDir;
+ float t1, t2;
+ for(int i=0; i<3; ++i)
+ {
+ invDir[i] = 1.f / dir[i];
+ t1 = (bounds.low()[i] - org[i]) * invDir[i];
+ t2 = (bounds.high()[i] - org[i]) * invDir[i];
+ if (invDir[i] > 0) {
+ if (t1 > intervalMin)
+ intervalMin = t1;
+ if (t2 < intervalMax)
+ intervalMax = t2;
+ } else {
+ if (t2 > intervalMin)
+ intervalMin = t2;
+ if (t1 < intervalMax)
+ intervalMax = t1;
+ }
+ if (intervalMin > intervalMax)
+ return;
+ }
+
+ uint32 offsetFront[3];
+ uint32 offsetBack[3];
+ uint32 offsetFront3[3];
+ uint32 offsetBack3[3];
+ // compute custom offsets from direction sign bit
+
+ for(int i=0; i<3; ++i)
+ {
+ offsetFront[i] = floatToRawIntBits(dir[i]) >> 31;
+ offsetBack[i] = offsetFront[i] ^ 1;
+ offsetFront3[i] = offsetFront[i] * 3;
+ offsetBack3[i] = offsetBack[i] * 3;
+
+ // avoid always adding 1 during the inner loop
+ ++offsetFront[i];
+ ++offsetBack[i];
+ }
+
+ StackNode stack[MAX_STACK_SIZE];
+ int stackPos = 0;
+ int node = 0;
+
+ while (true) {
+ while (true)
+ {
+ uint32 tn = tree[node];
+ uint32 axis = (tn & (3 << 30)) >> 30;
+ bool BVH2 = tn & (1 << 29);
+ int offset = tn & ~(7 << 29);
+ if (!BVH2)
+ {
+ if (axis < 3)
+ {
+ // "normal" interior node
+ float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
+ float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
+ // ray passes between clip zones
+ if (tf < intervalMin && tb > intervalMax)
+ break;
+ int back = offset + offsetBack3[axis];
+ node = back;
+ // ray passes through far node only
+ if (tf < intervalMin) {
+ intervalMin = (tb >= intervalMin) ? tb : intervalMin;
+ continue;
+ }
+ node = offset + offsetFront3[axis]; // front
+ // ray passes through near node only
+ if (tb > intervalMax) {
+ intervalMax = (tf <= intervalMax) ? tf : intervalMax;
+ continue;
+ }
+ // ray passes through both nodes
+ // push back node
+ stack[stackPos].node = back;
+ stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
+ stack[stackPos].tfar = intervalMax;
+ stackPos++;
+ // update ray interval for front node
+ intervalMax = (tf <= intervalMax) ? tf : intervalMax;
+ continue;
+ }
+ else
+ {
+ // leaf - test some objects
+ int n = tree[node + 1];
+ while (n > 0) {
+ bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst);
+ if(stopAtFirst && hit) return;
+ --n;
+ ++offset;
+ }
+ break;
+ }
+ }
+ else
+ {
+ if (axis>2)
+ return; // should not happen
+ float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
+ float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
+ node = offset;
+ intervalMin = (tf >= intervalMin) ? tf : intervalMin;
+ intervalMax = (tb <= intervalMax) ? tb : intervalMax;
+ if (intervalMin > intervalMax)
+ break;
+ continue;
+ }
+ } // traversal loop
+ do
+ {
+ // stack is empty?
+ if (stackPos == 0)
+ return;
+ // move back up the stack
+ stackPos--;
+ intervalMin = stack[stackPos].tnear;
+ if (maxDist < intervalMin)
+ continue;
+ node = stack[stackPos].node;
+ intervalMax = stack[stackPos].tfar;
+ break;
+ } while (true);
+ }
+ }
+
+ template<typename IsectCallback>
+ void intersectPoint(const Vector3 &p, IsectCallback& intersectCallback) const
+ {
+ if (!bounds.contains(p))
+ return;
+
+ StackNode stack[MAX_STACK_SIZE];
+ int stackPos = 0;
+ int node = 0;
+
+ while (true) {
+ while (true)
+ {
+ uint32 tn = tree[node];
+ uint32 axis = (tn & (3 << 30)) >> 30;
+ bool BVH2 = tn & (1 << 29);
+ int offset = tn & ~(7 << 29);
+ if (!BVH2)
+ {
+ if (axis < 3)
+ {
+ // "normal" interior node
+ float tl = intBitsToFloat(tree[node + 1]);
+ float tr = intBitsToFloat(tree[node + 2]);
+ // point is between clip zones
+ if (tl < p[axis] && tr > p[axis])
+ break;
+ int right = offset + 3;
+ node = right;
+ // point is in right node only
+ if (tl < p[axis]) {
+ continue;
+ }
+ node = offset; // left
+ // point is in left node only
+ if (tr > p[axis]) {
+ continue;
+ }
+ // point is in both nodes
+ // push back right node
+ stack[stackPos].node = right;
+ stackPos++;
+ continue;
+ }
+ else
+ {
+ // leaf - test some objects
+ int n = tree[node + 1];
+ while (n > 0) {
+ intersectCallback(p, objects[offset]); // !!!
+ --n;
+ ++offset;
+ }
+ break;
+ }
+ }
+ else // BVH2 node (empty space cut off left and right)
+ {
+ if (axis>2)
+ return; // should not happen
+ float tl = intBitsToFloat(tree[node + 1]);
+ float tr = intBitsToFloat(tree[node + 2]);
+ node = offset;
+ if (tl > p[axis] || tr < p[axis])
+ break;
+ continue;
+ }
+ } // traversal loop
+
+ // stack is empty?
+ if (stackPos == 0)
+ return;
+ // move back up the stack
+ stackPos--;
+ node = stack[stackPos].node;
+ }
+ }
+
+ bool writeToFile(FILE *wf) const;
+ bool readFromFile(FILE *rf);
+
+ protected:
+ std::vector<uint32> tree;
+ std::vector<uint32> objects;
+ AABox bounds;
+
+ struct buildData
+ {
+ uint32 *indices;
+ AABox *primBound;
+ uint32 numPrims;
+ int maxPrims;
+ };
+ struct StackNode
+ {
+ uint32 node;
+ float tnear;
+ float tfar;
+ };
+
+ class BuildStats
+ {
+ private:
+ int numNodes;
+ int numLeaves;
+ int sumObjects;
+ int minObjects;
+ int maxObjects;
+ int sumDepth;
+ int minDepth;
+ int maxDepth;
+ int numLeavesN[6];
+ int numBVH2;
+
+ public:
+ BuildStats():
+ numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF),
+ maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF),
+ maxDepth(0xFFFFFFFF), numBVH2(0)
+ {
+ for(int i=0; i<6; ++i) numLeavesN[i] = 0;
+ }
+
+ void updateInner() { numNodes++; }
+ void updateBVH2() { numBVH2++; }
+ void updateLeaf(int depth, int n);
+ void printStats();
+ };
+
+ void buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats);
+
+ void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) {
+ // write leaf node
+ tempTree[nodeIndex + 0] = (3 << 30) | left;
+ tempTree[nodeIndex + 1] = right - left + 1;
+ }
+
+ void subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats);
+};
+
+#endif // _BIH_H
diff --git a/src/server/shared/vmap/CMakeLists.txt b/src/server/shared/vmap/CMakeLists.txt
new file mode 100644
index 00000000000..c930a0c5a25
--- /dev/null
+++ b/src/server/shared/vmap/CMakeLists.txt
@@ -0,0 +1,30 @@
+
+########### next target ###############
+
+SET(vmaps_STAT_SRCS
+ BIH.h
+ BIH.cpp
+ IVMapManager.h
+ MapTree.cpp
+ MapTree.h
+ ModelInstance.cpp
+ ModelInstance.h
+ TileAssembler.cpp
+ TileAssembler.h
+ VMapDefinitions.h
+ VMapFactory.cpp
+ VMapFactory.h
+ VMapManager2.cpp
+ VMapManager2.h
+ VMapTools.h
+ WorldModel.cpp
+ WorldModel.h
+)
+
+include_directories(
+ ${ACE_INCLUDE_DIR}
+ ${CMAKE_SOURCE_DIR}/src/framework
+ ${CMAKE_SOURCE_DIR}/dep/include/g3dlite
+)
+
+add_library(vmaps STATIC ${vmaps_STAT_SRCS})
diff --git a/src/server/shared/vmap/IVMapManager.h b/src/server/shared/vmap/IVMapManager.h
new file mode 100644
index 00000000000..00629eb122c
--- /dev/null
+++ b/src/server/shared/vmap/IVMapManager.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _IVMAPMANAGER_H
+#define _IVMAPMANAGER_H
+
+#include<string>
+#include <Platform/Define.h>
+
+//===========================================================
+
+/**
+This is the minimum interface to the VMapMamager.
+*/
+
+namespace VMAP
+{
+
+ enum VMAP_LOAD_RESULT
+ {
+ VMAP_LOAD_RESULT_ERROR,
+ VMAP_LOAD_RESULT_OK,
+ VMAP_LOAD_RESULT_IGNORED,
+ };
+
+ #define VMAP_INVALID_HEIGHT -100000.0f // for check
+ #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case
+
+ //===========================================================
+ class IVMapManager
+ {
+ private:
+ bool iEnableLineOfSightCalc;
+ bool iEnableHeightCalc;
+
+ public:
+ IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) {}
+
+ virtual ~IVMapManager(void) {}
+
+ virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
+
+ virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
+
+ virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
+ virtual void unloadMap(unsigned int pMapId) = 0;
+
+ virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
+ virtual float getHeight(unsigned int pMapId, float x, float y, float z) = 0;
+ /**
+ test if we hit an object. return true if we hit one. rx,ry,rz will hold the hit position or the dest position, if no intersection was found
+ return a position, that is pReduceDist closer to the origin
+ */
+ virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0;
+ /**
+ send debug commands
+ */
+ virtual bool processCommand(char *pCommand)= 0;
+
+ /**
+ Enable/disable LOS calculation
+ It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
+ */
+ void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; }
+ /**
+ Enable/disable model height calculation
+ It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
+ */
+ void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; }
+
+ bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); }
+ bool isHeightCalcEnabled() const { return(iEnableHeightCalc); }
+ bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); }
+
+ virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0;
+ /**
+ Block maps from being used.
+ parameter: String of map ids. Delimiter = ","
+ e.g.: "0,1,530"
+ */
+ virtual void preventMapsFromBeingUsed(const char* pMapIdString) =0;
+ /**
+ Query world model area info.
+ \param z gets adjusted to the ground height for which this are info is valid
+ */
+ virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0;
+ virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0;
+ };
+
+}
+#endif
diff --git a/src/server/shared/vmap/MapTree.cpp b/src/server/shared/vmap/MapTree.cpp
new file mode 100644
index 00000000000..8c77ee109f3
--- /dev/null
+++ b/src/server/shared/vmap/MapTree.cpp
@@ -0,0 +1,450 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "MapTree.h"
+#include "ModelInstance.h"
+#include "VMapManager2.h"
+#include "VMapDefinitions.h"
+
+#include <string>
+#include <sstream>
+#include <iomanip>
+
+using G3D::Vector3;
+
+namespace VMAP
+{
+
+ class MapRayCallback
+ {
+ public:
+ MapRayCallback(ModelInstance *val): prims(val) {}
+ ModelInstance *prims;
+ bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true)
+ {
+ return prims[entry].intersectRay(ray, distance, pStopAtFirstHit);
+ //std::cout << "trying to intersect '" << entity->name << "'\n";
+ }
+ };
+
+ class AreaInfoCallback
+ {
+ public:
+ AreaInfoCallback(ModelInstance *val): prims(val) {}
+ void operator()(const Vector3& point, uint32 entry)
+ {
+#ifdef VMAP_DEBUG
+ std::cout << "trying to intersect '" << prims[entry].name << "'\n";
+#endif
+ prims[entry].intersectPoint(point, aInfo);
+ }
+
+ ModelInstance *prims;
+ AreaInfo aInfo;
+ };
+
+ class LocationInfoCallback
+ {
+ public:
+ LocationInfoCallback(ModelInstance *val, LocationInfo &info): prims(val), locInfo(info), result(false) {}
+ void operator()(const Vector3& point, uint32 entry)
+ {
+#ifdef VMAP_DEBUG
+ std::cout << "trying to intersect '" << prims[entry].name << "'\n";
+#endif
+ if (prims[entry].GetLocationInfo(point, locInfo))
+ result = true;
+ }
+
+ ModelInstance *prims;
+ LocationInfo &locInfo;
+ bool result;
+ };
+
+
+ //=========================================================
+
+ std::string StaticMapTree::getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY)
+ {
+ std::stringstream tilefilename;
+ tilefilename.fill('0');
+ tilefilename << std::setw(3) << mapID << "_";
+ //tilefilename << std::setw(2) << tileX << "_" << std::setw(2) << tileY << ".vmtile";
+ tilefilename << std::setw(2) << tileY << "_" << std::setw(2) << tileX << ".vmtile";
+ return tilefilename.str();
+ }
+
+ bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const
+ {
+ AreaInfoCallback intersectionCallBack(iTreeValues);
+ iTree.intersectPoint(pos, intersectionCallBack);
+ if (intersectionCallBack.aInfo.result)
+ {
+ flags = intersectionCallBack.aInfo.flags;
+ adtId = intersectionCallBack.aInfo.adtId;
+ rootId = intersectionCallBack.aInfo.rootId;
+ groupId = intersectionCallBack.aInfo.groupId;
+ pos.z = intersectionCallBack.aInfo.ground_Z;
+ return true;
+ }
+ return false;
+ }
+
+ bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const
+ {
+ LocationInfoCallback intersectionCallBack(iTreeValues, info);
+ iTree.intersectPoint(pos, intersectionCallBack);
+ return intersectionCallBack.result;
+ }
+
+ StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath):
+ iMapID(mapID), /* iTree(0), */ iTreeValues(0), iBasePath(basePath)
+ {
+ if (iBasePath.length() > 0 && (iBasePath[iBasePath.length()-1] != '/' || iBasePath[iBasePath.length()-1] != '\\'))
+ {
+ iBasePath.append("/");
+ }
+ }
+
+ //=========================================================
+ //! Make sure to call unloadMap() to unregister acquired model references before destroying
+ StaticMapTree::~StaticMapTree()
+ {
+ delete[] iTreeValues;
+ }
+
+ //=========================================================
+ /**
+ return dist to hit or inf() if no hit
+ */
+
+ float StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const
+ {
+ float distance = pMaxDist;
+ MapRayCallback intersectionCallBack(iTreeValues);
+ iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit);
+ return distance;
+ }
+ //=========================================================
+
+ bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) const
+ {
+ bool result = true;
+ float maxDist = (pos2 - pos1).magnitude();
+ // prevent NaN values which can cause BIH intersection to enter infinite loop
+ if (maxDist < 1e-10f)
+ return true;
+ // direction with length of 1
+ G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
+ float resultDist = getIntersectionTime(ray, maxDist, true);
+ if (resultDist < maxDist)
+ {
+ result = false;
+ }
+ return result;
+ }
+ //=========================================================
+ /**
+ When moving from pos1 to pos2 check if we hit an object. Return true and the position if we hit one
+ Return the hit pos or the original dest pos
+ */
+
+ bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const
+ {
+ bool result=false;
+ float maxDist = (pPos2 - pPos1).magnitude();
+ // prevent NaN values which can cause BIH intersection to enter infinite loop
+ if (maxDist < 1e-10f)
+ {
+ pResultHitPos = pPos2;
+ return false;
+ }
+ Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
+ G3D::Ray ray(pPos1, dir);
+ float dist = getIntersectionTime(ray, maxDist, false);
+ if (dist < maxDist)
+ {
+ pResultHitPos = pPos1 + dir * dist;
+ if (pModifyDist < 0)
+ {
+ if ((pResultHitPos - pPos1).magnitude() > -pModifyDist)
+ {
+ pResultHitPos = pResultHitPos + dir*pModifyDist;
+ }
+ else
+ {
+ pResultHitPos = pPos1;
+ }
+ }
+ else
+ {
+ pResultHitPos = pResultHitPos + dir*pModifyDist;
+ }
+ result = true;
+ }
+ else
+ {
+ pResultHitPos = pPos2;
+ result = false;
+ }
+ return result;
+ }
+
+ //=========================================================
+
+ float StaticMapTree::getHeight(const Vector3& pPos) const
+ {
+ float height = G3D::inf();
+ Vector3 dir = Vector3(0,0,-1);
+ G3D::Ray ray(pPos, dir); // direction with length of 1
+ float maxDist = VMapDefinitions::getMaxCanFallDistance();
+ float dist = getIntersectionTime(ray, maxDist, false);
+ if (dist < maxDist)
+ {
+ height = pPos.z - dist;
+ }
+ return(height);
+ }
+
+ //=========================================================
+
+ bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY)
+ {
+ std::string basePath = vmapPath;
+ if (basePath.length() > 0 && (basePath[basePath.length()-1] != '/' || basePath[basePath.length()-1] != '\\'))
+ basePath.append("/");
+ std::string fullname = basePath + VMapManager2::getMapFileName(mapID);
+ bool success = true;
+ FILE *rf = fopen(fullname.c_str(), "rb");
+ if (!rf)
+ return false;
+ // TODO: check magic number when implemented...
+ char tiled;
+ char chunk[8];
+ if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1)
+ {
+ fclose(rf);
+ return false;
+ }
+ if (tiled)
+ {
+ std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY);
+ FILE* tf = fopen(tilefile.c_str(), "rb");
+ if (!tf)
+ success = false;
+ else
+ fclose(tf);
+ }
+ fclose(rf);
+ return success;
+ }
+
+ //=========================================================
+
+ bool StaticMapTree::InitMap(const std::string &fname, VMapManager2 *vm)
+ {
+ std::cout << "Initializing StaticMapTree '" << fname << "'\n";
+ bool success = true;
+ std::string fullname = iBasePath + fname;
+ FILE *rf = fopen(fullname.c_str(), "rb");
+ if (!rf)
+ return false;
+ else
+ {
+ char chunk[8];
+ //general info
+ if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) success = false;
+ char tiled;
+ if (success && fread(&tiled, sizeof(char), 1, rf) != 1) success = false;
+ iIsTiled = bool(tiled);
+ // Nodes
+ if (success && !readChunk(rf, chunk, "NODE", 4)) success = false;
+ if (success) success = iTree.readFromFile(rf);
+ if (success)
+ {
+ iNTreeValues = iTree.primCount();
+ iTreeValues = new ModelInstance[iNTreeValues];
+ }
+
+ if (success && !readChunk(rf, chunk, "GOBJ", 4)) success = false;
+ // global model spawns
+ // only non-tiled maps have them, and if so exactly one (so far at least...)
+ ModelSpawn spawn;
+#ifdef VMAP_DEBUG
+ std::cout << "Map isTiled:" << bool(iIsTiled) << std::endl;
+#endif
+ if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn))
+ {
+ WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name);
+ std::cout << "StaticMapTree::InitMap(): loading " << spawn.name << std::endl;
+ if (model)
+ {
+ // assume that global model always is the first and only tree value (could be improved...)
+ iTreeValues[0] = ModelInstance(spawn, model);
+ iLoadedSpawns[0] = 1;
+ }
+ else
+ {
+ success = false;
+ std::cout << "error: could not acquire WorldModel pointer!\n";
+ }
+ }
+
+ fclose(rf);
+ }
+ return success;
+ }
+
+ //=========================================================
+
+ void StaticMapTree::UnloadMap(VMapManager2 *vm)
+ {
+ for (loadedSpawnMap::iterator i = iLoadedSpawns.begin(); i != iLoadedSpawns.end(); ++i)
+ {
+ iTreeValues[i->first].setUnloaded();
+ for (uint32 refCount = 0; refCount < i->second; ++refCount)
+ vm->releaseModelInstance(iTreeValues[i->first].name);
+ }
+ iLoadedSpawns.clear();
+ iLoadedTiles.clear();
+ }
+
+ //=========================================================
+
+ bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm)
+ {
+ if (!iIsTiled)
+ {
+ // currently, core creates grids for all maps, whether it has terrain tiles or not
+ // so we need "fake" tile loads to know when we can unload map geometry
+ iLoadedTiles[packTileID(tileX, tileY)] = false;
+ return true;
+ }
+ if (!iTreeValues)
+ {
+ std::cout << "Tree has not been initialized!\n";
+ return false;
+ }
+ bool result = true;
+
+ std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY);
+ FILE* tf = fopen(tilefile.c_str(), "rb");
+ if (tf)
+ {
+ uint32 numSpawns;
+ if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
+ result = false;
+ for (uint32 i=0; i<numSpawns && result; ++i)
+ {
+ // read model spawns
+ ModelSpawn spawn;
+ result = ModelSpawn::readFromFile(tf, spawn);
+ if (result)
+ {
+ // acquire model instance
+ WorldModel *model = vm->acquireModelInstance(iBasePath, spawn.name);
+ if (!model) std::cout << "error: could not acquire WorldModel pointer!\n";
+
+ // update tree
+ uint32 referencedVal;
+
+ fread(&referencedVal, sizeof(uint32), 1, tf);
+ if (!iLoadedSpawns.count(referencedVal))
+ {
+#ifdef VMAP_DEBUG
+ if (referencedVal > iNTreeValues)
+ {
+ std::cout << "invalid tree element! (" << referencedVal << "/" << iNTreeValues << ")\n";
+ continue;
+ }
+#endif
+ iTreeValues[referencedVal] = ModelInstance(spawn, model);
+ iLoadedSpawns[referencedVal] = 1;
+ }
+ else
+ {
+ ++iLoadedSpawns[referencedVal];
+#ifdef VMAP_DEBUG
+ if (iTreeValues[referencedVal].ID != spawn.ID) std::cout << "error: trying to load wrong spawn in node!\n";
+ else if (iTreeValues[referencedVal].name != spawn.name) std::cout << "error: name collision on GUID="<< spawn.ID << "\n";
+#endif
+ }
+ }
+ }
+ iLoadedTiles[packTileID(tileX, tileY)] = true;
+ fclose(tf);
+ }
+ else
+ iLoadedTiles[packTileID(tileX, tileY)] = false;
+ return result;
+ }
+
+ //=========================================================
+
+ void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm)
+ {
+ uint32 tileID = packTileID(tileX, tileY);
+ loadedTileMap::iterator tile = iLoadedTiles.find(tileID);
+ if (tile == iLoadedTiles.end())
+ {
+ std::cout << "WARNING: trying to unload non-loaded tile. Map:" << iMapID << " X:" << tileX << " Y:" << tileY << std::endl;
+ return;
+ }
+ if (tile->second) // file associated with tile
+ {
+ std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY);
+ FILE* tf = fopen(tilefile.c_str(), "rb");
+ if (tf)
+ {
+ bool result=true;
+ uint32 numSpawns;
+ if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
+ result = false;
+ for (uint32 i=0; i<numSpawns && result; ++i)
+ {
+ // read model spawns
+ ModelSpawn spawn;
+ result = ModelSpawn::readFromFile(tf, spawn);
+ if (result)
+ {
+ // release model instance
+ vm->releaseModelInstance(spawn.name);
+
+ // update tree
+ uint32 referencedNode;
+
+ fread(&referencedNode, sizeof(uint32), 1, tf);
+ if (!iLoadedSpawns.count(referencedNode))
+ {
+ std::cout << "error! trying to unload non-referenced model '" << spawn.name << "' (ID:" << spawn.ID << ")\n";
+ }
+ else if (--iLoadedSpawns[referencedNode] == 0)
+ {
+ //std::cout << "MapTree: removing '" << spawn.name << "' from tree\n";
+ iTreeValues[referencedNode].setUnloaded();
+ iLoadedSpawns.erase(referencedNode);
+ }
+ }
+ }
+ fclose(tf);
+ }
+ }
+ iLoadedTiles.erase(tile);
+ }
+
+}
diff --git a/src/server/shared/vmap/MapTree.h b/src/server/shared/vmap/MapTree.h
new file mode 100644
index 00000000000..7955cb92d68
--- /dev/null
+++ b/src/server/shared/vmap/MapTree.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MAPTREE_H
+#define _MAPTREE_H
+
+#include "Platform/Define.h"
+#include "Utilities/UnorderedMap.h"
+#include "BIH.h"
+
+namespace VMAP
+{
+ class ModelInstance;
+ class GroupModel;
+ class VMapManager2;
+
+ struct LocationInfo
+ {
+ LocationInfo(): hitInstance(0), hitModel(0), ground_Z(-G3D::inf()) {};
+ const ModelInstance *hitInstance;
+ const GroupModel *hitModel;
+ float ground_Z;
+ };
+
+ class StaticMapTree
+ {
+ typedef UNORDERED_MAP<uint32, bool> loadedTileMap;
+ typedef UNORDERED_MAP<uint32, uint32> loadedSpawnMap;
+ private:
+ uint32 iMapID;
+ bool iIsTiled;
+ BIH iTree;
+ ModelInstance *iTreeValues; // the tree entries
+ uint32 iNTreeValues;
+
+ // Store all the map tile idents that are loaded for that map
+ // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed
+ // empty tiles have no tile file, hence map with bool instead of just a set (consistency check)
+ loadedTileMap iLoadedTiles;
+ // stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors
+ loadedSpawnMap iLoadedSpawns;
+ std::string iBasePath;
+
+ private:
+ float getIntersectionTime(const G3D::Ray& pRay, float pMaxDist, bool pStopAtFirstHit) const;
+ //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
+ public:
+ static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
+ static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; }
+ static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; }
+ static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY);
+
+ StaticMapTree(uint32 mapID, const std::string &basePath);
+ ~StaticMapTree();
+
+ bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const;
+ bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const;
+ float getHeight(const G3D::Vector3& pPos) const;
+ bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const;
+ bool GetLocationInfo(const Vector3 &pos, LocationInfo &info) const;
+
+ bool InitMap(const std::string &fname, VMapManager2 *vm);
+ void UnloadMap(VMapManager2 *vm);
+ bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm);
+ void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2 *vm);
+ bool isTiled() const { return iIsTiled; }
+ uint32 numLoadedTiles() const { return iLoadedTiles.size(); }
+ };
+
+ struct AreaInfo
+ {
+ AreaInfo(): result(false), ground_Z(-G3D::inf()) {};
+ bool result;
+ float ground_Z;
+ uint32 flags;
+ int32 adtId;
+ int32 rootId;
+ int32 groupId;
+ };
+} // VMAP
+
+#endif // _MAPTREE_H
diff --git a/src/server/shared/vmap/ModelInstance.cpp b/src/server/shared/vmap/ModelInstance.cpp
new file mode 100644
index 00000000000..677a08e147a
--- /dev/null
+++ b/src/server/shared/vmap/ModelInstance.cpp
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "ModelInstance.h"
+#include "WorldModel.h"
+#include "MapTree.h"
+
+using G3D::Vector3;
+using G3D::Ray;
+
+namespace VMAP
+{
+ ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel *model): ModelSpawn(spawn), iModel(model)
+ {
+ iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iRot.y/180.f, G3D::pi()*iRot.x/180.f, G3D::pi()*iRot.z/180.f).inverse();
+ iInvScale = 1.f/iScale;
+ }
+
+ bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const
+ {
+ if (!iModel)
+ {
+ //std::cout << "<object not loaded>\n";
+ return false;
+ }
+ float time = pRay.intersectionTime(iBound);
+ if (time == G3D::inf())
+ {
+// std::cout << "Ray does not hit '" << name << "'\n";
+
+ return false;
+ }
+// std::cout << "Ray crosses bound of '" << name << "'\n";
+/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z
+ << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z
+ << " t/tmax:" << time << "/" << pMaxDist;
+ std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: "
+ << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */
+ // child bounds are defined in object space:
+ Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
+ Ray modRay(p, iInvRot * pRay.direction());
+ float distance = pMaxDist * iInvScale;
+ bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit);
+ distance *= iScale;
+ pMaxDist = distance;
+ return hit;
+ }
+
+ void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const
+ {
+ if (!iModel)
+ {
+#ifdef VMAP_DEBUG
+ std::cout << "<object not loaded>\n";
+#endif
+ return;
+ }
+
+ // M2 files don't contain area info, only WMO files
+ if (flags & MOD_M2)
+ return;
+ if (!iBound.contains(p))
+ return;
+ // child bounds are defined in object space:
+ Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
+ Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
+ float zDist;
+ if (iModel->IntersectPoint(pModel, zDirModel, zDist, info))
+ {
+ Vector3 modelGround = pModel + zDist * zDirModel;
+ // Transform back to world space. Note that:
+ // Mat * vec == vec * Mat.transpose()
+ // and for rotation matrices: Mat.inverse() == Mat.transpose()
+ float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
+ if (info.ground_Z < world_Z)
+ {
+ info.ground_Z = world_Z;
+ info.adtId = adtId;
+ }
+ }
+ }
+
+ bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const
+ {
+ if (!iModel)
+ {
+#ifdef VMAP_DEBUG
+ std::cout << "<object not loaded>\n";
+#endif
+ return false;
+ }
+
+ // M2 files don't contain area info, only WMO files
+ if (flags & MOD_M2)
+ return false;
+ if (!iBound.contains(p))
+ return false;
+ // child bounds are defined in object space:
+ Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
+ Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
+ float zDist;
+ if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info))
+ {
+ Vector3 modelGround = pModel + zDist * zDirModel;
+ // Transform back to world space. Note that:
+ // Mat * vec == vec * Mat.transpose()
+ // and for rotation matrices: Mat.inverse() == Mat.transpose()
+ float world_Z = ((modelGround * iInvRot) * iScale + iPos).z;
+ if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection?
+ {
+ info.ground_Z = world_Z;
+ info.hitInstance = this;
+ return true;
+ }
+ }
+ return false;
+ }
+
+ bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const
+ {
+ // child bounds are defined in object space:
+ Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
+ //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f);
+ float zDist;
+ if (info.hitModel->GetLiquidLevel(pModel, zDist))
+ {
+ // calculate world height (zDist in model coords):
+ // assume WMO not tilted (wouldn't make much sense anyway)
+ liqHeight = zDist * iScale + iPos.z;
+ return true;
+ }
+ return false;
+ }
+
+ bool ModelSpawn::readFromFile(FILE *rf, ModelSpawn &spawn)
+ {
+ uint32 check=0, nameLen;
+ check += fread(&spawn.flags, sizeof(uint32), 1, rf);
+ // EoF?
+ if (!check)
+ {
+ if (ferror(rf))
+ std::cout << "Error reading ModelSpawn!\n";
+ return false;
+ }
+ check += fread(&spawn.adtId, sizeof(uint16), 1, rf);
+ check += fread(&spawn.ID, sizeof(uint32), 1, rf);
+ check += fread(&spawn.iPos, sizeof(float), 3, rf);
+ check += fread(&spawn.iRot, sizeof(float), 3, rf);
+ check += fread(&spawn.iScale, sizeof(float), 1, rf);
+ bool has_bound = (spawn.flags & MOD_HAS_BOUND);
+ if (has_bound) // only WMOs have bound in MPQ, only available after computation
+ {
+ Vector3 bLow, bHigh;
+ check += fread(&bLow, sizeof(float), 3, rf);
+ check += fread(&bHigh, sizeof(float), 3, rf);
+ spawn.iBound = G3D::AABox(bLow, bHigh);
+ }
+ check += fread(&nameLen, sizeof(uint32), 1, rf);
+ if(check != (has_bound ? 17 : 11))
+ {
+ std::cout << "Error reading ModelSpawn!\n";
+ return false;
+ }
+ char nameBuff[500];
+ if (nameLen>500) // file names should never be that long, must be file error
+ {
+ std::cout << "Error reading ModelSpawn, file name too long!\n";
+ return false;
+ }
+ check = fread(nameBuff, sizeof(char), nameLen, rf);
+ if (check != nameLen)
+ {
+ std::cout << "Error reading ModelSpawn!\n";
+ return false;
+ }
+ spawn.name = std::string(nameBuff, nameLen);
+ return true;
+ }
+
+ bool ModelSpawn::writeToFile(FILE *wf, const ModelSpawn &spawn)
+ {
+ uint32 check=0;
+ check += fwrite(&spawn.flags, sizeof(uint32), 1, wf);
+ check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf);
+ check += fwrite(&spawn.ID, sizeof(uint32), 1, wf);
+ check += fwrite(&spawn.iPos, sizeof(float), 3, wf);
+ check += fwrite(&spawn.iRot, sizeof(float), 3, wf);
+ check += fwrite(&spawn.iScale, sizeof(float), 1, wf);
+ bool has_bound = (spawn.flags & MOD_HAS_BOUND);
+ if(has_bound) // only WMOs have bound in MPQ, only available after computation
+ {
+ check += fwrite(&spawn.iBound.low(), sizeof(float), 3, wf);
+ check += fwrite(&spawn.iBound.high(), sizeof(float), 3, wf);
+ }
+ uint32 nameLen = spawn.name.length();
+ check += fwrite(&nameLen, sizeof(uint32), 1, wf);
+ if(check != (has_bound ? 17 : 11)) return false;
+ check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf);
+ if(check != nameLen) return false;
+ return true;
+ }
+
+}
diff --git a/src/server/shared/vmap/ModelInstance.h b/src/server/shared/vmap/ModelInstance.h
new file mode 100644
index 00000000000..97b3ab632a1
--- /dev/null
+++ b/src/server/shared/vmap/ModelInstance.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _MODELINSTANCE_H_
+#define _MODELINSTANCE_H_
+
+#include <G3D/Matrix3.h>
+#include <G3D/Vector3.h>
+#include <G3D/AABox.h>
+#include <G3D/Ray.h>
+
+#include "Platform/Define.h"
+
+namespace VMAP
+{
+ class WorldModel;
+ struct AreaInfo;
+ struct LocationInfo;
+
+ enum ModelFlags
+ {
+ MOD_M2 = 1,
+ MOD_WORLDSPAWN = 1<<1,
+ MOD_HAS_BOUND = 1<<2
+ };
+
+ class ModelSpawn
+ {
+ public:
+ //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
+ uint32 flags;
+ uint16 adtId;
+ uint32 ID;
+ G3D::Vector3 iPos;
+ G3D::Vector3 iRot;
+ float iScale;
+ G3D::AABox iBound;
+ std::string name;
+ bool operator==(const ModelSpawn &other) const { return ID == other.ID; }
+ //uint32 hashCode() const { return ID; }
+ // temp?
+ const G3D::AABox& getBounds() const { return iBound; }
+
+
+ static bool readFromFile(FILE *rf, ModelSpawn &spawn);
+ static bool writeToFile(FILE *rw, const ModelSpawn &spawn);
+ };
+
+ class ModelInstance: public ModelSpawn
+ {
+ public:
+ ModelInstance(): iModel(0) {}
+ ModelInstance(const ModelSpawn &spawn, WorldModel *model);
+ void setUnloaded() { iModel = 0; }
+ bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const;
+ void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const;
+ bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const;
+ bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const;
+ protected:
+ G3D::Matrix3 iInvRot;
+ float iInvScale;
+ WorldModel *iModel;
+ };
+} // namespace VMAP
+
+#endif // _MODELINSTANCE
diff --git a/src/server/shared/vmap/TileAssembler.cpp b/src/server/shared/vmap/TileAssembler.cpp
new file mode 100644
index 00000000000..d01b54a7564
--- /dev/null
+++ b/src/server/shared/vmap/TileAssembler.cpp
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "WorldModel.h"
+#include "TileAssembler.h"
+#include "MapTree.h"
+#include "BIH.h"
+#include "VMapDefinitions.h"
+
+#include <set>
+#include <iomanip>
+#include <sstream>
+#include <iomanip>
+
+using G3D::Vector3;
+using G3D::AABox;
+using G3D::inf;
+using std::pair;
+
+template<> struct BoundsTrait<VMAP::ModelSpawn*>
+{
+ static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); }
+};
+
+namespace VMAP
+{
+ bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len)
+ {
+ if (fread(dest, sizeof(char), len, rf) != len) return false;
+ return memcmp(dest, compare, len) == 0;
+ }
+
+ Vector3 ModelPosition::transform(const Vector3& pIn) const
+ {
+ Vector3 out = pIn * iScale;
+ out = iRotation * out;
+ return(out);
+ }
+
+ //=================================================================
+
+ TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
+ {
+ iCurrentUniqueNameId = 0;
+ iFilterMethod = NULL;
+ iSrcDir = pSrcDirName;
+ iDestDir = pDestDirName;
+ //mkdir(iDestDir);
+ //init();
+ }
+
+ TileAssembler::~TileAssembler()
+ {
+ //delete iCoordModelMapping;
+ }
+
+ bool TileAssembler::convertWorld2()
+ {
+ std::set<std::string> spawnedModelFiles;
+ bool success = readMapSpawns();
+ if (!success)
+ return false;
+
+ // export Map data
+ for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter)
+ {
+ // build global map tree
+ std::vector<ModelSpawn*> mapSpawns;
+ UniqueEntryMap::iterator entry;
+ for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry)
+ {
+ // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail
+ if (entry->second.flags & MOD_M2)
+ {
+ if (!calculateTransformedBound(entry->second))
+ break;
+ }
+ else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/
+ {
+ // TODO: remove extractor hack and uncomment below line:
+ //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f);
+ entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f);
+ }
+ mapSpawns.push_back(&(entry->second));
+ spawnedModelFiles.insert(entry->second.name);
+ }
+
+ BIH pTree;
+ pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds);
+
+ // ===> possibly move this code to StaticMapTree class
+ std::map<uint32, uint32> modelNodeIdx;
+ for (uint32 i=0; i<mapSpawns.size(); ++i)
+ modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i));
+ if (!modelNodeIdx.empty())
+ printf("min GUID: %u, max GUID: %u\n", modelNodeIdx.begin()->first, modelNodeIdx.rbegin()->first);
+
+ // write map tree file
+ std::stringstream mapfilename;
+ mapfilename << iDestDir << "/" << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree";
+ FILE *mapfile = fopen(mapfilename.str().c_str(), "wb");
+ if (!mapfile)
+ {
+ success = false;
+ printf("Cannot open %s\n", mapfilename.str().c_str());
+ break;
+ }
+
+ //general info
+ if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false;
+ uint32 globalTileID = StaticMapTree::packTileID(65, 65);
+ pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID);
+ char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO
+ if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false;
+ // Nodes
+ if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false;
+ if (success) success = pTree.writeToFile(mapfile);
+ // global map spawns (WDT), if any (most instances)
+ if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false;
+
+ for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob)
+ {
+ success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]);
+ }
+
+ fclose(mapfile);
+
+ // <====
+
+ // write map tile files, similar to ADT files, only with extra BSP tree node info
+ TileMap &tileEntries = map_iter->second->TileEntries;
+ TileMap::iterator tile;
+ for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile)
+ {
+ const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second];
+ if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently...
+ continue;
+ uint32 nSpawns = tileEntries.count(tile->first);
+ std::stringstream tilefilename;
+ tilefilename.fill('0');
+ tilefilename << iDestDir << "/" << std::setw(3) << map_iter->first << "_";
+ uint32 x, y;
+ StaticMapTree::unpackTileID(tile->first, x, y);
+ tilefilename << std::setw(2) << x << "_" << std::setw(2) << y << ".vmtile";
+ FILE *tilefile = fopen(tilefilename.str().c_str(), "wb");
+ // write number of tile spawns
+ if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false;
+ // write tile spawns
+ for (uint32 s=0; s<nSpawns; ++s)
+ {
+ if (s)
+ ++tile;
+ const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second];
+ success = success && ModelSpawn::writeToFile(tilefile, spawn2);
+ // MapTree nodes to update when loading tile:
+ std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID);
+ if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false;
+ }
+ fclose(tilefile);
+ }
+ // break; //test, extract only first map; TODO: remvoe this line
+ }
+
+ // export objects
+ std::cout << "\nConverting Model Files" << std::endl;
+ for (std::set<std::string>::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile)
+ {
+ std::cout << "Converting " << *mfile << std::endl;
+ if (!convertRawFile(*mfile))
+ {
+ std::cout << "error converting " << *mfile << std::endl;
+ success = false;
+ break;
+ }
+ }
+
+ //cleanup:
+ for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter)
+ {
+ delete map_iter->second;
+ }
+ return success;
+ }
+
+ bool TileAssembler::readMapSpawns()
+ {
+ std::string fname = iSrcDir + "/dir_bin";
+ FILE *dirf = fopen(fname.c_str(), "rb");
+ if (!dirf)
+ {
+ printf("Could not read dir_bin file!\n");
+ return false;
+ }
+ printf("Read coordinate mapping...\n");
+ uint32 mapID, tileX, tileY, check=0;
+ G3D::Vector3 v1, v2;
+ ModelSpawn spawn;
+ while (!feof(dirf))
+ {
+ check = 0;
+ // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
+ check += fread(&mapID, sizeof(uint32), 1, dirf);
+ if (check == 0) // EoF...
+ break;
+ check += fread(&tileX, sizeof(uint32), 1, dirf);
+ check += fread(&tileY, sizeof(uint32), 1, dirf);
+ if (!ModelSpawn::readFromFile(dirf, spawn))
+ break;
+
+ MapSpawns *current;
+ MapData::iterator map_iter = mapData.find(mapID);
+ if (map_iter == mapData.end())
+ {
+ printf("spawning Map %d\n", mapID);
+ mapData[mapID] = current = new MapSpawns();
+ }
+ else current = (*map_iter).second;
+ current->UniqueEntries.insert(pair<uint32, ModelSpawn>(spawn.ID, spawn));
+ current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID));
+ }
+ bool success = (ferror(dirf) == 0);
+ fclose(dirf);
+ return success;
+ }
+
+ bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn)
+ {
+ std::string modelFilename = iSrcDir + "/" + spawn.name;
+ ModelPosition modelPosition;
+ modelPosition.iDir = spawn.iRot;
+ modelPosition.iScale = spawn.iScale;
+ modelPosition.init();
+
+ FILE *rf = fopen(modelFilename.c_str(), "rb");
+ if (!rf)
+ {
+ printf("ERROR: Can't open model file: %s\n", modelFilename.c_str());
+ return false;
+ }
+
+ AABox modelBound;
+ bool boundEmpty=true;
+ char ident[8];
+
+ int readOperation = 1;
+
+ // temporary use defines to simplify read/check code (close file and return at fail)
+ #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \
+ fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++;
+ #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \
+ fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); }
+
+ READ_OR_RETURN(&ident, 8);
+ CMP_OR_RETURN(ident, "VMAP003");
+
+ // we have to read one int. This is needed during the export and we have to skip it here
+ uint32 tempNVectors;
+ READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors));
+
+ uint32 groups, wmoRootId;
+ char blockId[5];
+ blockId[4] = 0;
+ int blocksize;
+ float *vectorarray = 0;
+
+ READ_OR_RETURN(&groups, sizeof(uint32));
+ READ_OR_RETURN(&wmoRootId, sizeof(uint32));
+ if (groups != 1) printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str());
+
+ for (uint32 g=0; g<groups; ++g) // should be only one for M2 files...
+ {
+ fseek(rf, 3*sizeof(uint32) + 6*sizeof(float), SEEK_CUR);
+
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "GRP ");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ fseek(rf, blocksize, SEEK_CUR);
+
+ // ---- indexes
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "INDX");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ fseek(rf, blocksize, SEEK_CUR);
+
+ // ---- vectors
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "VERT");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ uint32 nvectors;
+ READ_OR_RETURN(&nvectors, sizeof(uint32));
+
+ if (nvectors >0)
+ {
+ vectorarray = new float[nvectors*3];
+ READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3);
+ }
+ else
+ {
+ std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl;
+ return false;
+ }
+
+ for (uint32 i=0, indexNo=0; indexNo<nvectors; indexNo++, i+=3)
+ {
+ Vector3 v = Vector3(vectorarray[i+0], vectorarray[i+1], vectorarray[i+2]);
+ v = modelPosition.transform(v);
+
+ if (boundEmpty)
+ modelBound = AABox(v, v), boundEmpty=false;
+ else
+ modelBound.merge(v);
+ }
+ delete[] vectorarray;
+ // drop of temporary use defines
+ #undef READ_OR_RETURN
+ #undef CMP_OR_RETURN
+ }
+ spawn.iBound = modelBound + spawn.iPos;
+ spawn.flags |= MOD_HAS_BOUND;
+ fclose(rf);
+ return true;
+ }
+
+ struct WMOLiquidHeader
+ {
+ int xverts, yverts, xtiles, ytiles;
+ float pos_x;
+ float pos_y;
+ float pos_z;
+ short type;
+ };
+ //=================================================================
+ bool TileAssembler::convertRawFile(const std::string& pModelFilename)
+ {
+ bool success = true;
+ std::string filename = iSrcDir;
+ if (filename.length() >0)
+ filename.append("/");
+ filename.append(pModelFilename);
+ FILE *rf = fopen(filename.c_str(), "rb");
+
+ if (!rf)
+ {
+ printf("ERROR: Can't open model file in form: %s",pModelFilename.c_str());
+ printf("... or form: %s",filename.c_str() );
+ return false;
+ }
+
+ char ident[8];
+
+ int readOperation = 1;
+
+ // temporary use defines to simplify read/check code (close file and return at fail)
+ #define READ_OR_RETURN(V,S) if(fread((V), (S), 1, rf) != 1) { \
+ fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }readOperation++;
+ #define CMP_OR_RETURN(V,S) if(strcmp((V),(S)) != 0) { \
+ fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); }
+
+ READ_OR_RETURN(&ident, 8);
+ CMP_OR_RETURN(ident, "VMAP003");
+
+ // we have to read one int. This is needed during the export and we have to skip it here
+ uint32 tempNVectors;
+ READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors));
+
+ uint32 groups;
+ uint32 RootWMOID;
+ char blockId[5];
+ blockId[4] = 0;
+ int blocksize;
+
+ READ_OR_RETURN(&groups, sizeof(uint32));
+ READ_OR_RETURN(&RootWMOID, sizeof(uint32));
+
+ std::vector<GroupModel> groupsArray;
+
+ for (uint32 g=0; g<groups; ++g)
+ {
+ std::vector<MeshTriangle> triangles;
+ std::vector<Vector3> vertexArray;
+
+ uint32 mogpflags, GroupWMOID;
+ READ_OR_RETURN(&mogpflags, sizeof(uint32));
+ READ_OR_RETURN(&GroupWMOID, sizeof(uint32));
+
+ float bbox1[3], bbox2[3];
+ READ_OR_RETURN(bbox1, sizeof(float)*3);
+ READ_OR_RETURN(bbox2, sizeof(float)*3);
+
+ uint32 liquidflags;
+ READ_OR_RETURN(&liquidflags, sizeof(uint32));
+
+ // will this ever be used? what is it good for anyway??
+ uint32 branches;
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "GRP ");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ READ_OR_RETURN(&branches, sizeof(uint32));
+ for (uint32 b=0; b<branches; ++b)
+ {
+ uint32 indexes;
+ // indexes for each branch (not used jet)
+ READ_OR_RETURN(&indexes, sizeof(uint32));
+ }
+
+ // ---- indexes
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "INDX");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ uint32 nindexes;
+ READ_OR_RETURN(&nindexes, sizeof(uint32));
+ if (nindexes >0)
+ {
+ uint16 *indexarray = new uint16[nindexes];
+ READ_OR_RETURN(indexarray, nindexes*sizeof(uint16));
+ for (uint32 i=0; i<nindexes; i+=3)
+ {
+ triangles.push_back(MeshTriangle(indexarray[i], indexarray[i+1], indexarray[i+2]));
+ }
+ delete[] indexarray;
+ }
+
+ // ---- vectors
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "VERT");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ uint32 nvectors;
+ READ_OR_RETURN(&nvectors, sizeof(uint32));
+
+ if (nvectors >0)
+ {
+ float *vectorarray = new float[nvectors*3];
+ READ_OR_RETURN(vectorarray, nvectors*sizeof(float)*3);
+ for (uint32 i=0; i<nvectors; ++i)
+ {
+ vertexArray.push_back( Vector3(vectorarray + 3*i) );
+ }
+ delete[] vectorarray;
+ }
+ // ----- liquid
+ WmoLiquid *liquid = 0;
+ if (liquidflags& 1)
+ {
+ WMOLiquidHeader hlq;
+ READ_OR_RETURN(&blockId, 4);
+ CMP_OR_RETURN(blockId, "LIQU");
+ READ_OR_RETURN(&blocksize, sizeof(int));
+ READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
+ liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type);
+ uint32 size = hlq.xverts*hlq.yverts;
+ READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float));
+ size = hlq.xtiles*hlq.ytiles;
+ READ_OR_RETURN(liquid->GetFlagsStorage(), size);
+ }
+
+ groupsArray.push_back(GroupModel(mogpflags, GroupWMOID, AABox(Vector3(bbox1), Vector3(bbox2))));
+ groupsArray.back().setMeshData(vertexArray, triangles);
+ groupsArray.back().setLiquidData(liquid);
+
+ // drop of temporary use defines
+ #undef READ_OR_RETURN
+ #undef CMP_OR_RETURN
+
+ }
+ fclose(rf);
+
+ // write WorldModel
+ WorldModel model;
+ model.setRootWmoID(RootWMOID);
+ if (groupsArray.size())
+ {
+ model.setGroupModels(groupsArray);
+ success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo");
+ }
+
+ //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl;
+ return success;
+ }
+}
diff --git a/src/server/shared/vmap/TileAssembler.h b/src/server/shared/vmap/TileAssembler.h
new file mode 100644
index 00000000000..b26735708af
--- /dev/null
+++ b/src/server/shared/vmap/TileAssembler.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _TILEASSEMBLER_H_
+#define _TILEASSEMBLER_H_
+
+#include <G3D/Vector3.h>
+#include <G3D/Matrix3.h>
+#include <map>
+
+#include "ModelInstance.h"
+
+namespace VMAP
+{
+ /**
+ This Class is used to convert raw vector data into balanced BSP-Trees.
+ To start the conversion call convertWorld().
+ */
+ //===============================================
+
+ class ModelPosition
+ {
+ private:
+ G3D::Matrix3 iRotation;
+ public:
+ G3D::Vector3 iPos;
+ G3D::Vector3 iDir;
+ float iScale;
+ void init()
+ {
+ iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iDir.y/180.f, G3D::pi()*iDir.x/180.f, G3D::pi()*iDir.z/180.f);
+ }
+ G3D::Vector3 transform(const G3D::Vector3& pIn) const;
+ void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; }
+ };
+
+ typedef std::map<uint32, ModelSpawn> UniqueEntryMap;
+ typedef std::multimap<uint32, uint32> TileMap;
+
+ struct MapSpawns
+ {
+ UniqueEntryMap UniqueEntries;
+ TileMap TileEntries;
+ };
+
+ typedef std::map<uint32, MapSpawns*> MapData;
+ //===============================================
+
+ class TileAssembler
+ {
+ private:
+ std::string iDestDir;
+ std::string iSrcDir;
+ bool (*iFilterMethod)(char *pName);
+ G3D::Table<std::string, unsigned int > iUniqueNameIds;
+ unsigned int iCurrentUniqueNameId;
+ MapData mapData;
+
+ public:
+ TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName);
+ virtual ~TileAssembler();
+
+ bool convertWorld2();
+ bool readMapSpawns();
+ bool calculateTransformedBound(ModelSpawn &spawn);
+
+ bool convertRawFile(const std::string& pModelFilename);
+ void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; }
+ std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName);
+ unsigned int getUniqueNameId(const std::string pName);
+ };
+
+} // VMAP
+#endif /*_TILEASSEMBLER_H_*/
diff --git a/src/server/shared/vmap/VMapDefinitions.h b/src/server/shared/vmap/VMapDefinitions.h
new file mode 100644
index 00000000000..e4a34cc1397
--- /dev/null
+++ b/src/server/shared/vmap/VMapDefinitions.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VMAPDEFINITIONS_H
+#define _VMAPDEFINITIONS_H
+#include <cstring>
+
+#define LIQUID_TILE_SIZE (533.333f / 128.f)
+
+namespace VMAP
+{
+ //=====================================
+ #define MAX_CAN_FALL_DISTANCE 10.0f
+ const char VMAP_MAGIC[] = "VMAP_3.0";
+
+ class VMapDefinitions
+ {
+ public:
+ static float getMaxCanFallDistance() { return MAX_CAN_FALL_DISTANCE; }
+ };
+
+ //======================================
+
+ // defined in TileAssembler.cpp currently...
+ bool readChunk(FILE *rf, char *dest, const char *compare, uint32 len);
+}
+#endif
diff --git a/src/server/shared/vmap/VMapFactory.cpp b/src/server/shared/vmap/VMapFactory.cpp
new file mode 100644
index 00000000000..331acbace47
--- /dev/null
+++ b/src/server/shared/vmap/VMapFactory.cpp
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <sys/types.h>
+#include "VMapFactory.h"
+#include "VMapManager2.h"
+
+using namespace G3D;
+
+namespace VMAP
+{
+ void chompAndTrim(std::string& str)
+ {
+ while(str.length() >0)
+ {
+ char lc = str[str.length()-1];
+ if(lc == '\r' || lc == '\n' || lc == ' ' || lc == '"' || lc == '\'')
+ {
+ str = str.substr(0,str.length()-1);
+ }
+ else
+ {
+ break;
+ }
+ }
+ while(str.length() >0)
+ {
+ char lc = str[0];
+ if(lc == ' ' || lc == '"' || lc == '\'')
+ {
+ str = str.substr(1,str.length()-1);
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ IVMapManager *gVMapManager = 0;
+ Table<unsigned int , bool>* iIgnoreSpellIds=0;
+
+ //===============================================
+ // result false, if no more id are found
+
+ bool getNextId(const std::string& pString, unsigned int& pStartPos, unsigned int& pId)
+ {
+ bool result = false;
+ unsigned int i;
+ for(i=pStartPos;i<pString.size(); ++i)
+ {
+ if(pString[i] == ',')
+ {
+ break;
+ }
+ }
+ if(i>pStartPos)
+ {
+ std::string idString = pString.substr(pStartPos, i-pStartPos);
+ pStartPos = i+1;
+ chompAndTrim(idString);
+ pId = atoi(idString.c_str());
+ result = true;
+ }
+ return(result);
+ }
+
+ //===============================================
+ /**
+ parameter: String of map ids. Delimiter = ","
+ */
+
+ void VMapFactory::preventSpellsFromBeingTestedForLoS(const char* pSpellIdString)
+ {
+ if(!iIgnoreSpellIds)
+ iIgnoreSpellIds = new Table<unsigned int , bool>();
+ if(pSpellIdString != NULL)
+ {
+ unsigned int pos =0;
+ unsigned int id;
+ std::string confString(pSpellIdString);
+ chompAndTrim(confString);
+ while(getNextId(confString, pos, id))
+ {
+ iIgnoreSpellIds->set(id, true);
+ }
+ }
+ }
+
+ //===============================================
+
+ bool VMapFactory::checkSpellForLoS(unsigned int pSpellId)
+ {
+ return(!iIgnoreSpellIds->containsKey(pSpellId));
+ }
+
+ //===============================================
+ // just return the instance
+ IVMapManager* VMapFactory::createOrGetVMapManager()
+ {
+ if(gVMapManager == 0)
+ gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-)
+ return gVMapManager;
+ }
+
+ //===============================================
+ // delete all internal data structures
+ void VMapFactory::clear()
+ {
+ if(iIgnoreSpellIds)
+ {
+ delete iIgnoreSpellIds;
+ iIgnoreSpellIds = NULL;
+ }
+ if(gVMapManager)
+ {
+ delete gVMapManager;
+ gVMapManager = NULL;
+ }
+ }
+}
diff --git a/src/server/shared/vmap/VMapFactory.h b/src/server/shared/vmap/VMapFactory.h
new file mode 100644
index 00000000000..8dc2c01938a
--- /dev/null
+++ b/src/server/shared/vmap/VMapFactory.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VMAPFACTORY_H
+#define _VMAPFACTORY_H
+
+#include "IVMapManager.h"
+
+/**
+This is the access point to the VMapManager.
+*/
+
+namespace VMAP
+{
+ //===========================================================
+
+ class VMapFactory
+ {
+ public:
+ static IVMapManager* createOrGetVMapManager();
+ static void clear();
+
+ static void preventSpellsFromBeingTestedForLoS(const char* pSpellIdString);
+ static bool checkSpellForLoS(unsigned int pSpellId);
+ };
+
+}
+#endif
diff --git a/src/server/shared/vmap/VMapManager2.cpp b/src/server/shared/vmap/VMapManager2.cpp
new file mode 100644
index 00000000000..1e8a84aee52
--- /dev/null
+++ b/src/server/shared/vmap/VMapManager2.cpp
@@ -0,0 +1,336 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <iostream>
+#include <iomanip>
+#include <string>
+#include <sstream>
+#include "VMapManager2.h"
+#include "MapTree.h"
+#include "ModelInstance.h"
+#include "WorldModel.h"
+#include "VMapDefinitions.h"
+
+using G3D::Vector3;
+
+namespace VMAP
+{
+
+ //=========================================================
+
+ VMapManager2::VMapManager2()
+ {
+ }
+
+ //=========================================================
+
+ VMapManager2::~VMapManager2(void)
+ {
+ for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i)
+ {
+ delete i->second;
+ }
+ for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i)
+ {
+ delete i->second.getModel();
+ }
+ }
+
+ //=========================================================
+
+ Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const
+ {
+ Vector3 pos;
+ const float mid = 0.5 * 64.0 * 533.33333333f;
+ pos.x = mid - x;
+ pos.y = mid - y;
+ pos.z = z;
+
+ return pos;
+ }
+
+ //=========================================================
+
+ Vector3 VMapManager2::convertPositionToMangosRep(float x, float y, float z) const
+ {
+ Vector3 pos;
+ const float mid = 0.5 * 64.0 * 533.33333333f;
+ pos.x = mid - x;
+ pos.y = mid - y;
+ pos.z = z;
+
+ return pos;
+ }
+ //=========================================================
+
+ // move to MapTree too?
+ std::string VMapManager2::getMapFileName(unsigned int pMapId)
+ {
+ std::stringstream fname;
+ fname.width(3);
+ fname << std::setfill('0') << pMapId << std::string(MAP_FILENAME_EXTENSION2);
+ return fname.str();
+ }
+
+ //=========================================================
+ /**
+ Block maps from being used.
+ parameter: String of map ids. Delimiter = ","
+ e.g.: "0,1,590"
+ */
+
+ void VMapManager2::preventMapsFromBeingUsed(const char* pMapIdString)
+ {
+ iIgnoreMapIds.clear();
+ if (pMapIdString != NULL)
+ {
+ std::string map_str;
+ std::stringstream map_ss;
+ map_ss.str(std::string(pMapIdString));
+ while (std::getline(map_ss, map_str, ','))
+ {
+ std::stringstream ss2(map_str);
+ int map_num = -1;
+ ss2 >> map_num;
+ if (map_num >= 0)
+ {
+ std::cout << "ingoring Map " << map_num << " for VMaps\n";
+ iIgnoreMapIds[map_num] = true;
+ // unload map in case it is loaded
+ unloadMap(map_num);
+ }
+ }
+ }
+ }
+
+ //=========================================================
+
+ int VMapManager2::loadMap(const char* pBasePath, unsigned int pMapId, int x, int y)
+ {
+ int result = VMAP_LOAD_RESULT_IGNORED;
+ if (isMapLoadingEnabled() && !iIgnoreMapIds.count(pMapId))
+ {
+ if (_loadMap(pMapId, pBasePath, x, y))
+ result = VMAP_LOAD_RESULT_OK;
+ else
+ result = VMAP_LOAD_RESULT_ERROR;
+ }
+ return result;
+ }
+
+ //=========================================================
+ // load one tile (internal use only)
+
+ bool VMapManager2::_loadMap(unsigned int pMapId, const std::string &basePath, uint32 tileX, uint32 tileY)
+ {
+ InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree == iInstanceMapTrees.end())
+ {
+ std::string mapFileName = getMapFileName(pMapId);
+ StaticMapTree *newTree = new StaticMapTree(pMapId, basePath);
+ if (!newTree->InitMap(mapFileName, this))
+ return false;
+ instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(pMapId, newTree)).first;
+ }
+ return instanceTree->second->LoadMapTile(tileX, tileY, this);
+ }
+
+ //=========================================================
+
+ void VMapManager2::unloadMap(unsigned int pMapId)
+ {
+ InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ instanceTree->second->UnloadMap(this);
+ if (instanceTree->second->numLoadedTiles() == 0)
+ {
+ delete instanceTree->second;
+ iInstanceMapTrees.erase(pMapId);
+ }
+ }
+ }
+
+ //=========================================================
+
+ void VMapManager2::unloadMap(unsigned int pMapId, int x, int y)
+ {
+ InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ instanceTree->second->UnloadMapTile(x, y, this);
+ if (instanceTree->second->numLoadedTiles() == 0)
+ {
+ delete instanceTree->second;
+ iInstanceMapTrees.erase(pMapId);
+ }
+ }
+ }
+
+ //==========================================================
+
+ bool VMapManager2::isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2)
+ {
+ if (!isLineOfSightCalcEnabled()) return true;
+ bool result = true;
+ InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ Vector3 pos1 = convertPositionToInternalRep(x1,y1,z1);
+ Vector3 pos2 = convertPositionToInternalRep(x2,y2,z2);
+ if (pos1 != pos2)
+ {
+ result = instanceTree->second->isInLineOfSight(pos1, pos2);
+ }
+ }
+ return result;
+ }
+ //=========================================================
+ /**
+ get the hit position and return true if we hit something
+ otherwise the result pos will be the dest pos
+ */
+ bool VMapManager2::getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist)
+ {
+ bool result = false;
+ rx=x2;
+ ry=y2;
+ rz=z2;
+ if (isLineOfSightCalcEnabled())
+ {
+ InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ Vector3 pos1 = convertPositionToInternalRep(x1,y1,z1);
+ Vector3 pos2 = convertPositionToInternalRep(x2,y2,z2);
+ Vector3 resultPos;
+ result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, pModifyDist);
+ resultPos = convertPositionToMangosRep(resultPos.x,resultPos.y,resultPos.z);
+ rx = resultPos.x;
+ ry = resultPos.y;
+ rz = resultPos.z;
+ }
+ }
+ return result;
+ }
+
+ //=========================================================
+ /**
+ get height or INVALID_HEIGHT if no height available
+ */
+
+ float VMapManager2::getHeight(unsigned int pMapId, float x, float y, float z)
+ {
+ float height = VMAP_INVALID_HEIGHT_VALUE; //no height
+ if (isHeightCalcEnabled())
+ {
+ InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ Vector3 pos = convertPositionToInternalRep(x,y,z);
+ height = instanceTree->second->getHeight(pos);
+ if (!(height < G3D::inf()))
+ {
+ height = VMAP_INVALID_HEIGHT_VALUE; //no height
+ }
+ }
+ }
+ return height;
+ }
+
+ //=========================================================
+
+ bool VMapManager2::getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const
+ {
+ bool result=false;
+ InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ Vector3 pos = convertPositionToInternalRep(x, y, z);
+ result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId);
+ // z is not touched by convertPositionToMangosRep(), so just copy
+ z = pos.z;
+ }
+ return(result);
+ }
+
+ bool VMapManager2::GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const
+ {
+ InstanceTreeMap::const_iterator instanceTree = iInstanceMapTrees.find(pMapId);
+ if (instanceTree != iInstanceMapTrees.end())
+ {
+ LocationInfo info;
+ Vector3 pos = convertPositionToInternalRep(x, y, z);
+ if (instanceTree->second->GetLocationInfo(pos, info))
+ {
+ floor = info.ground_Z;
+ type = info.hitModel->GetLiquidType();
+ if (ReqLiquidType && !(type & ReqLiquidType))
+ return false;
+ if (info.hitInstance->GetLiquidLevel(pos, info, level))
+ return true;
+ }
+ }
+ return false;
+ }
+
+ //=========================================================
+
+ WorldModel* VMapManager2::acquireModelInstance(const std::string &basepath, const std::string &filename)
+ {
+ ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
+ if (model == iLoadedModelFiles.end())
+ {
+ WorldModel *worldmodel = new WorldModel();
+ if (!worldmodel->readFile(basepath + filename + ".vmo"))
+ {
+ std::cout << "VMapManager2: could not load '" << basepath << filename << ".vmo'!\n";
+ delete worldmodel;
+ return NULL;
+ }
+ std::cout << "VMapManager2: loading file '" << basepath << filename << "'.\n";
+ model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first;
+ model->second.setModel(worldmodel);
+ }
+ model->second.incRefCount();
+ return model->second.getModel();
+ }
+
+ void VMapManager2::releaseModelInstance(const std::string &filename)
+ {
+ ModelFileMap::iterator model = iLoadedModelFiles.find(filename);
+ if (model == iLoadedModelFiles.end())
+ {
+ std::cout << "VMapManager2: trying to unload non-loaded file '" << filename << "'!\n";
+ return;
+ }
+ if( model->second.decRefCount() == 0)
+ {
+ std::cout << "VMapManager2: unloading file '" << filename << "'.\n";
+ delete model->second.getModel();
+ iLoadedModelFiles.erase(model);
+ }
+ }
+ //=========================================================
+
+ bool VMapManager2::existsMap(const char* pBasePath, unsigned int pMapId, int x, int y)
+ {
+ return StaticMapTree::CanLoadMap(std::string(pBasePath), pMapId, x, y);
+ }
+
+} // namespace VMAP
diff --git a/src/server/shared/vmap/VMapManager2.h b/src/server/shared/vmap/VMapManager2.h
new file mode 100644
index 00000000000..5f03b87b07f
--- /dev/null
+++ b/src/server/shared/vmap/VMapManager2.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _VMAPMANAGER2_H
+#define _VMAPMANAGER2_H
+
+#include "IVMapManager.h"
+#include "Utilities/UnorderedMap.h"
+#include "Platform/Define.h"
+#include <G3D/Vector3.h>
+
+//===========================================================
+
+#define MAP_FILENAME_EXTENSION2 ".vmtree"
+
+#define FILENAMEBUFFER_SIZE 500
+
+/**
+This is the main Class to manage loading and unloading of maps, line of sight, height calculation and so on.
+For each map or map tile to load it reads a directory file that contains the ModelContainer files used by this map or map tile.
+Each global map or instance has its own dynamic BSP-Tree.
+The loaded ModelContainers are included in one of these BSP-Trees.
+Additionally a table to match map ids and map names is used.
+*/
+
+//===========================================================
+
+namespace VMAP
+{
+ class StaticMapTree;
+ class WorldModel;
+
+ class ManagedModel
+ {
+ public:
+ ManagedModel(): iModel(0), iRefCount(0) {}
+ void setModel(WorldModel *model) { iModel = model; }
+ WorldModel *getModel() { return iModel; }
+ void incRefCount() { ++iRefCount; }
+ int decRefCount() { return --iRefCount; }
+ protected:
+ WorldModel *iModel;
+ int iRefCount;
+ };
+
+ typedef UNORDERED_MAP<uint32 , StaticMapTree *> InstanceTreeMap;
+ typedef UNORDERED_MAP<std::string, ManagedModel> ModelFileMap;
+
+ class VMapManager2 : public IVMapManager
+ {
+ protected:
+ // Tree to check collision
+ ModelFileMap iLoadedModelFiles;
+ InstanceTreeMap iInstanceMapTrees;
+ // UNORDERED_MAP<unsigned int , bool> iMapsSplitIntoTiles;
+ UNORDERED_MAP<unsigned int , bool> iIgnoreMapIds;
+
+ bool _loadMap(uint32 pMapId, const std::string &basePath, uint32 tileX, uint32 tileY);
+ /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
+
+ public:
+ // public for debug
+ G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const;
+ G3D::Vector3 convertPositionToMangosRep(float x, float y, float z) const;
+ static std::string getMapFileName(unsigned int pMapId);
+
+ VMapManager2();
+ ~VMapManager2(void);
+
+ int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y);
+
+ void unloadMap(unsigned int pMapId, int x, int y);
+ void unloadMap(unsigned int pMapId);
+
+ bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) ;
+ /**
+ fill the hit pos and return true, if an object was hit
+ */
+ bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist);
+ float getHeight(unsigned int pMapId, float x, float y, float z);
+
+ bool processCommand(char *pCommand) { return false; } // for debug and extensions
+
+ void preventMapsFromBeingUsed(const char* pMapIdString);
+ bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const;
+ bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const;
+
+ WorldModel* acquireModelInstance(const std::string &basepath, const std::string &filename);
+ void releaseModelInstance(const std::string &filename);
+
+ // what's the use of this? o.O
+ virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const
+ {
+ return getMapFileName(pMapId);
+ }
+ virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y);
+ };
+}
+#endif
diff --git a/src/server/shared/vmap/VMapTools.h b/src/server/shared/vmap/VMapTools.h
new file mode 100644
index 00000000000..dbbd9af9271
--- /dev/null
+++ b/src/server/shared/vmap/VMapTools.h
@@ -0,0 +1,150 @@
+/*
+* Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation; either version 2 of the License, or
+* (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with this program; if not, write to the Free Software
+* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _VMAPTOOLS_H
+#define _VMAPTOOLS_H
+
+#include <G3D/CollisionDetection.h>
+#include <G3D/AABox.h>
+
+#include "NodeValueAccess.h"
+
+/**
+The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure.
+This is an iterator that helps us analysing the BSP-Trees.
+The collision detection is modified to return true, if we are inside an object.
+*/
+
+namespace VMAP
+{
+ template<class TValue>
+ class IntersectionCallBack {
+ public:
+ TValue* closestEntity;
+ G3D::Vector3 hitLocation;
+ G3D::Vector3 hitNormal;
+
+ void operator()(const G3D::Ray& ray, const TValue* entity, bool pStopAtFirstHit, float& distance) {
+ entity->intersect(ray, distance, pStopAtFirstHit, hitLocation, hitNormal);
+ }
+ };
+
+ //==============================================================
+ //==============================================================
+ //==============================================================
+
+ class MyCollisionDetection
+ {
+ private:
+ public:
+
+ static bool collisionLocationForMovingPointFixedAABox(
+ const G3D::Vector3& origin,
+ const G3D::Vector3& dir,
+ const G3D::AABox& box,
+ G3D::Vector3& location,
+ bool& Inside)
+ {
+
+ // Integer representation of a floating-point value.
+#define IR(x) (reinterpret_cast<G3D::uint32 const&>(x))
+
+ Inside = true;
+ const G3D::Vector3& MinB = box.low();
+ const G3D::Vector3& MaxB = box.high();
+ G3D::Vector3 MaxT(-1.0f, -1.0f, -1.0f);
+
+ // Find candidate planes.
+ for (int i = 0; i < 3; ++i)
+ {
+ if (origin[i] < MinB[i])
+ {
+ location[i] = MinB[i];
+ Inside = false;
+
+ // Calculate T distances to candidate planes
+ if (IR(dir[i]))
+ {
+ MaxT[i] = (MinB[i] - origin[i]) / dir[i];
+ }
+ }
+ else if (origin[i] > MaxB[i])
+ {
+ location[i] = MaxB[i];
+ Inside = false;
+
+ // Calculate T distances to candidate planes
+ if (IR(dir[i]))
+ {
+ MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
+ }
+ }
+ }
+
+ if (Inside)
+ {
+ // definite hit
+ location = origin;
+ return true;
+ }
+
+ // Get largest of the maxT's for final choice of intersection
+ int WhichPlane = 0;
+ if (MaxT[1] > MaxT[WhichPlane])
+ {
+ WhichPlane = 1;
+ }
+
+ if (MaxT[2] > MaxT[WhichPlane])
+ {
+ WhichPlane = 2;
+ }
+
+ // Check final candidate actually inside box
+ if (IR(MaxT[WhichPlane]) & 0x80000000)
+ {
+ // Miss the box
+ return false;
+ }
+
+ for (int i = 0; i < 3; ++i)
+ {
+ if (i != WhichPlane)
+ {
+ location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
+ if ((location[i] < MinB[i]) ||
+ (location[i] > MaxB[i]))
+ {
+ // On this plane we're outside the box extents, so
+ // we miss the box
+ return false;
+ }
+ }
+ }
+ /*
+ // Choose the normal to be the plane normal facing into the ray
+ normal = G3D::Vector3::zero();
+ normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0;
+ */
+ return true;
+
+#undef IR
+ }
+ };
+}
+#endif
diff --git a/src/server/shared/vmap/WorldModel.cpp b/src/server/shared/vmap/WorldModel.cpp
new file mode 100644
index 00000000000..690c77577ae
--- /dev/null
+++ b/src/server/shared/vmap/WorldModel.cpp
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "WorldModel.h"
+#include "VMapDefinitions.h"
+#include "MapTree.h"
+
+using G3D::Vector3;
+using G3D::Ray;
+
+template<> struct BoundsTrait<VMAP::GroupModel>
+{
+ static void getBounds(const VMAP::GroupModel& obj, G3D::AABox& out) { out = obj.GetBound(); }
+};
+
+
+namespace VMAP
+{
+ bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance)
+ {
+ static const float EPS = 1e-5f;
+
+ // See RTR2 ch. 13.7 for the algorithm.
+
+ const Vector3 e1 = points[tri.idx1] - points[tri.idx0];
+ const Vector3 e2 = points[tri.idx2] - points[tri.idx0];
+ const Vector3 p(ray.direction().cross(e2));
+ const float a = e1.dot(p);
+
+ if (abs(a) < EPS) {
+ // Determinant is ill-conditioned; abort early
+ return false;
+ }
+
+ const float f = 1.0f / a;
+ const Vector3 s(ray.origin() - points[tri.idx0]);
+ const float u = f * s.dot(p);
+
+ if ((u < 0.0f) || (u > 1.0f)) {
+ // We hit the plane of the m_geometry, but outside the m_geometry
+ return false;
+ }
+
+ const Vector3 q(s.cross(e1));
+ const float v = f * ray.direction().dot(q);
+
+ if ((v < 0.0f) || ((u + v) > 1.0f)) {
+ // We hit the plane of the triangle, but outside the triangle
+ return false;
+ }
+
+ const float t = f * e2.dot(q);
+
+ if ((t > 0.0f) && (t < distance))
+ {
+ // This is a new hit, closer than the previous one
+ distance = t;
+
+ /* baryCoord[0] = 1.0 - u - v;
+ baryCoord[1] = u;
+ baryCoord[2] = v; */
+
+ return true;
+ }
+ // This hit is after the previous hit, so ignore it
+ return false;
+ }
+
+ class TriBoundFunc
+ {
+ public:
+ TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) {}
+ void operator()(const MeshTriangle &tri, G3D::AABox &out) const
+ {
+ G3D::Vector3 lo = vertices[tri.idx0];
+ G3D::Vector3 hi = lo;
+
+ lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]);
+ hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]);
+
+ out = G3D::AABox(lo, hi);
+ }
+ protected:
+ const std::vector<Vector3>::const_iterator vertices;
+ };
+
+ // ===================== WmoLiquid ==================================
+
+ WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type):
+ iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
+ {
+ iHeight = new float[(width+1)*(height+1)];
+ iFlags = new uint8[width*height];
+ }
+
+ WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(0), iFlags(0)
+ {
+ *this = other; // use assignment operator...
+ }
+
+ WmoLiquid::~WmoLiquid()
+ {
+ delete[] iHeight;
+ delete[] iFlags;
+ }
+
+ WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other)
+ {
+ if (this == &other)
+ return *this;
+ iTilesX = other.iTilesX;
+ iTilesY = other.iTilesY;
+ iCorner = other.iCorner;
+ iType = other.iType;
+ delete iHeight;
+ delete iFlags;
+ if (other.iHeight)
+ {
+ iHeight = new float[(iTilesX+1)*(iTilesY+1)];
+ memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float));
+ }
+ else
+ iHeight = 0;
+ if (other.iFlags)
+ {
+ iFlags = new uint8[iTilesX * iTilesY];
+ memcpy(iFlags, other.iFlags, iTilesX * iTilesY);
+ }
+ else
+ iFlags = 0;
+ return *this;
+ }
+
+ bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const
+ {
+ uint32 tx = (pos.x - iCorner.x)/LIQUID_TILE_SIZE;
+ if (tx<0 || tx >= iTilesX) return false;
+ uint32 ty = (pos.y - iCorner.y)/LIQUID_TILE_SIZE;
+ if (ty<0 || ty >= iTilesY) return false;
+ // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F:
+ if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F)
+ return false;
+ //placeholder...use only lower left corner vertex
+ liqHeight = /* iCorner.z + */ iHeight[tx + ty*(iTilesX+1)];
+ return true;
+ }
+
+ uint32 WmoLiquid::GetFileSize()
+ {
+ return 2 * sizeof(uint32) +
+ sizeof(Vector3) +
+ (iTilesX + 1)*(iTilesY + 1) * sizeof(float) +
+ iTilesX * iTilesY;
+ }
+
+ bool WmoLiquid::writeToFile(FILE *wf)
+ {
+ bool result = true;
+ if (result && fwrite(&iTilesX, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&iTilesY, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&iCorner, sizeof(Vector3), 1, wf) != 1) result = false;
+ if (result && fwrite(&iType, sizeof(uint32), 1, wf) != 1) result = false;
+ uint32 size = (iTilesX + 1)*(iTilesY + 1);
+ if (result && fwrite(iHeight, sizeof(float), size, wf) != size) result = false;
+ size = iTilesX*iTilesY;
+ if (result && fwrite(iFlags, sizeof(uint8), size, wf) != size) result = false;
+ return result;
+ }
+
+ bool WmoLiquid::readFromFile(FILE *rf, WmoLiquid *&out)
+ {
+ bool result = true;
+ WmoLiquid *liquid = new WmoLiquid();
+ if (result && fread(&liquid->iTilesX, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && fread(&liquid->iTilesY, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && fread(&liquid->iCorner, sizeof(Vector3), 1, rf) != 1) result = false;
+ if (result && fread(&liquid->iType, sizeof(uint32), 1, rf) != 1) result = false;
+ uint32 size = (liquid->iTilesX + 1)*(liquid->iTilesY + 1);
+ liquid->iHeight = new float[size];
+ if (result && fread(liquid->iHeight, sizeof(float), size, rf) != size) result = false;
+ size = liquid->iTilesX * liquid->iTilesY;
+ liquid->iFlags = new uint8[size];
+ if (result && fread(liquid->iFlags, sizeof(uint8), size, rf) != size) result = false;
+ if (!result)
+ delete liquid;
+ out = liquid;
+ return result;
+ }
+
+ // ===================== GroupModel ==================================
+
+ GroupModel::GroupModel(const GroupModel &other):
+ iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
+ vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0)
+ {
+ if (other.iLiquid)
+ iLiquid = new WmoLiquid(*other.iLiquid);
+ }
+
+ void GroupModel::setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri)
+ {
+ vertices.swap(vert);
+ triangles.swap(tri);
+ TriBoundFunc bFunc(vertices);
+ meshTree.build(triangles, bFunc);
+ }
+
+ bool GroupModel::writeToFile(FILE *wf)
+ {
+ bool result = true;
+ uint32 chunkSize, count;
+
+ if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false;
+ if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false;
+
+ // write vertices
+ if (result && fwrite("VERT", 1, 4, wf) != 4) result = false;
+ count = vertices.size();
+ chunkSize = sizeof(uint32)+ sizeof(Vector3)*count;
+ if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
+ if (!count) // models without (collision) geometry end here, unsure if they are useful
+ return result;
+ if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false;
+
+ // write triangle mesh
+ if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false;
+ count = triangles.size();
+ chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count;
+ if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false;
+
+ // write mesh BIH
+ if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false;
+ if (result) result = meshTree.writeToFile(wf);
+
+ // write liquid data
+ if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false;
+ if (!iLiquid)
+ {
+ chunkSize = 0;
+ if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
+ return result;
+ }
+ chunkSize = iLiquid->GetFileSize();
+ if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result) result = iLiquid->writeToFile(wf);
+
+ return result;
+ }
+
+ bool GroupModel::readFromFile(FILE *rf)
+ {
+ char chunk[8];
+ bool result = true;
+ uint32 chunkSize, count;
+ triangles.clear();
+ vertices.clear();
+ delete iLiquid;
+ iLiquid = 0;
+
+ if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false;
+ if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false;
+
+ // read vertices
+ if (result && !readChunk(rf, chunk, "VERT", 4)) result = false;
+ if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
+ if (!count) // models without (collision) geometry end here, unsure if they are useful
+ return result;
+ if (result) vertices.resize(count);
+ if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false;
+
+ // read triangle mesh
+ if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false;
+ if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result) triangles.resize(count);
+ if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false;
+
+ // read mesh BIH
+ if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false;
+ if (result) result = meshTree.readFromFile(rf);
+
+ // write liquid data
+ if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false;
+ if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && chunkSize > 0)
+ result = WmoLiquid::readFromFile(rf, iLiquid);
+ return result;
+ }
+
+ struct GModelRayCallback
+ {
+ GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert):
+ vertices(vert.begin()), triangles(tris.begin()), hit(false) {}
+ bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit)
+ {
+ bool result = IntersectTriangle(triangles[entry], vertices, ray, distance);
+ if (result) hit=true;
+ return hit;
+ }
+ std::vector<Vector3>::const_iterator vertices;
+ std::vector<MeshTriangle>::const_iterator triangles;
+ bool hit;
+ };
+
+ bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
+ {
+ if (!triangles.size())
+ return false;
+ GModelRayCallback callback(triangles, vertices);
+ meshTree.intersectRay(ray, callback, distance, stopAtFirstHit);
+ return callback.hit;
+ }
+
+ bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const
+ {
+ if (!triangles.size() || !iBound.contains(pos))
+ return false;
+ GModelRayCallback callback(triangles, vertices);
+ Vector3 rPos = pos - 0.1f * down;
+ float dist = G3D::inf();
+ G3D::Ray ray(rPos, down);
+ bool hit = IntersectRay(ray, dist, false);
+ if (hit)
+ z_dist = dist - 0.1f;
+ return hit;
+ }
+
+ bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const
+ {
+ if (iLiquid)
+ return iLiquid->GetLiquidHeight(pos, liqHeight);
+ return false;
+ }
+
+ uint32 GroupModel::GetLiquidType() const
+ {
+ // convert to type mask, matching MAP_LIQUID_TYPE_* defines in Map.h
+ if (iLiquid)
+ return (1 << iLiquid->GetType());
+ return 0;
+ }
+
+ // ===================== WorldModel ==================================
+
+ void WorldModel::setGroupModels(std::vector<GroupModel> &models)
+ {
+ groupModels.swap(models);
+ groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1);
+ }
+
+ struct WModelRayCallBack
+ {
+ WModelRayCallBack(const std::vector<GroupModel> &mod): models(mod.begin()), hit(false) {}
+ bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit)
+ {
+ bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit);
+ if (result) hit=true;
+ return hit;
+ }
+ std::vector<GroupModel>::const_iterator models;
+ bool hit;
+ };
+
+ bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
+ {
+ // small M2 workaround, maybe better make separate class with virtual intersection funcs
+ // in any case, there's no need to use a bound tree if we only have one submodel
+ if (groupModels.size() == 1)
+ return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit);
+
+ WModelRayCallBack isc(groupModels);
+ groupTree.intersectRay(ray, isc, distance, stopAtFirstHit);
+ return isc.hit;
+ }
+
+ class WModelAreaCallback {
+ public:
+ WModelAreaCallback(const std::vector<GroupModel> &vals, const Vector3 &down):
+ prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) {}
+ std::vector<GroupModel>::const_iterator prims;
+ std::vector<GroupModel>::const_iterator hit;
+ float minVol;
+ float zDist;
+ Vector3 zVec;
+ void operator()(const Vector3& point, uint32 entry)
+ {
+ float group_Z;
+ //float pVol = prims[entry].GetBound().volume();
+ //if(pVol < minVol)
+ //{
+ /* if (prims[entry].iBound.contains(point)) */
+ if (prims[entry].IsInsideObject(point, zVec, group_Z))
+ {
+ //minVol = pVol;
+ //hit = prims + entry;
+ if (group_Z < zDist)
+ {
+ zDist = group_Z;
+ hit = prims + entry;
+ }
+#ifdef VMAP_DEBUG
+ const GroupModel &gm = prims[entry];
+ printf("%10u %8X %7.3f,%7.3f,%7.3f | %7.3f,%7.3f,%7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(),
+ gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z,
+ gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
+#endif
+ }
+ //}
+ //std::cout << "trying to intersect '" << prims[entry].name << "'\n";
+ }
+ };
+
+ bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const
+ {
+ if (!groupModels.size())
+ return false;
+ WModelAreaCallback callback(groupModels, down);
+ groupTree.intersectPoint(p, callback);
+ if (callback.hit != groupModels.end())
+ {
+ info.rootId = RootWMOID;
+ info.groupId = callback.hit->GetWmoID();
+ info.flags = callback.hit->GetMogpFlags();
+ info.result = true;
+ dist = callback.zDist;
+ return true;
+ }
+ return false;
+ }
+
+ bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const
+ {
+ if (!groupModels.size())
+ return false;
+ WModelAreaCallback callback(groupModels, down);
+ groupTree.intersectPoint(p, callback);
+ if (callback.hit != groupModels.end())
+ {
+ info.hitModel = &(*callback.hit);
+ dist = callback.zDist;
+ return true;
+ }
+ return false;
+ }
+
+ bool WorldModel::writeFile(const std::string &filename)
+ {
+ FILE *wf = fopen(filename.c_str(), "wb");
+ if (!wf)
+ return false;
+
+ bool result = true;
+ uint32 chunkSize, count;
+ result = fwrite(VMAP_MAGIC,1,8,wf) == 8;
+ if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false;
+ chunkSize = sizeof(uint32) + sizeof(uint32);
+ if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false;
+
+ // write group models
+ count=groupModels.size();
+ if (count)
+ {
+ if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false;
+ //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count;
+ //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
+ if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false;
+ for (uint32 i=0; i<groupModels.size() && result; ++i)
+ result = groupModels[i].writeToFile(wf);
+
+ // write group BIH
+ if (result && fwrite("GBIH", 1, 4, wf) != 4) result = false;
+ if (result) result = groupTree.writeToFile(wf);
+ }
+
+ fclose(wf);
+ return result;
+ }
+
+ bool WorldModel::readFile(const std::string &filename)
+ {
+ FILE *rf = fopen(filename.c_str(), "rb");
+ if (!rf)
+ return false;
+
+ bool result = true;
+ uint32 chunkSize, count;
+ char chunk[8]; // Ignore the added magic header
+ if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) result = false;
+
+ if (result && !readChunk(rf, chunk, "WMOD", 4)) result = false;
+ if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) result = false;
+
+ // read group models
+ if (result && readChunk(rf, chunk, "GMOD", 4))
+ {
+ //if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false;
+
+ if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false;
+ if (result) groupModels.resize(count);
+ //if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false;
+ for (uint32 i=0; i<count && result; ++i)
+ result = groupModels[i].readFromFile(rf);
+
+ // read group BIH
+ if (result && !readChunk(rf, chunk, "GBIH", 4)) result = false;
+ if (result) result = groupTree.readFromFile(rf);
+ }
+
+ fclose(rf);
+ return result;
+ }
+}
diff --git a/src/server/shared/vmap/WorldModel.h b/src/server/shared/vmap/WorldModel.h
new file mode 100644
index 00000000000..f12efed4f5d
--- /dev/null
+++ b/src/server/shared/vmap/WorldModel.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2005-2010 MaNGOS <http://getmangos.com/>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _WORLDMODEL_H
+#define _WORLDMODEL_H
+
+#include <G3D/HashTrait.h>
+#include <G3D/Vector3.h>
+#include <G3D/AABox.h>
+#include <G3D/Ray.h>
+#include "BIH.h"
+
+#include "Platform/Define.h"
+
+namespace VMAP
+{
+ class TreeNode;
+ struct AreaInfo;
+ struct LocationInfo;
+
+ class MeshTriangle
+ {
+ public:
+ MeshTriangle(){};
+ MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) {};
+
+ uint32 idx0;
+ uint32 idx1;
+ uint32 idx2;
+ };
+
+ class WmoLiquid
+ {
+ public:
+ WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type);
+ WmoLiquid(const WmoLiquid &other);
+ ~WmoLiquid();
+ WmoLiquid& operator=(const WmoLiquid &other);
+ bool GetLiquidHeight(const Vector3 &pos, float &liqHeight) const;
+ uint32 GetType() const { return iType; }
+ float *GetHeightStorage() { return iHeight; }
+ uint8 *GetFlagsStorage() { return iFlags; }
+ uint32 GetFileSize();
+ bool writeToFile(FILE *wf);
+ static bool readFromFile(FILE *rf, WmoLiquid *&liquid);
+ private:
+ WmoLiquid(): iHeight(0), iFlags(0) {};
+ uint32 iTilesX; //!< number of tiles in x direction, each
+ uint32 iTilesY;
+ Vector3 iCorner; //!< the lower corner
+ uint32 iType; //!< liquid type
+ float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values
+ uint8 *iFlags; //!< info if liquid tile is used
+ };
+
+ /*! holding additional info for WMO group files */
+ class GroupModel
+ {
+ public:
+ GroupModel(): iLiquid(0) {}
+ GroupModel(const GroupModel &other);
+ GroupModel(uint32 mogpFlags, uint32 groupWMOID, const AABox &bound):
+ iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) {}
+ ~GroupModel() { delete iLiquid; }
+
+ //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry!
+ void setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri);
+ void setLiquidData(WmoLiquid *liquid) { iLiquid = liquid; }
+ bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const;
+ bool IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const;
+ bool GetLiquidLevel(const Vector3 &pos, float &liqHeight) const;
+ uint32 GetLiquidType() const;
+ bool writeToFile(FILE *wf);
+ bool readFromFile(FILE *rf);
+ const G3D::AABox& GetBound() const { return iBound; }
+ uint32 GetMogpFlags() const { return iMogpFlags; }
+ uint32 GetWmoID() const { return iGroupWMOID; }
+ protected:
+ G3D::AABox iBound;
+ uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor
+ uint32 iGroupWMOID;
+ std::vector<Vector3> vertices;
+ std::vector<MeshTriangle> triangles;
+ BIH meshTree;
+ WmoLiquid *iLiquid;
+ };
+ /*! Holds a model (converted M2 or WMO) in its original coordinate space */
+ class WorldModel
+ {
+ public:
+ WorldModel(): RootWMOID(0) {}
+
+ //! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
+ void setGroupModels(std::vector<GroupModel> &models);
+ void setRootWmoID(uint32 id) { RootWMOID = id; }
+ bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const;
+ bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const;
+ bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const;
+ bool writeFile(const std::string &filename);
+ bool readFile(const std::string &filename);
+ protected:
+ uint32 RootWMOID;
+ std::vector<GroupModel> groupModels;
+ BIH groupTree;
+ };
+} // namespace VMAP
+
+#endif // _WORLDMODEL_H