diff options
Diffstat (limited to 'src/common')
83 files changed, 1676 insertions, 909 deletions
diff --git a/src/common/Banner.cpp b/src/common/Banner.cpp new file mode 100644 index 00000000000..e927ac6ef4a --- /dev/null +++ b/src/common/Banner.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#include "Banner.h" +#include "GitRevision.h" +#include "StringFormat.h" + +void Trinity::Banner::Show(char const* applicationName, void(*log)(char const* text), void(*logExtraInfo)()) +{ + log(Trinity::StringFormat("%s (%s)", GitRevision::GetFullVersion(), applicationName).c_str()); + log("<Ctrl-C> to stop.\n"); + log(" ______ __"); + log("/\\__ _\\ __ __/\\ \\__"); + log("\\/_/\\ \\/ _ __ /\\_\\ ___ /\\_\\ \\, _\\ __ __"); + log(" \\ \\ \\/\\`'__\\/\\ \\ /' _ `\\/\\ \\ \\ \\/ /\\ \\/\\ \\"); + log(" \\ \\ \\ \\ \\/ \\ \\ \\/\\ \\/\\ \\ \\ \\ \\ \\_\\ \\ \\_\\ \\"); + log(" \\ \\_\\ \\_\\ \\ \\_\\ \\_\\ \\_\\ \\_\\ \\__\\\\/`____ \\"); + log(" \\/_/\\/_/ \\/_/\\/_/\\/_/\\/_/\\/__/ `/___/> \\"); + log(" C O R E /\\___/"); + log("http://TrinityCore.org \\/__/\n"); + + if (logExtraInfo) + logExtraInfo(); +} diff --git a/src/common/Banner.h b/src/common/Banner.h new file mode 100644 index 00000000000..a23377ea04b --- /dev/null +++ b/src/common/Banner.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TrinityCore_Banner_h__ +#define TrinityCore_Banner_h__ + +#include "Define.h" + +namespace Trinity +{ + namespace Banner + { + TC_COMMON_API void Show(char const* applicationName, void(*log)(char const* text), void(*logExtraInfo)()); + } +} + +#endif // TrinityCore_Banner_h__ diff --git a/src/common/Collision/BoundingIntervalHierarchy.h b/src/common/Collision/BoundingIntervalHierarchy.h index a80759f6cf7..539e535fa14 100644 --- a/src/common/Collision/BoundingIntervalHierarchy.h +++ b/src/common/Collision/BoundingIntervalHierarchy.h @@ -19,9 +19,9 @@ #ifndef _BIH_H #define _BIH_H -#include "G3D/Vector3.h" -#include "G3D/Ray.h" -#include "G3D/AABox.h" +#include <G3D/Vector3.h> +#include <G3D/Ray.h> +#include <G3D/AABox.h> #include "Define.h" @@ -80,8 +80,8 @@ class TC_COMMON_API BIH } public: BIH() { init_empty(); } - template< class BoundsFunc, class PrimArray > - void build(const PrimArray &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) + template <class BoundsFunc, class PrimArray> + void build(PrimArray const& primitives, BoundsFunc& getBounds, uint32 leafSize = 3, bool printStats = false) { if (primitives.size() == 0) { @@ -118,7 +118,7 @@ class TC_COMMON_API BIH uint32 primCount() const { return uint32(objects.size()); } template<typename RayCallback> - void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const + void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst = false) const { float intervalMin = -1.f; float intervalMax = -1.f; diff --git a/src/common/Collision/BoundingIntervalHierarchyWrapper.h b/src/common/Collision/BoundingIntervalHierarchyWrapper.h index b7f78ea7baf..32c99798768 100644 --- a/src/common/Collision/BoundingIntervalHierarchyWrapper.h +++ b/src/common/Collision/BoundingIntervalHierarchyWrapper.h @@ -19,10 +19,10 @@ #ifndef _BIH_WRAP #define _BIH_WRAP -#include "G3D/Table.h" -#include "G3D/Array.h" -#include "G3D/Set.h" #include "BoundingIntervalHierarchy.h" +#include <G3D/Table.h> +#include <G3D/Array.h> +#include <G3D/Set.h> template<class T, class BoundsFunc = BoundsTrait<T> > @@ -80,7 +80,7 @@ public: uint32 Idx = 0; const T * temp; if (m_obj2Idx.getRemove(&obj, temp, Idx)) - m_objects[Idx] = NULL; + m_objects[Idx] = nullptr; else m_objects_to_push.remove(&obj); } diff --git a/src/common/Collision/DynamicTree.cpp b/src/common/Collision/DynamicTree.cpp index 38e10318a57..46dfdb1707e 100644 --- a/src/common/Collision/DynamicTree.cpp +++ b/src/common/Collision/DynamicTree.cpp @@ -41,20 +41,20 @@ int CHECK_TREE_PERIOD = 200; } // namespace template<> struct HashTrait< GameObjectModel>{ - static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; } + static size_t hashCode(GameObjectModel const& g) { return (size_t)(void*)&g; } }; template<> struct PositionTrait< GameObjectModel> { - static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); } + static void getPosition(GameObjectModel const& g, G3D::Vector3& p) { p = g.getPosition(); } }; template<> struct BoundsTrait< GameObjectModel> { - static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();} - static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();} + static void getBounds(GameObjectModel const& g, G3D::AABox& out) { out = g.getBounds();} + static void getBounds2(GameObjectModel const* g, G3D::AABox& out) { out = g->getBounds();} }; /* -static bool operator == (const GameObjectModel& mdl, const GameObjectModel& mdl2){ +static bool operator==(GameObjectModel const& mdl, GameObjectModel const& mdl2){ return &mdl == &mdl2; } */ @@ -72,13 +72,13 @@ struct DynTreeImpl : public ParentTree/*, public Intersectable*/ { } - void insert(const Model& mdl) + void insert(Model const& mdl) { base::insert(mdl); ++unbalanced_times; } - void remove(const Model& mdl) + void remove(Model const& mdl) { base::remove(mdl); ++unbalanced_times; @@ -115,17 +115,17 @@ DynamicMapTree::~DynamicMapTree() delete impl; } -void DynamicMapTree::insert(const GameObjectModel& mdl) +void DynamicMapTree::insert(GameObjectModel const& mdl) { impl->insert(mdl); } -void DynamicMapTree::remove(const GameObjectModel& mdl) +void DynamicMapTree::remove(GameObjectModel const& mdl) { impl->remove(mdl); } -bool DynamicMapTree::contains(const GameObjectModel& mdl) const +bool DynamicMapTree::contains(GameObjectModel const& mdl) const { return impl->contains(mdl); } @@ -145,7 +145,7 @@ struct DynamicTreeIntersectionCallback bool did_hit; uint32 phase_mask; DynamicTreeIntersectionCallback(uint32 phasemask) : did_hit(false), phase_mask(phasemask) { } - bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) + bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance) { did_hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing); return did_hit; @@ -161,7 +161,7 @@ struct DynamicTreeIntersectionCallback_WithLogger { TC_LOG_DEBUG("maps", "Dynamic Intersection log"); } - bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) + bool operator()(G3D::Ray const& r, GameObjectModel const& obj, float& distance) { TC_LOG_DEBUG("maps", "testing intersection with %s", obj.name.c_str()); bool hit = obj.intersectRay(r, distance, true, phase_mask, VMAP::ModelIgnoreFlags::Nothing); diff --git a/src/common/Collision/DynamicTree.h b/src/common/Collision/DynamicTree.h index 49458393906..0e1d1f0342b 100644 --- a/src/common/Collision/DynamicTree.h +++ b/src/common/Collision/DynamicTree.h @@ -52,9 +52,9 @@ public: float getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const; - void insert(const GameObjectModel&); - void remove(const GameObjectModel&); - bool contains(const GameObjectModel&) const; + void insert(GameObjectModel const&); + void remove(GameObjectModel const&); + bool contains(GameObjectModel const&) const; void balance(); void update(uint32 diff); diff --git a/src/common/Collision/Management/IVMapManager.h b/src/common/Collision/Management/IVMapManager.h index e77987a721d..0371135cfa5 100644 --- a/src/common/Collision/Management/IVMapManager.h +++ b/src/common/Collision/Management/IVMapManager.h @@ -19,10 +19,10 @@ #ifndef _IVMAPMANAGER_H #define _IVMAPMANAGER_H -#include <string> #include "Define.h" #include "ModelIgnoreFlags.h" -#include "Common.h" +#include "Optional.h" +#include <string> //=========================================================== @@ -83,9 +83,9 @@ namespace VMAP virtual ~IVMapManager(void) { } - virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; + virtual int loadMap(char const* pBasePath, unsigned int pMapId, int x, int y) = 0; - virtual LoadResult existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; + virtual LoadResult existsMap(char const* 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; diff --git a/src/common/Collision/Management/MMapFactory.cpp b/src/common/Collision/Management/MMapFactory.cpp index 1257d852697..02295c2b2db 100644 --- a/src/common/Collision/Management/MMapFactory.cpp +++ b/src/common/Collision/Management/MMapFactory.cpp @@ -23,11 +23,11 @@ namespace MMAP { // ######################## MMapFactory ######################## // our global singleton copy - MMapManager* g_MMapManager = NULL; + MMapManager* g_MMapManager = nullptr; MMapManager* MMapFactory::createOrGetMMapManager() { - if (g_MMapManager == NULL) + if (g_MMapManager == nullptr) g_MMapManager = new MMapManager(); return g_MMapManager; @@ -38,7 +38,7 @@ namespace MMAP if (g_MMapManager) { delete g_MMapManager; - g_MMapManager = NULL; + g_MMapManager = nullptr; } } }
\ No newline at end of file diff --git a/src/common/Collision/Management/MMapManager.cpp b/src/common/Collision/Management/MMapManager.cpp index cec5c0da7f0..ff87ed369cc 100644 --- a/src/common/Collision/Management/MMapManager.cpp +++ b/src/common/Collision/Management/MMapManager.cpp @@ -17,6 +17,7 @@ */ #include "MMapManager.h" +#include "Errors.h" #include "Log.h" #include "Config.h" #include "MapDefines.h" @@ -39,7 +40,7 @@ namespace MMAP void MMapManager::InitializeThreadUnsafe(const std::vector<uint32>& mapIds) { // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (const uint32& mapId : mapIds) + for (uint32 const& mapId : mapIds) loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)); thread_safe_environment = false; @@ -222,7 +223,7 @@ namespace MMAP dtTileRef tileRef = mmap->loadedTileRefs[packedGridPos]; // unload, and mark as non loaded - if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL))) + if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, nullptr, nullptr))) { // this is technically a memory leak // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used @@ -257,7 +258,7 @@ namespace MMAP { uint32 x = (i->first >> 16); uint32 y = (i->first & 0x0000FFFF); - if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL))) + if (dtStatusFailed(mmap->navMesh->removeTile(i->second, nullptr, nullptr))) TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); else { @@ -304,7 +305,7 @@ namespace MMAP { MMapDataSet::const_iterator itr = GetMMapData(mapId); if (itr == loadedMMaps.end()) - return NULL; + return nullptr; return itr->second->navMesh; } @@ -313,7 +314,7 @@ namespace MMAP { MMapDataSet::const_iterator itr = GetMMapData(mapId); if (itr == loadedMMaps.end()) - return NULL; + return nullptr; MMapData* mmap = itr->second; if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) @@ -325,7 +326,7 @@ namespace MMAP { dtFreeNavMeshQuery(query); TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - return NULL; + return nullptr; } TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); diff --git a/src/common/Collision/Management/VMapFactory.cpp b/src/common/Collision/Management/VMapFactory.cpp index f36f237c4b2..f8c4be61617 100644 --- a/src/common/Collision/Management/VMapFactory.cpp +++ b/src/common/Collision/Management/VMapFactory.cpp @@ -21,7 +21,7 @@ namespace VMAP { - IVMapManager* gVMapManager = NULL; + IVMapManager* gVMapManager = nullptr; //=============================================== // just return the instance @@ -37,6 +37,6 @@ namespace VMAP void VMapFactory::clear() { delete gVMapManager; - gVMapManager = NULL; + gVMapManager = nullptr; } } diff --git a/src/common/Collision/Management/VMapManager2.cpp b/src/common/Collision/Management/VMapManager2.cpp index 33bf7338616..7c894efa1ca 100644 --- a/src/common/Collision/Management/VMapManager2.cpp +++ b/src/common/Collision/Management/VMapManager2.cpp @@ -55,7 +55,7 @@ namespace VMAP void VMapManager2::InitializeThreadUnsafe(const std::vector<uint32>& mapIds) { // the caller must pass the list of all mapIds that will be used in the VMapManager2 lifetime - for (const uint32& mapId : mapIds) + for (uint32 const& mapId : mapIds) iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)); thread_safe_environment = false; @@ -82,7 +82,7 @@ namespace VMAP return fname.str(); } - int VMapManager2::loadMap(const char* basePath, unsigned int mapId, int x, int y) + int VMapManager2::loadMap(char const* basePath, unsigned int mapId, int x, int y) { int result = VMAP_LOAD_RESULT_IGNORED; if (isMapLoadingEnabled()) @@ -323,7 +323,7 @@ namespace VMAP { VMAP_ERROR_LOG("misc", "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); delete worldmodel; - return NULL; + return nullptr; } VMAP_DEBUG_LOG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); @@ -355,7 +355,7 @@ namespace VMAP } } - LoadResult VMapManager2::existsMap(const char* basePath, unsigned int mapId, int x, int y) + LoadResult VMapManager2::existsMap(char const* basePath, unsigned int mapId, int x, int y) { return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y); } diff --git a/src/common/Collision/Management/VMapManager2.h b/src/common/Collision/Management/VMapManager2.h index 3fdc427d6eb..b8d59b9c09e 100644 --- a/src/common/Collision/Management/VMapManager2.h +++ b/src/common/Collision/Management/VMapManager2.h @@ -102,7 +102,7 @@ namespace VMAP ~VMapManager2(void); void InitializeThreadUnsafe(const std::vector<uint32>& mapIds); - int loadMap(const char* pBasePath, unsigned int mapId, int x, int y) override; + int loadMap(char const* pBasePath, unsigned int mapId, int x, int y) override; void unloadMap(unsigned int mapId, int x, int y) override; void unloadMap(unsigned int mapId) override; @@ -128,7 +128,7 @@ namespace VMAP { return getMapFileName(mapId); } - virtual LoadResult existsMap(const char* basePath, unsigned int mapId, int x, int y) override; + virtual LoadResult existsMap(char const* basePath, unsigned int mapId, int x, int y) override; void getInstanceMapTree(InstanceTreeMap &instanceMapTree); diff --git a/src/common/Collision/Maps/MapDefines.h b/src/common/Collision/Maps/MapDefines.h index 4b53975237e..3dd19735ff9 100644 --- a/src/common/Collision/Maps/MapDefines.h +++ b/src/common/Collision/Maps/MapDefines.h @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + #ifndef _MAPDEFINES_H #define _MAPDEFINES_H diff --git a/src/common/Collision/Maps/MapTree.cpp b/src/common/Collision/Maps/MapTree.cpp index f3fe8c1f56f..1f2a8a60c73 100644 --- a/src/common/Collision/Maps/MapTree.cpp +++ b/src/common/Collision/Maps/MapTree.cpp @@ -37,7 +37,7 @@ namespace VMAP { public: MapRayCallback(ModelInstance* val, ModelIgnoreFlags ignoreFlags): prims(val), hit(false), flags(ignoreFlags) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) + bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit = true) { bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit, flags); if (result) @@ -55,7 +55,7 @@ namespace VMAP { public: AreaInfoCallback(ModelInstance* val): prims(val) { } - void operator()(const Vector3& point, uint32 entry) + void operator()(Vector3 const& point, uint32 entry) { #ifdef VMAP_DEBUG TC_LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); @@ -71,7 +71,7 @@ namespace VMAP { public: LocationInfoCallback(ModelInstance* val, LocationInfo &info): prims(val), locInfo(info), result(false) { } - void operator()(const Vector3& point, uint32 entry) + void operator()(Vector3 const& point, uint32 entry) { #ifdef VMAP_DEBUG TC_LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); @@ -113,15 +113,15 @@ namespace VMAP return false; } - bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const + bool StaticMapTree::GetLocationInfo(Vector3 const& 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), iIsTiled(false), iTreeValues(NULL), + StaticMapTree::StaticMapTree(uint32 mapID, std::string const& basePath) : + iMapID(mapID), iIsTiled(false), iTreeValues(nullptr), iNTreeValues(0), iBasePath(basePath) { if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') @@ -153,7 +153,7 @@ namespace VMAP } //========================================================= - bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2, ModelIgnoreFlags ignoreFlag) const + bool StaticMapTree::isInLineOfSight(Vector3 const& pos1, Vector3 const& pos2, ModelIgnoreFlags ignoreFlag) const { float maxDist = (pos2 - pos1).magnitude(); // return false if distance is over max float, in case of cheater teleporting to the end of the universe @@ -178,9 +178,9 @@ namespace VMAP Return the hit pos or the original dest pos */ - bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const + bool StaticMapTree::getObjectHitPos(Vector3 const& pPos1, Vector3 const& pPos2, Vector3& pResultHitPos, float pModifyDist) const { - bool result=false; + bool result = false; float maxDist = (pPos2 - pPos1).magnitude(); // valid map coords should *never ever* produce float overflow, but this would produce NaNs too ASSERT(maxDist < std::numeric_limits<float>::max()); @@ -223,7 +223,7 @@ namespace VMAP //========================================================= - float StaticMapTree::getHeight(const Vector3& pPos, float maxSearchDist) const + float StaticMapTree::getHeight(Vector3 const& pPos, float maxSearchDist) const { float height = G3D::finf(); Vector3 dir = Vector3(0, 0, -1); @@ -438,7 +438,7 @@ namespace VMAP FILE* tf = fopen(tilefile.c_str(), "rb"); if (tf) { - bool result=true; + bool result = true; char chunk[8]; if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) result = false; diff --git a/src/common/Collision/Maps/MapTree.h b/src/common/Collision/Maps/MapTree.h index bc18e07789b..6dc32c1241a 100644 --- a/src/common/Collision/Maps/MapTree.h +++ b/src/common/Collision/Maps/MapTree.h @@ -36,8 +36,8 @@ namespace VMAP { LocationInfo(): hitInstance(nullptr), hitModel(nullptr), ground_Z(-G3D::finf()) { } int32 rootId; - const ModelInstance* hitInstance; - const GroupModel* hitModel; + ModelInstance const* hitInstance; + GroupModel const* hitModel; float ground_Z; }; diff --git a/src/common/Collision/Maps/TileAssembler.cpp b/src/common/Collision/Maps/TileAssembler.cpp index 2c4d3105050..fe00458cf6d 100644 --- a/src/common/Collision/Maps/TileAssembler.cpp +++ b/src/common/Collision/Maps/TileAssembler.cpp @@ -32,7 +32,7 @@ using std::pair; template<> struct BoundsTrait<VMAP::ModelSpawn*> { - static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } + static void getBounds(VMAP::ModelSpawn const* const& obj, G3D::AABox& out) { out = obj->getBounds(); } }; namespace VMAP @@ -43,7 +43,7 @@ namespace VMAP return memcmp(dest, compare, len) == 0; } - Vector3 ModelPosition::transform(const Vector3& pIn) const + Vector3 ModelPosition::transform(Vector3 const& pIn) const { Vector3 out = pIn * iScale; out = iRotation * out; @@ -53,7 +53,7 @@ namespace VMAP //================================================================= TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) - : iDestDir(pDestDirName), iSrcDir(pSrcDirName), iFilterMethod(NULL), iCurrentUniqueNameId(0) + : iDestDir(pDestDirName), iSrcDir(pSrcDirName), iFilterMethod(nullptr), iCurrentUniqueNameId(0) { //mkdir(iDestDir); //init(); @@ -136,10 +136,8 @@ namespace VMAP // 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) - { + for (TileMap::iterator glob = globalRange.first; glob != globalRange.second && success; ++glob) success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); - } fclose(mapfile); @@ -150,7 +148,7 @@ namespace VMAP TileMap::iterator tile; for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) { - const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; + ModelSpawn const& 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); @@ -171,7 +169,7 @@ namespace VMAP { if (s) ++tile; - const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; + ModelSpawn const& 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); @@ -266,9 +264,9 @@ namespace VMAP printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); AABox modelBound; - bool boundEmpty=true; + bool boundEmpty = true; - for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... + for (uint32 g = 0; g < groups; ++g) // should be only one for M2 files... { std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; @@ -284,7 +282,10 @@ namespace VMAP Vector3 v = modelPosition.transform(vertices[i]); if (boundEmpty) - modelBound = AABox(v, v), boundEmpty=false; + { + modelBound = AABox(v, v); + boundEmpty = false; + } else modelBound.merge(v); } diff --git a/src/common/Collision/Maps/TileAssembler.h b/src/common/Collision/Maps/TileAssembler.h index ae0585dbd57..f11f2682a0d 100644 --- a/src/common/Collision/Maps/TileAssembler.h +++ b/src/common/Collision/Maps/TileAssembler.h @@ -76,7 +76,7 @@ namespace VMAP class WmoLiquid* liquid; GroupModel_Raw() : mogpflags(0), GroupWMOID(0), liquidflags(0), - liquid(NULL) { } + liquid(nullptr) { } ~GroupModel_Raw(); bool Read(FILE* f); diff --git a/src/common/Collision/Models/GameObjectModel.cpp b/src/common/Collision/Models/GameObjectModel.cpp index 2950a48c21b..992ec59e1af 100644 --- a/src/common/Collision/Models/GameObjectModel.cpp +++ b/src/common/Collision/Models/GameObjectModel.cpp @@ -30,7 +30,7 @@ using G3D::AABox; struct GameobjectModelData { - GameobjectModelData(const std::string& name_, const AABox& box) : + GameobjectModelData(std::string const& name_, AABox const& box) : bound(box), name(name_) { } AABox bound; @@ -147,7 +147,7 @@ GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBas if (!mdl->initialize(std::move(modelOwner), dataPath)) { delete mdl; - return NULL; + return nullptr; } return mdl; diff --git a/src/common/Collision/Models/GameObjectModel.h b/src/common/Collision/Models/GameObjectModel.h index c121e421e6d..72fee944380 100644 --- a/src/common/Collision/Models/GameObjectModel.h +++ b/src/common/Collision/Models/GameObjectModel.h @@ -50,7 +50,7 @@ public: class TC_COMMON_API GameObjectModel /*, public Intersectable*/ { - GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { } + GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(nullptr) { } public: std::string name; diff --git a/src/common/Collision/Models/ModelInstance.cpp b/src/common/Collision/Models/ModelInstance.cpp index 3390b233c82..3eeb0e8c669 100644 --- a/src/common/Collision/Models/ModelInstance.cpp +++ b/src/common/Collision/Models/ModelInstance.cpp @@ -25,13 +25,13 @@ using G3D::Ray; namespace VMAP { - ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel* model): ModelSpawn(spawn), iModel(model) + ModelInstance::ModelInstance(ModelSpawn const& spawn, WorldModel* model): ModelSpawn(spawn), iModel(model) { iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iRot.y/180.f, G3D::pif()*iRot.x/180.f, G3D::pif()*iRot.z/180.f).inverse(); iInvScale = 1.f/iScale; } - bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const + bool ModelInstance::intersectRay(G3D::Ray const& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const { if (!iModel) { @@ -196,7 +196,7 @@ namespace VMAP return true; } - bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn &spawn) + bool ModelSpawn::writeToFile(FILE* wf, ModelSpawn const& spawn) { uint32 check=0; check += fwrite(&spawn.flags, sizeof(uint32), 1, wf); diff --git a/src/common/Collision/Models/ModelInstance.h b/src/common/Collision/Models/ModelInstance.h index 3036ac10117..fa53ceab70d 100644 --- a/src/common/Collision/Models/ModelInstance.h +++ b/src/common/Collision/Models/ModelInstance.h @@ -52,25 +52,25 @@ namespace VMAP float iScale; G3D::AABox iBound; std::string name; - bool operator==(const ModelSpawn &other) const { return ID == other.ID; } + bool operator==(ModelSpawn const& 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); + static bool writeToFile(FILE* rw, ModelSpawn const& spawn); }; class TC_COMMON_API ModelInstance: public ModelSpawn { public: ModelInstance(): iInvScale(0.0f), iModel(nullptr) { } - ModelInstance(const ModelSpawn &spawn, WorldModel* model); + ModelInstance(ModelSpawn const& spawn, WorldModel* model); void setUnloaded() { iModel = nullptr; } - bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) 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; + bool intersectRay(G3D::Ray const& pRay, float& pMaxDist, bool pStopAtFirstHit, ModelIgnoreFlags ignoreFlags) const; + void intersectPoint(G3D::Vector3 const& p, AreaInfo &info) const; + bool GetLocationInfo(G3D::Vector3 const& p, LocationInfo &info) const; + bool GetLiquidLevel(G3D::Vector3 const& p, LocationInfo &info, float &liqHeight) const; WorldModel* getWorldModel() { return iModel; } protected: G3D::Matrix3 iInvRot; diff --git a/src/common/Collision/Models/WorldModel.cpp b/src/common/Collision/Models/WorldModel.cpp index d04bcf4d241..7a40ba215cf 100644 --- a/src/common/Collision/Models/WorldModel.cpp +++ b/src/common/Collision/Models/WorldModel.cpp @@ -32,7 +32,7 @@ template<> struct BoundsTrait<VMAP::GroupModel> namespace VMAP { - bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance) + bool IntersectTriangle(MeshTriangle const& tri, std::vector<Vector3>::const_iterator points, G3D::Ray const& ray, float& distance) { static const float EPS = 1e-5f; @@ -85,8 +85,8 @@ namespace VMAP class TriBoundFunc { public: - TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) { } - void operator()(const MeshTriangle &tri, G3D::AABox &out) const + TriBoundFunc(std::vector<Vector3>& vert): vertices(vert.begin()) { } + void operator()(MeshTriangle const& tri, G3D::AABox& out) const { G3D::Vector3 lo = vertices[tri.idx0]; G3D::Vector3 hi = lo; @@ -102,14 +102,14 @@ namespace VMAP // ===================== WmoLiquid ================================== - WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): + WmoLiquid::WmoLiquid(uint32 width, uint32 height, Vector3 const& corner, uint32 type) : iTilesX(width), iTilesY(height), iCorner(corner), iType(type) { - iHeight = new float[(width+1)*(height+1)]; + iHeight = new float[(width + 1) * (height + 1)]; iFlags = new uint8[width*height]; } - WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr) + WmoLiquid::WmoLiquid(WmoLiquid const& other): iHeight(nullptr), iFlags(nullptr) { *this = other; // use assignment operator... } @@ -120,7 +120,7 @@ namespace VMAP delete[] iFlags; } - WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other) + WmoLiquid& WmoLiquid::operator=(WmoLiquid const& other) { if (this == &other) return *this; @@ -147,7 +147,7 @@ namespace VMAP return *this; } - bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const + bool WmoLiquid::GetLiquidHeight(Vector3 const& pos, float &liqHeight) const { float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; uint32 tx = uint32(tx_f); @@ -180,7 +180,7 @@ namespace VMAP 0 1 */ - const uint32 rowOffset = iTilesX + 1; + uint32 const rowOffset = iTilesX + 1; if (dx > dy) // case (a) { float sx = iHeight[tx+1 + ty * rowOffset] - iHeight[tx + ty * rowOffset]; @@ -260,7 +260,7 @@ namespace VMAP // ===================== GroupModel ================================== - GroupModel::GroupModel(const GroupModel &other): + GroupModel::GroupModel(GroupModel const& other): iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID), vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr) { @@ -331,7 +331,7 @@ namespace VMAP triangles.clear(); vertices.clear(); delete iLiquid; - iLiquid = NULL; + iLiquid = nullptr; if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false; if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false; @@ -367,12 +367,13 @@ namespace VMAP struct GModelRayCallback { - GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert): + GModelRayCallback(std::vector<MeshTriangle> const& 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 operator()(G3D::Ray const& ray, uint32 entry, float& distance, bool /*pStopAtFirstHit*/) { bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); - if (result) hit=true; + if (result) + hit = true; return hit; } std::vector<Vector3>::const_iterator vertices; @@ -380,7 +381,7 @@ namespace VMAP bool hit; }; - bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const + bool GroupModel::IntersectRay(G3D::Ray const& ray, float& distance, bool stopAtFirstHit) const { if (triangles.empty()) return false; @@ -390,7 +391,7 @@ namespace VMAP return callback.hit; } - bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const + bool GroupModel::IsInsideObject(Vector3 const& pos, Vector3 const& down, float& z_dist) const { if (triangles.empty() || !iBound.contains(pos)) return false; @@ -404,7 +405,7 @@ namespace VMAP return hit; } - bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const + bool GroupModel::GetLiquidLevel(Vector3 const& pos, float& liqHeight) const { if (iLiquid) return iLiquid->GetLiquidHeight(pos, liqHeight); @@ -427,7 +428,7 @@ namespace VMAP // ===================== WorldModel ================================== - void WorldModel::setGroupModels(std::vector<GroupModel> &models) + void WorldModel::setGroupModels(std::vector<GroupModel>& models) { groupModels.swap(models); groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1); @@ -435,18 +436,19 @@ namespace VMAP 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) + WModelRayCallBack(std::vector<GroupModel> const& mod): models(mod.begin()), hit(false) { } + bool operator()(G3D::Ray const& ray, uint32 entry, float& distance, bool pStopAtFirstHit) { bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit); - if (result) hit=true; + 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, ModelIgnoreFlags ignoreFlags) const + bool WorldModel::IntersectRay(G3D::Ray const& ray, float& distance, bool stopAtFirstHit, ModelIgnoreFlags ignoreFlags) const { // If the caller asked us to ignore certain objects we should check flags if ((ignoreFlags & ModelIgnoreFlags::M2) != ModelIgnoreFlags::Nothing) @@ -468,14 +470,14 @@ namespace VMAP class WModelAreaCallback { public: - WModelAreaCallback(const std::vector<GroupModel> &vals, const Vector3 &down): + WModelAreaCallback(std::vector<GroupModel> const& vals, Vector3 const& down) : prims(vals.begin()), hit(vals.end()), minVol(G3D::finf()), zDist(G3D::finf()), 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) + void operator()(Vector3 const& point, uint32 entry) { float group_Z; //float pVol = prims[entry].GetBound().volume(); @@ -492,7 +494,7 @@ namespace VMAP hit = prims + entry; } #ifdef VMAP_DEBUG - const GroupModel &gm = prims[entry]; + GroupModel const& 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); @@ -553,7 +555,7 @@ namespace VMAP if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false; // write group models - count=groupModels.size(); + count = groupModels.size(); if (count) { if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false; diff --git a/src/common/Collision/Models/WorldModel.h b/src/common/Collision/Models/WorldModel.h index df472708209..935598d3941 100644 --- a/src/common/Collision/Models/WorldModel.h +++ b/src/common/Collision/Models/WorldModel.h @@ -48,11 +48,11 @@ namespace VMAP class TC_COMMON_API WmoLiquid { public: - WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type); - WmoLiquid(const WmoLiquid &other); + WmoLiquid(uint32 width, uint32 height, G3D::Vector3 const& corner, uint32 type); + WmoLiquid(WmoLiquid const& other); ~WmoLiquid(); - WmoLiquid& operator=(const WmoLiquid &other); - bool GetLiquidHeight(const G3D::Vector3 &pos, float &liqHeight) const; + WmoLiquid& operator=(WmoLiquid const& other); + bool GetLiquidHeight(G3D::Vector3 const& pos, float& liqHeight) const; uint32 GetType() const { return iType; } float *GetHeightStorage() { return iHeight; } uint8 *GetFlagsStorage() { return iFlags; } @@ -61,7 +61,7 @@ namespace VMAP static bool readFromFile(FILE* rf, WmoLiquid* &liquid); void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const; private: - WmoLiquid() : iTilesX(0), iTilesY(0), iCorner(), iType(0), iHeight(NULL), iFlags(NULL) { } + WmoLiquid() : iTilesX(0), iTilesY(0), iCorner(), iType(0), iHeight(nullptr), iFlags(nullptr) { } uint32 iTilesX; //!< number of tiles in x direction, each uint32 iTilesY; G3D::Vector3 iCorner; //!< the lower corner @@ -74,15 +74,15 @@ namespace VMAP class TC_COMMON_API GroupModel { public: - GroupModel() : iBound(), iMogpFlags(0), iGroupWMOID(0), iLiquid(NULL) { } - GroupModel(const GroupModel &other); - GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound): - iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(NULL) { } + GroupModel() : iBound(), iMogpFlags(0), iGroupWMOID(0), iLiquid(nullptr) { } + GroupModel(GroupModel const& other); + GroupModel(uint32 mogpFlags, uint32 groupWMOID, G3D::AABox const& bound): + iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(nullptr) { } ~GroupModel() { delete iLiquid; } //! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry! void setMeshData(std::vector<G3D::Vector3> &vert, std::vector<MeshTriangle> &tri); - void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; } + void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = nullptr; } bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; bool IsInsideObject(const G3D::Vector3 &pos, const G3D::Vector3 &down, float &z_dist) const; bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const; diff --git a/src/common/Collision/RegularGrid.h b/src/common/Collision/RegularGrid.h index 4d045179290..0800276f065 100644 --- a/src/common/Collision/RegularGrid.h +++ b/src/common/Collision/RegularGrid.h @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + #ifndef _REGULAR_GRID_H #define _REGULAR_GRID_H @@ -86,15 +103,18 @@ public: struct Cell { int x, y; - bool operator == (const Cell& c2) const { return x == c2.x && y == c2.y;} + bool operator==(Cell const& c2) const + { + return x == c2.x && y == c2.y; + } static Cell ComputeCell(float fx, float fy) { - Cell c = { int(fx * (1.f/CELL_SIZE) + (CELL_NUMBER/2)), int(fy * (1.f/CELL_SIZE) + (CELL_NUMBER/2)) }; + Cell c = { int(fx * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)), int(fy * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)) }; return c; } - bool isValid() const { return x >= 0 && x < CELL_NUMBER && y >= 0 && y < CELL_NUMBER;} + bool isValid() const { return x >= 0 && x < CELL_NUMBER && y >= 0 && y < CELL_NUMBER; } }; Node& getGrid(int x, int y) diff --git a/src/common/Collision/VMapTools.h b/src/common/Collision/VMapTools.h deleted file mode 100644 index b73e524ce5a..00000000000 --- a/src/common/Collision/VMapTools.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> - * 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, see <http://www.gnu.org/licenses/>. - */ - -#ifndef _VMAPTOOLS_H -#define _VMAPTOOLS_H - -#include <G3D/CollisionDetection.h> -#include <G3D/AABox.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 TC_COMMON_API 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/common/Common.h b/src/common/Common.h index 1097249bcab..78b7df6a895 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -20,38 +20,9 @@ #define TRINITYCORE_COMMON_H #include "Define.h" - -#include <algorithm> -#include <array> -#include <exception> -#include <list> -#include <map> #include <memory> -#include <queue> -#include <set> -#include <sstream> #include <string> -#include <type_traits> -#include <unordered_map> -#include <unordered_set> -#include <vector> -#include <numeric> - -#include <cmath> -#include <cstdio> -#include <cstdlib> -#include <cstring> -#include <ctime> -#include <cerrno> -#include <csignal> - -#include <boost/optional.hpp> -#include <boost/utility/in_place_factory.hpp> -#include <boost/functional/hash.hpp> - -#include "Debugging/Errors.h" - -#include "Threading/LockedQueue.h" +#include <utility> #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS # include <ws2tcpip.h> @@ -61,7 +32,6 @@ # define BOOST_ASIO_HAS_MOVE # endif // !defined(BOOST_ASIO_HAS_MOVE) # endif // if TRINITY_COMPILER == TRINITY_COMPILER_INTEL - #else # include <sys/types.h> # include <sys/ioctl.h> @@ -69,12 +39,11 @@ # include <netinet/in.h> # include <unistd.h> # include <netdb.h> +# include <cstdlib> #endif #if TRINITY_COMPILER == TRINITY_COMPILER_MICROSOFT -#include <float.h> - #define snprintf _snprintf #define atoll _atoi64 #define vsnprintf _vsnprintf @@ -87,8 +56,6 @@ #endif -inline float finiteAlways(float f) { return std::isfinite(f) ? f : 0.0f; } - inline unsigned long atoul(char const* str) { return strtoul(str, nullptr, 10); } inline unsigned long long atoull(char const* str) { return strtoull(str, nullptr, 10); } @@ -114,7 +81,7 @@ enum AccountTypes SEC_CONSOLE = 4 // must be always last in list, accounts must have less security level always also }; -enum LocaleConstant +enum LocaleConstant : uint8 { LOCALE_enUS = 0, LOCALE_koKR = 1, @@ -136,11 +103,9 @@ enum LocaleConstant TC_COMMON_API extern char const* localeNames[TOTAL_LOCALES]; -TC_COMMON_API LocaleConstant GetLocaleByName(const std::string& name); - -typedef std::vector<std::string> StringVector; +TC_COMMON_API LocaleConstant GetLocaleByName(std::string const& name); -// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms) +// we always use stdlib std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms) #ifdef max #undef max #endif @@ -155,33 +120,26 @@ typedef std::vector<std::string> StringVector; #define MAX_QUERY_LEN 32*1024 -//! Optional helper class to wrap optional values within. -template <typename T> -using Optional = boost::optional<T>; - namespace Trinity { //! std::make_unique implementation (TODO: remove this once C++14 is supported) template<typename T, typename ...Args> - std::unique_ptr<T> make_unique(Args&& ...args) + inline auto make_unique(Args&& ...args) -> + typename std::enable_if<!std::is_array<T>::value, std::unique_ptr<T>>::type { return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); } -} -//! Hash implementation for std::pair to allow using pairs in unordered_set or as key for unordered_map -//! Individual types used in pair must be hashable by boost::hash -namespace std -{ - template<class K, class V> - struct hash<std::pair<K, V>> + template<typename T> + inline auto make_unique(std::size_t size) -> + typename std::enable_if<std::is_array<T>::value && std::extent<T>::value == 0, std::unique_ptr<T>>::type { - public: - size_t operator()(std::pair<K, V> const& key) const - { - return boost::hash_value(key); - } - }; + return std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]()); + } + + template<typename T, typename... Args> + inline auto make_unique(Args&&...) -> + typename std::enable_if<std::extent<T>::value != 0, void>::type = delete; } #endif diff --git a/src/common/Configuration/BuiltInConfig.h b/src/common/Configuration/BuiltInConfig.h index cc21555f4bf..a818407fb74 100644 --- a/src/common/Configuration/BuiltInConfig.h +++ b/src/common/Configuration/BuiltInConfig.h @@ -18,8 +18,8 @@ #ifndef BUILT_IN_CONFIG_H #define BUILT_IN_CONFIG_H -#include <string> #include "Define.h" +#include <string> /// Provides helper functions to access built-in values /// which can be overwritten in config diff --git a/src/common/Configuration/Config.cpp b/src/common/Configuration/Config.cpp index be05916e805..d4e56716501 100644 --- a/src/common/Configuration/Config.cpp +++ b/src/common/Configuration/Config.cpp @@ -16,14 +16,23 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <algorithm> -#include <mutex> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/ini_parser.hpp> #include "Config.h" #include "Log.h" +#include "Util.h" +#include <boost/property_tree/ini_parser.hpp> +#include <algorithm> +#include <memory> +#include <mutex> -using namespace boost::property_tree; +namespace bpt = boost::property_tree; + +namespace +{ + std::string _filename; + std::vector<std::string> _args; + bpt::ptree _config; + std::mutex _configLock; +} bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> args, std::string& error) @@ -35,8 +44,8 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> ar try { - ptree fullTree; - ini_parser::read_ini(file, fullTree); + bpt::ptree fullTree; + bpt::ini_parser::read_ini(file, fullTree); if (fullTree.empty()) { @@ -47,7 +56,7 @@ bool ConfigMgr::LoadInitial(std::string const& file, std::vector<std::string> ar // Since we're using only one section per config file, we skip the section and have direct property access _config = fullTree.begin()->second; } - catch (ini_parser::ini_parser_error const& e) + catch (bpt::ini_parser::ini_parser_error const& e) { if (e.line() == 0) error = e.message() + " (" + e.filename() + ")"; @@ -75,14 +84,14 @@ T ConfigMgr::GetValueDefault(std::string const& name, T def) const { try { - return _config.get<T>(ptree::path_type(name, '/')); + return _config.get<T>(bpt::ptree::path_type(name, '/')); } - catch (boost::property_tree::ptree_bad_path) + catch (bpt::ptree_bad_path) { TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %s\" to this file", name.c_str(), _filename.c_str(), name.c_str(), std::to_string(def).c_str()); } - catch (boost::property_tree::ptree_bad_data) + catch (bpt::ptree_bad_data) { TC_LOG_ERROR("server.loading", "Bad value defined for name %s in config file %s, going to use %s instead", name.c_str(), _filename.c_str(), std::to_string(def).c_str()); @@ -96,14 +105,14 @@ std::string ConfigMgr::GetValueDefault<std::string>(std::string const& name, std { try { - return _config.get<std::string>(ptree::path_type(name, '/')); + return _config.get<std::string>(bpt::ptree::path_type(name, '/')); } - catch (boost::property_tree::ptree_bad_path) + catch (bpt::ptree_bad_path) { TC_LOG_WARN("server.loading", "Missing name %s in config file %s, add \"%s = %s\" to this file", name.c_str(), _filename.c_str(), name.c_str(), def.c_str()); } - catch (boost::property_tree::ptree_bad_data) + catch (bpt::ptree_bad_data) { TC_LOG_ERROR("server.loading", "Bad value defined for name %s in config file %s, going to use %s instead", name.c_str(), _filename.c_str(), def.c_str()); @@ -123,7 +132,7 @@ bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) const { std::string val = GetValueDefault(name, std::string(def ? "1" : "0")); val.erase(std::remove(val.begin(), val.end(), '"'), val.end()); - return (val == "1" || val == "true" || val == "TRUE" || val == "yes" || val == "YES"); + return StringToBool(val); } int ConfigMgr::GetIntDefault(std::string const& name, int def) const @@ -142,13 +151,18 @@ std::string const& ConfigMgr::GetFilename() return _filename; } -std::list<std::string> ConfigMgr::GetKeysByString(std::string const& name) +std::vector<std::string> const& ConfigMgr::GetArguments() const +{ + return _args; +} + +std::vector<std::string> ConfigMgr::GetKeysByString(std::string const& name) { std::lock_guard<std::mutex> lock(_configLock); - std::list<std::string> keys; + std::vector<std::string> keys; - for (const ptree::value_type& child : _config) + for (bpt::ptree::value_type const& child : _config) if (child.first.compare(0, name.length(), name) == 0) keys.push_back(child.first); diff --git a/src/common/Configuration/Config.h b/src/common/Configuration/Config.h index 1e0f558b007..df82a4e6668 100644 --- a/src/common/Configuration/Config.h +++ b/src/common/Configuration/Config.h @@ -20,12 +20,8 @@ #define CONFIG_H #include "Define.h" - #include <string> -#include <list> #include <vector> -#include <mutex> -#include <boost/property_tree/ptree.hpp> class TC_COMMON_API ConfigMgr { @@ -36,8 +32,7 @@ class TC_COMMON_API ConfigMgr public: /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) - bool LoadInitial(std::string const& file, std::vector<std::string> args, - std::string& error); + bool LoadInitial(std::string const& file, std::vector<std::string> args, std::string& error); static ConfigMgr* instance(); @@ -49,15 +44,10 @@ public: float GetFloatDefault(std::string const& name, float def) const; std::string const& GetFilename(); - std::vector<std::string> const& GetArguments() const { return _args; } - std::list<std::string> GetKeysByString(std::string const& name); + std::vector<std::string> const& GetArguments() const; + std::vector<std::string> GetKeysByString(std::string const& name); private: - std::string _filename; - std::vector<std::string> _args; - boost::property_tree::ptree _config; - std::mutex _configLock; - template<class T> T GetValueDefault(std::string const& name, T def) const; }; diff --git a/src/common/Cryptography/ARC4.cpp b/src/common/Cryptography/ARC4.cpp index 1a568f99700..ee5837b5b42 100644 --- a/src/common/Cryptography/ARC4.cpp +++ b/src/common/Cryptography/ARC4.cpp @@ -21,16 +21,16 @@ ARC4::ARC4(uint32 len) : m_ctx() { EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), nullptr, nullptr, nullptr); EVP_CIPHER_CTX_set_key_length(&m_ctx, len); } ARC4::ARC4(uint8 *seed, uint32 len) : m_ctx() { EVP_CIPHER_CTX_init(&m_ctx); - EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), NULL, NULL, NULL); + EVP_EncryptInit_ex(&m_ctx, EVP_rc4(), nullptr, nullptr, nullptr); EVP_CIPHER_CTX_set_key_length(&m_ctx, len); - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); + EVP_EncryptInit_ex(&m_ctx, nullptr, nullptr, seed, nullptr); } ARC4::~ARC4() @@ -40,7 +40,7 @@ ARC4::~ARC4() void ARC4::Init(uint8 *seed) { - EVP_EncryptInit_ex(&m_ctx, NULL, NULL, seed, NULL); + EVP_EncryptInit_ex(&m_ctx, nullptr, nullptr, seed, nullptr); } void ARC4::UpdateData(int len, uint8 *data) diff --git a/src/common/Cryptography/BigNumber.cpp b/src/common/Cryptography/BigNumber.cpp index fe048104f85..c67e8c8fbbc 100644 --- a/src/common/Cryptography/BigNumber.cpp +++ b/src/common/Cryptography/BigNumber.cpp @@ -112,7 +112,7 @@ BigNumber BigNumber::operator/=(BigNumber const& bn) BN_CTX *bnctx; bnctx = BN_CTX_new(); - BN_div(_bn, NULL, _bn, bn._bn, bnctx); + BN_div(_bn, nullptr, _bn, bn._bn, bnctx); BN_CTX_free(bnctx); return *this; diff --git a/src/common/Cryptography/BigNumber.h b/src/common/Cryptography/BigNumber.h index c8ca5860933..8936ffffe53 100644 --- a/src/common/Cryptography/BigNumber.h +++ b/src/common/Cryptography/BigNumber.h @@ -19,8 +19,8 @@ #ifndef _AUTH_BIGNUMBER_H #define _AUTH_BIGNUMBER_H -#include <memory> #include "Define.h" +#include <memory> #include <string> struct bignum_st; diff --git a/src/common/Cryptography/HMACSHA1.cpp b/src/common/Cryptography/HMACSHA1.cpp index a10c012e896..c6936cacaef 100644 --- a/src/common/Cryptography/HMACSHA1.cpp +++ b/src/common/Cryptography/HMACSHA1.cpp @@ -18,12 +18,13 @@ #include "HMACSHA1.h" #include "BigNumber.h" -#include "Common.h" +#include "Errors.h" +#include <cstring> -HmacHash::HmacHash(uint32 len, uint8 *seed) +HmacHash::HmacHash(uint32 len, uint8* seed) { HMAC_CTX_init(&m_ctx); - HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), NULL); + HMAC_Init_ex(&m_ctx, seed, len, EVP_sha1(), nullptr); memset(m_digest, 0, sizeof(m_digest)); } @@ -32,12 +33,12 @@ HmacHash::~HmacHash() HMAC_CTX_cleanup(&m_ctx); } -void HmacHash::UpdateData(const std::string &str) +void HmacHash::UpdateData(std::string const& str) { HMAC_Update(&m_ctx, (uint8 const*)str.c_str(), str.length()); } -void HmacHash::UpdateData(const uint8* data, size_t len) +void HmacHash::UpdateData(uint8 const* data, size_t len) { HMAC_Update(&m_ctx, data, len); } diff --git a/src/common/Cryptography/HMACSHA1.h b/src/common/Cryptography/HMACSHA1.h index 19db12f82c0..972c9b02012 100644 --- a/src/common/Cryptography/HMACSHA1.h +++ b/src/common/Cryptography/HMACSHA1.h @@ -31,10 +31,10 @@ class BigNumber; class TC_COMMON_API HmacHash { public: - HmacHash(uint32 len, uint8 *seed); + HmacHash(uint32 len, uint8* seed); ~HmacHash(); - void UpdateData(const std::string &str); - void UpdateData(const uint8* data, size_t len); + void UpdateData(std::string const& str); + void UpdateData(uint8 const* data, size_t len); void Finalize(); uint8 *ComputeHash(BigNumber* bn); uint8 *GetDigest() { return (uint8*)m_digest; } diff --git a/src/common/Cryptography/OpenSSLCrypto.cpp b/src/common/Cryptography/OpenSSLCrypto.cpp index 7a97cc2375e..3f7bdef9fce 100644 --- a/src/common/Cryptography/OpenSSLCrypto.cpp +++ b/src/common/Cryptography/OpenSSLCrypto.cpp @@ -23,7 +23,7 @@ std::vector<std::mutex*> cryptoLocks; -static void lockingCallback(int mode, int type, const char* /*file*/, int /*line*/) +static void lockingCallback(int mode, int type, char const* /*file*/, int /*line*/) { if (mode & CRYPTO_LOCK) cryptoLocks[type]->lock(); @@ -49,8 +49,8 @@ void OpenSSLCrypto::threadsSetup() void OpenSSLCrypto::threadsCleanup() { - CRYPTO_set_locking_callback(NULL); - CRYPTO_THREADID_set_callback(NULL); + CRYPTO_set_locking_callback(nullptr); + CRYPTO_THREADID_set_callback(nullptr); for(int i = 0 ; i < CRYPTO_num_locks(); ++i) { delete cryptoLocks[i]; diff --git a/src/common/DataStores/DBCFileLoader.cpp b/src/common/DataStores/DBCFileLoader.cpp new file mode 100644 index 00000000000..c1102c25d8c --- /dev/null +++ b/src/common/DataStores/DBCFileLoader.cpp @@ -0,0 +1,316 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * 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, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "DBCFileLoader.h" +#include "Errors.h" + +DBCFileLoader::DBCFileLoader() : recordSize(0), recordCount(0), fieldCount(0), stringSize(0), fieldsOffset(nullptr), data(nullptr), stringTable(nullptr) { } + +bool DBCFileLoader::Load(char const* filename, char const* fmt) +{ + uint32 header; + if (data) + { + delete [] data; + data = nullptr; + } + + FILE* f = fopen(filename, "rb"); + if (!f) + return false; + + if (fread(&header, 4, 1, f) != 1) // Number of records + { + fclose(f); + return false; + } + + + EndianConvert(header); + + if (header != 0x43424457) //'WDBC' + { + fclose(f); + return false; + } + + if (fread(&recordCount, 4, 1, f) != 1) // Number of records + { + fclose(f); + return false; + } + + EndianConvert(recordCount); + + if (fread(&fieldCount, 4, 1, f) != 1) // Number of fields + { + fclose(f); + return false; + } + + EndianConvert(fieldCount); + + if (fread(&recordSize, 4, 1, f) != 1) // Size of a record + { + fclose(f); + return false; + } + + EndianConvert(recordSize); + + if (fread(&stringSize, 4, 1, f) != 1) // String size + { + fclose(f); + 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] += sizeof(uint8); + else // 4 byte fields (int32/float/strings) + fieldsOffset[i] += sizeof(uint32); + } + + data = new unsigned char[recordSize * recordCount + stringSize]; + stringTable = data + recordSize*recordCount; + + if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1) + { + fclose(f); + return false; + } + + fclose(f); + + return true; +} + +DBCFileLoader::~DBCFileLoader() +{ + delete[] data; + + delete[] fieldsOffset; +} + +DBCFileLoader::Record DBCFileLoader::getRecord(size_t id) +{ + assert(data); + return Record(*this, data + id * recordSize); +} + +uint32 DBCFileLoader::GetFormatRecordSize(char const* format, int32* index_pos) +{ + uint32 recordsize = 0; + int32 i = -1; + for (uint32 x = 0; format[x]; ++x) + { + switch (format[x]) + { + case FT_FLOAT: + recordsize += sizeof(float); + break; + case FT_INT: + recordsize += sizeof(uint32); + break; + case FT_STRING: + recordsize += sizeof(char*); + break; + case FT_SORT: + i = x; + break; + case FT_IND: + i = x; + recordsize += sizeof(uint32); + break; + case FT_BYTE: + recordsize += sizeof(uint8); + break; + case FT_NA: + case FT_NA_BYTE: + break; + case FT_LOGIC: + ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); + break; + default: + ASSERT(false && "Unknown field format character in DBCfmt.h"); + break; + } + } + + if (index_pos) + *index_pos = i; + + return recordsize; +} + +char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**& indexTable) +{ + /* + 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 nullptr; + + //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; + } + + ++maxi; + records = maxi; + indexTable = new ptr[maxi]; + memset(indexTable, 0, maxi * sizeof(ptr)); + } + else + { + records = recordCount; + indexTable = new ptr[recordCount]; + } + + char* dataTable = new char[recordCount * 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 += sizeof(float); + break; + case FT_IND: + case FT_INT: + *((uint32*)(&dataTable[offset])) = getRecord(y).getUInt(x); + offset += sizeof(uint32); + break; + case FT_BYTE: + *((uint8*)(&dataTable[offset])) = getRecord(y).getUInt8(x); + offset += sizeof(uint8); + break; + case FT_STRING: + *((char**)(&dataTable[offset])) = nullptr; // will replace non-empty or "" strings in AutoProduceStrings + offset += sizeof(char*); + break; + case FT_LOGIC: + ASSERT(false && "Attempted to load DBC files that do not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); + break; + case FT_NA: + case FT_NA_BYTE: + case FT_SORT: + break; + default: + ASSERT(false && "Unknown field format character in DBCfmt.h"); + break; + } + } + } + + return dataTable; +} + +char* DBCFileLoader::AutoProduceStrings(char const* format, char* dataTable) +{ + if (strlen(format) != fieldCount) + return nullptr; + + 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: + offset += sizeof(float); + break; + case FT_IND: + case FT_INT: + offset += sizeof(uint32); + break; + case FT_BYTE: + offset += sizeof(uint8); + 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 - (char const*)stringTable); + } + offset += sizeof(char*); + break; + } + case FT_LOGIC: + ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files."); + break; + case FT_NA: + case FT_NA_BYTE: + case FT_SORT: + break; + default: + ASSERT(false && "Unknown field format character in DBCfmt.h"); + break; + } + } + } + + return stringPool; +} diff --git a/src/common/DataStores/DBCFileLoader.h b/src/common/DataStores/DBCFileLoader.h new file mode 100644 index 00000000000..85cad0d9e7b --- /dev/null +++ b/src/common/DataStores/DBCFileLoader.h @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <http://www.trinitycore.org/> + * 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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef DBC_FILE_LOADER_H +#define DBC_FILE_LOADER_H + +#include "Define.h" +#include "Utilities/ByteConverter.h" +#include <cassert> + +enum DbcFieldFormat +{ + 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 TC_COMMON_API 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 != nullptr && id < fieldCount) ? fieldsOffset[id] : 0; } + bool IsLoaded() const { return data != nullptr; } + char* AutoProduceData(char const* fmt, uint32& count, char**& indexTable); + char* AutoProduceStrings(char const* fmt, char* dataTable); + static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = nullptr); + private: + + uint32 recordSize; + uint32 recordCount; + uint32 fieldCount; + uint32 stringSize; + uint32 *fieldsOffset; + unsigned char *data; + unsigned char *stringTable; + + DBCFileLoader(DBCFileLoader const& right) = delete; + DBCFileLoader& operator=(DBCFileLoader const& right) = delete; +}; +#endif diff --git a/src/common/Debugging/Errors.cpp b/src/common/Debugging/Errors.cpp index 2e67f3bf539..4b56f43b067 100644 --- a/src/common/Debugging/Errors.cpp +++ b/src/common/Debugging/Errors.cpp @@ -40,7 +40,7 @@ void Assert(char const* file, int line, char const* function, char const* messag { fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message); - *((volatile int*)NULL) = 0; + *((volatile int*)nullptr) = 0; exit(1); } @@ -55,7 +55,7 @@ void Assert(char const* file, int line, char const* function, char const* messag fflush(stderr); va_end(args); - *((volatile int*)NULL) = 0; + *((volatile int*)nullptr) = 0; exit(1); } @@ -70,7 +70,7 @@ void Fatal(char const* file, int line, char const* function, char const* message fflush(stderr); std::this_thread::sleep_for(std::chrono::seconds(10)); - *((volatile int*)NULL) = 0; + *((volatile int*)nullptr) = 0; exit(1); } @@ -78,7 +78,7 @@ void Error(char const* file, int line, char const* function, char const* message { fprintf(stderr, "\n%s:%i in %s ERROR:\n %s\n", file, line, function, message); - *((volatile int*)NULL) = 0; + *((volatile int*)nullptr) = 0; exit(1); } @@ -92,14 +92,14 @@ void Abort(char const* file, int line, char const* function) { fprintf(stderr, "\n%s:%i in %s ABORTED.\n", file, line, function); - *((volatile int*)NULL) = 0; + *((volatile int*)nullptr) = 0; exit(1); } void AbortHandler(int /*sigval*/) { // nothing useful to log here, no way to pass args - *((volatile int*)NULL) = 0; + *((volatile int*)nullptr) = 0; exit(1); } diff --git a/src/common/Debugging/WheatyExceptionReport.cpp b/src/common/Debugging/WheatyExceptionReport.cpp index 5585dd25c13..5b6e9e76ebc 100644 --- a/src/common/Debugging/WheatyExceptionReport.cpp +++ b/src/common/Debugging/WheatyExceptionReport.cpp @@ -6,7 +6,9 @@ #include "CompilerDefs.h" #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS && !defined(__MINGW32__) +#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN +#endif #pragma warning(disable:4996) #pragma warning(disable:4312) #pragma warning(disable:4311) @@ -21,6 +23,7 @@ #include "Common.h" #include "GitRevision.h" +#include <algorithm> #define CrashFolder _T("Crashes") #pragma comment(linker, "/DEFAULTLIB:dbghelp.lib") @@ -915,7 +918,7 @@ DWORD64 modBase, DWORD dwTypeIndex, DWORD_PTR offset, bool & bHandled, -const char* Name, +char const* Name, char* /*suffix*/, bool newSymbol, bool logChildren) diff --git a/src/common/Debugging/WheatyExceptionReport.h b/src/common/Debugging/WheatyExceptionReport.h index 91c2ae93179..2fee14708f2 100644 --- a/src/common/Debugging/WheatyExceptionReport.h +++ b/src/common/Debugging/WheatyExceptionReport.h @@ -56,7 +56,7 @@ enum DataKind // Stolen from CVCONS DataIsConstant }; -const char* const rgBaseType[] = +char const* const rgBaseType[] = { "<user defined>", // btNoType = 0, "void", // btVoid = 1, @@ -100,7 +100,7 @@ struct SymbolPair _offset = offset; } - bool operator<(const SymbolPair& other) const + bool operator<(SymbolPair const& other) const { return _offset < other._offset || (_offset == other._offset && _type < other._type); @@ -174,7 +174,7 @@ class WheatyExceptionReport static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *); - static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool &, const char*, char*, bool, bool); + static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool &, char const*, char*, bool, bool); static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0); diff --git a/src/common/Define.h b/src/common/Define.h index e34ee8bfa18..2e991610d45 100644 --- a/src/common/Define.h +++ b/src/common/Define.h @@ -56,7 +56,7 @@ #endif #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS -# define TRINITY_PATH_MAX MAX_PATH +# define TRINITY_PATH_MAX 260 # define _USE_MATH_DEFINES # ifndef DECLSPEC_NORETURN # define DECLSPEC_NORETURN __declspec(noreturn) diff --git a/src/common/GitRevision.cpp b/src/common/GitRevision.cpp index 3e578cf1ee8..86362955792 100644 --- a/src/common/GitRevision.cpp +++ b/src/common/GitRevision.cpp @@ -1,3 +1,20 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + #include "GitRevision.h" #include "revision_data.h" diff --git a/src/common/GitRevision.h b/src/common/GitRevision.h index 9a31b3f1a66..d6a290ad0d5 100644 --- a/src/common/GitRevision.h +++ b/src/common/GitRevision.h @@ -18,7 +18,6 @@ #ifndef __GITREVISION_H__ #define __GITREVISION_H__ -#include <string> #include "Define.h" namespace GitRevision diff --git a/src/common/Logging/Appender.cpp b/src/common/Logging/Appender.cpp index ec88d5fd4c1..616e3a2137f 100644 --- a/src/common/Logging/Appender.cpp +++ b/src/common/Logging/Appender.cpp @@ -16,27 +16,11 @@ */ #include "Appender.h" -#include "Common.h" -#include "Util.h" +#include "LogMessage.h" #include "StringFormat.h" -#include <utility> #include <sstream> -std::string LogMessage::getTimeStr(time_t time) -{ - tm aTm; - localtime_r(&time, &aTm); - 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); -} - -std::string LogMessage::getTimeStr() -{ - return getTimeStr(mtime); -} - Appender::Appender(uint8 _id, std::string const& _name, LogLevel _level /* = LOG_LEVEL_DISABLED */, AppenderFlags _flags /* = APPENDER_FLAGS_NONE */): id(_id), name(_name), level(_level), flags(_flags) { } @@ -87,7 +71,7 @@ void Appender::write(LogMessage* message) _write(message); } -const char* Appender::getLogLevelString(LogLevel level) +char const* Appender::getLogLevelString(LogLevel level) { switch (level) { diff --git a/src/common/Logging/Appender.h b/src/common/Logging/Appender.h index 6a9932b7935..fd17ad71fdd 100644 --- a/src/common/Logging/Appender.h +++ b/src/common/Logging/Appender.h @@ -18,72 +18,13 @@ #ifndef APPENDER_H #define APPENDER_H -#include <unordered_map> +#include "Define.h" +#include "LogCommon.h" #include <stdexcept> #include <string> -#include <time.h> -#include <type_traits> #include <vector> -#include <utility> -#include "Define.h" - -// Values assigned have their equivalent in enum ACE_Log_Priority -enum LogLevel -{ - LOG_LEVEL_DISABLED = 0, - LOG_LEVEL_TRACE = 1, - LOG_LEVEL_DEBUG = 2, - LOG_LEVEL_INFO = 3, - LOG_LEVEL_WARN = 4, - LOG_LEVEL_ERROR = 5, - LOG_LEVEL_FATAL = 6 -}; - -const uint8 MaxLogLevels = 6; - -enum AppenderType : uint8 -{ - APPENDER_NONE, - APPENDER_CONSOLE, - APPENDER_FILE, - APPENDER_DB -}; - -enum AppenderFlags -{ - APPENDER_FLAGS_NONE = 0x00, - APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01, - APPENDER_FLAGS_PREFIX_LOGLEVEL = 0x02, - APPENDER_FLAGS_PREFIX_LOGFILTERTYPE = 0x04, - APPENDER_FLAGS_USE_TIMESTAMP = 0x08, // only used by FileAppender - APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10 // only used by FileAppender -}; - -struct TC_COMMON_API LogMessage -{ - LogMessage(LogLevel _level, std::string const& _type, std::string&& _text) - : level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(NULL)) - { } - LogMessage(LogMessage const& /*other*/) = delete; - LogMessage& operator=(LogMessage const& /*other*/) = delete; - - static std::string getTimeStr(time_t time); - std::string getTimeStr(); - - LogLevel const level; - std::string const type; - std::string const text; - std::string prefix; - std::string param1; - time_t mtime; - - ///@ Returns size of the log message content in bytes - uint32 Size() const - { - return static_cast<uint32>(prefix.size() + text.size()); - } -}; +struct LogMessage; class TC_COMMON_API Appender { @@ -99,7 +40,7 @@ class TC_COMMON_API Appender void setLogLevel(LogLevel); void write(LogMessage* message); - static const char* getLogLevelString(LogLevel level); + static char const* getLogLevelString(LogLevel level); virtual void setRealmId(uint32 /*realmId*/) { } private: @@ -111,18 +52,6 @@ class TC_COMMON_API Appender AppenderFlags flags; }; -typedef std::unordered_map<uint8, Appender*> AppenderMap; - -typedef std::vector<char const*> ExtraAppenderArgs; -typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); -typedef std::unordered_map<uint8, AppenderCreatorFn> AppenderCreatorMap; - -template<class AppenderImpl> -Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) -{ - return new AppenderImpl(id, name, level, flags, std::forward<ExtraAppenderArgs>(extraArgs)); -} - class TC_COMMON_API InvalidAppenderArgsException : public std::length_error { public: diff --git a/src/common/Logging/AppenderConsole.cpp b/src/common/Logging/AppenderConsole.cpp index 3378c185cc5..7ae1987162e 100644 --- a/src/common/Logging/AppenderConsole.cpp +++ b/src/common/Logging/AppenderConsole.cpp @@ -15,20 +15,19 @@ * with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include <sstream> - #include "AppenderConsole.h" -#include "Config.h" +#include "LogMessage.h" #include "Util.h" +#include <sstream> #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS #include <Windows.h> #endif -AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) +AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) : Appender(id, name, level, flags), _colored(false) { - for (uint8 i = 0; i < MaxLogLevels; ++i) + for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) _colors[i] = ColorTypes(MaxColors); if (!extraArgs.empty()) @@ -43,11 +42,11 @@ void AppenderConsole::InitColors(std::string const& str) return; } - int color[MaxLogLevels]; + int color[NUM_ENABLED_LOG_LEVELS]; std::istringstream ss(str); - for (uint8 i = 0; i < MaxLogLevels; ++i) + for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) { ss >> color[i]; @@ -58,7 +57,7 @@ void AppenderConsole::InitColors(std::string const& str) return; } - for (uint8 i = 0; i < MaxLogLevels; ++i) + for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) _colors[i] = ColorTypes(color[i]); _colored = true; diff --git a/src/common/Logging/AppenderConsole.h b/src/common/Logging/AppenderConsole.h index c56a745bfba..9fd57c99f8a 100644 --- a/src/common/Logging/AppenderConsole.h +++ b/src/common/Logging/AppenderConsole.h @@ -18,7 +18,6 @@ #ifndef APPENDERCONSOLE_H #define APPENDERCONSOLE_H -#include <string> #include "Appender.h" enum ColorTypes @@ -47,7 +46,7 @@ class TC_COMMON_API AppenderConsole : public Appender public: typedef std::integral_constant<AppenderType, APPENDER_CONSOLE>::type TypeIndex; - AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); + AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs); void InitColors(const std::string& init_str); AppenderType getType() const override { return TypeIndex::value; } @@ -56,7 +55,7 @@ class TC_COMMON_API AppenderConsole : public Appender void ResetColor(bool stdout_stream); void _write(LogMessage const* message) override; bool _colored; - ColorTypes _colors[MaxLogLevels]; + ColorTypes _colors[NUM_ENABLED_LOG_LEVELS]; }; #endif diff --git a/src/common/Logging/AppenderFile.cpp b/src/common/Logging/AppenderFile.cpp index 6c68406667d..d2109936e65 100644 --- a/src/common/Logging/AppenderFile.cpp +++ b/src/common/Logging/AppenderFile.cpp @@ -16,17 +16,13 @@ */ #include "AppenderFile.h" -#include "Common.h" -#include "StringFormat.h" #include "Log.h" +#include "LogMessage.h" +#include <algorithm> -#if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS -# include <Windows.h> -#endif - -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) : +AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) : Appender(id, name, level, flags), - logfile(NULL), + logfile(nullptr), _logDir(sLog->GetLogsDir()), _maxFileSize(0), _fileSize(0) @@ -101,7 +97,7 @@ FILE* AppenderFile::OpenFile(std::string const& filename, std::string const& mod CloseFile(); std::string newName(fullName); newName.push_back('.'); - newName.append(LogMessage::getTimeStr(time(NULL))); + newName.append(LogMessage::getTimeStr(time(nullptr))); std::replace(newName.begin(), newName.end(), ':', '-'); rename(fullName.c_str(), newName.c_str()); // no error handling... if we couldn't make a backup, just ignore } @@ -112,7 +108,7 @@ FILE* AppenderFile::OpenFile(std::string const& filename, std::string const& mod return ret; } - return NULL; + return nullptr; } void AppenderFile::CloseFile() @@ -120,6 +116,6 @@ void AppenderFile::CloseFile() if (logfile) { fclose(logfile); - logfile = NULL; + logfile = nullptr; } } diff --git a/src/common/Logging/AppenderFile.h b/src/common/Logging/AppenderFile.h index aeb1c2d8001..8e728cbdf4d 100644 --- a/src/common/Logging/AppenderFile.h +++ b/src/common/Logging/AppenderFile.h @@ -18,15 +18,15 @@ #ifndef APPENDERFILE_H #define APPENDERFILE_H -#include <atomic> #include "Appender.h" +#include <atomic> class TC_COMMON_API AppenderFile : public Appender { public: typedef std::integral_constant<AppenderType, APPENDER_FILE>::type TypeIndex; - AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs); + AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs); ~AppenderFile(); FILE* OpenFile(std::string const& name, std::string const& mode, bool backup); AppenderType getType() const override { return TypeIndex::value; } diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index a2e3ee99471..d0ba17b52a7 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -17,14 +17,17 @@ */ #include "Log.h" -#include "Common.h" -#include "Config.h" -#include "Util.h" #include "AppenderConsole.h" #include "AppenderFile.h" +#include "AsioHacksImpl.h" +#include "Common.h" +#include "Config.h" +#include "Errors.h" +#include "Logger.h" +#include "LogMessage.h" #include "LogOperation.h" - -#include <cstdio> +#include "Util.h" +#include <chrono> #include <sstream> Log::Log() : AppenderId(0), lowestLogLevel(LOG_LEVEL_FATAL), _ioService(nullptr), _strand(nullptr) @@ -45,25 +48,13 @@ uint8 Log::NextAppenderId() return AppenderId++; } -int32 GetConfigIntDefault(std::string base, const char* name, int32 value) -{ - base.append(name); - return sConfigMgr->GetIntDefault(base.c_str(), value); -} - -std::string GetConfigStringDefault(std::string base, const char* name, const char* value) -{ - base.append(name); - return sConfigMgr->GetStringDefault(base.c_str(), value); -} - Appender* Log::GetAppenderByName(std::string const& name) { - AppenderMap::iterator it = appenders.begin(); + auto it = appenders.begin(); while (it != appenders.end() && it->second && it->second->getName() != name) ++it; - return it == appenders.end() ? NULL : it->second; + return it == appenders.end() ? nullptr : it->second.get(); } void Log::CreateAppenderFromConfig(std::string const& appenderName) @@ -71,13 +62,13 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName) if (appenderName.empty()) return; - // Format=type, level, flags, optional1, optional2 + // Format = type, level, flags, optional1, optional2 // if type = File. optional1 = file and option2 = mode // if type = Console. optional1 = Color std::string options = sConfigMgr->GetStringDefault(appenderName.c_str(), ""); Tokenizer tokens(options, ','); - Tokenizer::const_iterator iter = tokens.begin(); + auto iter = tokens.begin(); size_t size = tokens.size(); std::string name = appenderName.substr(9); @@ -110,8 +101,8 @@ void Log::CreateAppenderFromConfig(std::string const& appenderName) try { - Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, ExtraAppenderArgs(iter, tokens.end())); - appenders[appender->getId()] = appender; + Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, std::vector<char const*>(iter, tokens.end())); + appenders[appender->getId()].reset(appender); } catch (InvalidAppenderArgsException const& iaae) { @@ -145,8 +136,8 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) return; } - Logger& logger = loggers[name]; - if (!logger.getName().empty()) + std::unique_ptr<Logger>& logger = loggers[name]; + if (logger) { fprintf(stderr, "Error while configuring Logger %s. Already defined\n", name.c_str()); return; @@ -162,7 +153,7 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) if (level < lowestLogLevel) lowestLogLevel = level; - logger.Create(name, level); + logger = Trinity::make_unique<Logger>(name, level); //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level); std::istringstream ss(*iter); @@ -173,7 +164,7 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) { if (Appender* appender = GetAppenderByName(str)) { - logger.addAppender(appender->getId(), appender); + logger->addAppender(appender->getId(), appender); //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str()); } else @@ -184,24 +175,16 @@ void Log::CreateLoggerFromConfig(std::string const& appenderName) void Log::ReadAppendersFromConfig() { - std::list<std::string> keys = sConfigMgr->GetKeysByString("Appender."); - - while (!keys.empty()) - { - CreateAppenderFromConfig(keys.front()); - keys.pop_front(); - } + std::vector<std::string> keys = sConfigMgr->GetKeysByString("Appender."); + for (std::string const& appenderName : keys) + CreateAppenderFromConfig(appenderName); } void Log::ReadLoggersFromConfig() { - std::list<std::string> keys = sConfigMgr->GetKeysByString("Logger."); - - while (!keys.empty()) - { - CreateLoggerFromConfig(keys.front()); - keys.pop_front(); - } + std::vector<std::string> keys = sConfigMgr->GetKeysByString("Logger."); + for (std::string const& loggerName : keys) + CreateLoggerFromConfig(loggerName); // Bad config configuration, creating default config if (loggers.find(LOGGER_ROOT) == loggers.end()) @@ -211,26 +194,43 @@ void Log::ReadLoggersFromConfig() Close(); // Clean any Logger or Appender created - AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs()); - appenders[appender->getId()] = appender; + AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, std::vector<char const*>()); + appenders[appender->getId()].reset(appender); - Logger& rootLogger = loggers[LOGGER_ROOT]; - rootLogger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR); - rootLogger.addAppender(appender->getId(), appender); + Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_ERROR); + rootLogger->addAppender(appender->getId(), appender); + loggers[LOGGER_ROOT].reset(rootLogger); - Logger& serverLogger = loggers["server"]; - serverLogger.Create("server", LOG_LEVEL_INFO); - serverLogger.addAppender(appender->getId(), appender); + Logger* serverLogger = new Logger("server", LOG_LEVEL_INFO); + serverLogger->addAppender(appender->getId(), appender); + loggers["server"].reset(serverLogger); } } +void Log::RegisterAppender(uint8 index, AppenderCreatorFn appenderCreateFn) +{ + auto itr = appenderFactory.find(index); + ASSERT(itr == appenderFactory.end()); + appenderFactory[index] = appenderCreateFn; +} + +void Log::outMessage(std::string const& filter, LogLevel level, std::string&& message) +{ + write(Trinity::make_unique<LogMessage>(level, filter, std::move(message))); +} + +void Log::outCommand(std::string&& message, std::string&& param1) +{ + write(Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm", std::move(message), std::move(param1))); +} + void Log::write(std::unique_ptr<LogMessage>&& msg) const { Logger const* logger = GetLoggerByType(msg->type); if (_ioService) { - auto logOperation = std::shared_ptr<LogOperation>(new LogOperation(logger, std::move(msg))); + auto logOperation = std::make_shared<LogOperation>(logger, std::move(msg)); _ioService->post(_strand->wrap([logOperation](){ logOperation->call(); })); } @@ -238,6 +238,23 @@ void Log::write(std::unique_ptr<LogMessage>&& msg) const logger->write(msg.get()); } +Logger const* Log::GetLoggerByType(std::string const& type) const +{ + auto it = loggers.find(type); + if (it != loggers.end()) + return it->second.get(); + + if (type == LOGGER_ROOT) + return nullptr; + + std::string parentLogger = LOGGER_ROOT; + size_t found = type.find_last_of('.'); + if (found != std::string::npos) + parentLogger = type.substr(0, found); + + return GetLoggerByType(parentLogger); +} + std::string Log::GetTimestampStr() { time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); @@ -255,7 +272,7 @@ std::string Log::GetTimestampStr() aTm.tm_year + 1900, aTm.tm_mon + 1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); } -bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLogger /* = true */) +bool Log::SetLogLevel(std::string const& name, char const* newLevelc, bool isLogger /* = true */) { LogLevel newLevel = LogLevel(atoi(newLevelc)); if (newLevel < 0) @@ -263,14 +280,14 @@ bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLog if (isLogger) { - LoggerMap::iterator it = loggers.begin(); - while (it != loggers.end() && it->second.getName() != name) + auto it = loggers.begin(); + while (it != loggers.end() && it->second->getName() != name) ++it; if (it == loggers.end()) return false; - it->second.setLogLevel(newLevel); + it->second->setLogLevel(newLevel); if (newLevel != LOG_LEVEL_DISABLED && newLevel < lowestLogLevel) lowestLogLevel = newLevel; @@ -307,19 +324,34 @@ void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const void Log::SetRealmId(uint32 id) { - for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) + for (auto it = appenders.begin(); it != appenders.end(); ++it) it->second->setRealmId(id); } void Log::Close() { loggers.clear(); - for (AppenderMap::iterator it = appenders.begin(); it != appenders.end(); ++it) - delete it->second; - appenders.clear(); } +bool Log::ShouldLog(std::string const& type, LogLevel level) const +{ + // TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should + // Speed up in cases where requesting "Type.sub1.sub2" but only configured + // Logger "Type" + + // Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers + if (level < lowestLogLevel) + return false; + + Logger const* logger = GetLoggerByType(type); + if (!logger) + return false; + + LogLevel logLevel = logger->getLogLevel(); + return logLevel != LOG_LEVEL_DISABLED && logLevel <= level; +} + Log* Log::instance() { static Log instance; @@ -331,7 +363,7 @@ void Log::Initialize(boost::asio::io_service* ioService) if (ioService) { _ioService = ioService; - _strand = new boost::asio::strand(*ioService); + _strand = new Trinity::AsioStrand(*ioService); } LoadFromConfig(); diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index fa67a8ea648..5065d8bb5b8 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -20,20 +20,36 @@ #define TRINITYCORE_LOG_H #include "Define.h" -#include "Appender.h" -#include "Logger.h" +#include "AsioHacksFwd.h" +#include "LogCommon.h" #include "StringFormat.h" -#include "Common.h" -#include <boost/asio/io_service.hpp> -#include <boost/asio/strand.hpp> -#include <stdarg.h> -#include <unordered_map> -#include <string> #include <memory> +#include <unordered_map> +#include <vector> + +class Appender; +class Logger; +struct LogMessage; + +namespace boost +{ + namespace asio + { + class io_service; + } +} #define LOGGER_ROOT "root" +typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs); + +template <class AppenderImpl> +Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs) +{ + return new AppenderImpl(id, name, level, flags, std::forward<std::vector<char const*>>(extraArgs)); +} + class TC_COMMON_API Log { typedef std::unordered_map<std::string, Logger> LoggerMap; @@ -41,9 +57,12 @@ class TC_COMMON_API Log private: Log(); ~Log(); + Log(Log const&) = delete; + Log(Log&&) = delete; + Log& operator=(Log const&) = delete; + Log& operator=(Log&&) = delete; public: - static Log* instance(); void Initialize(boost::asio::io_service* ioService); @@ -56,8 +75,7 @@ class TC_COMMON_API Log template<typename Format, typename... Args> inline void outMessage(std::string const& filter, LogLevel const level, Format&& fmt, Args&&... args) { - write(Trinity::make_unique<LogMessage>(level, filter, - Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...))); + outMessage(filter, level, Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); } template<typename Format, typename... Args> @@ -66,13 +84,7 @@ class TC_COMMON_API Log if (!ShouldLog("commands.gm", LOG_LEVEL_INFO)) return; - std::unique_ptr<LogMessage> msg = - Trinity::make_unique<LogMessage>(LOG_LEVEL_INFO, "commands.gm", - Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...)); - - msg->param1 = std::to_string(account); - - write(std::move(msg)); + outCommand(Trinity::StringFormat(std::forward<Format>(fmt), std::forward<Args>(args)...), std::to_string(account)); } void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name); @@ -83,9 +95,7 @@ class TC_COMMON_API Log void RegisterAppender() { using Index = typename AppenderImpl::TypeIndex; - auto itr = appenderFactory.find(Index::value); - ASSERT(itr == appenderFactory.end()); - appenderFactory[Index::value] = &CreateAppender<AppenderImpl>; + RegisterAppender(Index::value, &CreateAppender<AppenderImpl>); } std::string const& GetLogsDir() const { return m_logsDir; } @@ -102,10 +112,13 @@ class TC_COMMON_API Log void CreateLoggerFromConfig(std::string const& name); void ReadAppendersFromConfig(); void ReadLoggersFromConfig(); + void RegisterAppender(uint8 index, AppenderCreatorFn appenderCreateFn); + void outMessage(std::string const& filter, LogLevel level, std::string&& message); + void outCommand(std::string&& message, std::string&& param1); - AppenderCreatorMap appenderFactory; - AppenderMap appenders; - LoggerMap loggers; + std::unordered_map<uint8, AppenderCreatorFn> appenderFactory; + std::unordered_map<uint8, std::unique_ptr<Appender>> appenders; + std::unordered_map<std::string, std::unique_ptr<Logger>> loggers; uint8 AppenderId; LogLevel lowestLogLevel; @@ -113,44 +126,9 @@ class TC_COMMON_API Log std::string m_logsTimestamp; boost::asio::io_service* _ioService; - boost::asio::strand* _strand; + Trinity::AsioStrand* _strand; }; -inline Logger const* Log::GetLoggerByType(std::string const& type) const -{ - LoggerMap::const_iterator it = loggers.find(type); - if (it != loggers.end()) - return &(it->second); - - if (type == LOGGER_ROOT) - return NULL; - - std::string parentLogger = LOGGER_ROOT; - size_t found = type.find_last_of('.'); - if (found != std::string::npos) - parentLogger = type.substr(0,found); - - return GetLoggerByType(parentLogger); -} - -inline bool Log::ShouldLog(std::string const& type, LogLevel level) const -{ - // TODO: Use cache to store "Type.sub1.sub2": "Type" equivalence, should - // Speed up in cases where requesting "Type.sub1.sub2" but only configured - // Logger "Type" - - // Don't even look for a logger if the LogLevel is lower than lowest log levels across all loggers - if (level < lowestLogLevel) - return false; - - Logger const* logger = GetLoggerByType(type); - if (!logger) - return false; - - LogLevel logLevel = logger->getLogLevel(); - return logLevel != LOG_LEVEL_DISABLED && logLevel <= level; -} - #define sLog Log::instance() #define LOG_EXCEPTION_FREE(filterType__, level__, ...) \ @@ -167,7 +145,7 @@ inline bool Log::ShouldLog(std::string const& type, LogLevel level) const } #if TRINITY_PLATFORM != TRINITY_PLATFORM_WINDOWS -void check_args(const char*, ...) ATTR_PRINTF(1, 2); +void check_args(char const*, ...) ATTR_PRINTF(1, 2); void check_args(std::string const&, ...); // This will catch format errors on build time diff --git a/src/common/Logging/LogCommon.h b/src/common/Logging/LogCommon.h new file mode 100644 index 00000000000..50ab6131a73 --- /dev/null +++ b/src/common/Logging/LogCommon.h @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LogCommon_h__ +#define LogCommon_h__ + +enum LogLevel +{ + LOG_LEVEL_DISABLED = 0, + LOG_LEVEL_TRACE = 1, + LOG_LEVEL_DEBUG = 2, + LOG_LEVEL_INFO = 3, + LOG_LEVEL_WARN = 4, + LOG_LEVEL_ERROR = 5, + LOG_LEVEL_FATAL = 6, + + NUM_ENABLED_LOG_LEVELS = 6 +}; + +enum AppenderType : uint8 +{ + APPENDER_NONE, + APPENDER_CONSOLE, + APPENDER_FILE, + APPENDER_DB +}; + +enum AppenderFlags +{ + APPENDER_FLAGS_NONE = 0x00, + APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01, + APPENDER_FLAGS_PREFIX_LOGLEVEL = 0x02, + APPENDER_FLAGS_PREFIX_LOGFILTERTYPE = 0x04, + APPENDER_FLAGS_USE_TIMESTAMP = 0x08, + APPENDER_FLAGS_MAKE_FILE_BACKUP = 0x10 +}; + +#endif // LogCommon_h__ diff --git a/src/common/Logging/LogMessage.cpp b/src/common/Logging/LogMessage.cpp new file mode 100644 index 00000000000..d907fbc12a2 --- /dev/null +++ b/src/common/Logging/LogMessage.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#include "LogMessage.h" +#include "Util.h" + +LogMessage::LogMessage(LogLevel _level, std::string const& _type, std::string&& _text) + : level(_level), type(_type), text(std::forward<std::string>(_text)), mtime(time(nullptr)) +{ +} + +LogMessage::LogMessage(LogLevel _level, std::string const& _type, std::string&& _text, std::string&& _param1) + : level(_level), type(_type), text(std::forward<std::string>(_text)), param1(std::forward<std::string>(_param1)), mtime(time(nullptr)) +{ +} + +std::string LogMessage::getTimeStr(time_t time) +{ + tm aTm; + localtime_r(&time, &aTm); + 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); +} + +std::string LogMessage::getTimeStr() const +{ + return getTimeStr(mtime); +} diff --git a/src/common/Logging/LogMessage.h b/src/common/Logging/LogMessage.h new file mode 100644 index 00000000000..ed9c51cec2f --- /dev/null +++ b/src/common/Logging/LogMessage.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef LogMessage_h__ +#define LogMessage_h__ + +#include "Define.h" +#include "LogCommon.h" +#include <string> +#include <ctime> + +struct TC_COMMON_API LogMessage +{ + LogMessage(LogLevel _level, std::string const& _type, std::string&& _text); + LogMessage(LogLevel _level, std::string const& _type, std::string&& _text, std::string&& _param1); + + LogMessage(LogMessage const& /*other*/) = delete; + LogMessage& operator=(LogMessage const& /*other*/) = delete; + + static std::string getTimeStr(time_t time); + std::string getTimeStr() const; + + LogLevel const level; + std::string const type; + std::string const text; + std::string prefix; + std::string param1; + time_t mtime; + + ///@ Returns size of the log message content in bytes + uint32 Size() const + { + return static_cast<uint32>(prefix.size() + text.size()); + } +}; + +#endif // LogMessage_h__ diff --git a/src/common/Logging/LogOperation.cpp b/src/common/Logging/LogOperation.cpp index 81bb98b9cce..c3a3711cc49 100644 --- a/src/common/Logging/LogOperation.cpp +++ b/src/common/Logging/LogOperation.cpp @@ -17,6 +17,15 @@ #include "LogOperation.h" #include "Logger.h" +#include "LogMessage.h" + +LogOperation::LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg)) +{ +} + +LogOperation::~LogOperation() +{ +} int LogOperation::call() { diff --git a/src/common/Logging/LogOperation.h b/src/common/Logging/LogOperation.h index a7230d1749d..ddf5ef1debc 100644 --- a/src/common/Logging/LogOperation.h +++ b/src/common/Logging/LogOperation.h @@ -18,8 +18,8 @@ #ifndef LOGOPERATION_H #define LOGOPERATION_H -#include <memory> #include "Define.h" +#include <memory> class Logger; struct LogMessage; @@ -27,11 +27,9 @@ struct LogMessage; class TC_COMMON_API LogOperation { public: - LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) - : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg)) - { } + LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg); - ~LogOperation() { } + ~LogOperation(); int call(); diff --git a/src/common/Logging/Logger.cpp b/src/common/Logging/Logger.cpp index 8e1f9c7ef9d..a3a72f15642 100644 --- a/src/common/Logging/Logger.cpp +++ b/src/common/Logging/Logger.cpp @@ -16,14 +16,10 @@ */ #include "Logger.h" +#include "Appender.h" +#include "LogMessage.h" -Logger::Logger(): name(""), level(LOG_LEVEL_DISABLED) { } - -void Logger::Create(std::string const& _name, LogLevel _level) -{ - name = _name; - level = _level; -} +Logger::Logger(std::string const& _name, LogLevel _level): name(_name), level(_level) { } std::string const& Logger::getName() const { @@ -58,7 +54,7 @@ void Logger::write(LogMessage* message) const return; } - for (AppenderMap::const_iterator it = appenders.begin(); it != appenders.end(); ++it) + for (auto it = appenders.begin(); it != appenders.end(); ++it) if (it->second) it->second->write(message); } diff --git a/src/common/Logging/Logger.h b/src/common/Logging/Logger.h index 1446062c22b..7aac15396f3 100644 --- a/src/common/Logging/Logger.h +++ b/src/common/Logging/Logger.h @@ -18,15 +18,20 @@ #ifndef LOGGER_H #define LOGGER_H -#include "Appender.h" +#include "Define.h" +#include "LogCommon.h" +#include <unordered_map> +#include <string> + +class Appender; +struct LogMessage; class TC_COMMON_API Logger { public: - Logger(); + Logger(std::string const& name, LogLevel level); - void Create(std::string const& name, LogLevel level); - void addAppender(uint8 type, Appender *); + void addAppender(uint8 type, Appender* appender); void delAppender(uint8 type); std::string const& getName() const; @@ -37,7 +42,7 @@ class TC_COMMON_API Logger private: std::string name; LogLevel level; - AppenderMap appenders; + std::unordered_map<uint8, Appender*> appenders; }; #endif diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp index fbd8695429b..10f0d13b688 100644 --- a/src/common/Metric/Metric.cpp +++ b/src/common/Metric/Metric.cpp @@ -16,12 +16,18 @@ */ #include "Metric.h" -#include "Log.h" +#include "AsioHacksImpl.h" +#include "Common.h" #include "Config.h" +#include "Log.h" #include "Util.h" +#include <boost/algorithm/string/replace.hpp> +#include <boost/asio/deadline_timer.hpp> +#include <boost/asio/ip/tcp.hpp> void Metric::Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger) { + _dataStream = Trinity::make_unique<boost::asio::ip::tcp::iostream>(); _realmName = FormatInfluxDBTagValue(realmName); _batchTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); _overallStatusTimer = Trinity::make_unique<boost::asio::deadline_timer>(ioService); @@ -31,8 +37,9 @@ void Metric::Initialize(std::string const& realmName, boost::asio::io_service& i bool Metric::Connect() { - _dataStream.connect(_hostname, _port); - auto error = _dataStream.error(); + auto& stream = static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()); + stream.connect(_hostname, _port); + auto error = stream.error(); if (error) { TC_LOG_ERROR("metric", "Error connecting to '%s:%s', disabling Metric. Error message : %s", @@ -40,7 +47,7 @@ bool Metric::Connect() _enabled = false; return false; } - _dataStream.clear(); + stream.clear(); return true; } @@ -156,22 +163,22 @@ void Metric::SendBatch() return; } - if (!_dataStream.good() && !Connect()) + if (!GetDataStream().good() && !Connect()) return; - _dataStream << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n"; - _dataStream << "Host: " << _hostname << ":" << _port << "\r\n"; - _dataStream << "Accept: */*\r\n"; - _dataStream << "Content-Type: application/octet-stream\r\n"; - _dataStream << "Content-Transfer-Encoding: binary\r\n"; + GetDataStream() << "POST " << "/write?db=" << _databaseName << " HTTP/1.1\r\n"; + GetDataStream() << "Host: " << _hostname << ":" << _port << "\r\n"; + GetDataStream() << "Accept: */*\r\n"; + GetDataStream() << "Content-Type: application/octet-stream\r\n"; + GetDataStream() << "Content-Transfer-Encoding: binary\r\n"; - _dataStream << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n"; - _dataStream << batchedData.rdbuf(); + GetDataStream() << "Content-Length: " << std::to_string(batchedData.tellp()) << "\r\n\r\n"; + GetDataStream() << batchedData.rdbuf(); std::string http_version; - _dataStream >> http_version; + GetDataStream() >> http_version; unsigned int status_code = 0; - _dataStream >> status_code; + GetDataStream() >> status_code; if (status_code != 204) { TC_LOG_ERROR("metric", "Error sending data, returned HTTP code: %u", status_code); @@ -179,14 +186,12 @@ void Metric::SendBatch() // Read and ignore the status description std::string status_description; - std::getline(_dataStream, status_description); + std::getline(GetDataStream(), status_description); // Read headers std::string header; - while (std::getline(_dataStream, header) && header != "\r") - { + while (std::getline(GetDataStream(), header) && header != "\r") if (header == "Connection: close\r") - _dataStream.close(); - } + static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close(); ScheduleSend(); } @@ -200,7 +205,7 @@ void Metric::ScheduleSend() } else { - _dataStream.close(); + static_cast<boost::asio::ip::tcp::iostream&>(GetDataStream()).close(); MetricData* data; // Clear the queue while (_queuedData.Dequeue(data)) @@ -228,8 +233,62 @@ void Metric::ScheduleOverallStatusLog() } } +std::string Metric::FormatInfluxDBValue(bool value) +{ + return value ? "t" : "f"; +} + +template<class T> +std::string Metric::FormatInfluxDBValue(T value) +{ + return std::to_string(value) + 'i'; +} + +std::string Metric::FormatInfluxDBValue(std::string const& value) +{ + return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"'; +} + +std::string Metric::FormatInfluxDBValue(char const* value) +{ + return FormatInfluxDBValue(std::string(value)); +} + +std::string Metric::FormatInfluxDBValue(double value) +{ + return std::to_string(value); +} + +std::string Metric::FormatInfluxDBValue(float value) +{ + return FormatInfluxDBValue(double(value)); +} + +std::string Metric::FormatInfluxDBTagValue(std::string const& value) +{ + // ToDo: should handle '=' and ',' characters too + return boost::replace_all_copy(value, " ", "\\ "); +} + +Metric::Metric() +{ +} + +Metric::~Metric() +{ +} + Metric* Metric::instance() { static Metric instance; return &instance; } + +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int8); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint8); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int16); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint16); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int32); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint32); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(int64); +template TC_COMMON_API std::string Metric::FormatInfluxDBValue(uint64); diff --git a/src/common/Metric/Metric.h b/src/common/Metric/Metric.h index a5d8e5f589a..49347ffe1b7 100644 --- a/src/common/Metric/Metric.h +++ b/src/common/Metric/Metric.h @@ -18,11 +18,22 @@ #ifndef METRIC_H__ #define METRIC_H__ -#include "Common.h" -#include "Threading/MPSCQueue.h" -#include <boost/asio/ip/tcp.hpp> -#include <boost/algorithm/string.hpp> -#include <type_traits> +#include "Define.h" +#include "AsioHacksFwd.h" +#include "MPSCQueue.h" +#include <chrono> +#include <functional> +#include <iosfwd> +#include <memory> +#include <string> + +namespace boost +{ + namespace asio + { + class io_service; + } +} enum MetricDataType { @@ -33,7 +44,7 @@ enum MetricDataType struct MetricData { std::string Category; - std::chrono::time_point<std::chrono::system_clock> Timestamp; + std::chrono::system_clock::time_point Timestamp; MetricDataType Type; // LogValue-specific fields @@ -47,7 +58,8 @@ struct MetricData class TC_COMMON_API Metric { private: - boost::asio::ip::tcp::iostream _dataStream; + std::iostream& GetDataStream() { return *_dataStream; } + std::unique_ptr<std::iostream> _dataStream; MPSCQueue<MetricData> _queuedData; std::unique_ptr<boost::asio::deadline_timer> _batchTimer; std::unique_ptr<boost::asio::deadline_timer> _overallStatusTimer; @@ -66,31 +78,24 @@ private: void ScheduleSend(); void ScheduleOverallStatusLog(); - template<class T, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr> - static std::string FormatInfluxDBValue(T value) { return std::to_string(value) + 'i'; } + static std::string FormatInfluxDBValue(bool value); + template <class T> + static std::string FormatInfluxDBValue(T value); + static std::string FormatInfluxDBValue(std::string const& value); + static std::string FormatInfluxDBValue(char const* value); + static std::string FormatInfluxDBValue(double value); + static std::string FormatInfluxDBValue(float value); - static std::string FormatInfluxDBValue(std::string const& value) - { - return '"' + boost::replace_all_copy(value, "\"", "\\\"") + '"'; - } - - static std::string FormatInfluxDBValue(bool value) { return value ? "t" : "f"; } - static std::string FormatInfluxDBValue(const char* value) { return FormatInfluxDBValue(std::string(value)); } - static std::string FormatInfluxDBValue(double value) { return std::to_string(value); } - static std::string FormatInfluxDBValue(float value) { return FormatInfluxDBValue(double(value)); } - - static std::string FormatInfluxDBTagValue(std::string const& value) - { - // ToDo: should handle '=' and ',' characters too - return boost::replace_all_copy(value, " ", "\\ "); - } + static std::string FormatInfluxDBTagValue(std::string const& value); // ToDo: should format TagKey and FieldKey too in the same way as TagValue public: + Metric(); + ~Metric(); static Metric* instance(); - void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger = [](){}); + void Initialize(std::string const& realmName, boost::asio::io_service& ioService, std::function<void()> overallStatusLogger); void LoadFromConfigs(); void Update(); diff --git a/src/common/PrecompiledHeaders/commonPCH.cpp b/src/common/PrecompiledHeaders/commonPCH.cpp index 52c623ca64a..eccfda05b32 100644 --- a/src/common/PrecompiledHeaders/commonPCH.cpp +++ b/src/common/PrecompiledHeaders/commonPCH.cpp @@ -1 +1,18 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + #include "PrecompiledHeaders/commonPCH.h" diff --git a/src/common/PrecompiledHeaders/commonPCH.h b/src/common/PrecompiledHeaders/commonPCH.h index 2d4f1ff4694..4071ee22c63 100644 --- a/src/common/PrecompiledHeaders/commonPCH.h +++ b/src/common/PrecompiledHeaders/commonPCH.h @@ -1,13 +1,41 @@ -#include "Define.h" -#include "Common.h" +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + #include "BoundingIntervalHierarchy.h" -#include "BoundingIntervalHierarchyWrapper.h" -#include "RegularGrid.h" -#include "Collision/VMapDefinitions.h" -#include "Collision/Maps/MapTree.h" -#include "Collision/Models/WorldModel.h" -#include "Collision/Models/ModelInstance.h" -#include "Collision/Models/GameObjectModel.h" -#include "Threading/ProducerConsumerQueue.h" -#include "Utilities/TaskScheduler.h" -#include "Utilities/EventMap.h" +#include "Common.h" +#include "Config.h" +#include "Define.h" +#include "Errors.h" +#include "GitRevision.h" +#include "Log.h" +#include "LogMessage.h" +#include "MapTree.h" +#include "ModelInstance.h" +#include "Util.h" +#include "VMapDefinitions.h" +#include "WorldModel.h" +#include <G3D/Ray.h> +#include <G3D/Vector3.h> +#include <algorithm> +#include <cstring> +#include <memory> +#include <mutex> +#include <set> +#include <sstream> +#include <string> +#include <unordered_map> +#include <vector> diff --git a/src/common/Threading/ProcessPriority.cpp b/src/common/Threading/ProcessPriority.cpp new file mode 100644 index 00000000000..83d7164a0f5 --- /dev/null +++ b/src/common/Threading/ProcessPriority.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#include "ProcessPriority.h" +#include "Log.h" + +#ifdef _WIN32 // Windows +#include <Windows.h> +#elif defined(__linux__) +#include <sched.h> +#include <sys/resource.h> +#define PROCESS_HIGH_PRIORITY -15 // [-20, 19], default is 0 +#endif + +void SetProcessPriority(std::string const& logChannel, uint32 affinity, bool highPriority) +{ + ///- Handle affinity for multiple processors and process priority +#ifdef _WIN32 // Windows + + HANDLE hProcess = GetCurrentProcess(); + if (affinity > 0) + { + ULONG_PTR appAff; + ULONG_PTR sysAff; + + if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) + { + // remove non accessible processors + ULONG_PTR currentAffinity = affinity & appAff; + + if (!currentAffinity) + TC_LOG_ERROR(logChannel, "Processors marked in UseProcessors bitmask (hex) %x are not accessible. Accessible processors bitmask (hex): %x", affinity, appAff); + else if (SetProcessAffinityMask(hProcess, currentAffinity)) + TC_LOG_INFO(logChannel, "Using processors (bitmask, hex): %x", currentAffinity); + else + TC_LOG_ERROR(logChannel, "Can't set used processors (hex): %x", currentAffinity); + } + } + + if (highPriority) + { + if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) + TC_LOG_INFO(logChannel, "Process priority class set to HIGH"); + else + TC_LOG_ERROR(logChannel, "Can't set process priority class."); + } + +#elif defined(__linux__) // Linux + + if (affinity > 0) + { + cpu_set_t mask; + CPU_ZERO(&mask); + + for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i) + if (affinity & (1 << i)) + CPU_SET(i, &mask); + + if (sched_setaffinity(0, sizeof(mask), &mask)) + TC_LOG_ERROR(logChannel, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno)); + else + { + CPU_ZERO(&mask); + sched_getaffinity(0, sizeof(mask), &mask); + TC_LOG_INFO(logChannel, "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask)); + } + } + + if (highPriority) + { + if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY)) + TC_LOG_ERROR(logChannel, "Can't set process priority class, error: %s", strerror(errno)); + else + TC_LOG_INFO(logChannel, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0)); + } + +#else + // Suppresses unused argument warning for all other platforms + (void)logChannel; + (void)affinity; + (void)highPriority; +#endif +} diff --git a/src/common/Threading/ProcessPriority.h b/src/common/Threading/ProcessPriority.h index b4ff3f5ecf6..3cb866c7de1 100644 --- a/src/common/Threading/ProcessPriority.h +++ b/src/common/Threading/ProcessPriority.h @@ -18,86 +18,12 @@ #ifndef _PROCESSPRIO_H #define _PROCESSPRIO_H -#include "Configuration/Config.h" +#include "Define.h" +#include <string> -#ifdef __linux__ -#include <sched.h> -#include <sys/resource.h> -#define PROCESS_HIGH_PRIORITY -15 // [-20, 19], default is 0 -#endif - -void SetProcessPriority(const std::string& logChannel) -{ -#if defined(_WIN32) || defined(__linux__) - - ///- Handle affinity for multiple processors and process priority - uint32 affinity = sConfigMgr->GetIntDefault("UseProcessors", 0); - bool highPriority = sConfigMgr->GetBoolDefault("ProcessPriority", false); - -#ifdef _WIN32 // Windows - - HANDLE hProcess = GetCurrentProcess(); - if (affinity > 0) - { - ULONG_PTR appAff; - ULONG_PTR sysAff; - - if (GetProcessAffinityMask(hProcess, &appAff, &sysAff)) - { - // remove non accessible processors - ULONG_PTR currentAffinity = affinity & appAff; - - if (!currentAffinity) - TC_LOG_ERROR(logChannel, "Processors marked in UseProcessors bitmask (hex) %x are not accessible. Accessible processors bitmask (hex): %x", affinity, appAff); - else if (SetProcessAffinityMask(hProcess, currentAffinity)) - TC_LOG_INFO(logChannel, "Using processors (bitmask, hex): %x", currentAffinity); - else - TC_LOG_ERROR(logChannel, "Can't set used processors (hex): %x", currentAffinity); - } - } - - if (highPriority) - { - if (SetPriorityClass(hProcess, HIGH_PRIORITY_CLASS)) - TC_LOG_INFO(logChannel, "Process priority class set to HIGH"); - else - TC_LOG_ERROR(logChannel, "Can't set process priority class."); - } +#define CONFIG_PROCESSOR_AFFINITY "UseProcessors" +#define CONFIG_HIGH_PRIORITY "ProcessPriority" -#else // Linux - - if (affinity > 0) - { - cpu_set_t mask; - CPU_ZERO(&mask); - - for (unsigned int i = 0; i < sizeof(affinity) * 8; ++i) - if (affinity & (1 << i)) - CPU_SET(i, &mask); - - if (sched_setaffinity(0, sizeof(mask), &mask)) - TC_LOG_ERROR(logChannel, "Can't set used processors (hex): %x, error: %s", affinity, strerror(errno)); - else - { - CPU_ZERO(&mask); - sched_getaffinity(0, sizeof(mask), &mask); - TC_LOG_INFO(logChannel, "Using processors (bitmask, hex): %lx", *(__cpu_mask*)(&mask)); - } - } - - if (highPriority) - { - if (setpriority(PRIO_PROCESS, 0, PROCESS_HIGH_PRIORITY)) - TC_LOG_ERROR(logChannel, "Can't set process priority class, error: %s", strerror(errno)); - else - TC_LOG_INFO(logChannel, "Process priority class set to %i", getpriority(PRIO_PROCESS, 0)); - } - -#endif -#else - // Suppresses unused argument warning for all other platforms - (void)logChannel; -#endif -} +void TC_COMMON_API SetProcessPriority(std::string const& logChannel, uint32 affinity, bool highPriority); #endif diff --git a/src/common/Utilities/AsioHacksFwd.h b/src/common/Utilities/AsioHacksFwd.h new file mode 100644 index 00000000000..402c390f4f0 --- /dev/null +++ b/src/common/Utilities/AsioHacksFwd.h @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef AsioHacksFwd_h__ +#define AsioHacksFwd_h__ + +namespace boost +{ + namespace posix_time + { + class ptime; + } + + namespace asio + { + namespace ip + { + class address; + + class tcp; + + template <typename InternetProtocol> + class basic_endpoint; + + typedef basic_endpoint<tcp> tcp_endpoint; + + template <typename InternetProtocol> + class resolver_service; + + template <typename InternetProtocol, typename ResolverService> + class basic_resolver; + + typedef basic_resolver<tcp, resolver_service<tcp>> tcp_resolver; + } + + template <typename Time> + struct time_traits; + + template <typename TimeType, typename TimeTraits> + class deadline_timer_service; + + template <typename Time, typename TimeTraits, typename TimerService> + class basic_deadline_timer; + + typedef basic_deadline_timer<posix_time::ptime, time_traits<posix_time::ptime>, deadline_timer_service<posix_time::ptime, time_traits<posix_time::ptime>>> deadline_timer; + } +} + +namespace Trinity +{ + class AsioStrand; +} + +#endif // AsioHacksFwd_h__ diff --git a/src/common/Utilities/AsioHacksImpl.h b/src/common/Utilities/AsioHacksImpl.h new file mode 100644 index 00000000000..86888927a72 --- /dev/null +++ b/src/common/Utilities/AsioHacksImpl.h @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef AsioHacksImpl_h__ +#define AsioHacksImpl_h__ + +#include <boost/asio/strand.hpp> + +namespace Trinity +{ + class AsioStrand : public boost::asio::io_service::strand + { + public: + AsioStrand(boost::asio::io_service& io_service) : boost::asio::io_service::strand(io_service) { } + }; +} + +#endif // AsioHacksImpl_h__ diff --git a/src/common/Utilities/EventMap.cpp b/src/common/Utilities/EventMap.cpp index d4ea70174c4..e1c46d0ae65 100644 --- a/src/common/Utilities/EventMap.cpp +++ b/src/common/Utilities/EventMap.cpp @@ -16,6 +16,7 @@ */ #include "EventMap.h" +#include "Random.h" void EventMap::Reset() { @@ -32,6 +33,11 @@ void EventMap::SetPhase(uint8 phase) _phase = uint8(1 << (phase - 1)); } +void EventMap::ScheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group /*= 0*/, uint32 phase /*= 0*/) +{ + ScheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); +} + void EventMap::ScheduleEvent(uint32 eventId, uint32 time, uint32 group /*= 0*/, uint8 phase /*= 0*/) { if (group && group <= 8) @@ -43,6 +49,16 @@ void EventMap::ScheduleEvent(uint32 eventId, uint32 time, uint32 group /*= 0*/, _eventMap.insert(EventStore::value_type(_time + time, eventId)); } +void EventMap::RescheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group /*= 0*/, uint32 phase /*= 0*/) +{ + RescheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); +} + +void EventMap::Repeat(uint32 minTime, uint32 maxTime) +{ + Repeat(urand(minTime, maxTime)); +} + uint32 EventMap::ExecuteEvent() { while (!Empty()) diff --git a/src/common/Utilities/EventMap.h b/src/common/Utilities/EventMap.h index edcc7a64455..22899ea6b60 100644 --- a/src/common/Utilities/EventMap.h +++ b/src/common/Utilities/EventMap.h @@ -18,9 +18,9 @@ #ifndef _EVENT_MAP_H_ #define _EVENT_MAP_H_ -#include "Common.h" +#include "Define.h" #include "Duration.h" -#include "Util.h" +#include <map> class TC_COMMON_API EventMap { @@ -134,10 +134,7 @@ public: * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. */ - void ScheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0) - { - ScheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); - } + void ScheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0); /** * @name ScheduleEvent @@ -171,10 +168,7 @@ public: * @param group The group which the event is associated to. Has to be between 1 and 8. 0 means it has no group. * @param phase The phase in which the event can occur. Has to be between 1 and 8. 0 means it can occur in all phases. */ - void RescheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0) - { - RescheduleEvent(eventId, urand(uint32(minTime.count()), uint32(maxTime.count())), group, phase); - } + void RescheduleEvent(uint32 eventId, Milliseconds const& minTime, Milliseconds const& maxTime, uint32 group = 0, uint32 phase = 0); /** * @name RescheduleEvent @@ -227,10 +221,7 @@ public: * @param minTime Minimum time until the event occurs. * @param maxTime Maximum time until the event occurs. */ - void Repeat(uint32 minTime, uint32 maxTime) - { - Repeat(urand(minTime, maxTime)); - } + void Repeat(uint32 minTime, uint32 maxTime); /** * @name ExecuteEvent diff --git a/src/common/Utilities/EventProcessor.cpp b/src/common/Utilities/EventProcessor.cpp index 039ca37b9d7..0149f222da8 100644 --- a/src/common/Utilities/EventProcessor.cpp +++ b/src/common/Utilities/EventProcessor.cpp @@ -44,7 +44,7 @@ void EventProcessor::Update(uint32 p_time) m_time += p_time; // main event loop - EventList::iterator i; + std::multimap<uint64, BasicEvent*>::iterator i; while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) { // get and remove event from queue diff --git a/src/common/Utilities/EventProcessor.h b/src/common/Utilities/EventProcessor.h index 2f65957581c..9a356b0e3f5 100644 --- a/src/common/Utilities/EventProcessor.h +++ b/src/common/Utilities/EventProcessor.h @@ -68,8 +68,6 @@ class TC_COMMON_API BasicEvent uint64 m_execTime; // planned time of next execution, filled by event handler }; -typedef std::multimap<uint64, BasicEvent*> EventList; - class TC_COMMON_API EventProcessor { public: @@ -84,7 +82,7 @@ class TC_COMMON_API EventProcessor protected: uint64 m_time; - EventList m_events; + std::multimap<uint64, BasicEvent*> m_events; }; #endif diff --git a/src/common/Utilities/Hash.h b/src/common/Utilities/Hash.h new file mode 100644 index 00000000000..fe2047f7024 --- /dev/null +++ b/src/common/Utilities/Hash.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TrinityCore_Hash_h__ +#define TrinityCore_Hash_h__ + +#include <functional> +#include <utility> + +namespace Trinity +{ + template<typename T> + inline void hash_combine(std::size_t& seed, T const& val) + { + seed ^= std::hash<T>()(val) + 0x9E3779B9 + (seed << 6) + (seed >> 2); + } +} + + //! Hash implementation for std::pair to allow using pairs in unordered_set or as key for unordered_map + //! Individual types used in pair must be hashable by std::hash +namespace std +{ + template<class K, class V> + struct hash<std::pair<K, V>> + { + public: + size_t operator()(std::pair<K, V> const& p) const + { + size_t hashVal = 0; + Trinity::hash_combine(hashVal, p.first); + Trinity::hash_combine(hashVal, p.second); + return hashVal; + } + }; +} + +#endif // TrinityCore_Hash_h__ diff --git a/src/common/Utilities/Optional.h b/src/common/Utilities/Optional.h new file mode 100644 index 00000000000..b46f5cba5b5 --- /dev/null +++ b/src/common/Utilities/Optional.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef TrinityCore_Optional_h__ +#define TrinityCore_Optional_h__ + +#include "OptionalFwd.h" +#include <boost/optional.hpp> +#include <boost/utility/in_place_factory.hpp> + +#endif // TrinityCore_Optional_h__ diff --git a/src/common/Utilities/OptionalFwd.h b/src/common/Utilities/OptionalFwd.h new file mode 100644 index 00000000000..d6b7a48f66e --- /dev/null +++ b/src/common/Utilities/OptionalFwd.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2008-2017 TrinityCore <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, see <http://www.gnu.org/licenses/>. + */ + +#ifndef OptionalFwd_h__ +#define OptionalFwd_h__ + +namespace boost +{ + template <class T> + class optional; +} + +//! Optional helper class to wrap optional values within. +template <class T> +using Optional = boost::optional<T>; + +#endif // OptionalFwd_h__ diff --git a/src/common/Utilities/Random.cpp b/src/common/Utilities/Random.cpp index 3a0cdedcf4b..890ba1b8fce 100644 --- a/src/common/Utilities/Random.cpp +++ b/src/common/Utilities/Random.cpp @@ -16,7 +16,6 @@ */ #include "Random.h" -#include "Common.h" #include "Errors.h" #include "SFMT.h" #include <boost/thread/tss.hpp> @@ -53,8 +52,8 @@ uint32 urand(uint32 min, uint32 max) uint32 urandms(uint32 min, uint32 max) { ASSERT(max >= min); - ASSERT(INT_MAX / IN_MILLISECONDS >= max); - return GetRng()->URandom(min * IN_MILLISECONDS, max * IN_MILLISECONDS); + ASSERT(std::numeric_limits<uint32>::max() / Milliseconds::period::den >= max); + return GetRng()->URandom(min * Milliseconds::period::den, max * Milliseconds::period::den); } float frand(float min, float max) diff --git a/src/common/Utilities/Random.h b/src/common/Utilities/Random.h index ded0a6c6e5c..d200282093a 100644 --- a/src/common/Utilities/Random.h +++ b/src/common/Utilities/Random.h @@ -21,7 +21,6 @@ #include "Define.h" #include "Duration.h" #include <limits> -#include <random> /* Return a random number in the range min..max. */ TC_COMMON_API int32 irand(int32 min, int32 max); diff --git a/src/common/Utilities/StartProcess.cpp b/src/common/Utilities/StartProcess.cpp index 6f4676232ca..dc25cde3767 100644 --- a/src/common/Utilities/StartProcess.cpp +++ b/src/common/Utilities/StartProcess.cpp @@ -16,27 +16,20 @@ */ #include "StartProcess.h" - -#include <atomic> -#include <thread> -#include <functional> +#include "Errors.h" +#include "Log.h" +#include "Optional.h" #include <boost/algorithm/string/join.hpp> -#include <boost/iostreams/stream.hpp> #include <boost/iostreams/copy.hpp> -#include <boost/iostreams/concepts.hpp> -#include <boost/iostreams/device/file_descriptor.hpp> #include <boost/process.hpp> -#include <boost/system/system_error.hpp> - -#include "Common.h" -#include "Log.h" using namespace boost::process; using namespace boost::process::initializers; using namespace boost::iostreams; -namespace Trinity { +namespace Trinity +{ template<typename T> class TCLogSink @@ -51,7 +44,7 @@ public: TCLogSink(T callback) : callback_(std::move(callback)) { } - std::streamsize write(const char* str, std::streamsize size) + std::streamsize write(char const* str, std::streamsize size) { callback_(std::string(str, size)); return size; @@ -250,19 +243,15 @@ std::shared_ptr<AsyncProcessResult> return handle; } -Optional<std::string> SearchExecutableInPath(std::string const& filename) +std::string SearchExecutableInPath(std::string const& filename) { try { - auto result = search_path(filename); - if (result.empty()) - return boost::none; - else - return result; + return search_path(filename); } catch (...) { - return boost::none; + return ""; } } diff --git a/src/common/Utilities/StartProcess.h b/src/common/Utilities/StartProcess.h index 120c4f26ea6..2f8f6ffdec5 100644 --- a/src/common/Utilities/StartProcess.h +++ b/src/common/Utilities/StartProcess.h @@ -18,11 +18,14 @@ #ifndef Process_h__ #define Process_h__ +#include "Define.h" #include <future> #include <memory> -#include "Common.h" +#include <vector> +#include <string> -namespace Trinity { +namespace Trinity +{ /// Starts a process with the given arguments and parameters and will block /// until the process is finished. @@ -59,8 +62,8 @@ TC_COMMON_API std::shared_ptr<AsyncProcessResult> bool secure = false); /// Searches for the given executable in the PATH variable -/// and returns a present optional when it was found. -TC_COMMON_API Optional<std::string> SearchExecutableInPath(std::string const& filename); +/// and returns a non-empty string when it was found. +TC_COMMON_API std::string SearchExecutableInPath(std::string const& filename); } // namespace Trinity diff --git a/src/common/Utilities/StringFormat.h b/src/common/Utilities/StringFormat.h index acda4b41c9f..12eeb2a6d14 100644 --- a/src/common/Utilities/StringFormat.h +++ b/src/common/Utilities/StringFormat.h @@ -31,7 +31,7 @@ namespace Trinity } /// Returns true if the given char pointer is null. - inline bool IsFormatEmptyOrNull(const char* fmt) + inline bool IsFormatEmptyOrNull(char const* fmt) { return fmt == nullptr; } diff --git a/src/common/Utilities/TaskScheduler.cpp b/src/common/Utilities/TaskScheduler.cpp index 730ef8d4b89..a9dcf5dc09b 100644 --- a/src/common/Utilities/TaskScheduler.cpp +++ b/src/common/Utilities/TaskScheduler.cpp @@ -16,6 +16,7 @@ */ #include "TaskScheduler.h" +#include "Errors.h" TaskScheduler& TaskScheduler::ClearValidator() { diff --git a/src/common/Utilities/TaskScheduler.h b/src/common/Utilities/TaskScheduler.h index d6c399639bc..0213fb90f9b 100644 --- a/src/common/Utilities/TaskScheduler.h +++ b/src/common/Utilities/TaskScheduler.h @@ -18,6 +18,9 @@ #ifndef _TASK_SCHEDULER_H_ #define _TASK_SCHEDULER_H_ +#include "Duration.h" +#include "Optional.h" +#include "Random.h" #include <algorithm> #include <chrono> #include <vector> @@ -26,11 +29,6 @@ #include <utility> #include <set> -#include <boost/optional.hpp> - -#include "Util.h" -#include "Duration.h" - class TaskContext; /// The TaskScheduler class provides the ability to schedule std::function's in the near future. @@ -73,13 +71,13 @@ class TC_COMMON_API TaskScheduler timepoint_t _end; duration_t _duration; - boost::optional<group_t> _group; + Optional<group_t> _group; repeated_t _repeated; task_handler_t _task; public: // All Argument construct - Task(timepoint_t const& end, duration_t const& duration, boost::optional<group_t> const& group, + Task(timepoint_t const& end, duration_t const& duration, Optional<group_t> const& group, repeated_t const repeated, task_handler_t const& task) : _end(end), _duration(duration), _group(group), _repeated(repeated), _task(task) { } diff --git a/src/common/Utilities/Timer.h b/src/common/Utilities/Timer.h index e774808bcb0..30a8873102c 100644 --- a/src/common/Utilities/Timer.h +++ b/src/common/Utilities/Timer.h @@ -19,6 +19,7 @@ #ifndef TRINITY_TIMER_H #define TRINITY_TIMER_H +#include "Define.h" #include <chrono> inline uint32 getMSTime() diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index 58b02addc37..01df50a03de 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -18,11 +18,12 @@ #include "Util.h" #include "Common.h" -#include "CompilerDefs.h" -#include "utf8.h" -#include "Errors.h" // for ASSERT -#include <stdarg.h> -#include <boost/algorithm/string/case_conv.hpp> +#include <boost/asio/ip/address.hpp> +#include <utf8.h> +#include <algorithm> +#include <sstream> +#include <cstdarg> +#include <ctime> #if TRINITY_COMPILER == TRINITY_COMPILER_GNU #include <sys/socket.h> @@ -100,7 +101,7 @@ void stripLineInvisibleChars(std::string &str) } #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) -struct tm* localtime_r(const time_t* time, struct tm *result) +struct tm* localtime_r(time_t const* time, struct tm *result) { localtime_s(result, time); return result; @@ -130,7 +131,7 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly) return ss.str(); } -int32 MoneyStringToMoney(const std::string& moneyString) +int32 MoneyStringToMoney(std::string const& moneyString) { int32 money = 0; @@ -149,7 +150,7 @@ int32 MoneyStringToMoney(const std::string& moneyString) if (gCount + sCount + cCount != 1) return 0; - uint32 amount = atoi(*itr); + uint32 amount = strtoul(*itr, nullptr, 10); if (gCount == 1) money += amount * 100 * 100; else if (sCount == 1) @@ -161,7 +162,7 @@ int32 MoneyStringToMoney(const std::string& moneyString) return money; } -uint32 TimeStringToSecs(const std::string& timestring) +uint32 TimeStringToSecs(std::string const& timestring) { uint32 secs = 0; uint32 buffer = 0; @@ -171,8 +172,8 @@ uint32 TimeStringToSecs(const std::string& timestring) { if (isdigit(*itr)) { - buffer*=10; - buffer+= (*itr)-'0'; + buffer *= 10; + buffer += (*itr) - '0'; } else { @@ -184,9 +185,9 @@ uint32 TimeStringToSecs(const std::string& timestring) case 's': multiplier = 1; break; default : return 0; //bad format } - buffer*=multiplier; - secs+=buffer; - buffer=0; + buffer *= multiplier; + secs += buffer; + buffer = 0; } } @@ -214,16 +215,16 @@ 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; + boost::system::error_code error; + boost::asio::ip::address::from_string(ipaddress, error); + return !error; } /// create PID file uint32 CreatePIDFile(std::string const& filename) { FILE* pid_file = fopen(filename.c_str(), "w"); - if (pid_file == NULL) + if (pid_file == nullptr) return 0; uint32 pid = GetPID(); @@ -374,6 +375,16 @@ bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str) typedef wchar_t const* const* wstrlist; +void wstrToUpper(std::wstring& str) +{ + std::transform(str.begin(), str.end(), str.begin(), wcharToUpper); +} + +void wstrToLower(std::wstring& str) +{ + std::transform(str.begin(), str.end(), str.begin(), wcharToLower); +} + std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension) { // supported only Cyrillic cases @@ -400,12 +411,12 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension) 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 } + { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], nullptr, nullptr }, + { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], nullptr, nullptr, nullptr, nullptr }, + { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], nullptr, nullptr, nullptr, nullptr }, + { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], nullptr }, + { &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], nullptr }, + { &ie_End[1], &i_End[1], nullptr, nullptr, nullptr, nullptr, nullptr, nullptr } }; for (wchar_t const* const* itr = &dropEnds[declension][0]; *itr; ++itr) @@ -552,12 +563,13 @@ void HexStrToByteArray(std::string const& str, uint8* out, bool reverse /*= fals for (int32 i = init; i != end; i += 2 * op) { char buffer[3] = { str[i], str[i + 1], '\0' }; - out[j++] = uint8(strtoul(buffer, NULL, 16)); + out[j++] = uint8(strtoul(buffer, nullptr, 16)); } } bool StringToBool(std::string const& str) { - std::string lowerStr = boost::algorithm::to_lower_copy(str); + std::string lowerStr = str; + std::transform(str.begin(), str.end(), lowerStr.begin(), ::tolower); return lowerStr == "1" || lowerStr == "true" || lowerStr == "yes"; } diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 92a2f601c3f..458c783152c 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -21,24 +21,10 @@ #include "Define.h" #include "Errors.h" -#include "Random.h" -#include <algorithm> #include <string> +#include <sstream> #include <vector> -#include <list> -#include <map> -#include <ctime> - -// Searcher for map of structs -template<typename T, class S> struct Finder -{ - T val_; - T S::* idMember_; - - Finder(T val, T S::* idMember) : val_(val), idMember_(idMember) {} - bool operator()(const std::pair<int, S> &obj) { return obj.second.*idMember_ == val_; } -}; class TC_COMMON_API Tokenizer { @@ -70,12 +56,12 @@ private: TC_COMMON_API void stripLineInvisibleChars(std::string &src); -TC_COMMON_API int32 MoneyStringToMoney(const std::string& moneyString); +TC_COMMON_API int32 MoneyStringToMoney(std::string const& moneyString); -TC_COMMON_API struct tm* localtime_r(const time_t* time, struct tm *result); +TC_COMMON_API struct tm* localtime_r(time_t const* time, struct tm *result); TC_COMMON_API std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false); -TC_COMMON_API uint32 TimeStringToSecs(const std::string& timestring); +TC_COMMON_API uint32 TimeStringToSecs(std::string const& timestring); TC_COMMON_API std::string TimeToTimestampStr(time_t t); // Percentage calculation @@ -289,15 +275,8 @@ inline wchar_t wcharToLower(wchar_t wchar) 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 ); -} +TC_COMMON_API void wstrToUpper(std::wstring& str); +TC_COMMON_API void wstrToLower(std::wstring& str); TC_COMMON_API std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension); @@ -382,7 +361,7 @@ public: part[2] = p3; } - inline bool operator <(const flag96 &right) const + inline bool operator<(flag96 const& right) const { for (uint8 i = 3; i > 0; --i) { @@ -394,7 +373,7 @@ public: return false; } - inline bool operator ==(const flag96 &right) const + inline bool operator==(flag96 const& right) const { return ( @@ -404,12 +383,12 @@ public: ); } - inline bool operator !=(const flag96 &right) const + inline bool operator!=(flag96 const& right) const { - return !this->operator ==(right); + return !(*this == right); } - inline flag96 & operator =(const flag96 &right) + inline flag96& operator=(flag96 const& right) { part[0] = right.part[0]; part[1] = right.part[1]; @@ -417,13 +396,12 @@ public: return *this; } - inline flag96 operator &(const flag96 &right) const + inline flag96 operator&(flag96 const& right) const { - return flag96(part[0] & right.part[0], part[1] & right.part[1], - part[2] & right.part[2]); + return flag96(part[0] & right.part[0], part[1] & right.part[1], part[2] & right.part[2]); } - inline flag96 & operator &=(const flag96 &right) + inline flag96& operator&=(flag96 const& right) { part[0] &= right.part[0]; part[1] &= right.part[1]; @@ -431,13 +409,12 @@ public: return *this; } - inline flag96 operator |(const flag96 &right) const + inline flag96 operator|(flag96 const& right) const { - return flag96(part[0] | right.part[0], part[1] | right.part[1], - part[2] | right.part[2]); + return flag96(part[0] | right.part[0], part[1] | right.part[1], part[2] | right.part[2]); } - inline flag96 & operator |=(const flag96 &right) + inline flag96& operator |=(flag96 const& right) { part[0] |= right.part[0]; part[1] |= right.part[1]; @@ -445,18 +422,17 @@ public: return *this; } - inline flag96 operator ~() const + inline flag96 operator~() const { return flag96(~part[0], ~part[1], ~part[2]); } - inline flag96 operator ^(const flag96 &right) const + inline flag96 operator^(flag96 const& right) const { - return flag96(part[0] ^ right.part[0], part[1] ^ right.part[1], - part[2] ^ right.part[2]); + return flag96(part[0] ^ right.part[0], part[1] ^ right.part[1], part[2] ^ right.part[2]); } - inline flag96 & operator ^=(const flag96 &right) + inline flag96& operator^=(flag96 const& right) { part[0] ^= right.part[0]; part[1] ^= right.part[1]; @@ -471,15 +447,15 @@ public: inline bool operator !() const { - return !this->operator bool(); + return !(bool(*this)); } - inline uint32 & operator [](uint8 el) + inline uint32& operator[](uint8 el) { return part[el]; } - inline const uint32 & operator [](uint8 el) const + inline uint32 const& operator [](uint8 el) const { return part[el]; } |