diff options
Diffstat (limited to 'src/server')
114 files changed, 190 insertions, 12786 deletions
diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt index fc4bf4328a3..5d3daef05d8 100644 --- a/src/server/CMakeLists.txt +++ b/src/server/CMakeLists.txt @@ -12,24 +12,20 @@ # This to stop a few silly crashes that could have been avoided IF people # weren't doing some -O3 psychooptimizations etc. +find_package(MySQL REQUIRED) + if(CMAKE_COMPILER_IS_GNUCXX AND NOT MINGW) add_definitions(-fno-delete-null-pointer-checks) endif() -if( SERVERS ) - set(sources_windows_Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging/WheatyExceptionReport.cpp - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging/WheatyExceptionReport.h - ) - add_subdirectory(shared) - add_subdirectory(game) - add_subdirectory(collision) - add_subdirectory(authserver) - add_subdirectory(scripts) - add_subdirectory(worldserver) -else() - if( TOOLS ) - add_subdirectory(collision) - add_subdirectory(shared) - endif() -endif() +set(sources_windows_Debugging + ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.cpp + ${CMAKE_SOURCE_DIR}/src/common/Debugging/WheatyExceptionReport.h +) +add_subdirectory(database) +add_subdirectory(shared) +add_subdirectory(game) +add_subdirectory(authserver) +add_subdirectory(scripts) +add_subdirectory(worldserver) + diff --git a/src/server/authserver/CMakeLists.txt b/src/server/authserver/CMakeLists.txt index f6d99de5271..24a2dc35fce 100644 --- a/src/server/authserver/CMakeLists.txt +++ b/src/server/authserver/CMakeLists.txt @@ -45,22 +45,29 @@ include_directories( ${CMAKE_BINARY_DIR} ${CMAKE_SOURCE_DIR}/dep/cppformat ${CMAKE_SOURCE_DIR}/dep/process + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/database/Updater ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Packets ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Networking - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/shared/Service ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Authentication ${CMAKE_CURRENT_SOURCE_DIR}/Realms ${CMAKE_CURRENT_SOURCE_DIR}/Server + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Logging ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} @@ -80,8 +87,10 @@ if( NOT WIN32 ) endif() target_link_libraries(authserver + common shared format + database ${MYSQL_LIBRARY} ${OPENSSL_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT} diff --git a/src/server/collision/BoundingIntervalHierarchy.cpp b/src/server/collision/BoundingIntervalHierarchy.cpp deleted file mode 100644 index 12af680712e..00000000000 --- a/src/server/collision/BoundingIntervalHierarchy.cpp +++ /dev/null @@ -1,310 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "BoundingIntervalHierarchy.h" - -#ifdef _MSC_VER - #define isnan _isnan -#else - #define isnan std::isnan -#endif - -void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats) -{ - // create space for the first node - tempTree.push_back(uint32(3 << 30)); // dummy leaf - tempTree.insert(tempTree.end(), 2, 0); - //tempTree.add(0); - - // seed bbox - AABound gridBox = { bounds.low(), bounds.high() }; - AABound nodeBox = gridBox; - // seed subdivide function - subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats); -} - -void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats) -{ - if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE) - { - // write leaf node - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - // calculate extents - int axis = -1, prevAxis, rightOrig; - float clipL = G3D::fnan(), clipR = G3D::fnan(), prevClip = G3D::fnan(); - float split = G3D::fnan(), prevSplit; - bool wasLeft = true; - while (true) - { - prevAxis = axis; - prevSplit = split; - // perform quick consistency checks - G3D::Vector3 d( gridBox.hi - gridBox.lo ); - if (d.x < 0 || d.y < 0 || d.z < 0) - throw std::logic_error("negative node extents"); - for (int i = 0; i < 3; i++) - { - if (nodeBox.hi[i] < gridBox.lo[i] || nodeBox.lo[i] > gridBox.hi[i]) - { - //UI.printError(Module.ACCEL, "Reached tree area in error - discarding node with: %d objects", right - left + 1); - throw std::logic_error("invalid node overlap"); - } - } - // find longest axis - axis = d.primaryAxis(); - split = 0.5f * (gridBox.lo[axis] + gridBox.hi[axis]); - // partition L/R subsets - clipL = -G3D::finf(); - clipR = G3D::finf(); - rightOrig = right; // save this for later - float nodeL = G3D::finf(); - float nodeR = -G3D::finf(); - for (int i = left; i <= right;) - { - int obj = dat.indices[i]; - float minb = dat.primBound[obj].low()[axis]; - float maxb = dat.primBound[obj].high()[axis]; - float center = (minb + maxb) * 0.5f; - if (center <= split) - { - // stay left - i++; - if (clipL < maxb) - clipL = maxb; - } - else - { - // move to the right most - int t = dat.indices[i]; - dat.indices[i] = dat.indices[right]; - dat.indices[right] = t; - right--; - if (clipR > minb) - clipR = minb; - } - nodeL = std::min(nodeL, minb); - nodeR = std::max(nodeR, maxb); - } - // check for empty space - if (nodeL > nodeBox.lo[axis] && nodeR < nodeBox.hi[axis]) - { - float nodeBoxW = nodeBox.hi[axis] - nodeBox.lo[axis]; - float nodeNewW = nodeR - nodeL; - // node box is too big compare to space occupied by primitives? - if (1.3f * nodeNewW < nodeBoxW) - { - stats.updateBVH2(); - int nextIndex = tempTree.size(); - // allocate child - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - // write bvh2 clip node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | (1 << 29) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(nodeL); - tempTree[nodeIndex + 2] = floatToRawIntBits(nodeR); - // update nodebox and recurse - nodeBox.lo[axis] = nodeL; - nodeBox.hi[axis] = nodeR; - subdivide(left, rightOrig, tempTree, dat, gridBox, nodeBox, nextIndex, depth + 1, stats); - return; - } - } - // ensure we are making progress in the subdivision - if (right == rightOrig) - { - // all left - if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - if (clipL <= split) { - // keep looping on left half - gridBox.hi[axis] = split; - prevClip = clipL; - wasLeft = true; - continue; - } - gridBox.hi[axis] = split; - prevClip = G3D::fnan(); - } - else if (left > right) - { - // all right - if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) { - // we are stuck here - create a leaf - stats.updateLeaf(depth, right - left + 1); - createNode(tempTree, nodeIndex, left, right); - return; - } - right = rightOrig; - if (clipR >= split) { - // keep looping on right half - gridBox.lo[axis] = split; - prevClip = clipR; - wasLeft = false; - continue; - } - gridBox.lo[axis] = split; - prevClip = G3D::fnan(); - } - else - { - // we are actually splitting stuff - if (prevAxis != -1 && !isnan(prevClip)) - { - // second time through - lets create the previous split - // since it produced empty space - int nextIndex = tempTree.size(); - // allocate child node - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - if (wasLeft) { - // create a node with a left child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip); - tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::finf()); - } else { - // create a node with a right child - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (prevAxis << 30) | (nextIndex - 3); - tempTree[nodeIndex + 1] = floatToRawIntBits(-G3D::finf()); - tempTree[nodeIndex + 2] = floatToRawIntBits(prevClip); - } - // count stats for the unused leaf - depth++; - stats.updateLeaf(depth, 0); - // now we keep going as we are, with a new nodeIndex: - nodeIndex = nextIndex; - } - break; - } - } - // compute index of child nodes - int nextIndex = tempTree.size(); - // allocate left node - int nl = right - left + 1; - int nr = rightOrig - (right + 1) + 1; - if (nl > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } else - nextIndex -= 3; - // allocate right node - if (nr > 0) { - tempTree.push_back(0); - tempTree.push_back(0); - tempTree.push_back(0); - } - // write leaf node - stats.updateInner(); - tempTree[nodeIndex + 0] = (axis << 30) | nextIndex; - tempTree[nodeIndex + 1] = floatToRawIntBits(clipL); - tempTree[nodeIndex + 2] = floatToRawIntBits(clipR); - // prepare L/R child boxes - AABound gridBoxL(gridBox), gridBoxR(gridBox); - AABound nodeBoxL(nodeBox), nodeBoxR(nodeBox); - gridBoxL.hi[axis] = gridBoxR.lo[axis] = split; - nodeBoxL.hi[axis] = clipL; - nodeBoxR.lo[axis] = clipR; - // recurse - if (nl > 0) - subdivide(left, right, tempTree, dat, gridBoxL, nodeBoxL, nextIndex, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); - if (nr > 0) - subdivide(right + 1, rightOrig, tempTree, dat, gridBoxR, nodeBoxR, nextIndex + 3, depth + 1, stats); - else - stats.updateLeaf(depth + 1, 0); -} - -bool BIH::writeToFile(FILE* wf) const -{ - uint32 treeSize = tree.size(); - uint32 check=0, count; - check += fwrite(&bounds.low(), sizeof(float), 3, wf); - check += fwrite(&bounds.high(), sizeof(float), 3, wf); - check += fwrite(&treeSize, sizeof(uint32), 1, wf); - check += fwrite(&tree[0], sizeof(uint32), treeSize, wf); - count = objects.size(); - check += fwrite(&count, sizeof(uint32), 1, wf); - check += fwrite(&objects[0], sizeof(uint32), count, wf); - return check == (3 + 3 + 2 + treeSize + count); -} - -bool BIH::readFromFile(FILE* rf) -{ - uint32 treeSize; - G3D::Vector3 lo, hi; - uint32 check=0, count=0; - check += fread(&lo, sizeof(float), 3, rf); - check += fread(&hi, sizeof(float), 3, rf); - bounds = G3D::AABox(lo, hi); - check += fread(&treeSize, sizeof(uint32), 1, rf); - tree.resize(treeSize); - check += fread(&tree[0], sizeof(uint32), treeSize, rf); - check += fread(&count, sizeof(uint32), 1, rf); - objects.resize(count); // = new uint32[nObjects]; - check += fread(&objects[0], sizeof(uint32), count, rf); - return uint64(check) == uint64(3 + 3 + 1 + 1 + uint64(treeSize) + uint64(count)); -} - -void BIH::BuildStats::updateLeaf(int depth, int n) -{ - numLeaves++; - minDepth = std::min(depth, minDepth); - maxDepth = std::max(depth, maxDepth); - sumDepth += depth; - minObjects = std::min(n, minObjects); - maxObjects = std::max(n, maxObjects); - sumObjects += n; - int nl = std::min(n, 5); - ++numLeavesN[nl]; -} - -void BIH::BuildStats::printStats() -{ - printf("Tree stats:\n"); - printf(" * Nodes: %d\n", numNodes); - printf(" * Leaves: %d\n", numLeaves); - printf(" * Objects: min %d\n", minObjects); - printf(" avg %.2f\n", (float) sumObjects / numLeaves); - printf(" avg(n>0) %.2f\n", (float) sumObjects / (numLeaves - numLeavesN[0])); - printf(" max %d\n", maxObjects); - printf(" * Depth: min %d\n", minDepth); - printf(" avg %.2f\n", (float) sumDepth / numLeaves); - printf(" max %d\n", maxDepth); - printf(" * Leaves w/: N=0 %3d%%\n", 100 * numLeavesN[0] / numLeaves); - printf(" N=1 %3d%%\n", 100 * numLeavesN[1] / numLeaves); - printf(" N=2 %3d%%\n", 100 * numLeavesN[2] / numLeaves); - printf(" N=3 %3d%%\n", 100 * numLeavesN[3] / numLeaves); - printf(" N=4 %3d%%\n", 100 * numLeavesN[4] / numLeaves); - printf(" N>4 %3d%%\n", 100 * numLeavesN[5] / numLeaves); - printf(" * BVH2 nodes: %d (%3d%%)\n", numBVH2, 100 * numBVH2 / (numNodes + numLeaves - 2 * numBVH2)); -} diff --git a/src/server/collision/BoundingIntervalHierarchy.h b/src/server/collision/BoundingIntervalHierarchy.h deleted file mode 100644 index 3a09772c41f..00000000000 --- a/src/server/collision/BoundingIntervalHierarchy.h +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _BIH_H -#define _BIH_H - -#include "G3D/Vector3.h" -#include "G3D/Ray.h" -#include "G3D/AABox.h" - -#include "Define.h" - -#include <stdexcept> -#include <vector> -#include <algorithm> -#include <limits> -#include <cmath> - -#define MAX_STACK_SIZE 64 - -static inline uint32 floatToRawIntBits(float f) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.fval=f; - return temp.ival; -} - -static inline float intBitsToFloat(uint32 i) -{ - union - { - uint32 ival; - float fval; - } temp; - temp.ival=i; - return temp.fval; -} - -struct AABound -{ - G3D::Vector3 lo, hi; -}; - -/** Bounding Interval Hierarchy Class. - Building and Ray-Intersection functions based on BIH from - Sunflow, a Java Raytracer, released under MIT/X11 License - http://sunflow.sourceforge.net/ - Copyright (c) 2003-2007 Christopher Kulla -*/ - -class BIH -{ - private: - void init_empty() - { - tree.clear(); - objects.clear(); - // create space for the first node - tree.push_back(3u << 30u); // dummy leaf - tree.insert(tree.end(), 2, 0); - } - public: - BIH() { init_empty(); } - template< class BoundsFunc, class PrimArray > - void build(const PrimArray &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false) - { - if (primitives.size() == 0) - { - init_empty(); - return; - } - - buildData dat; - dat.maxPrims = leafSize; - dat.numPrims = primitives.size(); - dat.indices = new uint32[dat.numPrims]; - dat.primBound = new G3D::AABox[dat.numPrims]; - getBounds(primitives[0], bounds); - for (uint32 i=0; i<dat.numPrims; ++i) - { - dat.indices[i] = i; - getBounds(primitives[i], dat.primBound[i]); - bounds.merge(dat.primBound[i]); - } - std::vector<uint32> tempTree; - BuildStats stats; - buildHierarchy(tempTree, dat, stats); - if (printStats) - stats.printStats(); - - objects.resize(dat.numPrims); - for (uint32 i=0; i<dat.numPrims; ++i) - objects[i] = dat.indices[i]; - //nObjects = dat.numPrims; - tree = tempTree; - delete[] dat.primBound; - delete[] dat.indices; - } - uint32 primCount() const { return objects.size(); } - - template<typename RayCallback> - void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirst=false) const - { - float intervalMin = -1.f; - float intervalMax = -1.f; - G3D::Vector3 org = r.origin(); - G3D::Vector3 dir = r.direction(); - G3D::Vector3 invDir; - for (int i=0; i<3; ++i) - { - invDir[i] = 1.f / dir[i]; - if (G3D::fuzzyNe(dir[i], 0.0f)) - { - float t1 = (bounds.low()[i] - org[i]) * invDir[i]; - float t2 = (bounds.high()[i] - org[i]) * invDir[i]; - if (t1 > t2) - std::swap(t1, t2); - if (t1 > intervalMin) - intervalMin = t1; - if (t2 < intervalMax || intervalMax < 0.f) - intervalMax = t2; - // intervalMax can only become smaller for other axis, - // and intervalMin only larger respectively, so stop early - if (intervalMax <= 0 || intervalMin >= maxDist) - return; - } - } - - if (intervalMin > intervalMax) - return; - intervalMin = std::max(intervalMin, 0.f); - intervalMax = std::min(intervalMax, maxDist); - - uint32 offsetFront[3]; - uint32 offsetBack[3]; - uint32 offsetFront3[3]; - uint32 offsetBack3[3]; - // compute custom offsets from direction sign bit - - for (int i=0; i<3; ++i) - { - offsetFront[i] = floatToRawIntBits(dir[i]) >> 31; - offsetBack[i] = offsetFront[i] ^ 1; - offsetFront3[i] = offsetFront[i] * 3; - offsetBack3[i] = offsetBack[i] * 3; - - // avoid always adding 1 during the inner loop - ++offsetFront[i]; - ++offsetBack[i]; - } - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = (tn & (1 << 29)) != 0; - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - // ray passes between clip zones - if (tf < intervalMin && tb > intervalMax) - break; - int back = offset + offsetBack3[axis]; - node = back; - // ray passes through far node only - if (tf < intervalMin) { - intervalMin = (tb >= intervalMin) ? tb : intervalMin; - continue; - } - node = offset + offsetFront3[axis]; // front - // ray passes through near node only - if (tb > intervalMax) { - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - // ray passes through both nodes - // push back node - stack[stackPos].node = back; - stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin; - stack[stackPos].tfar = intervalMax; - stackPos++; - // update ray interval for front node - intervalMax = (tf <= intervalMax) ? tf : intervalMax; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirst); - if (stopAtFirst && hit) return; - --n; - ++offset; - } - break; - } - } - else - { - if (axis>2) - return; // should not happen - float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis]; - float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis]; - node = offset; - intervalMin = (tf >= intervalMin) ? tf : intervalMin; - intervalMax = (tb <= intervalMax) ? tb : intervalMax; - if (intervalMin > intervalMax) - break; - continue; - } - } // traversal loop - do - { - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - intervalMin = stack[stackPos].tnear; - if (maxDist < intervalMin) - continue; - node = stack[stackPos].node; - intervalMax = stack[stackPos].tfar; - break; - } while (true); - } - } - - template<typename IsectCallback> - void intersectPoint(const G3D::Vector3 &p, IsectCallback& intersectCallback) const - { - if (!bounds.contains(p)) - return; - - StackNode stack[MAX_STACK_SIZE]; - int stackPos = 0; - int node = 0; - - while (true) { - while (true) - { - uint32 tn = tree[node]; - uint32 axis = (tn & (3 << 30)) >> 30; - bool BVH2 = (tn & (1 << 29)) != 0; - int offset = tn & ~(7 << 29); - if (!BVH2) - { - if (axis < 3) - { - // "normal" interior node - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - // point is between clip zones - if (tl < p[axis] && tr > p[axis]) - break; - int right = offset + 3; - node = right; - // point is in right node only - if (tl < p[axis]) { - continue; - } - node = offset; // left - // point is in left node only - if (tr > p[axis]) { - continue; - } - // point is in both nodes - // push back right node - stack[stackPos].node = right; - stackPos++; - continue; - } - else - { - // leaf - test some objects - int n = tree[node + 1]; - while (n > 0) { - intersectCallback(p, objects[offset]); // !!! - --n; - ++offset; - } - break; - } - } - else // BVH2 node (empty space cut off left and right) - { - if (axis>2) - return; // should not happen - float tl = intBitsToFloat(tree[node + 1]); - float tr = intBitsToFloat(tree[node + 2]); - node = offset; - if (tl > p[axis] || tr < p[axis]) - break; - continue; - } - } // traversal loop - - // stack is empty? - if (stackPos == 0) - return; - // move back up the stack - stackPos--; - node = stack[stackPos].node; - } - } - - bool writeToFile(FILE* wf) const; - bool readFromFile(FILE* rf); - - protected: - std::vector<uint32> tree; - std::vector<uint32> objects; - G3D::AABox bounds; - - struct buildData - { - uint32 *indices; - G3D::AABox *primBound; - uint32 numPrims; - int maxPrims; - }; - struct StackNode - { - uint32 node; - float tnear; - float tfar; - }; - - class BuildStats - { - private: - int numNodes; - int numLeaves; - int sumObjects; - int minObjects; - int maxObjects; - int sumDepth; - int minDepth; - int maxDepth; - int numLeavesN[6]; - int numBVH2; - - public: - BuildStats(): - numNodes(0), numLeaves(0), sumObjects(0), minObjects(0x0FFFFFFF), - maxObjects(0xFFFFFFFF), sumDepth(0), minDepth(0x0FFFFFFF), - maxDepth(0xFFFFFFFF), numBVH2(0) - { - for (int i=0; i<6; ++i) numLeavesN[i] = 0; - } - - void updateInner() { numNodes++; } - void updateBVH2() { numBVH2++; } - void updateLeaf(int depth, int n); - void printStats(); - }; - - void buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats); - - void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) const - { - // write leaf node - tempTree[nodeIndex + 0] = (3 << 30) | left; - tempTree[nodeIndex + 1] = right - left + 1; - } - - void subdivide(int left, int right, std::vector<uint32> &tempTree, buildData &dat, AABound &gridBox, AABound &nodeBox, int nodeIndex, int depth, BuildStats &stats); -}; - -#endif // _BIH_H diff --git a/src/server/collision/BoundingIntervalHierarchyWrapper.h b/src/server/collision/BoundingIntervalHierarchyWrapper.h deleted file mode 100644 index 60bb6a569df..00000000000 --- a/src/server/collision/BoundingIntervalHierarchyWrapper.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _BIH_WRAP -#define _BIH_WRAP - -#include "G3D/Table.h" -#include "G3D/Array.h" -#include "G3D/Set.h" -#include "BoundingIntervalHierarchy.h" - - -template<class T, class BoundsFunc = BoundsTrait<T> > -class BIHWrap -{ - template<class RayCallback> - struct MDLCallback - { - const T* const* objects; - RayCallback& _callback; - uint32 objects_size; - - MDLCallback(RayCallback& callback, const T* const* objects_array, uint32 objects_size ) : objects(objects_array), _callback(callback), objects_size(objects_size) { } - - /// Intersect ray - bool operator() (const G3D::Ray& ray, uint32 idx, float& maxDist, bool /*stopAtFirst*/) - { - if (idx >= objects_size) - return false; - if (const T* obj = objects[idx]) - return _callback(ray, *obj, maxDist/*, stopAtFirst*/); - return false; - } - - /// Intersect point - void operator() (const G3D::Vector3& p, uint32 idx) - { - if (idx >= objects_size) - return; - if (const T* obj = objects[idx]) - _callback(p, *obj); - } - }; - - typedef G3D::Array<const T*> ObjArray; - - BIH m_tree; - ObjArray m_objects; - G3D::Table<const T*, uint32> m_obj2Idx; - G3D::Set<const T*> m_objects_to_push; - int unbalanced_times; - -public: - BIHWrap() : unbalanced_times(0) { } - - void insert(const T& obj) - { - ++unbalanced_times; - m_objects_to_push.insert(&obj); - } - - void remove(const T& obj) - { - ++unbalanced_times; - uint32 Idx = 0; - const T * temp; - if (m_obj2Idx.getRemove(&obj, temp, Idx)) - m_objects[Idx] = NULL; - else - m_objects_to_push.remove(&obj); - } - - void balance() - { - if (unbalanced_times == 0) - return; - - unbalanced_times = 0; - m_objects.fastClear(); - m_obj2Idx.getKeys(m_objects); - m_objects_to_push.getMembers(m_objects); - //assert that m_obj2Idx has all the keys - - m_tree.build(m_objects, BoundsFunc::getBounds2); - } - - template<typename RayCallback> - void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& maxDist) - { - balance(); - MDLCallback<RayCallback> temp_cb(intersectCallback, m_objects.getCArray(), m_objects.size()); - m_tree.intersectRay(ray, temp_cb, maxDist, true); - } - - template<typename IsectCallback> - void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback) - { - balance(); - MDLCallback<IsectCallback> callback(intersectCallback, m_objects.getCArray(), m_objects.size()); - m_tree.intersectPoint(point, callback); - } -}; - -#endif // _BIH_WRAP diff --git a/src/server/collision/CMakeLists.txt b/src/server/collision/CMakeLists.txt deleted file mode 100644 index f394fe791be..00000000000 --- a/src/server/collision/CMakeLists.txt +++ /dev/null @@ -1,97 +0,0 @@ -# Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> -# -# This file is free software; as a special exception the author gives -# unlimited permission to copy and/or distribute it, with or without -# modifications, as long as this notice is preserved. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the -# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - -if( USE_COREPCH ) - include_directories(${CMAKE_CURRENT_BINARY_DIR}) -endif() - -file(GLOB_RECURSE sources_Management Management/*.cpp Management/*.h) -file(GLOB_RECURSE sources_Maps Maps/*.cpp Maps/*.h) -file(GLOB_RECURSE sources_Models Models/*.cpp Models/*.h) -file(GLOB sources_localdir *.cpp *.h) - -if (USE_COREPCH) - set(collision_STAT_PCH_HDR PrecompiledHeaders/collisionPCH.h) - set(collision_STAT_PCH_SRC PrecompiledHeaders/collisionPCH.cpp) -endif () - -set(collision_STAT_SRCS - ${collision_STAT_SRCS} - ${sources_Management} - ${sources_Maps} - ${sources_Models} - ${sources_localdir} -) - -include_directories( - ${CMAKE_BINARY_DIR} - ${CMAKE_SOURCE_DIR}/dep/g3dlite/include - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour - ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour/Include - ${CMAKE_SOURCE_DIR}/dep/cppformat - ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Database - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Addons - ${CMAKE_SOURCE_DIR}/src/server/game/Conditions - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Item - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/GameObject - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Creature - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object/Updates - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Unit - ${CMAKE_SOURCE_DIR}/src/server/game/Combat - ${CMAKE_SOURCE_DIR}/src/server/game/Loot - ${CMAKE_SOURCE_DIR}/src/server/game/Miscellaneous - ${CMAKE_SOURCE_DIR}/src/server/game/Grids - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Cells - ${CMAKE_SOURCE_DIR}/src/server/game/Grids/Notifiers - ${CMAKE_SOURCE_DIR}/src/server/game/Maps - ${CMAKE_SOURCE_DIR}/src/server/game/DataStores - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Waypoints - ${CMAKE_SOURCE_DIR}/src/server/game/Movement/Spline - ${CMAKE_SOURCE_DIR}/src/server/game/Movement - ${CMAKE_SOURCE_DIR}/src/server/game/Server - ${CMAKE_SOURCE_DIR}/src/server/game/Server/Protocol - ${CMAKE_SOURCE_DIR}/src/server/game/World - ${CMAKE_SOURCE_DIR}/src/server/game/Spells - ${CMAKE_SOURCE_DIR}/src/server/game/Spells/Auras - ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Management - ${CMAKE_CURRENT_SOURCE_DIR}/Maps - ${CMAKE_CURRENT_SOURCE_DIR}/Models - ${MYSQL_INCLUDE_DIR} - ${VALGRIND_INCLUDE_DIR} -) - -GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) - -add_library(collision STATIC - ${collision_STAT_SRCS} - ${collision_STAT_PCH_SRC} -) - -target_link_libraries(collision - shared -) - -# Generate precompiled header -if (USE_COREPCH) - add_cxx_pch(collision ${collision_STAT_PCH_HDR} ${collision_STAT_PCH_SRC}) -endif () diff --git a/src/server/collision/DynamicTree.cpp b/src/server/collision/DynamicTree.cpp deleted file mode 100644 index 1de2543543d..00000000000 --- a/src/server/collision/DynamicTree.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "DynamicTree.h" -//#include "QuadTree.h" -//#include "RegularGrid.h" -#include "BoundingIntervalHierarchyWrapper.h" - -#include "Log.h" -#include "RegularGrid.h" -#include "Timer.h" -#include "GameObjectModel.h" -#include "ModelInstance.h" - -#include <G3D/AABox.h> -#include <G3D/Ray.h> -#include <G3D/Vector3.h> - -using VMAP::ModelInstance; - -namespace { - -int CHECK_TREE_PERIOD = 200; - -} // namespace - -template<> struct HashTrait< GameObjectModel>{ - static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; } -}; - -template<> struct PositionTrait< GameObjectModel> { - static void getPosition(const GameObjectModel& 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 bool operator == (const GameObjectModel& mdl, const GameObjectModel& mdl2){ - return &mdl == &mdl2; -} -*/ - -typedef RegularGrid2D<GameObjectModel, BIHWrap<GameObjectModel> > ParentTree; - -struct DynTreeImpl : public ParentTree/*, public Intersectable*/ -{ - typedef GameObjectModel Model; - typedef ParentTree base; - - DynTreeImpl() : - rebalance_timer(CHECK_TREE_PERIOD), - unbalanced_times(0) - { - } - - void insert(const Model& mdl) - { - base::insert(mdl); - ++unbalanced_times; - } - - void remove(const Model& mdl) - { - base::remove(mdl); - ++unbalanced_times; - } - - void balance() - { - base::balance(); - unbalanced_times = 0; - } - - void update(uint32 difftime) - { - if (!size()) - return; - - rebalance_timer.Update(difftime); - if (rebalance_timer.Passed()) - { - rebalance_timer.Reset(CHECK_TREE_PERIOD); - if (unbalanced_times > 0) - balance(); - } - } - - TimeTrackerSmall rebalance_timer; - int unbalanced_times; -}; - -DynamicMapTree::DynamicMapTree() : impl(new DynTreeImpl()) { } - -DynamicMapTree::~DynamicMapTree() -{ - delete impl; -} - -void DynamicMapTree::insert(const GameObjectModel& mdl) -{ - impl->insert(mdl); -} - -void DynamicMapTree::remove(const GameObjectModel& mdl) -{ - impl->remove(mdl); -} - -bool DynamicMapTree::contains(const GameObjectModel& mdl) const -{ - return impl->contains(mdl); -} - -void DynamicMapTree::balance() -{ - impl->balance(); -} - -int DynamicMapTree::size() const -{ - return impl->size(); -} - -void DynamicMapTree::update(uint32 t_diff) -{ - impl->update(t_diff); -} - -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) - { - did_hit = obj.intersectRay(r, distance, true, phase_mask); - return did_hit; - } - bool didHit() const { return did_hit;} -}; - -struct DynamicTreeIntersectionCallback_WithLogger -{ - bool did_hit; - uint32 phase_mask; - DynamicTreeIntersectionCallback_WithLogger(uint32 phasemask) : did_hit(false), phase_mask(phasemask) - { - TC_LOG_DEBUG("maps", "Dynamic Intersection log"); - } - bool operator()(const G3D::Ray& r, const GameObjectModel& obj, float& distance) - { - TC_LOG_DEBUG("maps", "testing intersection with %s", obj.name.c_str()); - bool hit = obj.intersectRay(r, distance, true, phase_mask); - if (hit) - { - did_hit = true; - TC_LOG_DEBUG("maps", "result: intersects"); - } - return hit; - } - bool didHit() const { return did_hit;} -}; - -bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray, - const G3D::Vector3& endPos, float& maxDist) const -{ - float distance = maxDist; - DynamicTreeIntersectionCallback callback(phasemask); - impl->intersectRay(ray, callback, distance, endPos); - if (callback.didHit()) - maxDist = distance; - return callback.didHit(); -} - -bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3& startPos, - const G3D::Vector3& endPos, G3D::Vector3& resultHit, - float modifyDist) const -{ - bool result = false; - float maxDist = (endPos - startPos).magnitude(); - // valid map coords should *never ever* produce float overflow, but this would produce NaNs too - ASSERT(maxDist < std::numeric_limits<float>::max()); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - { - resultHit = endPos; - return false; - } - G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1 - G3D::Ray ray(startPos, dir); - float dist = maxDist; - if (getIntersectionTime(phasemask, ray, endPos, dist)) - { - resultHit = startPos + dir * dist; - if (modifyDist < 0) - { - if ((resultHit - startPos).magnitude() > -modifyDist) - resultHit = resultHit + dir*modifyDist; - else - resultHit = startPos; - } - else - resultHit = resultHit + dir*modifyDist; - - result = true; - } - else - { - resultHit = endPos; - result = false; - } - return result; -} - -bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const -{ - G3D::Vector3 v1(x1, y1, z1), v2(x2, y2, z2); - - float maxDist = (v2 - v1).magnitude(); - - if (!G3D::fuzzyGt(maxDist, 0) ) - return true; - - G3D::Ray r(v1, (v2-v1) / maxDist); - DynamicTreeIntersectionCallback callback(phasemask); - impl->intersectRay(r, callback, maxDist, v2); - - return !callback.did_hit; -} - -float DynamicMapTree::getHeight(float x, float y, float z, float maxSearchDist, uint32 phasemask) const -{ - G3D::Vector3 v(x, y, z); - G3D::Ray r(v, G3D::Vector3(0, 0, -1)); - DynamicTreeIntersectionCallback callback(phasemask); - impl->intersectZAllignedRay(r, callback, maxSearchDist); - - if (callback.didHit()) - return v.z - maxSearchDist; - else - return -G3D::finf(); -} diff --git a/src/server/collision/DynamicTree.h b/src/server/collision/DynamicTree.h deleted file mode 100644 index 5e905323640..00000000000 --- a/src/server/collision/DynamicTree.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _DYNTREE_H -#define _DYNTREE_H - -#include "Define.h" - -namespace G3D -{ - class Ray; - class Vector3; -} - -class GameObjectModel; -struct DynTreeImpl; - -class DynamicMapTree -{ - DynTreeImpl *impl; - -public: - - DynamicMapTree(); - ~DynamicMapTree(); - - bool isInLineOfSight(float x1, float y1, float z1, float x2, float y2, - float z2, uint32 phasemask) const; - - bool getIntersectionTime(uint32 phasemask, const G3D::Ray& ray, - const G3D::Vector3& endPos, float& maxDist) const; - - bool getObjectHitPos(uint32 phasemask, const G3D::Vector3& pPos1, - const G3D::Vector3& pPos2, G3D::Vector3& pResultHitPos, - float pModifyDist) const; - - 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; - int size() const; - - void balance(); - void update(uint32 diff); -}; - -#endif // _DYNTREE_H diff --git a/src/server/collision/Management/IVMapManager.h b/src/server/collision/Management/IVMapManager.h deleted file mode 100644 index b890554257c..00000000000 --- a/src/server/collision/Management/IVMapManager.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _IVMAPMANAGER_H -#define _IVMAPMANAGER_H - -#include <string> -#include "Define.h" - -//=========================================================== - -/** -This is the minimum interface to the VMapMamager. -*/ - -namespace VMAP -{ - - enum VMAP_LOAD_RESULT - { - VMAP_LOAD_RESULT_ERROR, - VMAP_LOAD_RESULT_OK, - VMAP_LOAD_RESULT_IGNORED - }; - - #define VMAP_INVALID_HEIGHT -100000.0f // for check - #define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case - - //=========================================================== - class IVMapManager - { - private: - bool iEnableLineOfSightCalc; - bool iEnableHeightCalc; - - public: - IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) { } - - virtual ~IVMapManager(void) { } - - virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; - - virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0; - - virtual void unloadMap(unsigned int pMapId, int x, int y) = 0; - virtual void unloadMap(unsigned int pMapId) = 0; - - virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0; - virtual float getHeight(unsigned int pMapId, float x, float y, float z, float maxSearchDist) = 0; - /** - test if we hit an object. return true if we hit one. rx, ry, rz will hold the hit position or the dest position, if no intersection was found - return a position, that is pReduceDist closer to the origin - */ - virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0; - /** - send debug commands - */ - virtual bool processCommand(char *pCommand)= 0; - - /** - Enable/disable LOS calculation - It is enabled by default. If it is enabled in mid game the maps have to loaded manualy - */ - void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; } - /** - Enable/disable model height calculation - It is enabled by default. If it is enabled in mid game the maps have to loaded manualy - */ - void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; } - - bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); } - bool isHeightCalcEnabled() const { return(iEnableHeightCalc); } - bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); } - - virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0; - /** - Query world model area info. - \param z gets adjusted to the ground height for which this are info is valid - */ - virtual bool getAreaInfo(unsigned int pMapId, float x, float y, float &z, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const=0; - virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float &level, float &floor, uint32 &type) const=0; - }; - -} -#endif diff --git a/src/server/collision/Management/MMapFactory.cpp b/src/server/collision/Management/MMapFactory.cpp deleted file mode 100644 index 667b8378c56..00000000000 --- a/src/server/collision/Management/MMapFactory.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "MMapFactory.h" -#include "Config.h" - -namespace MMAP -{ - // ######################## MMapFactory ######################## - // our global singleton copy - MMapManager* g_MMapManager = NULL; - - MMapManager* MMapFactory::createOrGetMMapManager() - { - if (g_MMapManager == NULL) - g_MMapManager = new MMapManager(); - - return g_MMapManager; - } - - void MMapFactory::clear() - { - if (g_MMapManager) - { - delete g_MMapManager; - g_MMapManager = NULL; - } - } -}
\ No newline at end of file diff --git a/src/server/collision/Management/MMapFactory.h b/src/server/collision/Management/MMapFactory.h deleted file mode 100644 index 773983f81eb..00000000000 --- a/src/server/collision/Management/MMapFactory.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _MMAP_FACTORY_H -#define _MMAP_FACTORY_H - -#include "Define.h" -#include "MMapManager.h" -#include "DetourAlloc.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" -#include <unordered_map> - -namespace MMAP -{ - enum MMAP_LOAD_RESULT - { - MMAP_LOAD_RESULT_ERROR, - MMAP_LOAD_RESULT_OK, - MMAP_LOAD_RESULT_IGNORED - }; - - // static class - // holds all mmap global data - // access point to MMapManager singleton - class MMapFactory - { - public: - static MMapManager* createOrGetMMapManager(); - static void clear(); - static bool IsPathfindingEnabled(uint32 mapId); - }; -} - -#endif - diff --git a/src/server/collision/Management/MMapManager.cpp b/src/server/collision/Management/MMapManager.cpp deleted file mode 100644 index b71b94e3291..00000000000 --- a/src/server/collision/Management/MMapManager.cpp +++ /dev/null @@ -1,337 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "MMapManager.h" -#include "Log.h" -#include "World.h" - -namespace MMAP -{ - // ######################## MMapManager ######################## - MMapManager::~MMapManager() - { - for (MMapDataSet::iterator i = loadedMMaps.begin(); i != loadedMMaps.end(); ++i) - delete i->second; - - // by now we should not have maps loaded - // if we had, tiles in MMapData->mmapLoadedTiles, their actual data is lost! - } - - 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) - loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)); - - thread_safe_environment = false; - } - - MMapDataSet::const_iterator MMapManager::GetMMapData(uint32 mapId) const - { - // return the iterator if found or end() if not found/NULL - MMapDataSet::const_iterator itr = loadedMMaps.find(mapId); - if (itr != loadedMMaps.cend() && !itr->second) - itr = loadedMMaps.cend(); - - return itr; - } - - bool MMapManager::loadMapData(uint32 mapId) - { - // we already have this map loaded? - MMapDataSet::iterator itr = loadedMMaps.find(mapId); - if (itr != loadedMMaps.end()) - { - if (itr->second) - return true; - } - else - { - if (thread_safe_environment) - itr = loadedMMaps.insert(MMapDataSet::value_type(mapId, nullptr)).first; - else - ASSERT(false, "Invalid mapId %u passed to MMapManager after startup in thread unsafe environment", mapId); - } - - // load and init dtNavMesh - read parameters from file - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1; - char *fileName = new char[pathLen]; - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId); - - FILE* file = fopen(fileName, "rb"); - if (!file) - { - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not open mmap file '%s'", fileName); - delete [] fileName; - return false; - } - - dtNavMeshParams params; - int count = fread(¶ms, sizeof(dtNavMeshParams), 1, file); - fclose(file); - if (count != 1) - { - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Error: Could not read params from file '%s'", fileName); - delete [] fileName; - return false; - } - - dtNavMesh* mesh = dtAllocNavMesh(); - ASSERT(mesh); - if (dtStatusFailed(mesh->init(¶ms))) - { - dtFreeNavMesh(mesh); - TC_LOG_ERROR("maps", "MMAP:loadMapData: Failed to initialize dtNavMesh for mmap %03u from file %s", mapId, fileName); - delete [] fileName; - return false; - } - - delete [] fileName; - - TC_LOG_DEBUG("maps", "MMAP:loadMapData: Loaded %03i.mmap", mapId); - - // store inside our map list - MMapData* mmap_data = new MMapData(mesh); - mmap_data->mmapLoadedTiles.clear(); - - itr->second = mmap_data; - return true; - } - - uint32 MMapManager::packTileID(int32 x, int32 y) - { - return uint32(x << 16 | y); - } - - bool MMapManager::loadMap(const std::string& /*basePath*/, uint32 mapId, int32 x, int32 y) - { - // make sure the mmap is loaded and ready to load tiles - if (!loadMapData(mapId)) - return false; - - // get this mmap data - MMapData* mmap = loadedMMaps[mapId]; - ASSERT(mmap->navMesh); - - // check if we already have this tile loaded - uint32 packedGridPos = packTileID(x, y); - if (mmap->mmapLoadedTiles.find(packedGridPos) != mmap->mmapLoadedTiles.end()) - return false; - - // load this tile :: mmaps/MMMXXYY.mmtile - uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1; - char *fileName = new char[pathLen]; - - snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y); - - FILE* file = fopen(fileName, "rb"); - if (!file) - { - TC_LOG_DEBUG("maps", "MMAP:loadMap: Could not open mmtile file '%s'", fileName); - delete [] fileName; - return false; - } - delete [] fileName; - - // read header - MmapTileHeader fileHeader; - if (fread(&fileHeader, sizeof(MmapTileHeader), 1, file) != 1 || fileHeader.mmapMagic != MMAP_MAGIC) - { - TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header in mmap %03u%02i%02i.mmtile", mapId, x, y); - fclose(file); - return false; - } - - if (fileHeader.mmapVersion != MMAP_VERSION) - { - TC_LOG_ERROR("maps", "MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i", - mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION); - fclose(file); - return false; - } - - unsigned char* data = (unsigned char*)dtAlloc(fileHeader.size, DT_ALLOC_PERM); - ASSERT(data); - - size_t result = fread(data, fileHeader.size, 1, file); - if (!result) - { - TC_LOG_ERROR("maps", "MMAP:loadMap: Bad header or data in mmap %03u%02i%02i.mmtile", mapId, x, y); - fclose(file); - return false; - } - - fclose(file); - - dtMeshHeader* header = (dtMeshHeader*)data; - dtTileRef tileRef = 0; - - // memory allocated for data is now managed by detour, and will be deallocated when the tile is removed - if (dtStatusSucceed(mmap->navMesh->addTile(data, fileHeader.size, DT_TILE_FREE_DATA, 0, &tileRef))) - { - mmap->mmapLoadedTiles.insert(std::pair<uint32, dtTileRef>(packedGridPos, tileRef)); - ++loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:loadMap: Loaded mmtile %03i[%02i, %02i] into %03i[%02i, %02i]", mapId, x, y, mapId, header->x, header->y); - return true; - } - else - { - TC_LOG_ERROR("maps", "MMAP:loadMap: Could not load %03u%02i%02i.mmtile into navmesh", mapId, x, y); - dtFree(data); - return false; - } - } - - bool MMapManager::unloadMap(uint32 mapId, int32 x, int32 y) - { - // check if we have this map loaded - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map. %03u%02i%02i.mmtile", mapId, x, y); - return false; - } - - MMapData* mmap = itr->second; - - // check if we have this tile loaded - uint32 packedGridPos = packTileID(x, y); - if (mmap->mmapLoadedTiles.find(packedGridPos) == mmap->mmapLoadedTiles.end()) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh tile. %03u%02i%02i.mmtile", mapId, x, y); - return false; - } - - dtTileRef tileRef = mmap->mmapLoadedTiles[packedGridPos]; - - // unload, and mark as non loaded - if (dtStatusFailed(mmap->navMesh->removeTile(tileRef, NULL, NULL))) - { - // this is technically a memory leak - // if the grid is later reloaded, dtNavMesh::addTile will return error but no extra memory is used - // we cannot recover from this error - assert out - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); - ASSERT(false); - } - else - { - mmap->mmapLoadedTiles.erase(packedGridPos); - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); - return true; - } - - return false; - } - - bool MMapManager::unloadMap(uint32 mapId) - { - MMapDataSet::iterator itr = loadedMMaps.find(mapId); - if (itr == loadedMMaps.end() || !itr->second) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Asked to unload not loaded navmesh map %03u", mapId); - return false; - } - - // unload all tiles from given map - MMapData* mmap = itr->second; - for (MMapTileSet::iterator i = mmap->mmapLoadedTiles.begin(); i != mmap->mmapLoadedTiles.end(); ++i) - { - uint32 x = (i->first >> 16); - uint32 y = (i->first & 0x0000FFFF); - if (dtStatusFailed(mmap->navMesh->removeTile(i->second, NULL, NULL))) - TC_LOG_ERROR("maps", "MMAP:unloadMap: Could not unload %03u%02i%02i.mmtile from navmesh", mapId, x, y); - else - { - --loadedTiles; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded mmtile %03i[%02i, %02i] from %03i", mapId, x, y, mapId); - } - } - - delete mmap; - itr->second = nullptr; - TC_LOG_DEBUG("maps", "MMAP:unloadMap: Unloaded %03i.mmap", mapId); - - return true; - } - - bool MMapManager::unloadMapInstance(uint32 mapId, uint32 instanceId) - { - // check if we have this map loaded - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - { - // file may not exist, therefore not loaded - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded navmesh map %03u", mapId); - return false; - } - - MMapData* mmap = itr->second; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) - { - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Asked to unload not loaded dtNavMeshQuery mapId %03u instanceId %u", mapId, instanceId); - return false; - } - - dtNavMeshQuery* query = mmap->navMeshQueries[instanceId]; - - dtFreeNavMeshQuery(query); - mmap->navMeshQueries.erase(instanceId); - TC_LOG_DEBUG("maps", "MMAP:unloadMapInstance: Unloaded mapId %03u instanceId %u", mapId, instanceId); - - return true; - } - - dtNavMesh const* MMapManager::GetNavMesh(uint32 mapId) - { - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - return NULL; - - return itr->second->navMesh; - } - - dtNavMeshQuery const* MMapManager::GetNavMeshQuery(uint32 mapId, uint32 instanceId) - { - MMapDataSet::const_iterator itr = GetMMapData(mapId); - if (itr == loadedMMaps.end()) - return NULL; - - MMapData* mmap = itr->second; - if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end()) - { - // allocate mesh query - dtNavMeshQuery* query = dtAllocNavMeshQuery(); - ASSERT(query); - if (dtStatusFailed(query->init(mmap->navMesh, 1024))) - { - dtFreeNavMeshQuery(query); - TC_LOG_ERROR("maps", "MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - return NULL; - } - - TC_LOG_DEBUG("maps", "MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId); - mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query)); - } - - return mmap->navMeshQueries[instanceId]; - } -} diff --git a/src/server/collision/Management/MMapManager.h b/src/server/collision/Management/MMapManager.h deleted file mode 100644 index 42292b76942..00000000000 --- a/src/server/collision/Management/MMapManager.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _MMAP_MANAGER_H -#define _MMAP_MANAGER_H - -#include "Define.h" -#include "DetourNavMesh.h" -#include "DetourNavMeshQuery.h" - -#include <string> -#include <unordered_map> -#include <vector> - -// move map related classes -namespace MMAP -{ - typedef std::unordered_map<uint32, dtTileRef> MMapTileSet; - typedef std::unordered_map<uint32, dtNavMeshQuery*> NavMeshQuerySet; - - // dummy struct to hold map's mmap data - struct MMapData - { - MMapData(dtNavMesh* mesh) : navMesh(mesh) { } - ~MMapData() - { - for (NavMeshQuerySet::iterator i = navMeshQueries.begin(); i != navMeshQueries.end(); ++i) - dtFreeNavMeshQuery(i->second); - - if (navMesh) - dtFreeNavMesh(navMesh); - } - - dtNavMesh* navMesh; - - // we have to use single dtNavMeshQuery for every instance, since those are not thread safe - NavMeshQuerySet navMeshQueries; // instanceId to query - MMapTileSet mmapLoadedTiles; // maps [map grid coords] to [dtTile] - }; - - - typedef std::unordered_map<uint32, MMapData*> MMapDataSet; - - // singleton class - // holds all all access to mmap loading unloading and meshes - class MMapManager - { - public: - MMapManager() : loadedTiles(0), thread_safe_environment(true) {} - ~MMapManager(); - - void InitializeThreadUnsafe(const std::vector<uint32>& mapIds); - bool loadMap(const std::string& basePath, uint32 mapId, int32 x, int32 y); - bool unloadMap(uint32 mapId, int32 x, int32 y); - bool unloadMap(uint32 mapId); - bool unloadMapInstance(uint32 mapId, uint32 instanceId); - - // the returned [dtNavMeshQuery const*] is NOT threadsafe - dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId); - dtNavMesh const* GetNavMesh(uint32 mapId); - - uint32 getLoadedTilesCount() const { return loadedTiles; } - uint32 getLoadedMapsCount() const { return loadedMMaps.size(); } - private: - bool loadMapData(uint32 mapId); - uint32 packTileID(int32 x, int32 y); - - MMapDataSet::const_iterator GetMMapData(uint32 mapId) const; - MMapDataSet loadedMMaps; - uint32 loadedTiles; - bool thread_safe_environment; - }; -} - -#endif
\ No newline at end of file diff --git a/src/server/collision/Management/VMapFactory.cpp b/src/server/collision/Management/VMapFactory.cpp deleted file mode 100644 index 4c2750a9e5c..00000000000 --- a/src/server/collision/Management/VMapFactory.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "VMapFactory.h" -#include "VMapManager2.h" - -namespace VMAP -{ - IVMapManager* gVMapManager = NULL; - - //=============================================== - // just return the instance - IVMapManager* VMapFactory::createOrGetVMapManager() - { - if (gVMapManager == nullptr) - gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-) - return gVMapManager; - } - - //=============================================== - // delete all internal data structures - void VMapFactory::clear() - { - delete gVMapManager; - gVMapManager = NULL; - } -} diff --git a/src/server/collision/Management/VMapFactory.h b/src/server/collision/Management/VMapFactory.h deleted file mode 100644 index 3067c2919d5..00000000000 --- a/src/server/collision/Management/VMapFactory.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _VMAPFACTORY_H -#define _VMAPFACTORY_H - -#include "IVMapManager.h" - -/** -This is the access point to the VMapManager. -*/ - -namespace VMAP -{ - //=========================================================== - - class VMapFactory - { - public: - static IVMapManager* createOrGetVMapManager(); - static void clear(); - }; - -} -#endif diff --git a/src/server/collision/Management/VMapManager2.cpp b/src/server/collision/Management/VMapManager2.cpp deleted file mode 100644 index 9594951196f..00000000000 --- a/src/server/collision/Management/VMapManager2.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include <iostream> -#include <iomanip> -#include <string> -#include <sstream> -#include "VMapManager2.h" -#include "MapTree.h" -#include "ModelInstance.h" -#include "WorldModel.h" -#include <G3D/Vector3.h> -#include "Log.h" -#include "VMapDefinitions.h" -#include "Errors.h" - -using G3D::Vector3; - -namespace VMAP -{ - VMapManager2::VMapManager2() - { - GetLiquidFlagsPtr = &GetLiquidFlagsDummy; - IsVMAPDisabledForPtr = &IsVMAPDisabledForDummy; - thread_safe_environment = true; - } - - VMapManager2::~VMapManager2(void) - { - for (InstanceTreeMap::iterator i = iInstanceMapTrees.begin(); i != iInstanceMapTrees.end(); ++i) - { - delete i->second; - } - for (ModelFileMap::iterator i = iLoadedModelFiles.begin(); i != iLoadedModelFiles.end(); ++i) - { - delete i->second.getModel(); - } - } - - 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) - iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)); - - thread_safe_environment = false; - } - - Vector3 VMapManager2::convertPositionToInternalRep(float x, float y, float z) const - { - Vector3 pos; - const float mid = 0.5f * 64.0f * 533.33333333f; - pos.x = mid - x; - pos.y = mid - y; - pos.z = z; - - return pos; - } - - // move to MapTree too? - std::string VMapManager2::getMapFileName(unsigned int mapId) - { - std::stringstream fname; - fname.width(3); - fname << std::setfill('0') << mapId << std::string(MAP_FILENAME_EXTENSION2); - - return fname.str(); - } - - int VMapManager2::loadMap(const char* basePath, unsigned int mapId, int x, int y) - { - int result = VMAP_LOAD_RESULT_IGNORED; - if (isMapLoadingEnabled()) - { - if (_loadMap(mapId, basePath, x, y)) - result = VMAP_LOAD_RESULT_OK; - else - result = VMAP_LOAD_RESULT_ERROR; - } - - return result; - } - - InstanceTreeMap::const_iterator VMapManager2::GetMapTree(uint32 mapId) const - { - // return the iterator if found or end() if not found/NULL - InstanceTreeMap::const_iterator itr = iInstanceMapTrees.find(mapId); - if (itr != iInstanceMapTrees.cend() && !itr->second) - itr = iInstanceMapTrees.cend(); - - return itr; - } - - // load one tile (internal use only) - bool VMapManager2::_loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); - if (instanceTree == iInstanceMapTrees.end()) - { - if (thread_safe_environment) - instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, nullptr)).first; - else - ASSERT(false, "Invalid mapId %u tile [%u, %u] passed to VMapManager2 after startup in thread unsafe environment", - mapId, tileX, tileY); - } - - if (!instanceTree->second) - { - std::string mapFileName = getMapFileName(mapId); - StaticMapTree* newTree = new StaticMapTree(mapId, basePath); - if (!newTree->InitMap(mapFileName, this)) - { - delete newTree; - return false; - } - instanceTree->second = newTree; - } - - return instanceTree->second->LoadMapTile(tileX, tileY, this); - } - - void VMapManager2::unloadMap(unsigned int mapId) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); - if (instanceTree != iInstanceMapTrees.end() && instanceTree->second) - { - instanceTree->second->UnloadMap(this); - if (instanceTree->second->numLoadedTiles() == 0) - { - delete instanceTree->second; - instanceTree->second = nullptr; - } - } - } - - void VMapManager2::unloadMap(unsigned int mapId, int x, int y) - { - InstanceTreeMap::iterator instanceTree = iInstanceMapTrees.find(mapId); - if (instanceTree != iInstanceMapTrees.end() && instanceTree->second) - { - instanceTree->second->UnloadMapTile(x, y, this); - if (instanceTree->second->numLoadedTiles() == 0) - { - delete instanceTree->second; - instanceTree->second = nullptr; - } - } - } - - bool VMapManager2::isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) - { - if (!isLineOfSightCalcEnabled() || IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) - return true; - - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); - Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2); - if (pos1 != pos2) - { - return instanceTree->second->isInLineOfSight(pos1, pos2); - } - } - - return true; - } - - /** - get the hit position and return true if we hit something - otherwise the result pos will be the dest pos - */ - bool VMapManager2::getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float modifyDist) - { - if (isLineOfSightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LOS)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos1 = convertPositionToInternalRep(x1, y1, z1); - Vector3 pos2 = convertPositionToInternalRep(x2, y2, z2); - Vector3 resultPos; - bool result = instanceTree->second->getObjectHitPos(pos1, pos2, resultPos, modifyDist); - resultPos = convertPositionToInternalRep(resultPos.x, resultPos.y, resultPos.z); - rx = resultPos.x; - ry = resultPos.y; - rz = resultPos.z; - return result; - } - } - - rx = x2; - ry = y2; - rz = z2; - - return false; - } - - /** - get height or INVALID_HEIGHT if no height available - */ - - float VMapManager2::getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) - { - if (isHeightCalcEnabled() && !IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_HEIGHT)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x, y, z); - float height = instanceTree->second->getHeight(pos, maxSearchDist); - if (!(height < G3D::finf())) - return height = VMAP_INVALID_HEIGHT_VALUE; // No height - - return height; - } - } - - return VMAP_INVALID_HEIGHT_VALUE; - } - - bool VMapManager2::getAreaInfo(unsigned int mapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const - { - if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_AREAFLAG)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - Vector3 pos = convertPositionToInternalRep(x, y, z); - bool result = instanceTree->second->getAreaInfo(pos, flags, adtId, rootId, groupId); - // z is not touched by convertPositionToInternalRep(), so just copy - z = pos.z; - return result; - } - } - - return false; - } - - bool VMapManager2::GetLiquidLevel(uint32 mapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const - { - if (!IsVMAPDisabledForPtr(mapId, VMAP_DISABLE_LIQUIDSTATUS)) - { - InstanceTreeMap::const_iterator instanceTree = GetMapTree(mapId); - if (instanceTree != iInstanceMapTrees.end()) - { - LocationInfo info; - Vector3 pos = convertPositionToInternalRep(x, y, z); - if (instanceTree->second->GetLocationInfo(pos, info)) - { - floor = info.ground_Z; - ASSERT(floor < std::numeric_limits<float>::max()); - ASSERT(info.hitModel); - type = info.hitModel->GetLiquidType(); // entry from LiquidType.dbc - if (reqLiquidType && !(GetLiquidFlagsPtr(type) & reqLiquidType)) - return false; - ASSERT(info.hitInstance); - if (info.hitInstance->GetLiquidLevel(pos, info, level)) - return true; - } - } - } - - return false; - } - - WorldModel* VMapManager2::acquireModelInstance(const std::string& basepath, const std::string& filename) - { - //! Critical section, thread safe access to iLoadedModelFiles - std::lock_guard<std::mutex> lock(LoadedModelFilesLock); - - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); - if (model == iLoadedModelFiles.end()) - { - WorldModel* worldmodel = new WorldModel(); - if (!worldmodel->readFile(basepath + filename + ".vmo")) - { - VMAP_ERROR_LOG("misc", "VMapManager2: could not load '%s%s.vmo'", basepath.c_str(), filename.c_str()); - delete worldmodel; - return NULL; - } - VMAP_DEBUG_LOG("maps", "VMapManager2: loading file '%s%s'", basepath.c_str(), filename.c_str()); - model = iLoadedModelFiles.insert(std::pair<std::string, ManagedModel>(filename, ManagedModel())).first; - model->second.setModel(worldmodel); - } - model->second.incRefCount(); - return model->second.getModel(); - } - - void VMapManager2::releaseModelInstance(const std::string &filename) - { - //! Critical section, thread safe access to iLoadedModelFiles - std::lock_guard<std::mutex> lock(LoadedModelFilesLock); - - ModelFileMap::iterator model = iLoadedModelFiles.find(filename); - if (model == iLoadedModelFiles.end()) - { - VMAP_ERROR_LOG("misc", "VMapManager2: trying to unload non-loaded file '%s'", filename.c_str()); - return; - } - if (model->second.decRefCount() == 0) - { - VMAP_DEBUG_LOG("maps", "VMapManager2: unloading file '%s'", filename.c_str()); - delete model->second.getModel(); - iLoadedModelFiles.erase(model); - } - } - - bool VMapManager2::existsMap(const char* basePath, unsigned int mapId, int x, int y) - { - return StaticMapTree::CanLoadMap(std::string(basePath), mapId, x, y); - } - -} // namespace VMAP diff --git a/src/server/collision/Management/VMapManager2.h b/src/server/collision/Management/VMapManager2.h deleted file mode 100644 index a5891e9642b..00000000000 --- a/src/server/collision/Management/VMapManager2.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _VMAPMANAGER2_H -#define _VMAPMANAGER2_H - -#include <mutex> -#include <unordered_map> -#include <vector> -#include "Define.h" -#include "IVMapManager.h" - -//=========================================================== - -#define MAP_FILENAME_EXTENSION2 ".vmtree" - -#define FILENAMEBUFFER_SIZE 500 - -/** -This is the main Class to manage loading and unloading of maps, line of sight, height calculation and so on. -For each map or map tile to load it reads a directory file that contains the ModelContainer files used by this map or map tile. -Each global map or instance has its own dynamic BSP-Tree. -The loaded ModelContainers are included in one of these BSP-Trees. -Additionally a table to match map ids and map names is used. -*/ - -//=========================================================== - -namespace G3D -{ - class Vector3; -} - -namespace VMAP -{ - class StaticMapTree; - class WorldModel; - - class ManagedModel - { - public: - ManagedModel() : iModel(nullptr), iRefCount(0) { } - void setModel(WorldModel* model) { iModel = model; } - WorldModel* getModel() { return iModel; } - void incRefCount() { ++iRefCount; } - int decRefCount() { return --iRefCount; } - protected: - WorldModel* iModel; - int iRefCount; - }; - - typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap; - typedef std::unordered_map<std::string, ManagedModel> ModelFileMap; - - enum DisableTypes - { - VMAP_DISABLE_AREAFLAG = 0x1, - VMAP_DISABLE_HEIGHT = 0x2, - VMAP_DISABLE_LOS = 0x4, - VMAP_DISABLE_LIQUIDSTATUS = 0x8 - }; - - class VMapManager2 : public IVMapManager - { - protected: - // Tree to check collision - ModelFileMap iLoadedModelFiles; - InstanceTreeMap iInstanceMapTrees; - bool thread_safe_environment; - // Mutex for iLoadedModelFiles - std::mutex LoadedModelFilesLock; - - bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY); - /* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */ - - static uint32 GetLiquidFlagsDummy(uint32) { return 0; } - static bool IsVMAPDisabledForDummy(uint32 /*entry*/, uint8 /*flags*/) { return false; } - - InstanceTreeMap::const_iterator GetMapTree(uint32 mapId) const; - - public: - // public for debug - G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const; - static std::string getMapFileName(unsigned int mapId); - - VMapManager2(); - ~VMapManager2(void); - - void InitializeThreadUnsafe(const std::vector<uint32>& mapIds); - int loadMap(const char* 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; - - bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) override ; - /** - fill the hit pos and return true, if an object was hit - */ - bool getObjectHitPos(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float& ry, float& rz, float modifyDist) override; - float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist) override; - - bool processCommand(char* /*command*/) override { return false; } // for debug and extensions - - bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const override; - bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const override; - - WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename); - void releaseModelInstance(const std::string& filename); - - // what's the use of this? o.O - virtual std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const override - { - return getMapFileName(mapId); - } - virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y) override; - public: - void getInstanceMapTree(InstanceTreeMap &instanceMapTree); - - typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType); - GetLiquidFlagsFn GetLiquidFlagsPtr; - - typedef bool(*IsVMAPDisabledForFn)(uint32 entry, uint8 flags); - IsVMAPDisabledForFn IsVMAPDisabledForPtr; - }; -} - -#endif diff --git a/src/server/collision/Maps/MapTree.cpp b/src/server/collision/Maps/MapTree.cpp deleted file mode 100644 index b493ec18f5f..00000000000 --- a/src/server/collision/Maps/MapTree.cpp +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "MapTree.h" -#include "ModelInstance.h" -#include "VMapManager2.h" -#include "VMapDefinitions.h" -#include "Log.h" -#include "Errors.h" - -#include <string> -#include <sstream> -#include <iomanip> -#include <limits> - -using G3D::Vector3; - -namespace VMAP -{ - - class MapRayCallback - { - public: - MapRayCallback(ModelInstance* val): prims(val), hit(false) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit=true) - { - bool result = prims[entry].intersectRay(ray, distance, pStopAtFirstHit); - if (result) - hit = true; - return result; - } - bool didHit() { return hit; } - protected: - ModelInstance* prims; - bool hit; - }; - - class AreaInfoCallback - { - public: - AreaInfoCallback(ModelInstance* val): prims(val) { } - void operator()(const Vector3& point, uint32 entry) - { -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); -#endif - prims[entry].intersectPoint(point, aInfo); - } - - ModelInstance* prims; - AreaInfo aInfo; - }; - - class LocationInfoCallback - { - public: - LocationInfoCallback(ModelInstance* val, LocationInfo &info): prims(val), locInfo(info), result(false) { } - void operator()(const Vector3& point, uint32 entry) - { -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str()); -#endif - if (prims[entry].GetLocationInfo(point, locInfo)) - result = true; - } - - ModelInstance* prims; - LocationInfo &locInfo; - bool result; - }; - - //========================================================= - - std::string StaticMapTree::getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY) - { - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << std::setw(3) << mapID << '_'; - //tilefilename << std::setw(2) << tileX << '_' << std::setw(2) << tileY << ".vmtile"; - tilefilename << std::setw(2) << tileY << '_' << std::setw(2) << tileX << ".vmtile"; - return tilefilename.str(); - } - - bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const - { - AreaInfoCallback intersectionCallBack(iTreeValues); - iTree.intersectPoint(pos, intersectionCallBack); - if (intersectionCallBack.aInfo.result) - { - flags = intersectionCallBack.aInfo.flags; - adtId = intersectionCallBack.aInfo.adtId; - rootId = intersectionCallBack.aInfo.rootId; - groupId = intersectionCallBack.aInfo.groupId; - pos.z = intersectionCallBack.aInfo.ground_Z; - return true; - } - return false; - } - - bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const - { - LocationInfoCallback intersectionCallBack(iTreeValues, info); - iTree.intersectPoint(pos, intersectionCallBack); - return intersectionCallBack.result; - } - - StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath) : - iMapID(mapID), iIsTiled(false), iTreeValues(NULL), - iNTreeValues(0), iBasePath(basePath) - { - if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\') - { - iBasePath.push_back('/'); - } - } - - //========================================================= - //! Make sure to call unloadMap() to unregister acquired model references before destroying - StaticMapTree::~StaticMapTree() - { - delete[] iTreeValues; - } - - //========================================================= - /** - If intersection is found within pMaxDist, sets pMaxDist to intersection distance and returns true. - Else, pMaxDist is not modified and returns false; - */ - - bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const - { - float distance = pMaxDist; - MapRayCallback intersectionCallBack(iTreeValues); - iTree.intersectRay(pRay, intersectionCallBack, distance, pStopAtFirstHit); - if (intersectionCallBack.didHit()) - pMaxDist = distance; - return intersectionCallBack.didHit(); - } - //========================================================= - - bool StaticMapTree::isInLineOfSight(const Vector3& pos1, const Vector3& pos2) 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 - if (maxDist == std::numeric_limits<float>::max() || !std::isfinite(maxDist)) - return false; - - // valid map coords should *never ever* produce float overflow, but this would produce NaNs too - ASSERT(maxDist < std::numeric_limits<float>::max()); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - return true; - // direction with length of 1 - G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist); - if (getIntersectionTime(ray, maxDist, true)) - return false; - - return true; - } - //========================================================= - /** - When moving from pos1 to pos2 check if we hit an object. Return true and the position if we hit one - Return the hit pos or the original dest pos - */ - - bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const - { - bool result=false; - float maxDist = (pPos2 - pPos1).magnitude(); - // valid map coords should *never ever* produce float overflow, but this would produce NaNs too - ASSERT(maxDist < std::numeric_limits<float>::max()); - // prevent NaN values which can cause BIH intersection to enter infinite loop - if (maxDist < 1e-10f) - { - pResultHitPos = pPos2; - return false; - } - Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1 - G3D::Ray ray(pPos1, dir); - float dist = maxDist; - if (getIntersectionTime(ray, dist, false)) - { - pResultHitPos = pPos1 + dir * dist; - if (pModifyDist < 0) - { - if ((pResultHitPos - pPos1).magnitude() > -pModifyDist) - { - pResultHitPos = pResultHitPos + dir*pModifyDist; - } - else - { - pResultHitPos = pPos1; - } - } - else - { - pResultHitPos = pResultHitPos + dir*pModifyDist; - } - result = true; - } - else - { - pResultHitPos = pPos2; - result = false; - } - return result; - } - - //========================================================= - - float StaticMapTree::getHeight(const Vector3& pPos, float maxSearchDist) const - { - float height = G3D::finf(); - Vector3 dir = Vector3(0, 0, -1); - G3D::Ray ray(pPos, dir); // direction with length of 1 - float maxDist = maxSearchDist; - if (getIntersectionTime(ray, maxDist, false)) - { - height = pPos.z - maxDist; - } - return(height); - } - - //========================================================= - - bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY) - { - std::string basePath = vmapPath; - if (basePath.length() > 0 && basePath[basePath.length()-1] != '/' && basePath[basePath.length()-1] != '\\') - basePath.push_back('/'); - std::string fullname = basePath + VMapManager2::getMapFileName(mapID); - bool success = true; - FILE* rf = fopen(fullname.c_str(), "rb"); - if (!rf) - return false; - /// @todo check magic number when implemented... - char tiled; - char chunk[8]; - if (!readChunk(rf, chunk, VMAP_MAGIC, 8) || fread(&tiled, sizeof(char), 1, rf) != 1) - { - fclose(rf); - return false; - } - if (tiled) - { - std::string tilefile = basePath + getTileFileName(mapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (!tf) - success = false; - else - { - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - success = false; - fclose(tf); - } - } - fclose(rf); - return success; - } - - //========================================================= - - bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm) - { - VMAP_DEBUG_LOG("maps", "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str()); - bool success = false; - std::string fullname = iBasePath + fname; - FILE* rf = fopen(fullname.c_str(), "rb"); - if (!rf) - return false; - - char chunk[8]; - char tiled = '\0'; - - if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 && - readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf)) - { - iNTreeValues = iTree.primCount(); - iTreeValues = new ModelInstance[iNTreeValues]; - success = readChunk(rf, chunk, "GOBJ", 4); - } - - iIsTiled = tiled != '\0'; - - // global model spawns - // only non-tiled maps have them, and if so exactly one (so far at least...) - ModelSpawn spawn; -#ifdef VMAP_DEBUG - TC_LOG_DEBUG("maps", "StaticMapTree::InitMap() : map isTiled: %u", static_cast<uint32>(iIsTiled)); -#endif - if (!iIsTiled && ModelSpawn::readFromFile(rf, spawn)) - { - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - VMAP_DEBUG_LOG("maps", "StaticMapTree::InitMap() : loading %s", spawn.name.c_str()); - if (model) - { - // assume that global model always is the first and only tree value (could be improved...) - iTreeValues[0] = ModelInstance(spawn, model); - iLoadedSpawns[0] = 1; - } - else - { - success = false; - VMAP_ERROR_LOG("misc", "StaticMapTree::InitMap() : could not acquire WorldModel pointer for '%s'", spawn.name.c_str()); - } - } - - fclose(rf); - return success; - } - - //========================================================= - - void StaticMapTree::UnloadMap(VMapManager2* vm) - { - for (loadedSpawnMap::iterator i = iLoadedSpawns.begin(); i != iLoadedSpawns.end(); ++i) - { - iTreeValues[i->first].setUnloaded(); - for (uint32 refCount = 0; refCount < i->second; ++refCount) - vm->releaseModelInstance(iTreeValues[i->first].name); - } - iLoadedSpawns.clear(); - iLoadedTiles.clear(); - } - - //========================================================= - - bool StaticMapTree::LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) - { - if (!iIsTiled) - { - // currently, core creates grids for all maps, whether it has terrain tiles or not - // so we need "fake" tile loads to know when we can unload map geometry - iLoadedTiles[packTileID(tileX, tileY)] = false; - return true; - } - if (!iTreeValues) - { - VMAP_ERROR_LOG("misc", "StaticMapTree::LoadMapTile() : tree has not been initialized [%u, %u]", tileX, tileY); - return false; - } - bool result = true; - - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) - { - char chunk[8]; - - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - result = false; - uint32 numSpawns = 0; - if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1) - result = false; - for (uint32 i=0; i<numSpawns && result; ++i) - { - // read model spawns - ModelSpawn spawn; - result = ModelSpawn::readFromFile(tf, spawn); - if (result) - { - // acquire model instance - WorldModel* model = vm->acquireModelInstance(iBasePath, spawn.name); - if (!model) - VMAP_ERROR_LOG("misc", "StaticMapTree::LoadMapTile() : could not acquire WorldModel pointer [%u, %u]", tileX, tileY); - - // update tree - uint32 referencedVal; - - if (fread(&referencedVal, sizeof(uint32), 1, tf) == 1) - { - if (!iLoadedSpawns.count(referencedVal)) - { - if (referencedVal > iNTreeValues) - { - VMAP_ERROR_LOG("maps", "StaticMapTree::LoadMapTile() : invalid tree element (%u/%u) referenced in tile %s", referencedVal, iNTreeValues, tilefile.c_str()); - continue; - } - - iTreeValues[referencedVal] = ModelInstance(spawn, model); - iLoadedSpawns[referencedVal] = 1; - } - else - { - ++iLoadedSpawns[referencedVal]; -#ifdef VMAP_DEBUG - if (iTreeValues[referencedVal].ID != spawn.ID) - TC_LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : trying to load wrong spawn in node"); - else if (iTreeValues[referencedVal].name != spawn.name) - TC_LOG_DEBUG("maps", "StaticMapTree::LoadMapTile() : name collision on GUID=%u", spawn.ID); -#endif - } - } - else - result = false; - } - } - iLoadedTiles[packTileID(tileX, tileY)] = true; - fclose(tf); - } - else - iLoadedTiles[packTileID(tileX, tileY)] = false; - return result; - } - - //========================================================= - - void StaticMapTree::UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm) - { - uint32 tileID = packTileID(tileX, tileY); - loadedTileMap::iterator tile = iLoadedTiles.find(tileID); - if (tile == iLoadedTiles.end()) - { - VMAP_ERROR_LOG("misc", "StaticMapTree::UnloadMapTile() : trying to unload non-loaded tile - Map:%u X:%u Y:%u", iMapID, tileX, tileY); - return; - } - if (tile->second) // file associated with tile - { - std::string tilefile = iBasePath + getTileFileName(iMapID, tileX, tileY); - FILE* tf = fopen(tilefile.c_str(), "rb"); - if (tf) - { - bool result=true; - char chunk[8]; - if (!readChunk(tf, chunk, VMAP_MAGIC, 8)) - result = false; - uint32 numSpawns; - if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1) - result = false; - for (uint32 i=0; i<numSpawns && result; ++i) - { - // read model spawns - ModelSpawn spawn; - result = ModelSpawn::readFromFile(tf, spawn); - if (result) - { - // release model instance - vm->releaseModelInstance(spawn.name); - - // update tree - uint32 referencedNode; - - if (fread(&referencedNode, sizeof(uint32), 1, tf) != 1) - result = false; - else - { - if (!iLoadedSpawns.count(referencedNode)) - VMAP_ERROR_LOG("misc", "StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID); - else if (--iLoadedSpawns[referencedNode] == 0) - { - iTreeValues[referencedNode].setUnloaded(); - iLoadedSpawns.erase(referencedNode); - } - } - } - } - fclose(tf); - } - } - iLoadedTiles.erase(tile); - } -} diff --git a/src/server/collision/Maps/MapTree.h b/src/server/collision/Maps/MapTree.h deleted file mode 100644 index 08bd5c3d3a1..00000000000 --- a/src/server/collision/Maps/MapTree.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _MAPTREE_H -#define _MAPTREE_H - -#include "Define.h" -#include "BoundingIntervalHierarchy.h" -#include <unordered_map> - -namespace VMAP -{ - class ModelInstance; - class GroupModel; - class VMapManager2; - - struct LocationInfo - { - LocationInfo(): hitInstance(nullptr), hitModel(nullptr), ground_Z(-G3D::finf()) { } - const ModelInstance* hitInstance; - const GroupModel* hitModel; - float ground_Z; - }; - - class StaticMapTree - { - typedef std::unordered_map<uint32, bool> loadedTileMap; - typedef std::unordered_map<uint32, uint32> loadedSpawnMap; - private: - uint32 iMapID; - bool iIsTiled; - BIH iTree; - ModelInstance* iTreeValues; // the tree entries - uint32 iNTreeValues; - - // Store all the map tile idents that are loaded for that map - // some maps are not splitted into tiles and we have to make sure, not removing the map before all tiles are removed - // empty tiles have no tile file, hence map with bool instead of just a set (consistency check) - loadedTileMap iLoadedTiles; - // stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors - loadedSpawnMap iLoadedSpawns; - std::string iBasePath; - - private: - bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool pStopAtFirstHit) const; - //bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); } - public: - static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY); - static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | tileY; } - static void unpackTileID(uint32 ID, uint32 &tileX, uint32 &tileY) { tileX = ID>>16; tileY = ID&0xFF; } - static bool CanLoadMap(const std::string &basePath, uint32 mapID, uint32 tileX, uint32 tileY); - - StaticMapTree(uint32 mapID, const std::string &basePath); - ~StaticMapTree(); - - bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const; - bool getObjectHitPos(const G3D::Vector3& pos1, const G3D::Vector3& pos2, G3D::Vector3& pResultHitPos, float pModifyDist) const; - float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const; - bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const; - bool GetLocationInfo(const G3D::Vector3 &pos, LocationInfo &info) const; - - bool InitMap(const std::string &fname, VMapManager2* vm); - void UnloadMap(VMapManager2* vm); - bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); - void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm); - bool isTiled() const { return iIsTiled; } - uint32 numLoadedTiles() const { return iLoadedTiles.size(); } - void getModelInstances(ModelInstance* &models, uint32 &count); - - private: - StaticMapTree(StaticMapTree const& right) = delete; - StaticMapTree& operator=(StaticMapTree const& right) = delete; - }; - - struct AreaInfo - { - AreaInfo(): result(false), ground_Z(-G3D::finf()), flags(0), adtId(0), - rootId(0), groupId(0) { } - bool result; - float ground_Z; - uint32 flags; - int32 adtId; - int32 rootId; - int32 groupId; - }; -} // VMAP - -#endif // _MAPTREE_H diff --git a/src/server/collision/Maps/TileAssembler.cpp b/src/server/collision/Maps/TileAssembler.cpp deleted file mode 100644 index ec7b759f975..00000000000 --- a/src/server/collision/Maps/TileAssembler.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "TileAssembler.h" -#include "MapTree.h" -#include "BoundingIntervalHierarchy.h" -#include "VMapDefinitions.h" - -#include <set> -#include <iomanip> -#include <sstream> - -using G3D::Vector3; -using G3D::AABox; -using G3D::inf; -using std::pair; - -template<> struct BoundsTrait<VMAP::ModelSpawn*> -{ - static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); } -}; - -namespace VMAP -{ - bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len) - { - if (fread(dest, sizeof(char), len, rf) != len) return false; - return memcmp(dest, compare, len) == 0; - } - - Vector3 ModelPosition::transform(const Vector3& pIn) const - { - Vector3 out = pIn * iScale; - out = iRotation * out; - return(out); - } - - //================================================================= - - TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName) - : iDestDir(pDestDirName), iSrcDir(pSrcDirName), iFilterMethod(NULL), iCurrentUniqueNameId(0) - { - //mkdir(iDestDir); - //init(); - } - - TileAssembler::~TileAssembler() - { - //delete iCoordModelMapping; - } - - bool TileAssembler::convertWorld2() - { - bool success = readMapSpawns(); - if (!success) - return false; - - // export Map data - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end() && success; ++map_iter) - { - // build global map tree - std::vector<ModelSpawn*> mapSpawns; - UniqueEntryMap::iterator entry; - printf("Calculating model bounds for map %u...\n", map_iter->first); - for (entry = map_iter->second->UniqueEntries.begin(); entry != map_iter->second->UniqueEntries.end(); ++entry) - { - // M2 models don't have a bound set in WDT/ADT placement data, i still think they're not used for LoS at all on retail - if (entry->second.flags & MOD_M2) - { - if (!calculateTransformedBound(entry->second)) - break; - } - else if (entry->second.flags & MOD_WORLDSPAWN) // WMO maps and terrain maps use different origin, so we need to adapt :/ - { - /// @todo remove extractor hack and uncomment below line: - //entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f); - entry->second.iBound = entry->second.iBound + Vector3(533.33333f*32, 533.33333f*32, 0.f); - } - mapSpawns.push_back(&(entry->second)); - spawnedModelFiles.insert(entry->second.name); - } - - printf("Creating map tree for map %u...\n", map_iter->first); - BIH pTree; - - try - { - pTree.build(mapSpawns, BoundsTrait<ModelSpawn*>::getBounds); - } - catch (std::exception& e) - { - printf("Exception ""%s"" when calling pTree.build", e.what()); - return false; - } - - // ===> possibly move this code to StaticMapTree class - std::map<uint32, uint32> modelNodeIdx; - for (uint32 i=0; i<mapSpawns.size(); ++i) - modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i)); - - // write map tree file - std::stringstream mapfilename; - mapfilename << iDestDir << '/' << std::setfill('0') << std::setw(3) << map_iter->first << ".vmtree"; - FILE* mapfile = fopen(mapfilename.str().c_str(), "wb"); - if (!mapfile) - { - success = false; - printf("Cannot open %s\n", mapfilename.str().c_str()); - break; - } - - //general info - if (success && fwrite(VMAP_MAGIC, 1, 8, mapfile) != 8) success = false; - uint32 globalTileID = StaticMapTree::packTileID(65, 65); - pair<TileMap::iterator, TileMap::iterator> globalRange = map_iter->second->TileEntries.equal_range(globalTileID); - char isTiled = globalRange.first == globalRange.second; // only maps without terrain (tiles) have global WMO - if (success && fwrite(&isTiled, sizeof(char), 1, mapfile) != 1) success = false; - // Nodes - if (success && fwrite("NODE", 4, 1, mapfile) != 1) success = false; - if (success) success = pTree.writeToFile(mapfile); - // global map spawns (WDT), if any (most instances) - if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false; - - for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob) - { - success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]); - } - - fclose(mapfile); - - // <==== - - // write map tile files, similar to ADT files, only with extra BSP tree node info - TileMap &tileEntries = map_iter->second->TileEntries; - TileMap::iterator tile; - for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile) - { - const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second]; - if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently... - continue; - uint32 nSpawns = tileEntries.count(tile->first); - std::stringstream tilefilename; - tilefilename.fill('0'); - tilefilename << iDestDir << '/' << std::setw(3) << map_iter->first << '_'; - uint32 x, y; - StaticMapTree::unpackTileID(tile->first, x, y); - tilefilename << std::setw(2) << x << '_' << std::setw(2) << y << ".vmtile"; - if (FILE* tilefile = fopen(tilefilename.str().c_str(), "wb")) - { - // file header - if (success && fwrite(VMAP_MAGIC, 1, 8, tilefile) != 8) success = false; - // write number of tile spawns - if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false; - // write tile spawns - for (uint32 s=0; s<nSpawns; ++s) - { - if (s) - ++tile; - const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second]; - success = success && ModelSpawn::writeToFile(tilefile, spawn2); - // MapTree nodes to update when loading tile: - std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID); - if (success && fwrite(&nIdx->second, sizeof(uint32), 1, tilefile) != 1) success = false; - } - fclose(tilefile); - } - } - // break; //test, extract only first map; TODO: remvoe this line - } - - // add an object models, listed in temp_gameobject_models file - exportGameobjectModels(); - // export objects - std::cout << "\nConverting Model Files" << std::endl; - for (std::set<std::string>::iterator mfile = spawnedModelFiles.begin(); mfile != spawnedModelFiles.end(); ++mfile) - { - std::cout << "Converting " << *mfile << std::endl; - if (!convertRawFile(*mfile)) - { - std::cout << "error converting " << *mfile << std::endl; - success = false; - break; - } - } - - //cleanup: - for (MapData::iterator map_iter = mapData.begin(); map_iter != mapData.end(); ++map_iter) - { - delete map_iter->second; - } - return success; - } - - bool TileAssembler::readMapSpawns() - { - std::string fname = iSrcDir + "/dir_bin"; - FILE* dirf = fopen(fname.c_str(), "rb"); - if (!dirf) - { - printf("Could not read dir_bin file!\n"); - return false; - } - printf("Read coordinate mapping...\n"); - uint32 mapID, tileX, tileY, check=0; - G3D::Vector3 v1, v2; - ModelSpawn spawn; - while (!feof(dirf)) - { - check = 0; - // read mapID, tileX, tileY, Flags, adtID, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name - check += fread(&mapID, sizeof(uint32), 1, dirf); - if (check == 0) // EoF... - break; - check += fread(&tileX, sizeof(uint32), 1, dirf); - check += fread(&tileY, sizeof(uint32), 1, dirf); - if (!ModelSpawn::readFromFile(dirf, spawn)) - break; - - MapSpawns *current; - MapData::iterator map_iter = mapData.find(mapID); - if (map_iter == mapData.end()) - { - printf("spawning Map %u\n", mapID); - mapData[mapID] = current = new MapSpawns(); - } - else current = (*map_iter).second; - current->UniqueEntries.insert(pair<uint32, ModelSpawn>(spawn.ID, spawn)); - current->TileEntries.insert(pair<uint32, uint32>(StaticMapTree::packTileID(tileX, tileY), spawn.ID)); - } - bool success = (ferror(dirf) == 0); - fclose(dirf); - return success; - } - - bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn) - { - std::string modelFilename(iSrcDir); - modelFilename.push_back('/'); - modelFilename.append(spawn.name); - - ModelPosition modelPosition; - modelPosition.iDir = spawn.iRot; - modelPosition.iScale = spawn.iScale; - modelPosition.init(); - - WorldModel_Raw raw_model; - if (!raw_model.Read(modelFilename.c_str())) - return false; - - uint32 groups = raw_model.groupsArray.size(); - if (groups != 1) - printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str()); - - AABox modelBound; - bool boundEmpty=true; - - for (uint32 g=0; g<groups; ++g) // should be only one for M2 files... - { - std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; - - if (vertices.empty()) - { - std::cout << "error: model '" << spawn.name << "' has no geometry!" << std::endl; - continue; - } - - uint32 nvectors = vertices.size(); - for (uint32 i = 0; i < nvectors; ++i) - { - Vector3 v = modelPosition.transform(vertices[i]); - - if (boundEmpty) - modelBound = AABox(v, v), boundEmpty=false; - else - modelBound.merge(v); - } - } - spawn.iBound = modelBound + spawn.iPos; - spawn.flags |= MOD_HAS_BOUND; - return true; - } - - struct WMOLiquidHeader - { - int xverts, yverts, xtiles, ytiles; - float pos_x; - float pos_y; - float pos_z; - short type; - }; - //================================================================= - bool TileAssembler::convertRawFile(const std::string& pModelFilename) - { - bool success = true; - std::string filename = iSrcDir; - if (filename.length() >0) - filename.push_back('/'); - filename.append(pModelFilename); - - WorldModel_Raw raw_model; - if (!raw_model.Read(filename.c_str())) - return false; - - // write WorldModel - WorldModel model; - model.setRootWmoID(raw_model.RootWMOID); - if (!raw_model.groupsArray.empty()) - { - std::vector<GroupModel> groupsArray; - - uint32 groups = raw_model.groupsArray.size(); - for (uint32 g = 0; g < groups; ++g) - { - GroupModel_Raw& raw_group = raw_model.groupsArray[g]; - groupsArray.push_back(GroupModel(raw_group.mogpflags, raw_group.GroupWMOID, raw_group.bounds )); - groupsArray.back().setMeshData(raw_group.vertexArray, raw_group.triangles); - groupsArray.back().setLiquidData(raw_group.liquid); - } - - model.setGroupModels(groupsArray); - } - - success = model.writeFile(iDestDir + "/" + pModelFilename + ".vmo"); - //std::cout << "readRawFile2: '" << pModelFilename << "' tris: " << nElements << " nodes: " << nNodes << std::endl; - return success; - } - - void TileAssembler::exportGameobjectModels() - { - FILE* model_list = fopen((iSrcDir + "/" + "temp_gameobject_models").c_str(), "rb"); - if (!model_list) - return; - - FILE* model_list_copy = fopen((iDestDir + "/" + GAMEOBJECT_MODELS).c_str(), "wb"); - if (!model_list_copy) - { - fclose(model_list); - return; - } - - uint32 name_length, displayId; - char buff[500]; - while (!feof(model_list)) - { - if (fread(&displayId, sizeof(uint32), 1, model_list) != 1 - || fread(&name_length, sizeof(uint32), 1, model_list) != 1 - || name_length >= sizeof(buff) - || fread(&buff, sizeof(char), name_length, model_list) != name_length) - { - std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl; - break; - } - - std::string model_name(buff, name_length); - - WorldModel_Raw raw_model; - if ( !raw_model.Read((iSrcDir + "/" + model_name).c_str()) ) - continue; - - spawnedModelFiles.insert(model_name); - AABox bounds; - bool boundEmpty = true; - for (uint32 g = 0; g < raw_model.groupsArray.size(); ++g) - { - std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray; - - uint32 nvectors = vertices.size(); - for (uint32 i = 0; i < nvectors; ++i) - { - Vector3& v = vertices[i]; - if (boundEmpty) - bounds = AABox(v, v), boundEmpty = false; - else - bounds.merge(v); - } - } - - if (bounds.isEmpty()) - { - std::cout << "\nModel " << std::string(buff, name_length) << " has empty bounding box" << std::endl; - continue; - } - - if (!bounds.isFinite()) - { - std::cout << "\nModel " << std::string(buff, name_length) << " has invalid bounding box" << std::endl; - continue; - } - - fwrite(&displayId, sizeof(uint32), 1, model_list_copy); - fwrite(&name_length, sizeof(uint32), 1, model_list_copy); - fwrite(&buff, sizeof(char), name_length, model_list_copy); - fwrite(&bounds.low(), sizeof(Vector3), 1, model_list_copy); - fwrite(&bounds.high(), sizeof(Vector3), 1, model_list_copy); - } - - fclose(model_list); - fclose(model_list_copy); - } - // temporary use defines to simplify read/check code (close file and return at fail) - #define READ_OR_RETURN(V, S) if (fread((V), (S), 1, rf) != 1) { \ - fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); } - #define READ_OR_RETURN_WITH_DELETE(V, S) if (fread((V), (S), 1, rf) != 1) { \ - fclose(rf); printf("readfail, op = %i\n", readOperation); delete[] V; return(false); }; - #define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \ - fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); } - - bool GroupModel_Raw::Read(FILE* rf) - { - char blockId[5]; - blockId[4] = 0; - int blocksize; - int readOperation = 0; - - READ_OR_RETURN(&mogpflags, sizeof(uint32)); - READ_OR_RETURN(&GroupWMOID, sizeof(uint32)); - - - Vector3 vec1, vec2; - READ_OR_RETURN(&vec1, sizeof(Vector3)); - - READ_OR_RETURN(&vec2, sizeof(Vector3)); - bounds.set(vec1, vec2); - - READ_OR_RETURN(&liquidflags, sizeof(uint32)); - - // will this ever be used? what is it good for anyway?? - uint32 branches; - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "GRP "); - READ_OR_RETURN(&blocksize, sizeof(int)); - READ_OR_RETURN(&branches, sizeof(uint32)); - for (uint32 b=0; b<branches; ++b) - { - uint32 indexes; - // indexes for each branch (not used jet) - READ_OR_RETURN(&indexes, sizeof(uint32)); - } - - // ---- indexes - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "INDX"); - READ_OR_RETURN(&blocksize, sizeof(int)); - uint32 nindexes; - READ_OR_RETURN(&nindexes, sizeof(uint32)); - if (nindexes >0) - { - uint16 *indexarray = new uint16[nindexes]; - READ_OR_RETURN_WITH_DELETE(indexarray, nindexes*sizeof(uint16)); - triangles.reserve(nindexes / 3); - for (uint32 i=0; i<nindexes; i+=3) - triangles.push_back(MeshTriangle(indexarray[i], indexarray[i+1], indexarray[i+2])); - - delete[] indexarray; - } - - // ---- vectors - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "VERT"); - READ_OR_RETURN(&blocksize, sizeof(int)); - uint32 nvectors; - READ_OR_RETURN(&nvectors, sizeof(uint32)); - - if (nvectors >0) - { - float *vectorarray = new float[nvectors*3]; - READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors*sizeof(float)*3); - for (uint32 i=0; i<nvectors; ++i) - vertexArray.push_back( Vector3(vectorarray + 3*i) ); - - delete[] vectorarray; - } - // ----- liquid - liquid = 0; - if (liquidflags& 1) - { - WMOLiquidHeader hlq; - READ_OR_RETURN(&blockId, 4); - CMP_OR_RETURN(blockId, "LIQU"); - READ_OR_RETURN(&blocksize, sizeof(int)); - READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader)); - liquid = new WmoLiquid(hlq.xtiles, hlq.ytiles, Vector3(hlq.pos_x, hlq.pos_y, hlq.pos_z), hlq.type); - uint32 size = hlq.xverts*hlq.yverts; - READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float)); - size = hlq.xtiles*hlq.ytiles; - READ_OR_RETURN(liquid->GetFlagsStorage(), size); - } - - return true; - } - - - GroupModel_Raw::~GroupModel_Raw() - { - delete liquid; - } - - bool WorldModel_Raw::Read(const char * path) - { - FILE* rf = fopen(path, "rb"); - if (!rf) - { - printf("ERROR: Can't open raw model file: %s\n", path); - return false; - } - - char ident[9]; - ident[8] = '\0'; - int readOperation = 0; - - READ_OR_RETURN(&ident, 8); - CMP_OR_RETURN(ident, RAW_VMAP_MAGIC); - - // we have to read one int. This is needed during the export and we have to skip it here - uint32 tempNVectors; - READ_OR_RETURN(&tempNVectors, sizeof(tempNVectors)); - - uint32 groups; - READ_OR_RETURN(&groups, sizeof(uint32)); - READ_OR_RETURN(&RootWMOID, sizeof(uint32)); - - groupsArray.resize(groups); - bool succeed = true; - for (uint32 g = 0; g < groups && succeed; ++g) - succeed = groupsArray[g].Read(rf); - - if (succeed) /// rf will be freed inside Read if the function had any errors. - fclose(rf); - return succeed; - } - - // drop of temporary use defines - #undef READ_OR_RETURN - #undef CMP_OR_RETURN -} diff --git a/src/server/collision/Maps/TileAssembler.h b/src/server/collision/Maps/TileAssembler.h deleted file mode 100644 index 581622c6b73..00000000000 --- a/src/server/collision/Maps/TileAssembler.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _TILEASSEMBLER_H_ -#define _TILEASSEMBLER_H_ - -#include <G3D/Vector3.h> -#include <G3D/Matrix3.h> -#include <map> -#include <set> - -#include "ModelInstance.h" -#include "WorldModel.h" - -namespace VMAP -{ - /** - This Class is used to convert raw vector data into balanced BSP-Trees. - To start the conversion call convertWorld(). - */ - //=============================================== - - class ModelPosition - { - private: - G3D::Matrix3 iRotation; - public: - ModelPosition(): iScale(0.0f) { } - G3D::Vector3 iPos; - G3D::Vector3 iDir; - float iScale; - void init() - { - iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iDir.y/180.f, G3D::pif()*iDir.x/180.f, G3D::pif()*iDir.z/180.f); - } - G3D::Vector3 transform(const G3D::Vector3& pIn) const; - void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; } - }; - - typedef std::map<uint32, ModelSpawn> UniqueEntryMap; - typedef std::multimap<uint32, uint32> TileMap; - - struct MapSpawns - { - UniqueEntryMap UniqueEntries; - TileMap TileEntries; - }; - - typedef std::map<uint32, MapSpawns*> MapData; - //=============================================== - - struct GroupModel_Raw - { - uint32 mogpflags; - uint32 GroupWMOID; - - G3D::AABox bounds; - uint32 liquidflags; - std::vector<MeshTriangle> triangles; - std::vector<G3D::Vector3> vertexArray; - class WmoLiquid* liquid; - - GroupModel_Raw() : mogpflags(0), GroupWMOID(0), liquidflags(0), - liquid(NULL) { } - ~GroupModel_Raw(); - - bool Read(FILE* f); - }; - - struct WorldModel_Raw - { - uint32 RootWMOID; - std::vector<GroupModel_Raw> groupsArray; - - bool Read(const char * path); - }; - - class TileAssembler - { - private: - std::string iDestDir; - std::string iSrcDir; - bool (*iFilterMethod)(char *pName); - G3D::Table<std::string, unsigned int > iUniqueNameIds; - unsigned int iCurrentUniqueNameId; - MapData mapData; - std::set<std::string> spawnedModelFiles; - - public: - TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName); - virtual ~TileAssembler(); - - bool convertWorld2(); - bool readMapSpawns(); - bool calculateTransformedBound(ModelSpawn &spawn); - void exportGameobjectModels(); - - bool convertRawFile(const std::string& pModelFilename); - void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; } - std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName); - }; - -} // VMAP -#endif /*_TILEASSEMBLER_H_*/ diff --git a/src/server/collision/Models/GameObjectModel.cpp b/src/server/collision/Models/GameObjectModel.cpp deleted file mode 100644 index dbdc0554e06..00000000000 --- a/src/server/collision/Models/GameObjectModel.cpp +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "VMapFactory.h" -#include "VMapManager2.h" -#include "VMapDefinitions.h" -#include "WorldModel.h" -#include "GameObjectModel.h" -#include "Log.h" -#include "Timer.h" - -using G3D::Vector3; -using G3D::Ray; -using G3D::AABox; - -struct GameobjectModelData -{ - GameobjectModelData(const std::string& name_, const AABox& box) : - bound(box), name(name_) { } - - AABox bound; - std::string name; -}; - -typedef std::unordered_map<uint32, GameobjectModelData> ModelList; -ModelList model_list; - -void LoadGameObjectModelList(std::string const& dataPath) -{ -#ifndef NO_CORE_FUNCS - uint32 oldMSTime = getMSTime(); -#endif - - FILE* model_list_file = fopen((dataPath + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb"); - if (!model_list_file) - { - VMAP_ERROR_LOG("misc", "Unable to open '%s' file.", VMAP::GAMEOBJECT_MODELS); - return; - } - - uint32 name_length, displayId; - char buff[500]; - while (true) - { - Vector3 v1, v2; - if (fread(&displayId, sizeof(uint32), 1, model_list_file) != 1) - if (feof(model_list_file)) // EOF flag is only set after failed reading attempt - break; - - if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1 - || name_length >= sizeof(buff) - || fread(&buff, sizeof(char), name_length, model_list_file) != name_length - || fread(&v1, sizeof(Vector3), 1, model_list_file) != 1 - || fread(&v2, sizeof(Vector3), 1, model_list_file) != 1) - { - VMAP_ERROR_LOG("misc", "File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS); - break; - } - - if (v1.isNaN() || v2.isNaN()) - { - VMAP_ERROR_LOG("misc", "File '%s' Model '%s' has invalid v1%s v2%s values!", VMAP::GAMEOBJECT_MODELS, std::string(buff, name_length).c_str(), v1.toString().c_str(), v2.toString().c_str()); - continue; - } - - model_list.insert - ( - ModelList::value_type(displayId, GameobjectModelData(std::string(buff, name_length), AABox(v1, v2))) - ); - } - - fclose(model_list_file); - VMAP_INFO_LOG("server.loading", ">> Loaded %u GameObject models in %u ms", uint32(model_list.size()), GetMSTimeDiffToNow(oldMSTime)); -} - -GameObjectModel::~GameObjectModel() -{ - if (iModel) - ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->releaseModelInstance(name); -} - -bool GameObjectModel::initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath) -{ - ModelList::const_iterator it = model_list.find(modelOwner->GetDisplayId()); - if (it == model_list.end()) - return false; - - G3D::AABox mdl_box(it->second.bound); - // ignore models with no bounds - if (mdl_box == G3D::AABox::zero()) - { - VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); - return false; - } - - iModel = ((VMAP::VMapManager2*)VMAP::VMapFactory::createOrGetVMapManager())->acquireModelInstance(dataPath + "vmaps/", it->second.name); - - if (!iModel) - return false; - - name = it->second.name; - iPos = modelOwner->GetPosition(); - phasemask = modelOwner->GetPhaseMask(); - iScale = modelOwner->GetScale(); - iInvScale = 1.f / iScale; - - G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(modelOwner->GetOrientation(), 0, 0); - iInvRot = iRotation.inverse(); - // transform bounding box: - mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale); - AABox rotated_bounds; - for (int i = 0; i < 8; ++i) - rotated_bounds.merge(iRotation * mdl_box.corner(i)); - - iBound = rotated_bounds + iPos; -#ifdef SPAWN_CORNERS - // test: - for (int i = 0; i < 8; ++i) - { - Vector3 pos(iBound.corner(i)); - modelOwner->DebugVisualizeCorner(pos); - } -#endif - - owner = std::move(modelOwner); - return true; -} - -GameObjectModel* GameObjectModel::Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath) -{ - GameObjectModel* mdl = new GameObjectModel(); - if (!mdl->initialize(std::move(modelOwner), dataPath)) - { - delete mdl; - return NULL; - } - - return mdl; -} - -bool GameObjectModel::intersectRay(const G3D::Ray& ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const -{ - if (!(phasemask & ph_mask) || !owner->IsSpawned()) - return false; - - float time = ray.intersectionTime(iBound); - if (time == G3D::finf()) - return false; - - // child bounds are defined in object space: - Vector3 p = iInvRot * (ray.origin() - iPos) * iInvScale; - Ray modRay(p, iInvRot * ray.direction()); - float distance = MaxDist * iInvScale; - bool hit = iModel->IntersectRay(modRay, distance, StopAtFirstHit); - if (hit) - { - distance *= iScale; - MaxDist = distance; - } - return hit; -} - -bool GameObjectModel::UpdatePosition() -{ - if (!iModel) - return false; - - ModelList::const_iterator it = model_list.find(owner->GetDisplayId()); - if (it == model_list.end()) - return false; - - G3D::AABox mdl_box(it->second.bound); - // ignore models with no bounds - if (mdl_box == G3D::AABox::zero()) - { - VMAP_ERROR_LOG("misc", "GameObject model %s has zero bounds, loading skipped", it->second.name.c_str()); - return false; - } - - iPos = owner->GetPosition(); - - G3D::Matrix3 iRotation = G3D::Matrix3::fromEulerAnglesZYX(owner->GetOrientation(), 0, 0); - iInvRot = iRotation.inverse(); - // transform bounding box: - mdl_box = AABox(mdl_box.low() * iScale, mdl_box.high() * iScale); - AABox rotated_bounds; - for (int i = 0; i < 8; ++i) - rotated_bounds.merge(iRotation * mdl_box.corner(i)); - - iBound = rotated_bounds + iPos; -#ifdef SPAWN_CORNERS - // test: - for (int i = 0; i < 8; ++i) - { - Vector3 pos(iBound.corner(i)); - owner->DebugVisualizeCorner(pos); - } -#endif - - return true; -} diff --git a/src/server/collision/Models/GameObjectModel.h b/src/server/collision/Models/GameObjectModel.h deleted file mode 100644 index 17669189af5..00000000000 --- a/src/server/collision/Models/GameObjectModel.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _GAMEOBJECT_MODEL_H -#define _GAMEOBJECT_MODEL_H - -#include <G3D/Matrix3.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> - -#include "Define.h" -#include <memory> - -namespace VMAP -{ - class WorldModel; -} - -class GameObject; -struct GameObjectDisplayInfoEntry; - -class GameObjectModelOwnerBase -{ -public: - virtual bool IsSpawned() const { return false; } - virtual uint32 GetDisplayId() const { return 0; } - virtual uint32 GetPhaseMask() const { return 0; } - virtual G3D::Vector3 GetPosition() const { return G3D::Vector3::zero(); } - virtual float GetOrientation() const { return 0.0f; } - virtual float GetScale() const { return 1.0f; } - virtual void DebugVisualizeCorner(G3D::Vector3 const& /*corner*/) const { } -}; - -class GameObjectModel /*, public Intersectable*/ -{ - GameObjectModel() : phasemask(0), iInvScale(0), iScale(0), iModel(NULL) { } -public: - std::string name; - - const G3D::AABox& getBounds() const { return iBound; } - - ~GameObjectModel(); - - const G3D::Vector3& getPosition() const { return iPos;} - - /** Enables\disables collision. */ - void disable() { phasemask = 0;} - void enable(uint32 ph_mask) { phasemask = ph_mask;} - - bool isEnabled() const {return phasemask != 0;} - - bool intersectRay(const G3D::Ray& Ray, float& MaxDist, bool StopAtFirstHit, uint32 ph_mask) const; - - static GameObjectModel* Create(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath); - - bool UpdatePosition(); - -private: - bool initialize(std::unique_ptr<GameObjectModelOwnerBase> modelOwner, std::string const& dataPath); - - uint32 phasemask; - G3D::AABox iBound; - G3D::Matrix3 iInvRot; - G3D::Vector3 iPos; - float iInvScale; - float iScale; - VMAP::WorldModel* iModel; - std::unique_ptr<GameObjectModelOwnerBase> owner; -}; - -#endif // _GAMEOBJECT_MODEL_H diff --git a/src/server/collision/Models/ModelInstance.cpp b/src/server/collision/Models/ModelInstance.cpp deleted file mode 100644 index 45440a99666..00000000000 --- a/src/server/collision/Models/ModelInstance.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "ModelInstance.h" -#include "WorldModel.h" -#include "MapTree.h" - -using G3D::Vector3; -using G3D::Ray; - -namespace VMAP -{ - ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel* model): ModelSpawn(spawn), iModel(model) - { - iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::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) const - { - if (!iModel) - { - //std::cout << "<object not loaded>\n"; - return false; - } - float time = pRay.intersectionTime(iBound); - if (time == G3D::finf()) - { -// std::cout << "Ray does not hit '" << name << "'\n"; - - return false; - } -// std::cout << "Ray crosses bound of '" << name << "'\n"; -/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z - << " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z - << " t/tmax:" << time << '/' << pMaxDist; - std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: " - << iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */ - // child bounds are defined in object space: - Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale; - Ray modRay(p, iInvRot * pRay.direction()); - float distance = pMaxDist * iInvScale; - bool hit = iModel->IntersectRay(modRay, distance, pStopAtFirstHit); - if (hit) - { - distance *= iScale; - pMaxDist = distance; - } - return hit; - } - - void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "<object not loaded>\n"; -#endif - return; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return; - if (!iBound.contains(p)) - return; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->IntersectPoint(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) - { - info.ground_Z = world_Z; - info.adtId = adtId; - } - } - } - - bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const - { - if (!iModel) - { -#ifdef VMAP_DEBUG - std::cout << "<object not loaded>\n"; -#endif - return false; - } - - // M2 files don't contain area info, only WMO files - if (flags & MOD_M2) - return false; - if (!iBound.contains(p)) - return false; - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (iModel->GetLocationInfo(pModel, zDirModel, zDist, info)) - { - Vector3 modelGround = pModel + zDist * zDirModel; - // Transform back to world space. Note that: - // Mat * vec == vec * Mat.transpose() - // and for rotation matrices: Mat.inverse() == Mat.transpose() - float world_Z = ((modelGround * iInvRot) * iScale + iPos).z; - if (info.ground_Z < world_Z) // hm...could it be handled automatically with zDist at intersection? - { - info.ground_Z = world_Z; - info.hitInstance = this; - return true; - } - } - return false; - } - - bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const - { - // child bounds are defined in object space: - Vector3 pModel = iInvRot * (p - iPos) * iInvScale; - //Vector3 zDirModel = iInvRot * Vector3(0.f, 0.f, -1.f); - float zDist; - if (info.hitModel->GetLiquidLevel(pModel, zDist)) - { - // calculate world height (zDist in model coords): - // assume WMO not tilted (wouldn't make much sense anyway) - liqHeight = zDist * iScale + iPos.z; - return true; - } - return false; - } - - bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn &spawn) - { - uint32 check = 0, nameLen; - check += fread(&spawn.flags, sizeof(uint32), 1, rf); - // EoF? - if (!check) - { - if (ferror(rf)) - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - check += fread(&spawn.adtId, sizeof(uint16), 1, rf); - check += fread(&spawn.ID, sizeof(uint32), 1, rf); - check += fread(&spawn.iPos, sizeof(float), 3, rf); - check += fread(&spawn.iRot, sizeof(float), 3, rf); - check += fread(&spawn.iScale, sizeof(float), 1, rf); - bool has_bound = (spawn.flags & MOD_HAS_BOUND) != 0; - if (has_bound) // only WMOs have bound in MPQ, only available after computation - { - Vector3 bLow, bHigh; - check += fread(&bLow, sizeof(float), 3, rf); - check += fread(&bHigh, sizeof(float), 3, rf); - spawn.iBound = G3D::AABox(bLow, bHigh); - } - check += fread(&nameLen, sizeof(uint32), 1, rf); - if (check != uint32(has_bound ? 17 : 11)) - { - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - char nameBuff[500]; - if (nameLen > 500) // file names should never be that long, must be file error - { - std::cout << "Error reading ModelSpawn, file name too long!\n"; - return false; - } - check = fread(nameBuff, sizeof(char), nameLen, rf); - if (check != nameLen) - { - std::cout << "Error reading ModelSpawn!\n"; - return false; - } - spawn.name = std::string(nameBuff, nameLen); - return true; - } - - bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn &spawn) - { - uint32 check=0; - check += fwrite(&spawn.flags, sizeof(uint32), 1, wf); - check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf); - check += fwrite(&spawn.ID, sizeof(uint32), 1, wf); - check += fwrite(&spawn.iPos, sizeof(float), 3, wf); - check += fwrite(&spawn.iRot, sizeof(float), 3, wf); - check += fwrite(&spawn.iScale, sizeof(float), 1, wf); - bool has_bound = (spawn.flags & MOD_HAS_BOUND) != 0; - if (has_bound) // only WMOs have bound in MPQ, only available after computation - { - check += fwrite(&spawn.iBound.low(), sizeof(float), 3, wf); - check += fwrite(&spawn.iBound.high(), sizeof(float), 3, wf); - } - uint32 nameLen = spawn.name.length(); - check += fwrite(&nameLen, sizeof(uint32), 1, wf); - if (check != uint32(has_bound ? 17 : 11)) return false; - check = fwrite(spawn.name.c_str(), sizeof(char), nameLen, wf); - if (check != nameLen) return false; - return true; - } - -} diff --git a/src/server/collision/Models/ModelInstance.h b/src/server/collision/Models/ModelInstance.h deleted file mode 100644 index dfdb001db0a..00000000000 --- a/src/server/collision/Models/ModelInstance.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _MODELINSTANCE_H_ -#define _MODELINSTANCE_H_ - -#include <G3D/Matrix3.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> - -#include "Define.h" - -namespace VMAP -{ - class WorldModel; - struct AreaInfo; - struct LocationInfo; - - enum ModelFlags - { - MOD_M2 = 1, - MOD_WORLDSPAWN = 1<<1, - MOD_HAS_BOUND = 1<<2 - }; - - class ModelSpawn - { - public: - //mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name - uint32 flags; - uint16 adtId; - uint32 ID; - G3D::Vector3 iPos; - G3D::Vector3 iRot; - float iScale; - G3D::AABox iBound; - std::string name; - bool operator==(const ModelSpawn &other) const { return ID == other.ID; } - //uint32 hashCode() const { return ID; } - // temp? - const G3D::AABox& getBounds() const { return iBound; } - - static bool readFromFile(FILE* rf, ModelSpawn &spawn); - static bool writeToFile(FILE* rw, const ModelSpawn &spawn); - }; - - class ModelInstance: public ModelSpawn - { - public: - ModelInstance(): iInvScale(0.0f), iModel(nullptr) { } - ModelInstance(const ModelSpawn &spawn, WorldModel* model); - void setUnloaded() { iModel = nullptr; } - bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit) const; - void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const; - bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const; - bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const; - protected: - G3D::Matrix3 iInvRot; - float iInvScale; - WorldModel* iModel; - public: - WorldModel* getWorldModel(); - }; -} // namespace VMAP - -#endif // _MODELINSTANCE diff --git a/src/server/collision/Models/WorldModel.cpp b/src/server/collision/Models/WorldModel.cpp deleted file mode 100644 index 86ab9366c71..00000000000 --- a/src/server/collision/Models/WorldModel.cpp +++ /dev/null @@ -1,585 +0,0 @@ -/* - * Copyright (C) 2008-2015 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/>. - */ - -#include "WorldModel.h" -#include "VMapDefinitions.h" -#include "MapTree.h" - -using G3D::Vector3; -using G3D::Ray; - -template<> struct BoundsTrait<VMAP::GroupModel> -{ - static void getBounds(const VMAP::GroupModel& obj, G3D::AABox& out) { out = obj.GetBound(); } -}; - -namespace VMAP -{ - bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance) - { - static const float EPS = 1e-5f; - - // See RTR2 ch. 13.7 for the algorithm. - - const Vector3 e1 = points[tri.idx1] - points[tri.idx0]; - const Vector3 e2 = points[tri.idx2] - points[tri.idx0]; - const Vector3 p(ray.direction().cross(e2)); - const float a = e1.dot(p); - - if (std::fabs(a) < EPS) { - // Determinant is ill-conditioned; abort early - return false; - } - - const float f = 1.0f / a; - const Vector3 s(ray.origin() - points[tri.idx0]); - const float u = f * s.dot(p); - - if ((u < 0.0f) || (u > 1.0f)) { - // We hit the plane of the m_geometry, but outside the m_geometry - return false; - } - - const Vector3 q(s.cross(e1)); - const float v = f * ray.direction().dot(q); - - if ((v < 0.0f) || ((u + v) > 1.0f)) { - // We hit the plane of the triangle, but outside the triangle - return false; - } - - const float t = f * e2.dot(q); - - if ((t > 0.0f) && (t < distance)) - { - // This is a new hit, closer than the previous one - distance = t; - - /* baryCoord[0] = 1.0 - u - v; - baryCoord[1] = u; - baryCoord[2] = v; */ - - return true; - } - // This hit is after the previous hit, so ignore it - return false; - } - - class TriBoundFunc - { - public: - TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) { } - void operator()(const MeshTriangle &tri, G3D::AABox &out) const - { - G3D::Vector3 lo = vertices[tri.idx0]; - G3D::Vector3 hi = lo; - - lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]); - hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]); - - out = G3D::AABox(lo, hi); - } - protected: - const std::vector<Vector3>::const_iterator vertices; - }; - - // ===================== WmoLiquid ================================== - - WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type): - iTilesX(width), iTilesY(height), iCorner(corner), iType(type) - { - iHeight = new float[(width+1)*(height+1)]; - iFlags = new uint8[width*height]; - } - - WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(nullptr), iFlags(nullptr) - { - *this = other; // use assignment operator... - } - - WmoLiquid::~WmoLiquid() - { - delete[] iHeight; - delete[] iFlags; - } - - WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other) - { - if (this == &other) - return *this; - iTilesX = other.iTilesX; - iTilesY = other.iTilesY; - iCorner = other.iCorner; - iType = other.iType; - delete iHeight; - delete iFlags; - if (other.iHeight) - { - iHeight = new float[(iTilesX+1)*(iTilesY+1)]; - memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float)); - } - else - iHeight = nullptr; - if (other.iFlags) - { - iFlags = new uint8[iTilesX * iTilesY]; - memcpy(iFlags, other.iFlags, iTilesX * iTilesY); - } - else - iFlags = nullptr; - return *this; - } - - bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const - { - float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE; - uint32 tx = uint32(tx_f); - if (tx_f < 0.0f || tx >= iTilesX) - return false; - float ty_f = (pos.y - iCorner.y)/LIQUID_TILE_SIZE; - uint32 ty = uint32(ty_f); - if (ty_f < 0.0f || ty >= iTilesY) - return false; - - // check if tile shall be used for liquid level - // checking for 0x08 *might* be enough, but disabled tiles always are 0x?F: - if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F) - return false; - - // (dx, dy) coordinates inside tile, in [0, 1]^2 - float dx = tx_f - (float)tx; - float dy = ty_f - (float)ty; - - /* Tesselate tile to two triangles (not sure if client does it exactly like this) - - ^ dy - | - 1 x---------x (1, 1) - | (b) / | - | / | - | / | - | / (a) | - x---------x---> dx - 0 1 - */ - - const uint32 rowOffset = iTilesX + 1; - if (dx > dy) // case (a) - { - float sx = iHeight[tx+1 + ty * rowOffset] - iHeight[tx + ty * rowOffset]; - float sy = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx+1 + ty * rowOffset]; - liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; - } - else // case (b) - { - float sx = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx + (ty+1) * rowOffset]; - float sy = iHeight[tx + (ty+1) * rowOffset] - iHeight[tx + ty * rowOffset]; - liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy; - } - return true; - } - - uint32 WmoLiquid::GetFileSize() - { - return 2 * sizeof(uint32) + - sizeof(Vector3) + - (iTilesX + 1)*(iTilesY + 1) * sizeof(float) + - iTilesX * iTilesY; - } - - bool WmoLiquid::writeToFile(FILE* wf) - { - bool result = false; - if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 && - fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 && - fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 && - fwrite(&iType, sizeof(uint32), 1, wf) == 1) - { - uint32 size = (iTilesX + 1) * (iTilesY + 1); - if (fwrite(iHeight, sizeof(float), size, wf) == size) - { - size = iTilesX*iTilesY; - result = fwrite(iFlags, sizeof(uint8), size, wf) == size; - } - } - - return result; - } - - bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid* &out) - { - bool result = false; - WmoLiquid* liquid = new WmoLiquid(); - - if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 && - fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 && - fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 && - fread(&liquid->iType, sizeof(uint32), 1, rf) == 1) - { - uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1); - liquid->iHeight = new float[size]; - if (fread(liquid->iHeight, sizeof(float), size, rf) == size) - { - size = liquid->iTilesX * liquid->iTilesY; - liquid->iFlags = new uint8[size]; - result = fread(liquid->iFlags, sizeof(uint8), size, rf) == size; - } - } - - if (!result) - delete liquid; - else - out = liquid; - - return result; - } - - // ===================== GroupModel ================================== - - GroupModel::GroupModel(const GroupModel &other): - iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID), - vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(nullptr) - { - if (other.iLiquid) - iLiquid = new WmoLiquid(*other.iLiquid); - } - - void GroupModel::setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri) - { - vertices.swap(vert); - triangles.swap(tri); - TriBoundFunc bFunc(vertices); - meshTree.build(triangles, bFunc); - } - - bool GroupModel::writeToFile(FILE* wf) - { - bool result = true; - uint32 chunkSize, count; - - if (result && fwrite(&iBound, sizeof(G3D::AABox), 1, wf) != 1) result = false; - if (result && fwrite(&iMogpFlags, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&iGroupWMOID, sizeof(uint32), 1, wf) != 1) result = false; - - // write vertices - if (result && fwrite("VERT", 1, 4, wf) != 4) result = false; - count = vertices.size(); - chunkSize = sizeof(uint32)+ sizeof(Vector3)*count; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - if (!count) // models without (collision) geometry end here, unsure if they are useful - return result; - if (result && fwrite(&vertices[0], sizeof(Vector3), count, wf) != count) result = false; - - // write triangle mesh - if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false; - count = triangles.size(); - chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false; - - // write mesh BIH - if (result && fwrite("MBIH", 1, 4, wf) != 4) result = false; - if (result) result = meshTree.writeToFile(wf); - - // write liquid data - if (result && fwrite("LIQU", 1, 4, wf) != 4) result = false; - if (!iLiquid) - { - chunkSize = 0; - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - return result; - } - chunkSize = iLiquid->GetFileSize(); - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result) result = iLiquid->writeToFile(wf); - - return result; - } - - bool GroupModel::readFromFile(FILE* rf) - { - char chunk[8]; - bool result = true; - uint32 chunkSize = 0; - uint32 count = 0; - triangles.clear(); - vertices.clear(); - delete iLiquid; - iLiquid = NULL; - - if (result && fread(&iBound, sizeof(G3D::AABox), 1, rf) != 1) result = false; - if (result && fread(&iMogpFlags, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&iGroupWMOID, sizeof(uint32), 1, rf) != 1) result = false; - - // read vertices - if (result && !readChunk(rf, chunk, "VERT", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (!count) // models without (collision) geometry end here, unsure if they are useful - return result; - if (result) vertices.resize(count); - if (result && fread(&vertices[0], sizeof(Vector3), count, rf) != count) result = false; - - // read triangle mesh - if (result && !readChunk(rf, chunk, "TRIM", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (result) triangles.resize(count); - if (result && fread(&triangles[0], sizeof(MeshTriangle), count, rf) != count) result = false; - - // read mesh BIH - if (result && !readChunk(rf, chunk, "MBIH", 4)) result = false; - if (result) result = meshTree.readFromFile(rf); - - // write liquid data - if (result && !readChunk(rf, chunk, "LIQU", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && chunkSize > 0) - result = WmoLiquid::readFromFile(rf, iLiquid); - return result; - } - - struct GModelRayCallback - { - GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert): - vertices(vert.begin()), triangles(tris.begin()), hit(false) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*pStopAtFirstHit*/) - { - bool result = IntersectTriangle(triangles[entry], vertices, ray, distance); - if (result) hit=true; - return hit; - } - std::vector<Vector3>::const_iterator vertices; - std::vector<MeshTriangle>::const_iterator triangles; - bool hit; - }; - - bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const - { - if (triangles.empty()) - return false; - - GModelRayCallback callback(triangles, vertices); - meshTree.intersectRay(ray, callback, distance, stopAtFirstHit); - return callback.hit; - } - - bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const - { - if (triangles.empty() || !iBound.contains(pos)) - return false; - GModelRayCallback callback(triangles, vertices); - Vector3 rPos = pos - 0.1f * down; - float dist = G3D::finf(); - G3D::Ray ray(rPos, down); - bool hit = IntersectRay(ray, dist, false); - if (hit) - z_dist = dist - 0.1f; - return hit; - } - - bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const - { - if (iLiquid) - return iLiquid->GetLiquidHeight(pos, liqHeight); - return false; - } - - uint32 GroupModel::GetLiquidType() const - { - if (iLiquid) - return iLiquid->GetType(); - return 0; - } - - // ===================== WorldModel ================================== - - void WorldModel::setGroupModels(std::vector<GroupModel> &models) - { - groupModels.swap(models); - groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1); - } - - struct WModelRayCallBack - { - WModelRayCallBack(const std::vector<GroupModel> &mod): models(mod.begin()), hit(false) { } - bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool pStopAtFirstHit) - { - bool result = models[entry].IntersectRay(ray, distance, pStopAtFirstHit); - if (result) hit=true; - return hit; - } - std::vector<GroupModel>::const_iterator models; - bool hit; - }; - - bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const - { - // small M2 workaround, maybe better make separate class with virtual intersection funcs - // in any case, there's no need to use a bound tree if we only have one submodel - if (groupModels.size() == 1) - return groupModels[0].IntersectRay(ray, distance, stopAtFirstHit); - - WModelRayCallBack isc(groupModels); - groupTree.intersectRay(ray, isc, distance, stopAtFirstHit); - return isc.hit; - } - - class WModelAreaCallback { - public: - WModelAreaCallback(const std::vector<GroupModel> &vals, const Vector3 &down): - prims(vals.begin()), hit(vals.end()), minVol(G3D::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) - { - float group_Z; - //float pVol = prims[entry].GetBound().volume(); - //if (pVol < minVol) - //{ - /* if (prims[entry].iBound.contains(point)) */ - if (prims[entry].IsInsideObject(point, zVec, group_Z)) - { - //minVol = pVol; - //hit = prims + entry; - if (group_Z < zDist) - { - zDist = group_Z; - hit = prims + entry; - } -#ifdef VMAP_DEBUG - const GroupModel &gm = prims[entry]; - printf("%10u %8X %7.3f, %7.3f, %7.3f | %7.3f, %7.3f, %7.3f | z=%f, p_z=%f\n", gm.GetWmoID(), gm.GetMogpFlags(), - gm.GetBound().low().x, gm.GetBound().low().y, gm.GetBound().low().z, - gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z); -#endif - } - //} - //std::cout << "trying to intersect '" << prims[entry].name << "'\n"; - } - }; - - bool WorldModel::IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const - { - if (groupModels.empty()) - return false; - - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.rootId = RootWMOID; - info.groupId = callback.hit->GetWmoID(); - info.flags = callback.hit->GetMogpFlags(); - info.result = true; - dist = callback.zDist; - return true; - } - return false; - } - - bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const - { - if (groupModels.empty()) - return false; - - WModelAreaCallback callback(groupModels, down); - groupTree.intersectPoint(p, callback); - if (callback.hit != groupModels.end()) - { - info.hitModel = &(*callback.hit); - dist = callback.zDist; - return true; - } - return false; - } - - bool WorldModel::writeFile(const std::string &filename) - { - FILE* wf = fopen(filename.c_str(), "wb"); - if (!wf) - return false; - - uint32 chunkSize, count; - bool result = fwrite(VMAP_MAGIC, 1, 8, wf) == 8; - if (result && fwrite("WMOD", 1, 4, wf) != 4) result = false; - chunkSize = sizeof(uint32) + sizeof(uint32); - if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false; - - // write group models - count=groupModels.size(); - if (count) - { - if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false; - //chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count; - //if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false; - if (result && fwrite(&count, sizeof(uint32), 1, wf) != 1) result = false; - for (uint32 i=0; i<groupModels.size() && result; ++i) - result = groupModels[i].writeToFile(wf); - - // write group BIH - if (result && fwrite("GBIH", 1, 4, wf) != 4) result = false; - if (result) result = groupTree.writeToFile(wf); - } - - fclose(wf); - return result; - } - - bool WorldModel::readFile(const std::string &filename) - { - FILE* rf = fopen(filename.c_str(), "rb"); - if (!rf) - return false; - - bool result = true; - uint32 chunkSize = 0; - uint32 count = 0; - char chunk[8]; // Ignore the added magic header - if (!readChunk(rf, chunk, VMAP_MAGIC, 8)) result = false; - - if (result && !readChunk(rf, chunk, "WMOD", 4)) result = false; - if (result && fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - if (result && fread(&RootWMOID, sizeof(uint32), 1, rf) != 1) result = false; - - // read group models - if (result && readChunk(rf, chunk, "GMOD", 4)) - { - //if (fread(&chunkSize, sizeof(uint32), 1, rf) != 1) result = false; - - if (result && fread(&count, sizeof(uint32), 1, rf) != 1) result = false; - if (result) groupModels.resize(count); - //if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false; - for (uint32 i=0; i<count && result; ++i) - result = groupModels[i].readFromFile(rf); - - // read group BIH - if (result && !readChunk(rf, chunk, "GBIH", 4)) result = false; - if (result) result = groupTree.readFromFile(rf); - } - - fclose(rf); - return result; - } -} diff --git a/src/server/collision/Models/WorldModel.h b/src/server/collision/Models/WorldModel.h deleted file mode 100644 index 6a901a59fdf..00000000000 --- a/src/server/collision/Models/WorldModel.h +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _WORLDMODEL_H -#define _WORLDMODEL_H - -#include <G3D/HashTrait.h> -#include <G3D/Vector3.h> -#include <G3D/AABox.h> -#include <G3D/Ray.h> -#include "BoundingIntervalHierarchy.h" - -#include "Define.h" - -namespace VMAP -{ - class TreeNode; - struct AreaInfo; - struct LocationInfo; - - class MeshTriangle - { - public: - MeshTriangle() : idx0(0), idx1(0), idx2(0) { } - MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { } - - uint32 idx0; - uint32 idx1; - uint32 idx2; - }; - - class WmoLiquid - { - public: - WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type); - WmoLiquid(const WmoLiquid &other); - ~WmoLiquid(); - WmoLiquid& operator=(const WmoLiquid &other); - bool GetLiquidHeight(const G3D::Vector3 &pos, float &liqHeight) const; - uint32 GetType() const { return iType; } - float *GetHeightStorage() { return iHeight; } - uint8 *GetFlagsStorage() { return iFlags; } - uint32 GetFileSize(); - bool writeToFile(FILE* wf); - static bool readFromFile(FILE* rf, WmoLiquid* &liquid); - private: - WmoLiquid() : iTilesX(0), iTilesY(0), iCorner(), iType(0), iHeight(NULL), iFlags(NULL) { } - uint32 iTilesX; //!< number of tiles in x direction, each - uint32 iTilesY; - G3D::Vector3 iCorner; //!< the lower corner - uint32 iType; //!< liquid type - float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values - uint8 *iFlags; //!< info if liquid tile is used - public: - void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const; - }; - - /*! holding additional info for WMO group files */ - class 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() { 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; } - 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; - uint32 GetLiquidType() const; - bool writeToFile(FILE* wf); - bool readFromFile(FILE* rf); - const G3D::AABox& GetBound() const { return iBound; } - uint32 GetMogpFlags() const { return iMogpFlags; } - uint32 GetWmoID() const { return iGroupWMOID; } - protected: - G3D::AABox iBound; - uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor - uint32 iGroupWMOID; - std::vector<G3D::Vector3> vertices; - std::vector<MeshTriangle> triangles; - BIH meshTree; - WmoLiquid* iLiquid; - public: - void getMeshData(std::vector<G3D::Vector3> &vertices, std::vector<MeshTriangle> &triangles, WmoLiquid* &liquid); - }; - /*! Holds a model (converted M2 or WMO) in its original coordinate space */ - class WorldModel - { - public: - WorldModel(): RootWMOID(0) { } - - //! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry! - void setGroupModels(std::vector<GroupModel> &models); - void setRootWmoID(uint32 id) { RootWMOID = id; } - bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const; - bool IntersectPoint(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, AreaInfo &info) const; - bool GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const; - bool writeFile(const std::string &filename); - bool readFile(const std::string &filename); - protected: - uint32 RootWMOID; - std::vector<GroupModel> groupModels; - BIH groupTree; - public: - void getGroupModels(std::vector<GroupModel> &groupModels); - }; -} // namespace VMAP - -#endif // _WORLDMODEL_H diff --git a/src/server/collision/PrecompiledHeaders/collisionPCH.cpp b/src/server/collision/PrecompiledHeaders/collisionPCH.cpp deleted file mode 100644 index 36eae8e2b0d..00000000000 --- a/src/server/collision/PrecompiledHeaders/collisionPCH.cpp +++ /dev/null @@ -1 +0,0 @@ -#include "collisionPCH.h" diff --git a/src/server/collision/PrecompiledHeaders/collisionPCH.h b/src/server/collision/PrecompiledHeaders/collisionPCH.h deleted file mode 100644 index ece2ef1b8ef..00000000000 --- a/src/server/collision/PrecompiledHeaders/collisionPCH.h +++ /dev/null @@ -1,9 +0,0 @@ -#include "Define.h" -#include "VMapDefinitions.h" -#include "MapTree.h" -#include "WorldModel.h" -#include "ModelInstance.h" -#include "BoundingIntervalHierarchy.h" -#include "RegularGrid.h" -#include "BoundingIntervalHierarchyWrapper.h" -#include "GameObjectModel.h" diff --git a/src/server/collision/RegularGrid.h b/src/server/collision/RegularGrid.h deleted file mode 100644 index 6a2a07968ad..00000000000 --- a/src/server/collision/RegularGrid.h +++ /dev/null @@ -1,212 +0,0 @@ -#ifndef _REGULAR_GRID_H -#define _REGULAR_GRID_H - - -#include <G3D/Ray.h> -#include <G3D/Table.h> -#include <G3D/BoundsTrait.h> -#include <G3D/PositionTrait.h> - -#include "Errors.h" - -template<class Node> -struct NodeCreator{ - static Node * makeNode(int /*x*/, int /*y*/) { return new Node();} -}; - -template<class T, -class Node, -class NodeCreatorFunc = NodeCreator<Node>, - /*class BoundsFunc = BoundsTrait<T>,*/ -class PositionFunc = PositionTrait<T> -> -class RegularGrid2D -{ -public: - - enum{ - CELL_NUMBER = 64, - }; - - #define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed - #define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER) - - typedef G3D::Table<const T*, Node*> MemberTable; - - MemberTable memberTable; - Node* nodes[CELL_NUMBER][CELL_NUMBER]; - - RegularGrid2D(){ - memset(nodes, 0, sizeof(nodes)); - } - - ~RegularGrid2D(){ - for (int x = 0; x < CELL_NUMBER; ++x) - for (int y = 0; y < CELL_NUMBER; ++y) - delete nodes[x][y]; - } - - void insert(const T& value) - { - G3D::Vector3 pos; - PositionFunc::getPosition(value, pos); - Node& node = getGridFor(pos.x, pos.y); - node.insert(value); - memberTable.set(&value, &node); - } - - void remove(const T& value) - { - memberTable[&value]->remove(value); - // Remove the member - memberTable.remove(&value); - } - - void balance() - { - for (int x = 0; x < CELL_NUMBER; ++x) - for (int y = 0; y < CELL_NUMBER; ++y) - if (Node* n = nodes[x][y]) - n->balance(); - } - - bool contains(const T& value) const { return memberTable.containsKey(&value); } - int size() const { return memberTable.size(); } - - struct Cell - { - int x, y; - bool operator == (const Cell& 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)) }; - return c; - } - - bool isValid() const { return x >= 0 && x < CELL_NUMBER && y >= 0 && y < CELL_NUMBER;} - }; - - - Node& getGridFor(float fx, float fy) - { - Cell c = Cell::ComputeCell(fx, fy); - return getGrid(c.x, c.y); - } - - Node& getGrid(int x, int y) - { - ASSERT(x < CELL_NUMBER && y < CELL_NUMBER); - if (!nodes[x][y]) - nodes[x][y] = NodeCreatorFunc::makeNode(x, y); - return *nodes[x][y]; - } - - template<typename RayCallback> - void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float max_dist) - { - intersectRay(ray, intersectCallback, max_dist, ray.origin() + ray.direction() * max_dist); - } - - template<typename RayCallback> - void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist, const G3D::Vector3& end) - { - Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); - if (!cell.isValid()) - return; - - Cell last_cell = Cell::ComputeCell(end.x, end.y); - - if (cell == last_cell) - { - if (Node* node = nodes[cell.x][cell.y]) - node->intersectRay(ray, intersectCallback, max_dist); - return; - } - - float voxel = (float)CELL_SIZE; - float kx_inv = ray.invDirection().x, bx = ray.origin().x; - float ky_inv = ray.invDirection().y, by = ray.origin().y; - - int stepX, stepY; - float tMaxX, tMaxY; - if (kx_inv >= 0) - { - stepX = 1; - float x_border = (cell.x+1) * voxel; - tMaxX = (x_border - bx) * kx_inv; - } - else - { - stepX = -1; - float x_border = (cell.x-1) * voxel; - tMaxX = (x_border - bx) * kx_inv; - } - - if (ky_inv >= 0) - { - stepY = 1; - float y_border = (cell.y+1) * voxel; - tMaxY = (y_border - by) * ky_inv; - } - else - { - stepY = -1; - float y_border = (cell.y-1) * voxel; - tMaxY = (y_border - by) * ky_inv; - } - - //int Cycles = std::max((int)ceilf(max_dist/tMaxX),(int)ceilf(max_dist/tMaxY)); - //int i = 0; - - float tDeltaX = voxel * std::fabs(kx_inv); - float tDeltaY = voxel * std::fabs(ky_inv); - do - { - if (Node* node = nodes[cell.x][cell.y]) - { - //float enterdist = max_dist; - node->intersectRay(ray, intersectCallback, max_dist); - } - if (cell == last_cell) - break; - if (tMaxX < tMaxY) - { - tMaxX += tDeltaX; - cell.x += stepX; - } - else - { - tMaxY += tDeltaY; - cell.y += stepY; - } - //++i; - } while (cell.isValid()); - } - - template<typename IsectCallback> - void intersectPoint(const G3D::Vector3& point, IsectCallback& intersectCallback) - { - Cell cell = Cell::ComputeCell(point.x, point.y); - if (!cell.isValid()) - return; - if (Node* node = nodes[cell.x][cell.y]) - node->intersectPoint(point, intersectCallback); - } - - // Optimized verson of intersectRay function for rays with vertical directions - template<typename RayCallback> - void intersectZAllignedRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& max_dist) - { - Cell cell = Cell::ComputeCell(ray.origin().x, ray.origin().y); - if (!cell.isValid()) - return; - if (Node* node = nodes[cell.x][cell.y]) - node->intersectRay(ray, intersectCallback, max_dist); - } -}; - -#undef CELL_SIZE -#undef HGRID_MAP_SIZE - -#endif diff --git a/src/server/collision/VMapDefinitions.h b/src/server/collision/VMapDefinitions.h deleted file mode 100644 index 1035d5307cc..00000000000 --- a/src/server/collision/VMapDefinitions.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _VMAPDEFINITIONS_H -#define _VMAPDEFINITIONS_H -#include <cstring> -#include <cstdio> - -#define LIQUID_TILE_SIZE (533.333f / 128.f) - -namespace VMAP -{ - const char VMAP_MAGIC[] = "VMAP_4.1"; - const char RAW_VMAP_MAGIC[] = "VMAP041"; // used in extracted vmap files with raw data - const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree"; - - // defined in TileAssembler.cpp currently... - bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len); -} - -// Set of helper macros for extractors (VMAP and MMAP) -#ifndef NO_CORE_FUNCS -#define VMAP_ERROR_LOG(FILTER, ...) TC_LOG_ERROR(FILTER, __VA_ARGS__) -#define VMAP_DEBUG_LOG(FILTER, ...) TC_LOG_DEBUG(FILTER, __VA_ARGS__) -#define VMAP_INFO_LOG(FILTER, ...) TC_LOG_INFO(FILTER, __VA_ARGS__) -#else -#define VMAP_ERROR_LOG(FILTER, ...) (void)sizeof(FILTER) -#define VMAP_DEBUG_LOG(FILTER, ...) (void)sizeof(FILTER) -#define VMAP_INFO_LOG(FILTER, ...) (void)sizeof(FILTER) -#endif - -#endif diff --git a/src/server/collision/VMapTools.h b/src/server/collision/VMapTools.h deleted file mode 100644 index fa7bc394ebc..00000000000 --- a/src/server/collision/VMapTools.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (C) 2008-2015 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> - -#include "NodeValueAccess.h" - -/** -The Class is mainly taken from G3D/AABSPTree.h but modified to be able to use our internal data structure. -This is an iterator that helps us analysing the BSP-Trees. -The collision detection is modified to return true, if we are inside an object. -*/ - -namespace VMAP -{ - template<class TValue> - class IntersectionCallBack { - public: - TValue* closestEntity; - G3D::Vector3 hitLocation; - G3D::Vector3 hitNormal; - - void operator()(const G3D::Ray& ray, const TValue* entity, bool pStopAtFirstHit, float& distance) { - entity->intersect(ray, distance, pStopAtFirstHit, hitLocation, hitNormal); - } - }; - - //============================================================== - //============================================================== - //============================================================== - - class MyCollisionDetection - { - private: - public: - - static bool collisionLocationForMovingPointFixedAABox( - const G3D::Vector3& origin, - const G3D::Vector3& dir, - const G3D::AABox& box, - G3D::Vector3& location, - bool& Inside) - { - - // Integer representation of a floating-point value. -#define IR(x) (reinterpret_cast<G3D::uint32 const&>(x)) - - Inside = true; - const G3D::Vector3& MinB = box.low(); - const G3D::Vector3& MaxB = box.high(); - G3D::Vector3 MaxT(-1.0f, -1.0f, -1.0f); - - // Find candidate planes. - for (int i = 0; i < 3; ++i) - { - if (origin[i] < MinB[i]) - { - location[i] = MinB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MinB[i] - origin[i]) / dir[i]; - } - } - else if (origin[i] > MaxB[i]) - { - location[i] = MaxB[i]; - Inside = false; - - // Calculate T distances to candidate planes - if (IR(dir[i])) - { - MaxT[i] = (MaxB[i] - origin[i]) / dir[i]; - } - } - } - - if (Inside) - { - // definite hit - location = origin; - return true; - } - - // Get largest of the maxT's for final choice of intersection - int WhichPlane = 0; - if (MaxT[1] > MaxT[WhichPlane]) - { - WhichPlane = 1; - } - - if (MaxT[2] > MaxT[WhichPlane]) - { - WhichPlane = 2; - } - - // Check final candidate actually inside box - if (IR(MaxT[WhichPlane]) & 0x80000000) - { - // Miss the box - return false; - } - - for (int i = 0; i < 3; ++i) - { - if (i != WhichPlane) - { - location[i] = origin[i] + MaxT[WhichPlane] * dir[i]; - if ((location[i] < MinB[i]) || - (location[i] > MaxB[i])) - { - // On this plane we're outside the box extents, so - // we miss the box - return false; - } - } - } - /* - // Choose the normal to be the plane normal facing into the ray - normal = G3D::Vector3::zero(); - normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0; - */ - return true; - -#undef IR - } - }; -} -#endif diff --git a/src/server/database/CMakeLists.txt b/src/server/database/CMakeLists.txt new file mode 100644 index 00000000000..3fa7ed10aaf --- /dev/null +++ b/src/server/database/CMakeLists.txt @@ -0,0 +1,74 @@ +# Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> +# +# This file is free software; as a special exception the author gives +# unlimited permission to copy and/or distribute it, with or without +# modifications, as long as this notice is preserved. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +if( USE_COREPCH ) + include_directories(${CMAKE_CURRENT_BINARY_DIR}) +endif() + +file(GLOB_RECURSE sources_Database Database/*.cpp Database/*.h) +file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) +file(GLOB_RECURSE sources_Updater Updater/*.cpp Updater/*.h) + +file(GLOB sources_localdir *.cpp *.h) + +# +# Build shared sourcelist +# + +if (USE_COREPCH) + set(database_STAT_PCH_HDR PrecompiledHeaders/databasePCH.h) + set(database_STAT_PCH_SRC PrecompiledHeaders/databasePCH.cpp) +endif() + +set(database_STAT_SRCS + ${database_STAT_SRCS} + ${sources_Database} + ${sources_Logging} + ${sources_Updater} +) + +include_directories( + ${CMAKE_BINARY_DIR} + ${CMAKE_SOURCE_DIR}/dep/recastnavigation/Detour + ${CMAKE_SOURCE_DIR}/dep/SFMT + ${CMAKE_SOURCE_DIR}/dep/cppformat + ${CMAKE_SOURCE_DIR}/dep/utf8cpp + ${CMAKE_SOURCE_DIR}/dep/process + ${CMAKE_SOURCE_DIR}/src/server + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/Database + ${CMAKE_CURRENT_SOURCE_DIR}/Logging + ${CMAKE_CURRENT_SOURCE_DIR}/Updater + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/server/shared + ${MYSQL_INCLUDE_DIR} + ${OPENSSL_INCLUDE_DIR} # seems needed for Windows build + ${VALGRIND_INCLUDE_DIR} +) + +GroupSources(${CMAKE_CURRENT_SOURCE_DIR}) + +add_library(database STATIC + ${database_STAT_SRCS} + ${database_STAT_PCH_SRC} +) + +# Generate precompiled header +if (USE_COREPCH) + add_cxx_pch(database ${database_STAT_PCH_HDR} ${database_STAT_PCH_SRC}) +endif () diff --git a/src/server/shared/Database/AdhocStatement.cpp b/src/server/database/Database/AdhocStatement.cpp index 547ff967efe..547ff967efe 100644 --- a/src/server/shared/Database/AdhocStatement.cpp +++ b/src/server/database/Database/AdhocStatement.cpp diff --git a/src/server/shared/Database/AdhocStatement.h b/src/server/database/Database/AdhocStatement.h index c449e0f6e59..c449e0f6e59 100644 --- a/src/server/shared/Database/AdhocStatement.h +++ b/src/server/database/Database/AdhocStatement.h diff --git a/src/server/shared/Database/DatabaseEnv.h b/src/server/database/Database/DatabaseEnv.h index c3e11c5b98e..c3e11c5b98e 100644 --- a/src/server/shared/Database/DatabaseEnv.h +++ b/src/server/database/Database/DatabaseEnv.h diff --git a/src/server/shared/Database/DatabaseLoader.cpp b/src/server/database/Database/DatabaseLoader.cpp index a3e2083fff4..a3e2083fff4 100644 --- a/src/server/shared/Database/DatabaseLoader.cpp +++ b/src/server/database/Database/DatabaseLoader.cpp diff --git a/src/server/shared/Database/DatabaseLoader.h b/src/server/database/Database/DatabaseLoader.h index d35597ba807..d35597ba807 100644 --- a/src/server/shared/Database/DatabaseLoader.h +++ b/src/server/database/Database/DatabaseLoader.h diff --git a/src/server/shared/Database/DatabaseWorker.cpp b/src/server/database/Database/DatabaseWorker.cpp index 56757ce12a0..56757ce12a0 100644 --- a/src/server/shared/Database/DatabaseWorker.cpp +++ b/src/server/database/Database/DatabaseWorker.cpp diff --git a/src/server/shared/Database/DatabaseWorker.h b/src/server/database/Database/DatabaseWorker.h index 0ca476b1e66..0ca476b1e66 100644 --- a/src/server/shared/Database/DatabaseWorker.h +++ b/src/server/database/Database/DatabaseWorker.h diff --git a/src/server/shared/Database/DatabaseWorkerPool.h b/src/server/database/Database/DatabaseWorkerPool.h index f5002c6943b..f5002c6943b 100644 --- a/src/server/shared/Database/DatabaseWorkerPool.h +++ b/src/server/database/Database/DatabaseWorkerPool.h diff --git a/src/server/shared/Database/Field.cpp b/src/server/database/Database/Field.cpp index 89195b699b7..89195b699b7 100644 --- a/src/server/shared/Database/Field.cpp +++ b/src/server/database/Database/Field.cpp diff --git a/src/server/shared/Database/Field.h b/src/server/database/Database/Field.h index 1bbd264482f..1bbd264482f 100644 --- a/src/server/shared/Database/Field.h +++ b/src/server/database/Database/Field.h diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index 1efdb16804f..1efdb16804f 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp diff --git a/src/server/shared/Database/Implementation/CharacterDatabase.h b/src/server/database/Database/Implementation/CharacterDatabase.h index f88a912e022..f88a912e022 100644 --- a/src/server/shared/Database/Implementation/CharacterDatabase.h +++ b/src/server/database/Database/Implementation/CharacterDatabase.h diff --git a/src/server/shared/Database/Implementation/LoginDatabase.cpp b/src/server/database/Database/Implementation/LoginDatabase.cpp index 8f0b5067957..8f0b5067957 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.cpp +++ b/src/server/database/Database/Implementation/LoginDatabase.cpp diff --git a/src/server/shared/Database/Implementation/LoginDatabase.h b/src/server/database/Database/Implementation/LoginDatabase.h index 7f6cffa520f..7f6cffa520f 100644 --- a/src/server/shared/Database/Implementation/LoginDatabase.h +++ b/src/server/database/Database/Implementation/LoginDatabase.h diff --git a/src/server/shared/Database/Implementation/WorldDatabase.cpp b/src/server/database/Database/Implementation/WorldDatabase.cpp index d9aad94293e..d9aad94293e 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.cpp +++ b/src/server/database/Database/Implementation/WorldDatabase.cpp diff --git a/src/server/shared/Database/Implementation/WorldDatabase.h b/src/server/database/Database/Implementation/WorldDatabase.h index 36fd6fbb186..36fd6fbb186 100644 --- a/src/server/shared/Database/Implementation/WorldDatabase.h +++ b/src/server/database/Database/Implementation/WorldDatabase.h diff --git a/src/server/shared/Database/MySQLConnection.cpp b/src/server/database/Database/MySQLConnection.cpp index 10f4a7baa18..10f4a7baa18 100644 --- a/src/server/shared/Database/MySQLConnection.cpp +++ b/src/server/database/Database/MySQLConnection.cpp diff --git a/src/server/shared/Database/MySQLConnection.h b/src/server/database/Database/MySQLConnection.h index 78d8d2fb5dd..78d8d2fb5dd 100644 --- a/src/server/shared/Database/MySQLConnection.h +++ b/src/server/database/Database/MySQLConnection.h diff --git a/src/server/shared/Database/MySQLThreading.h b/src/server/database/Database/MySQLThreading.h index 441f30cb6ec..441f30cb6ec 100644 --- a/src/server/shared/Database/MySQLThreading.h +++ b/src/server/database/Database/MySQLThreading.h diff --git a/src/server/shared/Database/PreparedStatement.cpp b/src/server/database/Database/PreparedStatement.cpp index 1938005c712..1938005c712 100644 --- a/src/server/shared/Database/PreparedStatement.cpp +++ b/src/server/database/Database/PreparedStatement.cpp diff --git a/src/server/shared/Database/PreparedStatement.h b/src/server/database/Database/PreparedStatement.h index 2b8ce8aac2d..2b8ce8aac2d 100644 --- a/src/server/shared/Database/PreparedStatement.h +++ b/src/server/database/Database/PreparedStatement.h diff --git a/src/server/shared/Database/QueryHolder.cpp b/src/server/database/Database/QueryHolder.cpp index 2fdb3825526..2fdb3825526 100644 --- a/src/server/shared/Database/QueryHolder.cpp +++ b/src/server/database/Database/QueryHolder.cpp diff --git a/src/server/shared/Database/QueryHolder.h b/src/server/database/Database/QueryHolder.h index b64da948a16..b64da948a16 100644 --- a/src/server/shared/Database/QueryHolder.h +++ b/src/server/database/Database/QueryHolder.h diff --git a/src/server/shared/Database/QueryResult.cpp b/src/server/database/Database/QueryResult.cpp index 02352f221a0..02352f221a0 100644 --- a/src/server/shared/Database/QueryResult.cpp +++ b/src/server/database/Database/QueryResult.cpp diff --git a/src/server/shared/Database/QueryResult.h b/src/server/database/Database/QueryResult.h index a61fb6331c1..a61fb6331c1 100644 --- a/src/server/shared/Database/QueryResult.h +++ b/src/server/database/Database/QueryResult.h diff --git a/src/server/shared/Database/SQLOperation.h b/src/server/database/Database/SQLOperation.h index c5667288ec0..c5667288ec0 100644 --- a/src/server/shared/Database/SQLOperation.h +++ b/src/server/database/Database/SQLOperation.h diff --git a/src/server/shared/Database/Transaction.cpp b/src/server/database/Database/Transaction.cpp index f657411f716..f657411f716 100644 --- a/src/server/shared/Database/Transaction.cpp +++ b/src/server/database/Database/Transaction.cpp diff --git a/src/server/shared/Database/Transaction.h b/src/server/database/Database/Transaction.h index 4fbbe1ed45b..4fbbe1ed45b 100644 --- a/src/server/shared/Database/Transaction.h +++ b/src/server/database/Database/Transaction.h diff --git a/src/server/shared/Logging/AppenderDB.cpp b/src/server/database/Logging/AppenderDB.cpp index 9e6ab1a057c..9e6ab1a057c 100644 --- a/src/server/shared/Logging/AppenderDB.cpp +++ b/src/server/database/Logging/AppenderDB.cpp diff --git a/src/server/shared/Logging/AppenderDB.h b/src/server/database/Logging/AppenderDB.h index 50607fd8136..50607fd8136 100644 --- a/src/server/shared/Logging/AppenderDB.h +++ b/src/server/database/Logging/AppenderDB.h diff --git a/src/server/database/PrecompiledHeaders/databasePCH.cpp b/src/server/database/PrecompiledHeaders/databasePCH.cpp new file mode 100644 index 00000000000..f84a52be82a --- /dev/null +++ b/src/server/database/PrecompiledHeaders/databasePCH.cpp @@ -0,0 +1 @@ +#include "PrecompiledHeaders/databasePCH.h" diff --git a/src/server/database/PrecompiledHeaders/databasePCH.h b/src/server/database/PrecompiledHeaders/databasePCH.h new file mode 100644 index 00000000000..d524d52ade0 --- /dev/null +++ b/src/server/database/PrecompiledHeaders/databasePCH.h @@ -0,0 +1,23 @@ +#include "Config.h" +#include "Database/AdhocStatement.h" +#include "Database/DatabaseEnv.h" +#include "Database/DatabaseLoader.h" +#include "Database/DatabaseWorker.h" +#include "Database/DatabaseWorkerPool.h" +#include "Database/Field.h" +#include "Database/MySQLConnection.h" +#include "Database/MySQLThreading.h" +#include "Database/PreparedStatement.h" +#include "Database/QueryHolder.h" +#include "Database/QueryResult.h" +#include "Database/SQLOperation.h" +#include "Database/Transaction.h" +#include "Logging/Appender.h" +#include "Logging/AppenderConsole.h" +#include "Logging/AppenderDB.h" +#include "Logging/AppenderFile.h" +#include "Logging/Log.h" +#include "Logging/LogOperation.h" +#include "Logging/Logger.h" +#include "Updater/DBUpdater.h" +#include "Updater/UpdateFetcher.h" diff --git a/src/server/shared/Updater/DBUpdater.cpp b/src/server/database/Updater/DBUpdater.cpp index c69d19b11d6..c69d19b11d6 100644 --- a/src/server/shared/Updater/DBUpdater.cpp +++ b/src/server/database/Updater/DBUpdater.cpp diff --git a/src/server/shared/Updater/DBUpdater.h b/src/server/database/Updater/DBUpdater.h index a2b12bed235..a2b12bed235 100644 --- a/src/server/shared/Updater/DBUpdater.h +++ b/src/server/database/Updater/DBUpdater.h diff --git a/src/server/shared/Updater/UpdateFetcher.cpp b/src/server/database/Updater/UpdateFetcher.cpp index ec023928b99..ec023928b99 100644 --- a/src/server/shared/Updater/UpdateFetcher.cpp +++ b/src/server/database/Updater/UpdateFetcher.cpp diff --git a/src/server/shared/Updater/UpdateFetcher.h b/src/server/database/Updater/UpdateFetcher.h index 4ff8c93bc76..4ff8c93bc76 100644 --- a/src/server/shared/Updater/UpdateFetcher.h +++ b/src/server/database/Updater/UpdateFetcher.h diff --git a/src/server/game/CMakeLists.txt b/src/server/game/CMakeLists.txt index 66425ed2dc7..ccc69b3ef68 100644 --- a/src/server/game/CMakeLists.txt +++ b/src/server/game/CMakeLists.txt @@ -112,25 +112,28 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/cppformat ${CMAKE_SOURCE_DIR}/dep/zlib - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models - ${CMAKE_SOURCE_DIR}/src/server/collision/Maps + ${CMAKE_SOURCE_DIR}/src/common + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Collision/Maps + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Logging + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/database/Updater ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Networking ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/Accounts ${CMAKE_CURRENT_SOURCE_DIR}/Achievements diff --git a/src/server/scripts/CMakeLists.txt b/src/server/scripts/CMakeLists.txt index 57f145eb15a..db15ce8c36d 100644 --- a/src/server/scripts/CMakeLists.txt +++ b/src/server/scripts/CMakeLists.txt @@ -52,24 +52,26 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/cppformat ${CMAKE_SOURCE_DIR}/dep/zlib + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/database/Updater ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography - ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Logging ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/game/Accounts ${CMAKE_SOURCE_DIR}/src/server/game/Achievements ${CMAKE_SOURCE_DIR}/src/server/game/Addons diff --git a/src/server/shared/CMakeLists.txt b/src/server/shared/CMakeLists.txt index d68ddf85ff3..1653d605faa 100644 --- a/src/server/shared/CMakeLists.txt +++ b/src/server/shared/CMakeLists.txt @@ -12,25 +12,16 @@ if( USE_COREPCH ) include_directories(${CMAKE_CURRENT_BINARY_DIR}) endif() -file(GLOB_RECURSE sources_Configuration Configuration/*.cpp Configuration/*.h) file(GLOB_RECURSE sources_Cryptography Cryptography/*.cpp Cryptography/*.h) -file(GLOB_RECURSE sources_Database Database/*.cpp Database/*.h) file(GLOB_RECURSE sources_DataStores DataStores/*.cpp DataStores/*.h) file(GLOB_RECURSE sources_Dynamic Dynamic/*.cpp Dynamic/*.h) -file(GLOB_RECURSE sources_Logging Logging/*.cpp Logging/*.h) file(GLOB_RECURSE sources_Networking Networking/*.cpp Networking/*.h) file(GLOB_RECURSE sources_Packets Packets/*.cpp Packets/*.h) -file(GLOB_RECURSE sources_Threading Threading/*.cpp Threading/*.h) -file(GLOB_RECURSE sources_Updater Updater/*.cpp Updater/*.h) -file(GLOB_RECURSE sources_Utilities Utilities/*.cpp Utilities/*.h) - +if( WIN32 ) + file(GLOB_RECURSE sources_Service Service/*.cpp Service/*.h) +endif( WIN32 ) file(GLOB sources_localdir *.cpp *.h) -# Manually set sources for Debugging directory as we don't want to include WheatyExceptionReport in shared project -# It needs to be included both in authserver and worldserver for the static global variable to be properly initialized -# and to handle crash logs on windows -set(sources_Debugging Debugging/Errors.cpp Debugging/Errors.h) - # # Build shared sourcelist # @@ -42,18 +33,13 @@ endif() set(shared_STAT_SRCS ${shared_STAT_SRCS} - ${sources_Configuration} ${sources_Cryptography} - ${sources_Database} ${sources_DataStores} - ${sources_Debugging} ${sources_Dynamic} - ${sources_Logging} ${sources_Networking} ${sources_Packets} - ${sources_Threading} - ${sources_Updater} ${sources_Utilities} + ${sources_Service} ${sources_localdir} ) @@ -65,20 +51,25 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/utf8cpp ${CMAKE_SOURCE_DIR}/dep/process ${CMAKE_SOURCE_DIR}/src/server + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/database/Updater ${CMAKE_CURRENT_SOURCE_DIR} - ${CMAKE_CURRENT_SOURCE_DIR}/Configuration ${CMAKE_CURRENT_SOURCE_DIR}/Cryptography - ${CMAKE_CURRENT_SOURCE_DIR}/Database ${CMAKE_CURRENT_SOURCE_DIR}/DataStores - ${CMAKE_CURRENT_SOURCE_DIR}/Debugging ${CMAKE_CURRENT_SOURCE_DIR}/Dynamic - ${CMAKE_CURRENT_SOURCE_DIR}/Logging ${CMAKE_CURRENT_SOURCE_DIR}/Networking ${CMAKE_CURRENT_SOURCE_DIR}/Packets - ${CMAKE_CURRENT_SOURCE_DIR}/Threading - ${CMAKE_CURRENT_SOURCE_DIR}/Utilities - ${CMAKE_CURRENT_SOURCE_DIR}/Updater - ${CMAKE_SOURCE_DIR}/src/server/game/Entities/Object + ${CMAKE_CURRENT_SOURCE_DIR}/Service + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/common/Configuration + ${CMAKE_SOURCE_DIR}/src/common/Logging ${MYSQL_INCLUDE_DIR} ${OPENSSL_INCLUDE_DIR} ${VALGRIND_INCLUDE_DIR} diff --git a/src/server/shared/Common.cpp b/src/server/shared/Common.cpp deleted file mode 100644 index 56e3c4faaf5..00000000000 --- a/src/server/shared/Common.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "Common.h" - -char const* localeNames[TOTAL_LOCALES] = { - "enUS", - "koKR", - "frFR", - "deDE", - "zhCN", - "zhTW", - "esES", - "esMX", - "ruRU" -}; - -LocaleConstant GetLocaleByName(const std::string& name) -{ - for (uint32 i = 0; i < TOTAL_LOCALES; ++i) - if (name==localeNames[i]) - return LocaleConstant(i); - - return LOCALE_enUS; // including enGB case -} - diff --git a/src/server/shared/Common.h b/src/server/shared/Common.h deleted file mode 100644 index 09d64acc795..00000000000 --- a/src/server/shared/Common.h +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITYCORE_COMMON_H -#define TRINITYCORE_COMMON_H - -#include "Define.h" - -#include <unordered_map> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <time.h> -#include <cmath> -#include <errno.h> -#include <signal.h> -#include <assert.h> - -#include <set> -#include <list> -#include <string> -#include <map> -#include <queue> -#include <sstream> -#include <algorithm> -#include <memory> - -#include "Debugging/Errors.h" - -#include "Threading/LockedQueue.h" - -#if PLATFORM == PLATFORM_WINDOWS -# include <ws2tcpip.h> - -# if defined(__INTEL_COMPILER) -# if !defined(BOOST_ASIO_HAS_MOVE) -# define BOOST_ASIO_HAS_MOVE -# endif // !defined(BOOST_ASIO_HAS_MOVE) -# endif // if defined(__INTEL_COMPILER) - -#else -# include <sys/types.h> -# include <sys/ioctl.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <unistd.h> -# include <netdb.h> -#endif - -#if COMPILER == COMPILER_MICROSOFT - -#include <float.h> - -#define snprintf _snprintf -#define atoll _atoi64 -#define vsnprintf _vsnprintf -#define llabs _abs64 - -#else - -#define stricmp strcasecmp -#define strnicmp strncasecmp - -#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); } - -#define STRINGIZE(a) #a - -enum TimeConstants -{ - MINUTE = 60, - HOUR = MINUTE*60, - DAY = HOUR*24, - WEEK = DAY*7, - MONTH = DAY*30, - YEAR = MONTH*12, - IN_MILLISECONDS = 1000 -}; - -enum AccountTypes -{ - SEC_PLAYER = 0, - SEC_MODERATOR = 1, - SEC_GAMEMASTER = 2, - SEC_ADMINISTRATOR = 3, - SEC_CONSOLE = 4 // must be always last in list, accounts must have less security level always also -}; - -enum LocaleConstant -{ - LOCALE_enUS = 0, - LOCALE_koKR = 1, - LOCALE_frFR = 2, - LOCALE_deDE = 3, - LOCALE_zhCN = 4, - LOCALE_zhTW = 5, - LOCALE_esES = 6, - LOCALE_esMX = 7, - LOCALE_ruRU = 8 -}; - -const uint8 TOTAL_LOCALES = 9; -#define DEFAULT_LOCALE LOCALE_enUS - -#define MAX_LOCALES 8 -#define MAX_ACCOUNT_TUTORIAL_VALUES 8 - -extern char const* localeNames[TOTAL_LOCALES]; - -LocaleConstant GetLocaleByName(const std::string& name); - -typedef std::vector<std::string> StringVector; - -// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some other platforms) -#ifdef max -#undef max -#endif - -#ifdef min -#undef min -#endif - -#ifndef M_PI -#define M_PI 3.14159265358979323846 -#endif - -#define MAX_QUERY_LEN 32*1024 - -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) - { - return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); - } -} - -#endif diff --git a/src/server/shared/CompilerDefs.h b/src/server/shared/CompilerDefs.h deleted file mode 100644 index c7867be517b..00000000000 --- a/src/server/shared/CompilerDefs.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITY_COMPILERDEFS_H -#define TRINITY_COMPILERDEFS_H - -#define PLATFORM_WINDOWS 0 -#define PLATFORM_UNIX 1 -#define PLATFORM_APPLE 2 -#define PLATFORM_INTEL 3 - -// must be first (win 64 also define _WIN32) -#if defined( _WIN64 ) -# define PLATFORM PLATFORM_WINDOWS -#elif defined( __WIN32__ ) || defined( WIN32 ) || defined( _WIN32 ) -# define PLATFORM PLATFORM_WINDOWS -#elif defined( __APPLE_CC__ ) -# define PLATFORM PLATFORM_APPLE -#elif defined( __INTEL_COMPILER ) -# define PLATFORM PLATFORM_INTEL -#else -# define PLATFORM PLATFORM_UNIX -#endif - -#define COMPILER_MICROSOFT 0 -#define COMPILER_GNU 1 -#define COMPILER_BORLAND 2 -#define COMPILER_INTEL 3 - -#ifdef _MSC_VER -# define COMPILER COMPILER_MICROSOFT -#elif defined( __BORLANDC__ ) -# define COMPILER COMPILER_BORLAND -#elif defined( __INTEL_COMPILER ) -# define COMPILER COMPILER_INTEL -#elif defined( __GNUC__ ) -# define COMPILER COMPILER_GNU -# define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#else -# error "FATAL ERROR: Unknown compiler." -#endif - -#endif diff --git a/src/server/shared/Configuration/Config.cpp b/src/server/shared/Configuration/Config.cpp deleted file mode 100644 index ea426a5d33e..00000000000 --- a/src/server/shared/Configuration/Config.cpp +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 <algorithm> -#include <mutex> -#include <boost/property_tree/ptree.hpp> -#include <boost/property_tree/ini_parser.hpp> -#include "Config.h" - -using namespace boost::property_tree; - -bool ConfigMgr::LoadInitial(std::string const& file, std::string& error) -{ - std::lock_guard<std::mutex> lock(_configLock); - - _filename = file; - - try - { - ptree fullTree; - ini_parser::read_ini(file, fullTree); - - if (fullTree.empty()) - { - error = "empty file (" + file + ")"; - return false; - } - - // 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) - { - if (e.line() == 0) - error = e.message() + " (" + e.filename() + ")"; - else - error = e.message() + " (" + e.filename() + ":" + std::to_string(e.line()) + ")"; - return false; - } - - return true; -} - -bool ConfigMgr::Reload(std::string& error) -{ - return LoadInitial(_filename, error); -} - -std::string ConfigMgr::GetStringDefault(std::string const& name, const std::string& def) -{ - std::string value = _config.get<std::string>(ptree::path_type(name, '/'), def); - - value.erase(std::remove(value.begin(), value.end(), '"'), value.end()); - - return value; -} - -bool ConfigMgr::GetBoolDefault(std::string const& name, bool def) -{ - try - { - std::string val = _config.get<std::string>(ptree::path_type(name, '/')); - val.erase(std::remove(val.begin(), val.end(), '"'), val.end()); - return (val == "true" || val == "TRUE" || val == "yes" || val == "YES" || val == "1"); - } - catch (std::exception const& /*ex*/) - { - return def; - } -} - -int ConfigMgr::GetIntDefault(std::string const& name, int def) -{ - return _config.get<int>(ptree::path_type(name, '/'), def); -} - -float ConfigMgr::GetFloatDefault(std::string const& name, float def) -{ - return _config.get<float>(ptree::path_type(name, '/'), def); -} - -std::string const& ConfigMgr::GetFilename() -{ - std::lock_guard<std::mutex> lock(_configLock); - return _filename; -} - -std::list<std::string> ConfigMgr::GetKeysByString(std::string const& name) -{ - std::lock_guard<std::mutex> lock(_configLock); - - std::list<std::string> keys; - - for (const ptree::value_type& child : _config) - if (child.first.compare(0, name.length(), name) == 0) - keys.push_back(child.first); - - return keys; -} diff --git a/src/server/shared/Configuration/Config.h b/src/server/shared/Configuration/Config.h deleted file mode 100644 index 5fb7cef9241..00000000000 --- a/src/server/shared/Configuration/Config.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 CONFIG_H -#define CONFIG_H - -#include <string> -#include <list> -#include <mutex> -#include <boost/property_tree/ptree.hpp> - -class ConfigMgr -{ - ConfigMgr() { } - ~ConfigMgr() { } - -public: - /// Method used only for loading main configuration files (authserver.conf and worldserver.conf) - bool LoadInitial(std::string const& file, std::string& error); - - static ConfigMgr* instance() - { - static ConfigMgr instance; - return &instance; - } - - bool Reload(std::string& error); - - std::string GetStringDefault(std::string const& name, const std::string& def); - bool GetBoolDefault(std::string const& name, bool def); - int GetIntDefault(std::string const& name, int def); - float GetFloatDefault(std::string const& name, float def); - - std::string const& GetFilename(); - std::list<std::string> GetKeysByString(std::string const& name); - -private: - std::string _filename; - boost::property_tree::ptree _config; - std::mutex _configLock; - - ConfigMgr(ConfigMgr const&); - ConfigMgr& operator=(ConfigMgr const&); -}; - -#define sConfigMgr ConfigMgr::instance() - -#endif diff --git a/src/server/shared/Debugging/Errors.cpp b/src/server/shared/Debugging/Errors.cpp deleted file mode 100644 index cebd9d4cf2f..00000000000 --- a/src/server/shared/Debugging/Errors.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "Errors.h" - -#include <cstdio> -#include <cstdlib> -#include <thread> -#include <cstdarg> - -namespace Trinity { - -void Assert(char const* file, int line, char const* function, char const* message) -{ - fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s\n", - file, line, function, message); - *((volatile int*)NULL) = 0; - exit(1); -} - -void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) -{ - va_list args; - va_start(args, format); - - fprintf(stderr, "\n%s:%i in %s ASSERTION FAILED:\n %s ", file, line, function, message); - vfprintf(stderr, format, args); - fprintf(stderr, "\n"); - fflush(stderr); - - va_end(args); - *((volatile int*)NULL) = 0; - exit(1); -} - -void Fatal(char const* file, int line, char const* function, char const* message) -{ - fprintf(stderr, "\n%s:%i in %s FATAL ERROR:\n %s\n", - file, line, function, message); - - std::this_thread::sleep_for(std::chrono::seconds(10)); - *((volatile int*)NULL) = 0; - exit(1); -} - -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; - exit(1); -} - -void Warning(char const* file, int line, char const* function, char const* message) -{ - fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n", - file, line, function, message); -} - -} // namespace Trinity diff --git a/src/server/shared/Debugging/Errors.h b/src/server/shared/Debugging/Errors.h deleted file mode 100644 index 4d4624b63dd..00000000000 --- a/src/server/shared/Debugging/Errors.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITYCORE_ERRORS_H -#define TRINITYCORE_ERRORS_H - -#include "Define.h" - -namespace Trinity -{ - DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; - DECLSPEC_NORETURN void Assert(char const* file, int line, char const* function, char const* message, char const* format, ...) ATTR_NORETURN ATTR_PRINTF(5, 6); - - DECLSPEC_NORETURN void Fatal(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; - - DECLSPEC_NORETURN void Error(char const* file, int line, char const* function, char const* message) ATTR_NORETURN; - - void Warning(char const* file, int line, char const* function, char const* message); - -} // namespace Trinity - -#if COMPILER == COMPILER_MICROSOFT -#define ASSERT_BEGIN __pragma(warning(push)) __pragma(warning(disable: 4127)) -#define ASSERT_END __pragma(warning(pop)) -#else -#define ASSERT_BEGIN -#define ASSERT_END -#endif - -#define WPAssert(cond, ...) ASSERT_BEGIN do { if (!(cond)) Trinity::Assert(__FILE__, __LINE__, __FUNCTION__, #cond, ##__VA_ARGS__); } while(0) ASSERT_END -#define WPFatal(cond, msg) ASSERT_BEGIN do { if (!(cond)) Trinity::Fatal(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END -#define WPError(cond, msg) ASSERT_BEGIN do { if (!(cond)) Trinity::Error(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END -#define WPWarning(cond, msg) ASSERT_BEGIN do { if (!(cond)) Trinity::Warning(__FILE__, __LINE__, __FUNCTION__, (msg)); } while(0) ASSERT_END - -#define ASSERT WPAssert - -template <typename T> inline T* ASSERT_NOTNULL(T* pointer) -{ - ASSERT(pointer); - return pointer; -} - -#endif diff --git a/src/server/shared/Debugging/WheatyExceptionReport.cpp b/src/server/shared/Debugging/WheatyExceptionReport.cpp deleted file mode 100644 index 70aa23a8eed..00000000000 --- a/src/server/shared/Debugging/WheatyExceptionReport.cpp +++ /dev/null @@ -1,1423 +0,0 @@ -//========================================== -// Matt Pietrek -// MSDN Magazine, 2002 -// FILE: WheatyExceptionReport.CPP -//========================================== -#include "CompilerDefs.h" - -#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__) -#define WIN32_LEAN_AND_MEAN -#pragma warning(disable:4996) -#pragma warning(disable:4312) -#pragma warning(disable:4311) -#include <windows.h> -#include <tlhelp32.h> -#include <stdio.h> -#include <tchar.h> -#define _NO_CVCONST_H -#include <dbghelp.h> - -#include "WheatyExceptionReport.h" - -#include "Common.h" -#include "Revision.h" - -#define CrashFolder _T("Crashes") -#pragma comment(linker, "/DEFAULTLIB:dbghelp.lib") - -inline LPTSTR ErrorMessage(DWORD dw) -{ - LPVOID lpMsgBuf; - DWORD formatResult = FormatMessage( - FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - dw, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPTSTR) &lpMsgBuf, - 0, NULL); - if (formatResult != 0) - return (LPTSTR)lpMsgBuf; - else - { - LPTSTR msgBuf = (LPTSTR)LocalAlloc(LPTR, 30); - sprintf(msgBuf, "Unknown error: %u", dw); - return msgBuf; - } - -} - -//============================== Global Variables ============================= - -// -// Declare the static variables of the WheatyExceptionReport class -// -TCHAR WheatyExceptionReport::m_szLogFileName[MAX_PATH]; -TCHAR WheatyExceptionReport::m_szDumpFileName[MAX_PATH]; -LPTOP_LEVEL_EXCEPTION_FILTER WheatyExceptionReport::m_previousFilter; -HANDLE WheatyExceptionReport::m_hReportFile; -HANDLE WheatyExceptionReport::m_hDumpFile; -HANDLE WheatyExceptionReport::m_hProcess; -SymbolPairs WheatyExceptionReport::symbols; -std::stack<SymbolDetail> WheatyExceptionReport::symbolDetails; -bool WheatyExceptionReport::stackOverflowException; -bool WheatyExceptionReport::alreadyCrashed; -std::mutex WheatyExceptionReport::alreadyCrashedLock; - -// Declare global instance of class -WheatyExceptionReport g_WheatyExceptionReport; - -//============================== Class Methods ============================= - -WheatyExceptionReport::WheatyExceptionReport() // Constructor -{ - // Install the unhandled exception filter function - m_previousFilter = SetUnhandledExceptionFilter(WheatyUnhandledExceptionFilter); - m_hProcess = GetCurrentProcess(); - stackOverflowException = false; - alreadyCrashed = false; - if (!IsDebuggerPresent()) - { - _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); - _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); - _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); - } -} - -//============ -// Destructor -//============ -WheatyExceptionReport::~WheatyExceptionReport() -{ - if (m_previousFilter) - SetUnhandledExceptionFilter(m_previousFilter); - ClearSymbols(); -} - -//=========================================================== -// Entry point where control comes on an unhandled exception -//=========================================================== -LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter( -PEXCEPTION_POINTERS pExceptionInfo) -{ - std::unique_lock<std::mutex> guard(alreadyCrashedLock); - // Handle only 1 exception in the whole process lifetime - if (alreadyCrashed) - return EXCEPTION_EXECUTE_HANDLER; - - alreadyCrashed = true; - - if (pExceptionInfo->ExceptionRecord->ExceptionCode == STATUS_STACK_OVERFLOW) - stackOverflowException = true; - - TCHAR module_folder_name[MAX_PATH]; - GetModuleFileName(0, module_folder_name, MAX_PATH); - TCHAR* pos = _tcsrchr(module_folder_name, '\\'); - if (!pos) - return 0; - pos[0] = '\0'; - ++pos; - - TCHAR crash_folder_path[MAX_PATH]; - sprintf(crash_folder_path, "%s\\%s", module_folder_name, CrashFolder); - if (!CreateDirectory(crash_folder_path, NULL)) - { - if (GetLastError() != ERROR_ALREADY_EXISTS) - return 0; - } - - SYSTEMTIME systime; - GetLocalTime(&systime); - sprintf(m_szDumpFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].dmp", - crash_folder_path, Revision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); - - sprintf(m_szLogFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].txt", - crash_folder_path, Revision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond); - - m_hDumpFile = CreateFile(m_szDumpFileName, - GENERIC_WRITE, - 0, - 0, - OPEN_ALWAYS, - FILE_FLAG_WRITE_THROUGH, - 0); - - m_hReportFile = CreateFile(m_szLogFileName, - GENERIC_WRITE, - 0, - 0, - OPEN_ALWAYS, - FILE_FLAG_WRITE_THROUGH, - 0); - - if (m_hDumpFile) - { - MINIDUMP_EXCEPTION_INFORMATION info; - info.ClientPointers = FALSE; - info.ExceptionPointers = pExceptionInfo; - info.ThreadId = GetCurrentThreadId(); - - MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), - m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, 0, 0); - - CloseHandle(m_hDumpFile); - } - - if (m_hReportFile) - { - SetFilePointer(m_hReportFile, 0, 0, FILE_END); - - GenerateExceptionReport(pExceptionInfo); - - CloseHandle(m_hReportFile); - m_hReportFile = 0; - } - - if (m_previousFilter) - return m_previousFilter(pExceptionInfo); - else - return EXCEPTION_EXECUTE_HANDLER/*EXCEPTION_CONTINUE_SEARCH*/; -} - -BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxcount) -{ - if (!sProcessorName) - return FALSE; - - HKEY hKey; - LONG lRet; - lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"), - 0, KEY_QUERY_VALUE, &hKey); - if (lRet != ERROR_SUCCESS) - return FALSE; - TCHAR szTmp[2048]; - DWORD cntBytes = sizeof(szTmp); - lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL, - (LPBYTE)szTmp, &cntBytes); - if (lRet != ERROR_SUCCESS) - return FALSE; - ::RegCloseKey(hKey); - sProcessorName[0] = '\0'; - // Skip spaces - TCHAR* psz = szTmp; - while (iswspace(*psz)) - ++psz; - _tcsncpy(sProcessorName, psz, maxcount); - return TRUE; -} - -BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax) -{ - // Try calling GetVersionEx using the OSVERSIONINFOEX structure. - // If that fails, try using the OSVERSIONINFO structure. - OSVERSIONINFOEX osvi = { 0 }; - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - BOOL bOsVersionInfoEx; - bOsVersionInfoEx = ::GetVersionEx((LPOSVERSIONINFO)(&osvi)); - if (!bOsVersionInfoEx) - { - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - if (!::GetVersionEx((OSVERSIONINFO*)&osvi)) - return FALSE; - } - *szVersion = _T('\0'); - TCHAR wszTmp[128]; - switch (osvi.dwPlatformId) - { - // Windows NT product family. - case VER_PLATFORM_WIN32_NT: - { - #if WINVER < 0x0500 - BYTE suiteMask = osvi.wReserved[0]; - BYTE productType = osvi.wReserved[1]; - #else - WORD suiteMask = osvi.wSuiteMask; - BYTE productType = osvi.wProductType; - #endif // WINVER < 0x0500 - - // Test for the specific product family. - if (osvi.dwMajorVersion == 6) - { - if (productType == VER_NT_WORKSTATION) - { - if (osvi.dwMinorVersion == 2) - _tcsncat(szVersion, _T("Windows 8 "), cntMax); - else if (osvi.dwMinorVersion == 1) - _tcsncat(szVersion, _T("Windows 7 "), cntMax); - else - _tcsncat(szVersion, _T("Windows Vista "), cntMax); - } - else if (osvi.dwMinorVersion == 2) - _tcsncat(szVersion, _T("Windows Server 2012 "), cntMax); - else if (osvi.dwMinorVersion == 1) - _tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax); - else - _tcsncat(szVersion, _T("Windows Server 2008 "), cntMax); - } - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - _tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax); - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1) - _tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax); - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - _tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax); - else if (osvi.dwMajorVersion <= 4) - _tcsncat(szVersion, _T("Microsoft Windows NT "), cntMax); - - // Test for specific product on Windows NT 4.0 SP6 and later. - if (bOsVersionInfoEx) - { - // Test for the workstation type. - if (productType == VER_NT_WORKSTATION) - { - if (osvi.dwMajorVersion == 4) - _tcsncat(szVersion, _T("Workstation 4.0 "), cntMax); - else if (suiteMask & VER_SUITE_PERSONAL) - _tcsncat(szVersion, _T("Home Edition "), cntMax); - else if (suiteMask & VER_SUITE_EMBEDDEDNT) - _tcsncat(szVersion, _T("Embedded "), cntMax); - else - _tcsncat(szVersion, _T("Professional "), cntMax); - } - // Test for the server type. - else if (productType == VER_NT_SERVER) - { - if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2) - { - if (suiteMask & VER_SUITE_DATACENTER) - _tcsncat(szVersion, _T("Datacenter Edition "), cntMax); - else if (suiteMask & VER_SUITE_ENTERPRISE) - _tcsncat(szVersion, _T("Enterprise Edition "), cntMax); - else if (suiteMask == VER_SUITE_BLADE) - _tcsncat(szVersion, _T("Web Edition "), cntMax); - else - _tcsncat(szVersion, _T("Standard Edition "), cntMax); - } - else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0) - { - if (suiteMask & VER_SUITE_DATACENTER) - _tcsncat(szVersion, _T("Datacenter Server "), cntMax); - else if (suiteMask & VER_SUITE_ENTERPRISE) - _tcsncat(szVersion, _T("Advanced Server "), cntMax); - else - _tcsncat(szVersion, _T("Server "), cntMax); - } - else // Windows NT 4.0 - { - if (suiteMask & VER_SUITE_ENTERPRISE) - _tcsncat(szVersion, _T("Server 4.0, Enterprise Edition "), cntMax); - else - _tcsncat(szVersion, _T("Server 4.0 "), cntMax); - } - } - } - - // Display service pack (if any) and build number. - if (osvi.dwMajorVersion == 4 && _tcsicmp(osvi.szCSDVersion, _T("Service Pack 6")) == 0) - { - HKEY hKey; - LONG lRet; - - // Test for SP6 versus SP6a. - lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Hotfix\\Q246009"), 0, KEY_QUERY_VALUE, &hKey); - if (lRet == ERROR_SUCCESS) - { - _stprintf(wszTmp, _T("Service Pack 6a (Version %d.%d, Build %d)"), - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - else // Windows NT 4.0 prior to SP6a - { - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - ::RegCloseKey(hKey); - } - else // Windows NT 3.51 and earlier or Windows 2000 and later - { - if (!_tcslen(osvi.szCSDVersion)) - _stprintf(wszTmp, _T("(Version %d.%d, Build %d)"), - osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - else - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - } - break; - } - default: - _stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"), - osvi.szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF); - _tcsncat(szVersion, wszTmp, cntMax); - break; - } - - return TRUE; -} - -void WheatyExceptionReport::PrintSystemInfo() -{ - SYSTEM_INFO SystemInfo; - ::GetSystemInfo(&SystemInfo); - - MEMORYSTATUS MemoryStatus; - MemoryStatus.dwLength = sizeof (MEMORYSTATUS); - ::GlobalMemoryStatus(&MemoryStatus); - TCHAR sString[1024]; - _tprintf(_T("//=====================================================\r\n")); - if (_GetProcessorName(sString, countof(sString))) - _tprintf(_T("*** Hardware ***\r\nProcessor: %s\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), - sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); - else - _tprintf(_T("*** Hardware ***\r\nProcessor: <unknown>\r\nNumber Of Processors: %d\r\nPhysical Memory: %d KB (Available: %d KB)\r\nCommit Charge Limit: %d KB\r\n"), - SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys/0x400, MemoryStatus.dwAvailPhys/0x400, MemoryStatus.dwTotalPageFile/0x400); - - if (_GetWindowsVersion(sString, countof(sString))) - _tprintf(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString); - else - _tprintf(_T("\r\n*** Operation System:\r\n<unknown>\r\n")); -} - -//=========================================================================== -void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables) -{ - THREADENTRY32 te32; - - DWORD dwOwnerPID = GetCurrentProcessId(); - m_hProcess = GetCurrentProcess(); - // Take a snapshot of all running threads - HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) - return; - - // Fill in the size of the structure before using it. - te32.dwSize = sizeof(THREADENTRY32); - - // Retrieve information about the first thread, - // and exit if unsuccessful - if (!Thread32First(hThreadSnap, &te32)) - { - CloseHandle(hThreadSnap); // Must clean up the - // snapshot object! - return; - } - - // Now walk the thread list of the system, - // and display information about each thread - // associated with the specified process - do - { - if (te32.th32OwnerProcessID == dwOwnerPID) - { - CONTEXT context; - context.ContextFlags = 0xffffffff; - HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, false, te32.th32ThreadID); - if (threadHandle) - { - if (GetThreadContext(threadHandle, &context)) - WriteStackDetails(&context, bWriteVariables, threadHandle); - CloseHandle(threadHandle); - } - } - } while (Thread32Next(hThreadSnap, &te32)); - -// Don't forget to clean up the snapshot object. - CloseHandle(hThreadSnap); -} - -//=========================================================================== -// Open the report file, and write the desired information to it. Called by -// WheatyUnhandledExceptionFilter -//=========================================================================== -void WheatyExceptionReport::GenerateExceptionReport( -PEXCEPTION_POINTERS pExceptionInfo) -{ - __try - { - SYSTEMTIME systime; - GetLocalTime(&systime); - - // Start out with a banner - _tprintf(_T("Revision: %s\r\n"), Revision::GetFullVersion()); - _tprintf(_T("Date %u:%u:%u. Time %u:%u \r\n"), systime.wDay, systime.wMonth, systime.wYear, systime.wHour, systime.wMinute); - PEXCEPTION_RECORD pExceptionRecord = pExceptionInfo->ExceptionRecord; - - PrintSystemInfo(); - // First print information about the type of fault - _tprintf(_T("\r\n//=====================================================\r\n")); - _tprintf(_T("Exception code: %08X %s\r\n"), - pExceptionRecord->ExceptionCode, - GetExceptionString(pExceptionRecord->ExceptionCode)); - - // Now print information about where the fault occured - TCHAR szFaultingModule[MAX_PATH]; - DWORD section; - DWORD_PTR offset; - GetLogicalAddress(pExceptionRecord->ExceptionAddress, - szFaultingModule, - sizeof(szFaultingModule), - section, offset); - -#ifdef _M_IX86 - _tprintf(_T("Fault address: %08X %02X:%08X %s\r\n"), - pExceptionRecord->ExceptionAddress, - section, offset, szFaultingModule); -#endif -#ifdef _M_X64 - _tprintf(_T("Fault address: %016I64X %02X:%016I64X %s\r\n"), - pExceptionRecord->ExceptionAddress, - section, offset, szFaultingModule); -#endif - - PCONTEXT pCtx = pExceptionInfo->ContextRecord; - - // Show the registers -#ifdef _M_IX86 // X86 Only! - _tprintf(_T("\r\nRegisters:\r\n")); - - _tprintf(_T("EAX:%08X\r\nEBX:%08X\r\nECX:%08X\r\nEDX:%08X\r\nESI:%08X\r\nEDI:%08X\r\n") - , pCtx->Eax, pCtx->Ebx, pCtx->Ecx, pCtx->Edx, - pCtx->Esi, pCtx->Edi); - - _tprintf(_T("CS:EIP:%04X:%08X\r\n"), pCtx->SegCs, pCtx->Eip); - _tprintf(_T("SS:ESP:%04X:%08X EBP:%08X\r\n"), - pCtx->SegSs, pCtx->Esp, pCtx->Ebp); - _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), - pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); - _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); -#endif - -#ifdef _M_X64 - _tprintf(_T("\r\nRegisters:\r\n")); - _tprintf(_T("RAX:%016I64X\r\nRBX:%016I64X\r\nRCX:%016I64X\r\nRDX:%016I64X\r\nRSI:%016I64X\r\nRDI:%016I64X\r\n") - _T("R8: %016I64X\r\nR9: %016I64X\r\nR10:%016I64X\r\nR11:%016I64X\r\nR12:%016I64X\r\nR13:%016I64X\r\nR14:%016I64X\r\nR15:%016I64X\r\n") - , pCtx->Rax, pCtx->Rbx, pCtx->Rcx, pCtx->Rdx, - pCtx->Rsi, pCtx->Rdi, pCtx->R9, pCtx->R10, pCtx->R11, pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15); - _tprintf(_T("CS:RIP:%04X:%016I64X\r\n"), pCtx->SegCs, pCtx->Rip); - _tprintf(_T("SS:RSP:%04X:%016X RBP:%08X\r\n"), - pCtx->SegSs, pCtx->Rsp, pCtx->Rbp); - _tprintf(_T("DS:%04X ES:%04X FS:%04X GS:%04X\r\n"), - pCtx->SegDs, pCtx->SegEs, pCtx->SegFs, pCtx->SegGs); - _tprintf(_T("Flags:%08X\r\n"), pCtx->EFlags); -#endif - - SymSetOptions(SYMOPT_DEFERRED_LOADS); - - // Initialize DbgHelp - if (!SymInitialize(GetCurrentProcess(), 0, TRUE)) - { - _tprintf(_T("\n\rCRITICAL ERROR.\n\r Couldn't initialize the symbol handler for process.\n\rError [%s].\n\r\n\r"), - ErrorMessage(GetLastError())); - } - - CONTEXT trashableContext = *pCtx; - - WriteStackDetails(&trashableContext, false, NULL); - printTracesForAllThreads(false); - - // #ifdef _M_IX86 // X86 Only! - - _tprintf(_T("========================\r\n")); - _tprintf(_T("Local Variables And Parameters\r\n")); - - trashableContext = *pCtx; - WriteStackDetails(&trashableContext, true, NULL); - printTracesForAllThreads(true); - - /*_tprintf(_T("========================\r\n")); - _tprintf(_T("Global Variables\r\n")); - - SymEnumSymbols(GetCurrentProcess(), - (UINT_PTR)GetModuleHandle(szFaultingModule), - 0, EnumerateSymbolsCallback, 0);*/ - // #endif // X86 Only! - - SymCleanup(GetCurrentProcess()); - - _tprintf(_T("\r\n")); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - _tprintf(_T("Error writing the crash log\r\n")); - } -} - -//====================================================================== -// Given an exception code, returns a pointer to a static string with a -// description of the exception -//====================================================================== -LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode) -{ - #define EXCEPTION(x) case EXCEPTION_##x: return _T(#x); - - switch (dwCode) - { - EXCEPTION(ACCESS_VIOLATION) - EXCEPTION(DATATYPE_MISALIGNMENT) - EXCEPTION(BREAKPOINT) - EXCEPTION(SINGLE_STEP) - EXCEPTION(ARRAY_BOUNDS_EXCEEDED) - EXCEPTION(FLT_DENORMAL_OPERAND) - EXCEPTION(FLT_DIVIDE_BY_ZERO) - EXCEPTION(FLT_INEXACT_RESULT) - EXCEPTION(FLT_INVALID_OPERATION) - EXCEPTION(FLT_OVERFLOW) - EXCEPTION(FLT_STACK_CHECK) - EXCEPTION(FLT_UNDERFLOW) - EXCEPTION(INT_DIVIDE_BY_ZERO) - EXCEPTION(INT_OVERFLOW) - EXCEPTION(PRIV_INSTRUCTION) - EXCEPTION(IN_PAGE_ERROR) - EXCEPTION(ILLEGAL_INSTRUCTION) - EXCEPTION(NONCONTINUABLE_EXCEPTION) - EXCEPTION(STACK_OVERFLOW) - EXCEPTION(INVALID_DISPOSITION) - EXCEPTION(GUARD_PAGE) - EXCEPTION(INVALID_HANDLE) - } - - // If not one of the "known" exceptions, try to get the string - // from NTDLL.DLL's message table. - - static TCHAR szBuffer[512] = { 0 }; - - FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE, - GetModuleHandle(_T("NTDLL.DLL")), - dwCode, 0, szBuffer, sizeof(szBuffer), 0); - - return szBuffer; -} - -//============================================================================= -// Given a linear address, locates the module, section, and offset containing -// that address. -// -// Note: the szModule paramater buffer is an output buffer of length specified -// by the len parameter (in characters!) -//============================================================================= -BOOL WheatyExceptionReport::GetLogicalAddress( -PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset) -{ - MEMORY_BASIC_INFORMATION mbi; - - if (!VirtualQuery(addr, &mbi, sizeof(mbi))) - return FALSE; - - DWORD_PTR hMod = (DWORD_PTR)mbi.AllocationBase; - - if (!hMod) - return FALSE; - - if (!GetModuleFileName((HMODULE)hMod, szModule, len)) - return FALSE; - - // Point to the DOS header in memory - PIMAGE_DOS_HEADER pDosHdr = (PIMAGE_DOS_HEADER)hMod; - - // From the DOS header, find the NT (PE) header - PIMAGE_NT_HEADERS pNtHdr = (PIMAGE_NT_HEADERS)(hMod + DWORD_PTR(pDosHdr->e_lfanew)); - - PIMAGE_SECTION_HEADER pSection = IMAGE_FIRST_SECTION(pNtHdr); - - DWORD_PTR rva = (DWORD_PTR)addr - hMod; // RVA is offset from module load address - - // Iterate through the section table, looking for the one that encompasses - // the linear address. - for (unsigned i = 0; - i < pNtHdr->FileHeader.NumberOfSections; - i++, pSection++) - { - DWORD_PTR sectionStart = pSection->VirtualAddress; - DWORD_PTR sectionEnd = sectionStart - + DWORD_PTR(std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize)); - - // Is the address in this section??? - if ((rva >= sectionStart) && (rva <= sectionEnd)) - { - // Yes, address is in the section. Calculate section and offset, - // and store in the "section" & "offset" params, which were - // passed by reference. - section = i+1; - offset = rva - sectionStart; - return TRUE; - } - } - - return FALSE; // Should never get here! -} - -// It contains SYMBOL_INFO structure plus additional -// space for the name of the symbol -struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE -{ - CSymbolInfoPackage() - { - si.SizeOfStruct = sizeof(SYMBOL_INFO); - si.MaxNameLen = sizeof(name); - } -}; - -//============================================================ -// Walks the stack, and writes the results to the report file -//============================================================ -void WheatyExceptionReport::WriteStackDetails( -PCONTEXT pContext, -bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output -{ - _tprintf(_T("\r\nCall stack:\r\n")); - - _tprintf(_T("Address Frame Function SourceFile\r\n")); - - DWORD dwMachineType = 0; - // Could use SymSetOptions here to add the SYMOPT_DEFERRED_LOADS flag - - STACKFRAME64 sf; - memset(&sf, 0, sizeof(sf)); - - #ifdef _M_IX86 - // Initialize the STACKFRAME structure for the first call. This is only - // necessary for Intel CPUs, and isn't mentioned in the documentation. - sf.AddrPC.Offset = pContext->Eip; - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Esp; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Ebp; - sf.AddrFrame.Mode = AddrModeFlat; - - dwMachineType = IMAGE_FILE_MACHINE_I386; - #endif - -#ifdef _M_X64 - sf.AddrPC.Offset = pContext->Rip; - sf.AddrPC.Mode = AddrModeFlat; - sf.AddrStack.Offset = pContext->Rsp; - sf.AddrStack.Mode = AddrModeFlat; - sf.AddrFrame.Offset = pContext->Rbp; - sf.AddrFrame.Mode = AddrModeFlat; - dwMachineType = IMAGE_FILE_MACHINE_AMD64; -#endif - - for (;;) - { - // Get the next stack frame - if (! StackWalk64(dwMachineType, - m_hProcess, - pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(), - &sf, - pContext, - 0, - SymFunctionTableAccess64, - SymGetModuleBase64, - 0)) - break; - if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure - break; // the frame is OK. Bail if not. -#ifdef _M_IX86 - _tprintf(_T("%08X %08X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif -#ifdef _M_X64 - _tprintf(_T("%016I64X %016I64X "), sf.AddrPC.Offset, sf.AddrFrame.Offset); -#endif - - DWORD64 symDisplacement = 0; // Displacement of the input address, - // relative to the start of the symbol - - // Get the name of the function for this stack frame entry - CSymbolInfoPackage sip; - if (SymFromAddr( - m_hProcess, // Process handle of the current process - sf.AddrPC.Offset, // Symbol address - &symDisplacement, // Address of the variable that will receive the displacement - &sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object) - { - _tprintf(_T("%hs+%I64X"), sip.si.Name, symDisplacement); - - } - else // No symbol found. Print out the logical address instead. - { - TCHAR szModule[MAX_PATH] = _T(""); - DWORD section = 0; - DWORD_PTR offset = 0; - - GetLogicalAddress((PVOID)sf.AddrPC.Offset, - szModule, sizeof(szModule), section, offset); -#ifdef _M_IX86 - _tprintf(_T("%04X:%08X %s"), section, offset, szModule); -#endif -#ifdef _M_X64 - _tprintf(_T("%04X:%016I64X %s"), section, offset, szModule); -#endif - } - - // Get the source line for this stack frame entry - IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) }; - DWORD dwLineDisplacement; - if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset, - &dwLineDisplacement, &lineInfo)) - { - _tprintf(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber); - } - - _tprintf(_T("\r\n")); - - // Write out the variables, if desired - if (bWriteVariables) - { - // Use SymSetContext to get just the locals/params for this frame - IMAGEHLP_STACK_FRAME imagehlpStackFrame; - imagehlpStackFrame.InstructionOffset = sf.AddrPC.Offset; - SymSetContext(m_hProcess, &imagehlpStackFrame, 0); - - // Enumerate the locals/parameters - SymEnumSymbols(m_hProcess, 0, 0, EnumerateSymbolsCallback, &sf); - - _tprintf(_T("\r\n")); - } - } - -} - -////////////////////////////////////////////////////////////////////////////// -// The function invoked by SymEnumSymbols -////////////////////////////////////////////////////////////////////////////// - -BOOL CALLBACK -WheatyExceptionReport::EnumerateSymbolsCallback( -PSYMBOL_INFO pSymInfo, -ULONG /*SymbolSize*/, -PVOID UserContext) -{ - - char szBuffer[WER_LARGE_BUFFER_SIZE]; - memset(szBuffer, 0, sizeof(szBuffer)); - - __try - { - ClearSymbols(); - if (FormatSymbolValue(pSymInfo, (STACKFRAME64*)UserContext, - szBuffer, sizeof(szBuffer))) - _tprintf(_T("%s"), szBuffer); - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - _tprintf(_T("punting on symbol %s, partial output:\r\n"), pSymInfo->Name); - if (szBuffer[0] != '\0') - _tprintf(_T("%s"), szBuffer); - } - - return TRUE; -} - -////////////////////////////////////////////////////////////////////////////// -// Given a SYMBOL_INFO representing a particular variable, displays its -// contents. If it's a user defined type, display the members and their -// values. -////////////////////////////////////////////////////////////////////////////// -bool WheatyExceptionReport::FormatSymbolValue( -PSYMBOL_INFO pSym, -STACKFRAME64 * sf, -char * pszBuffer, -unsigned /*cbBuffer*/) -{ - char * pszCurrBuffer = pszBuffer; - - // If it's a function, don't do anything. - if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK - return false; - - DWORD_PTR pVariable = 0; // Will point to the variable's data in memory - - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE) - { - // if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1) - { // This may change!!! -#ifdef _M_IX86 - pVariable = sf->AddrFrame.Offset; -#elif _M_X64 - pVariable = sf->AddrStack.Offset; -#endif - pVariable += (DWORD_PTR)pSym->Address; - } - // else - // return false; - } - else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGISTER) - return false; // Don't try to report register variable - else - { - pVariable = (DWORD_PTR)pSym->Address; // It must be a global variable - } - - pszCurrBuffer = PushSymbolDetail(pszCurrBuffer); - - // Indicate if the variable is a local or parameter - if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_PARAMETER) - symbolDetails.top().Prefix = "Parameter "; - else if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_LOCAL) - symbolDetails.top().Prefix = "Local "; - - // Determine if the variable is a user defined type (UDT). IF so, bHandled - // will return true. - bool bHandled; - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, pSym->ModBase, pSym->TypeIndex, - 0, pVariable, bHandled, pSym->Name, "", false, true); - - if (!bHandled) - { - // The symbol wasn't a UDT, so do basic, stupid formatting of the - // variable. Based on the size, we're assuming it's a char, WORD, or - // DWORD. - BasicType basicType = GetBasicType(pSym->TypeIndex, pSym->ModBase); - if (symbolDetails.top().Type.empty()) - symbolDetails.top().Type = rgBaseType[basicType]; - - // Emit the variable name - if (pSym->Name[0] != '\0') - symbolDetails.top().Name = pSym->Name; - - char buffer[50]; - FormatOutputValue(buffer, basicType, pSym->Size, (PVOID)pVariable, sizeof(buffer)); - symbolDetails.top().Value = buffer; - } - - pszCurrBuffer = PopSymbolDetail(pszCurrBuffer); - return true; -} - -////////////////////////////////////////////////////////////////////////////// -// If it's a user defined type (UDT), recurse through its members until we're -// at fundamental types. When he hit fundamental types, return -// bHandled = false, so that FormatSymbolValue() will format them. -////////////////////////////////////////////////////////////////////////////// -char * WheatyExceptionReport::DumpTypeIndex( -char * pszCurrBuffer, -DWORD64 modBase, -DWORD dwTypeIndex, -unsigned nestingLevel, -DWORD_PTR offset, -bool & bHandled, -const char* Name, -char* /*suffix*/, -bool newSymbol, -bool logChildren) -{ - bHandled = false; - - if (newSymbol) - pszCurrBuffer = PushSymbolDetail(pszCurrBuffer); - - DWORD typeTag; - if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMTAG, &typeTag)) - return pszCurrBuffer; - - // Get the name of the symbol. This will either be a Type name (if a UDT), - // or the structure member name. - WCHAR * pwszTypeName; - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME, - &pwszTypeName)) - { - // handle special cases - if (wcscmp(pwszTypeName, L"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0) - { - LocalFree(pwszTypeName); - symbolDetails.top().Type = "std::string"; - char buffer[50]; - FormatOutputValue(buffer, btStdString, 0, (PVOID)offset, sizeof(buffer)); - symbolDetails.top().Value = buffer; - if (Name != NULL && Name[0] != '\0') - symbolDetails.top().Name = Name; - bHandled = true; - return pszCurrBuffer; - } - - char buffer[200]; - wcstombs(buffer, pwszTypeName, sizeof(buffer)); - buffer[199] = '\0'; - if (Name != NULL && Name[0] != '\0') - { - symbolDetails.top().Type = buffer; - symbolDetails.top().Name = Name; - } - else if (buffer[0] != '\0') - symbolDetails.top().Name = buffer; - - LocalFree(pwszTypeName); - } - else if (Name != NULL && Name[0] != '\0') - symbolDetails.top().Name = Name; - - if (!StoreSymbol(dwTypeIndex, offset)) - { - // Skip printing address and base class if it has been printed already - if (typeTag == SymTagBaseClass) - bHandled = true; - return pszCurrBuffer; - } - - DWORD innerTypeID; - switch (typeTag) - { - case SymTagPointerType: - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID)) - { - if (Name != NULL && Name[0] != '\0') - symbolDetails.top().Name = Name; - - BOOL isReference; - SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_IS_REFERENCE, &isReference); - - char addressStr[40]; - memset(addressStr, 0, sizeof(addressStr)); - - if (isReference) - symbolDetails.top().Suffix += "&"; - else - symbolDetails.top().Suffix += "*"; - - // Try to dereference the pointer in a try/except block since it might be invalid - DWORD_PTR address = DereferenceUnsafePointer(offset); - - char buffer[50]; - FormatOutputValue(buffer, btVoid, sizeof(PVOID), (PVOID)offset, sizeof(buffer)); - symbolDetails.top().Value = buffer; - - if (nestingLevel >= WER_MAX_NESTING_LEVEL) - logChildren = false; - - // no need to log any children since the address is invalid anyway - if (address == NULL || address == DWORD_PTR(-1)) - logChildren = false; - - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, - address, bHandled, Name, addressStr, false, logChildren); - - if (!bHandled) - { - BasicType basicType = GetBasicType(dwTypeIndex, modBase); - if (symbolDetails.top().Type.empty()) - symbolDetails.top().Type = rgBaseType[basicType]; - - if (address == NULL) - symbolDetails.top().Value = "NULL"; - else if (address == DWORD_PTR(-1)) - symbolDetails.top().Value = "<Unable to read memory>"; - else - { - // Get the size of the child member - ULONG64 length; - SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length); - char buffer2[50]; - FormatOutputValue(buffer2, basicType, length, (PVOID)address, sizeof(buffer)); - symbolDetails.top().Value = buffer2; - } - bHandled = true; - return pszCurrBuffer; - } - else if (address == NULL) - symbolDetails.top().Value = "NULL"; - else if (address == DWORD_PTR(-1)) - { - symbolDetails.top().Value = "<Unable to read memory>"; - bHandled = true; - return pszCurrBuffer; - } - } - break; - case SymTagData: - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID)) - { - DWORD innerTypeTag; - if (!SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_SYMTAG, &innerTypeTag)) - break; - - switch (innerTypeTag) - { - case SymTagUDT: - if (nestingLevel >= WER_MAX_NESTING_LEVEL) - logChildren = false; - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, - offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren); - break; - case SymTagPointerType: - if (Name != NULL && Name[0] != '\0') - symbolDetails.top().Name = Name; - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, - offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren); - break; - case SymTagArrayType: - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, - offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren); - break; - default: - break; - } - } - break; - case SymTagArrayType: - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_TYPEID, &innerTypeID)) - { - symbolDetails.top().HasChildren = true; - - BasicType basicType = btNoType; - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, innerTypeID, nestingLevel + 1, - offset, bHandled, Name, "", false, false); - - // Set Value back to an empty string since the Array object itself has no value, only its elements have - symbolDetails.top().Value.clear(); - - DWORD elementsCount; - if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_COUNT, &elementsCount)) - symbolDetails.top().Suffix += "[" + std::to_string(elementsCount) + "]"; - else - symbolDetails.top().Suffix += "[<unknown count>]"; - - if (!bHandled) - { - basicType = GetBasicType(dwTypeIndex, modBase); - if (symbolDetails.top().Type.empty()) - symbolDetails.top().Type = rgBaseType[basicType]; - bHandled = true; - } - - // Get the size of the child member - ULONG64 length; - SymGetTypeInfo(m_hProcess, modBase, innerTypeID, TI_GET_LENGTH, &length); - - char buffer[50]; - switch (basicType) - { - case btChar: - case btStdString: - FormatOutputValue(buffer, basicType, length, (PVOID)offset, sizeof(buffer), elementsCount); - symbolDetails.top().Value = buffer; - break; - default: - for (DWORD index = 0; index < elementsCount && index < WER_MAX_ARRAY_ELEMENTS_COUNT; index++) - { - pszCurrBuffer = PushSymbolDetail(pszCurrBuffer); - symbolDetails.top().Suffix += "[" + std::to_string(index) + "]"; - FormatOutputValue(buffer, basicType, length, (PVOID)(offset + length * index), sizeof(buffer)); - symbolDetails.top().Value = buffer; - pszCurrBuffer = PopSymbolDetail(pszCurrBuffer); - } - break; - } - - return pszCurrBuffer; - } - break; - case SymTagBaseType: - break; - case SymTagEnum: - return pszCurrBuffer; - default: - break; - } - - // Determine how many children this type has. - DWORD dwChildrenCount = 0; - SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_CHILDRENCOUNT, &dwChildrenCount); - - if (!dwChildrenCount) // If no children, we're done - return pszCurrBuffer; - - // Prepare to get an array of "TypeIds", representing each of the children. - // SymGetTypeInfo(TI_FINDCHILDREN) expects more memory than just a - // TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this. - struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS - { - ULONG MoreChildIds[1024*2]; - FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);} - } children; - - children.Count = dwChildrenCount; - children.Start= 0; - - // Get the array of TypeIds, one for each child type - if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN, - &children)) - { - return pszCurrBuffer; - } - - // Iterate through each of the children - for (unsigned i = 0; i < dwChildrenCount; i++) - { - DWORD symTag; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag); - - if (symTag == SymTagFunction || - symTag == SymTagEnum || - symTag == SymTagTypedef || - symTag == SymTagVTable) - continue; - - // Ignore static fields - DWORD dataKind; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind); - if (dataKind == DataIsStaticLocal || - dataKind == DataIsGlobal || - dataKind == DataIsStaticMember) - continue; - - - symbolDetails.top().HasChildren = true; - if (!logChildren) - { - bHandled = false; - return pszCurrBuffer; - } - - // Recurse for each of the child types - bool bHandled2; - BasicType basicType = GetBasicType(children.ChildId[i], modBase); - - // Get the offset of the child member, relative to its parent - DWORD dwMemberOffset; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_OFFSET, &dwMemberOffset); - - // Calculate the address of the member - DWORD_PTR dwFinalOffset = offset + dwMemberOffset; - - pszCurrBuffer = DumpTypeIndex(pszCurrBuffer, modBase, - children.ChildId[i], nestingLevel+1, - dwFinalOffset, bHandled2, ""/*Name */, "", true, true); - - // If the child wasn't a UDT, format it appropriately - if (!bHandled2) - { - if (symbolDetails.top().Type.empty()) - symbolDetails.top().Type = rgBaseType[basicType]; - - // Get the real "TypeId" of the child. We need this for the - // SymGetTypeInfo(TI_GET_TYPEID) call below. - DWORD typeId; - SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], - TI_GET_TYPEID, &typeId); - - // Get the size of the child member - ULONG64 length; - SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_LENGTH, &length); - - char buffer[50]; - FormatOutputValue(buffer, basicType, length, (PVOID)dwFinalOffset, sizeof(buffer)); - symbolDetails.top().Value = buffer; - } - - pszCurrBuffer = PopSymbolDetail(pszCurrBuffer); - } - - bHandled = true; - return pszCurrBuffer; -} - -void WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer, -BasicType basicType, -DWORD64 length, -PVOID pAddress, -size_t bufferSize, -size_t countOverride) -{ - __try - { - switch (basicType) - { - case btChar: - { - // Special case handling for char[] type - if (countOverride != 0) - length = countOverride; - else - length = strlen((char*)pAddress); - if (length > bufferSize - 6) - pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), (char*)pAddress); - else - pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s\"", (DWORD)length, (char*)pAddress); - break; - } - case btStdString: - { - std::string* value = static_cast<std::string*>(pAddress); - if (value->length() > bufferSize - 6) - pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), value->c_str()); - else - pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", value->c_str()); - break; - } - default: - // Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!) - if (length == 1) - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PBYTE)pAddress); - else if (length == 2) - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PWORD)pAddress); - else if (length == 4) - { - if (basicType == btFloat) - pszCurrBuffer += sprintf(pszCurrBuffer, "%f", *(PFLOAT)pAddress); - else - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", *(PDWORD)pAddress); - } - else if (length == 8) - { - if (basicType == btFloat) - { - pszCurrBuffer += sprintf(pszCurrBuffer, "%f", - *(double *)pAddress); - } - else - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", - *(DWORD64*)pAddress); - } - else - { - #if _WIN64 - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", (DWORD64)pAddress); - #else - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", (DWORD)pAddress); - #endif - } - break; - } - } - __except (EXCEPTION_EXECUTE_HANDLER) - { -#if _WIN64 - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X <Unable to read memory>", (DWORD64)pAddress); -#else - pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X <Unable to read memory>", (DWORD)pAddress); -#endif - } -} - -BasicType -WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase) -{ - BasicType basicType; - if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, - TI_GET_BASETYPE, &basicType)) - { - return basicType; - } - - // Get the real "TypeId" of the child. We need this for the - // SymGetTypeInfo(TI_GET_TYPEID) call below. - DWORD typeId; - if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, TI_GET_TYPEID, &typeId)) - { - if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE, - &basicType)) - { - return basicType; - } - } - - return btNoType; -} - -DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address) -{ - __try - { - return *(PDWORD_PTR)address; - } - __except (EXCEPTION_EXECUTE_HANDLER) - { - return DWORD_PTR(-1); - } -} - -//============================================================================ -// Helper function that writes to the report file, and allows the user to use -// printf style formating -//============================================================================ -int __cdecl WheatyExceptionReport::_tprintf(const TCHAR * format, ...) -{ - int retValue; - va_list argptr; - va_start(argptr, format); - if (stackOverflowException) - { - retValue = heapprintf(format, argptr); - va_end(argptr); - } - else - { - retValue = stackprintf(format, argptr); - va_end(argptr); - } - - return retValue; -} - -int __cdecl WheatyExceptionReport::stackprintf(const TCHAR * format, va_list argptr) -{ - int retValue; - DWORD cbWritten; - - TCHAR szBuff[WER_LARGE_BUFFER_SIZE]; - retValue = vsprintf(szBuff, format, argptr); - WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0); - - return retValue; -} - -int __cdecl WheatyExceptionReport::heapprintf(const TCHAR * format, va_list argptr) -{ - int retValue; - DWORD cbWritten; - TCHAR* szBuff = (TCHAR*)malloc(sizeof(TCHAR) * WER_LARGE_BUFFER_SIZE); - retValue = vsprintf(szBuff, format, argptr); - WriteFile(m_hReportFile, szBuff, retValue * sizeof(TCHAR), &cbWritten, 0); - free(szBuff); - - return retValue; -} - -bool WheatyExceptionReport::StoreSymbol(DWORD type, DWORD_PTR offset) -{ - return symbols.insert(SymbolPair(type, offset)).second; -} - -void WheatyExceptionReport::ClearSymbols() -{ - symbols.clear(); - while (!symbolDetails.empty()) - symbolDetails.pop(); -} - -char* WheatyExceptionReport::PushSymbolDetail(char* pszCurrBuffer) -{ - // Log current symbol and then add another to the stack to keep the hierarchy format - pszCurrBuffer = PrintSymbolDetail(pszCurrBuffer); - symbolDetails.emplace(); - return pszCurrBuffer; -} - -char* WheatyExceptionReport::PopSymbolDetail(char* pszCurrBuffer) -{ - pszCurrBuffer = PrintSymbolDetail(pszCurrBuffer); - symbolDetails.pop(); - return pszCurrBuffer; -} - -char* WheatyExceptionReport::PrintSymbolDetail(char* pszCurrBuffer) -{ - if (symbolDetails.empty()) - return pszCurrBuffer; - - // Don't log anything if has been logged already or if it's empty - if (symbolDetails.top().Logged || symbolDetails.top().empty()) - return pszCurrBuffer; - - // Add appropriate indentation level (since this routine is recursive) - for (size_t i = 0; i < symbolDetails.size(); i++) - pszCurrBuffer += sprintf(pszCurrBuffer, "\t"); - - pszCurrBuffer += sprintf(pszCurrBuffer, "%s\r\n", symbolDetails.top().ToString().c_str()); - - return pszCurrBuffer; -} - -#endif // _WIN32 diff --git a/src/server/shared/Debugging/WheatyExceptionReport.h b/src/server/shared/Debugging/WheatyExceptionReport.h deleted file mode 100644 index 8c2479d5232..00000000000 --- a/src/server/shared/Debugging/WheatyExceptionReport.h +++ /dev/null @@ -1,210 +0,0 @@ -#ifndef _WHEATYEXCEPTIONREPORT_ -#define _WHEATYEXCEPTIONREPORT_ - -#if PLATFORM == PLATFORM_WINDOWS && !defined(__MINGW32__) - -#include <dbghelp.h> -#include <set> -#include <stdlib.h> -#include <stack> -#include <mutex> -#define countof _countof - -#define WER_MAX_ARRAY_ELEMENTS_COUNT 10 -#define WER_MAX_NESTING_LEVEL 5 -#define WER_LARGE_BUFFER_SIZE 1024 * 128 - -enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK -{ - btNoType = 0, - btVoid = 1, - btChar = 2, - btWChar = 3, - btInt = 6, - btUInt = 7, - btFloat = 8, - btBCD = 9, - btBool = 10, - btLong = 13, - btULong = 14, - btCurrency = 25, - btDate = 26, - btVariant = 27, - btComplex = 28, - btBit = 29, - btBSTR = 30, - btHresult = 31, - - // Custom types - btStdString = 101 -}; - -enum DataKind // Stolen from CVCONST.H in the DIA 2.0 SDK -{ - DataIsUnknown, - DataIsLocal, - DataIsStaticLocal, - DataIsParam, - DataIsObjectPtr, - DataIsFileStatic, - DataIsGlobal, - DataIsMember, - DataIsStaticMember, - DataIsConstant -}; - -const char* const rgBaseType[] = -{ - "<user defined>", // btNoType = 0, - "void", // btVoid = 1, - "char",//char* // btChar = 2, - "wchar_t*", // btWChar = 3, - "signed char", - "unsigned char", - "int", // btInt = 6, - "unsigned int", // btUInt = 7, - "float", // btFloat = 8, - "<BCD>", // btBCD = 9, - "bool", // btBool = 10, - "short", - "unsigned short", - "long", // btLong = 13, - "unsigned long", // btULong = 14, - "int8", - "int16", - "int32", - "int64", - "int128", - "uint8", - "uint16", - "uint32", - "uint64", - "uint128", - "<currency>", // btCurrency = 25, - "<date>", // btDate = 26, - "VARIANT", // btVariant = 27, - "<complex>", // btComplex = 28, - "<bit>", // btBit = 29, - "BSTR", // btBSTR = 30, - "HRESULT" // btHresult = 31 -}; - -struct SymbolPair -{ - SymbolPair(DWORD type, DWORD_PTR offset) - { - _type = type; - _offset = offset; - } - - bool operator<(const SymbolPair& other) const - { - return _offset < other._offset || - (_offset == other._offset && _type < other._type); - } - - DWORD _type; - DWORD_PTR _offset; -}; -typedef std::set<SymbolPair> SymbolPairs; - -struct SymbolDetail -{ - SymbolDetail() : Prefix(), Type(), Suffix(), Name(), Value(), Logged(false), HasChildren(false) {} - - std::string ToString() - { - Logged = true; - std::string formatted = Prefix + Type + Suffix; - if (!Name.empty()) - { - if (!formatted.empty()) - formatted += " "; - formatted += Name; - } - if (!Value.empty()) - formatted += " = " + Value; - return formatted; - } - - bool empty() const - { - return Value.empty() && !HasChildren; - } - - std::string Prefix; - std::string Type; - std::string Suffix; - std::string Name; - std::string Value; - bool Logged; - bool HasChildren; -}; - -class WheatyExceptionReport -{ - public: - - WheatyExceptionReport(); - ~WheatyExceptionReport(); - - // entry point where control comes on an unhandled exception - static LONG WINAPI WheatyUnhandledExceptionFilter( - PEXCEPTION_POINTERS pExceptionInfo); - - static void printTracesForAllThreads(bool); - private: - // where report info is extracted and generated - static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo); - static void PrintSystemInfo(); - static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax); - static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount); - - // Helper functions - static LPTSTR GetExceptionString(DWORD dwCode); - static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len, - DWORD& section, DWORD_PTR& offset); - - static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle); - - static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID); - - static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *, char * pszBuffer, unsigned cbBuffer); - - static char * DumpTypeIndex(char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool &, const char*, char*, bool, bool); - - static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0); - - static BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase); - static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address); - - static int __cdecl _tprintf(const TCHAR * format, ...); - static int __cdecl stackprintf(const TCHAR * format, va_list argptr); - static int __cdecl heapprintf(const TCHAR * format, va_list argptr); - - static bool StoreSymbol(DWORD type , DWORD_PTR offset); - static void ClearSymbols(); - - // Variables used by the class - static TCHAR m_szLogFileName[MAX_PATH]; - static TCHAR m_szDumpFileName[MAX_PATH]; - static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter; - static HANDLE m_hReportFile; - static HANDLE m_hDumpFile; - static HANDLE m_hProcess; - static SymbolPairs symbols; - static std::stack<SymbolDetail> symbolDetails; - static bool stackOverflowException; - static bool alreadyCrashed; - static std::mutex alreadyCrashedLock; - - static char* PushSymbolDetail(char* pszCurrBuffer); - static char* PopSymbolDetail(char* pszCurrBuffer); - static char* PrintSymbolDetail(char* pszCurrBuffer); - -}; - -extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class -#endif // _WIN32 -#endif // _WHEATYEXCEPTIONREPORT_ - diff --git a/src/server/shared/Define.h b/src/server/shared/Define.h deleted file mode 100644 index 97e07cef8b3..00000000000 --- a/src/server/shared/Define.h +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITY_DEFINE_H -#define TRINITY_DEFINE_H - -#include "CompilerDefs.h" - -#if COMPILER == COMPILER_GNU -# if !defined(__STDC_FORMAT_MACROS) -# define __STDC_FORMAT_MACROS -# endif -# if !defined(__STDC_CONSTANT_MACROS) -# define __STDC_CONSTANT_MACROS -# endif -# if !defined(_GLIBCXX_USE_NANOSLEEP) -# define _GLIBCXX_USE_NANOSLEEP -# endif -# if defined(HELGRIND) -# include <valgrind/helgrind.h> -# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) ANNOTATE_HAPPENS_BEFORE(A) -# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) ANNOTATE_HAPPENS_AFTER(A) -# endif -#endif - -#include <cstddef> -#include <cinttypes> -#include <climits> - -#define TRINITY_LITTLEENDIAN 0 -#define TRINITY_BIGENDIAN 1 - -#if !defined(TRINITY_ENDIAN) -# if defined (BOOST_BIG_ENDIAN) -# define TRINITY_ENDIAN TRINITY_BIGENDIAN -# else -# define TRINITY_ENDIAN TRINITY_LITTLEENDIAN -# endif -#endif - -#if PLATFORM == PLATFORM_WINDOWS -# define TRINITY_PATH_MAX MAX_PATH -# define _USE_MATH_DEFINES -# ifndef DECLSPEC_NORETURN -# define DECLSPEC_NORETURN __declspec(noreturn) -# endif //DECLSPEC_NORETURN -# ifndef DECLSPEC_DEPRECATED -# define DECLSPEC_DEPRECATED __declspec(deprecated) -# endif //DECLSPEC_DEPRECATED -#else //PLATFORM != PLATFORM_WINDOWS -# define TRINITY_PATH_MAX PATH_MAX -# define DECLSPEC_NORETURN -# define DECLSPEC_DEPRECATED -#endif //PLATFORM - -#if !defined(COREDEBUG) -# define TRINITY_INLINE inline -#else //COREDEBUG -# if !defined(TRINITY_DEBUG) -# define TRINITY_DEBUG -# endif //TRINITY_DEBUG -# define TRINITY_INLINE -#endif //!COREDEBUG - -#if COMPILER == COMPILER_GNU -# define ATTR_NORETURN __attribute__((__noreturn__)) -# define ATTR_PRINTF(F, V) __attribute__ ((__format__ (__printf__, F, V))) -# define ATTR_DEPRECATED __attribute__((__deprecated__)) -#else //COMPILER != COMPILER_GNU -# define ATTR_NORETURN -# define ATTR_PRINTF(F, V) -# define ATTR_DEPRECATED -#endif //COMPILER == COMPILER_GNU - -#define UI64FMTD "%" PRIu64 -#define UI64LIT(N) UINT64_C(N) - -#define SI64FMTD "%" PRId64 -#define SI64LIT(N) INT64_C(N) - -#define SZFMTD "%" PRIuPTR - -typedef int64_t int64; -typedef int32_t int32; -typedef int16_t int16; -typedef int8_t int8; -typedef uint64_t uint64; -typedef uint32_t uint32; -typedef uint16_t uint16; -typedef uint8_t uint8; - -#endif //TRINITY_DEFINE_H diff --git a/src/server/shared/Logging/Appender.cpp b/src/server/shared/Logging/Appender.cpp deleted file mode 100644 index d19ef8cf96f..00000000000 --- a/src/server/shared/Logging/Appender.cpp +++ /dev/null @@ -1,109 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "Appender.h" -#include "Common.h" -#include "Util.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) { } - -Appender::~Appender() { } - -uint8 Appender::getId() const -{ - return id; -} - -std::string const& Appender::getName() const -{ - return name; -} - -LogLevel Appender::getLogLevel() const -{ - return level; -} - -AppenderFlags Appender::getFlags() const -{ - return flags; -} - -void Appender::setLogLevel(LogLevel _level) -{ - level = _level; -} - -void Appender::write(LogMessage* message) -{ - if (!level || level > message->level) - return; - - std::ostringstream ss; - - if (flags & APPENDER_FLAGS_PREFIX_TIMESTAMP) - ss << message->getTimeStr() << ' '; - - if (flags & APPENDER_FLAGS_PREFIX_LOGLEVEL) - ss << Trinity::StringFormat("%-5s ", Appender::getLogLevelString(message->level)); - - if (flags & APPENDER_FLAGS_PREFIX_LOGFILTERTYPE) - ss << '[' << message->type << "] "; - - message->prefix = ss.str(); - _write(message); -} - -const char* Appender::getLogLevelString(LogLevel level) -{ - switch (level) - { - case LOG_LEVEL_FATAL: - return "FATAL"; - case LOG_LEVEL_ERROR: - return "ERROR"; - case LOG_LEVEL_WARN: - return "WARN"; - case LOG_LEVEL_INFO: - return "INFO"; - case LOG_LEVEL_DEBUG: - return "DEBUG"; - case LOG_LEVEL_TRACE: - return "TRACE"; - default: - return "DISABLED"; - } -} diff --git a/src/server/shared/Logging/Appender.h b/src/server/shared/Logging/Appender.h deleted file mode 100644 index 7c5aa41924d..00000000000 --- a/src/server/shared/Logging/Appender.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 APPENDER_H -#define APPENDER_H - -#include <unordered_map> -#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 -{ - 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 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()); - } -}; - -class Appender -{ - public: - Appender(uint8 _id, std::string const& name, LogLevel level = LOG_LEVEL_DISABLED, AppenderFlags flags = APPENDER_FLAGS_NONE); - virtual ~Appender(); - - uint8 getId() const; - std::string const& getName() const; - virtual AppenderType getType() const = 0; - LogLevel getLogLevel() const; - AppenderFlags getFlags() const; - - void setLogLevel(LogLevel); - void write(LogMessage* message); - static const char* getLogLevelString(LogLevel level); - virtual void setRealmId(uint32 /*realmId*/) { } - - private: - virtual void _write(LogMessage const* /*message*/) = 0; - - uint8 id; - std::string name; - LogLevel level; - 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 InvalidAppenderArgsException : public std::length_error -{ -public: - using std::length_error::length_error; - - explicit InvalidAppenderArgsException(std::string const& message) : length_error(message) { } -}; - -#endif diff --git a/src/server/shared/Logging/AppenderConsole.cpp b/src/server/shared/Logging/AppenderConsole.cpp deleted file mode 100644 index 531df266aa1..00000000000 --- a/src/server/shared/Logging/AppenderConsole.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 <sstream> - -#include "AppenderConsole.h" -#include "Config.h" -#include "Util.h" - -#if PLATFORM == PLATFORM_WINDOWS - #include <Windows.h> -#endif - -AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) - : Appender(id, name, level, flags), _colored(false) -{ - for (uint8 i = 0; i < MaxLogLevels; ++i) - _colors[i] = ColorTypes(MaxColors); - - if (!extraArgs.empty()) - InitColors(extraArgs[0]); -} - -void AppenderConsole::InitColors(std::string const& str) -{ - if (str.empty()) - { - _colored = false; - return; - } - - int color[MaxLogLevels]; - - std::istringstream ss(str); - - for (uint8 i = 0; i < MaxLogLevels; ++i) - { - ss >> color[i]; - - if (!ss) - return; - - if (color[i] < 0 || color[i] >= MaxColors) - return; - } - - for (uint8 i = 0; i < MaxLogLevels; ++i) - _colors[i] = ColorTypes(color[i]); - - _colored = true; -} - -void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color) -{ -#if PLATFORM == PLATFORM_WINDOWS - static WORD WinColorFG[MaxColors] = - { - 0, // BLACK - FOREGROUND_RED, // RED - FOREGROUND_GREEN, // GREEN - FOREGROUND_RED | FOREGROUND_GREEN, // BROWN - FOREGROUND_BLUE, // BLUE - FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA - FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE - // YELLOW - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY, - // RED_BOLD - FOREGROUND_RED | FOREGROUND_INTENSITY, - // GREEN_BOLD - FOREGROUND_GREEN | FOREGROUND_INTENSITY, - FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD - // MAGENTA_BOLD - FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY, - // CYAN_BOLD - FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY, - // WHITE_BOLD - FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY - }; - - HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); - SetConsoleTextAttribute(hConsole, WinColorFG[color]); -#else - enum ANSITextAttr - { - TA_NORMAL = 0, - TA_BOLD = 1, - TA_BLINK = 5, - TA_REVERSE = 7 - }; - - enum ANSIFgTextAttr - { - FG_BLACK = 30, - FG_RED, - FG_GREEN, - FG_BROWN, - FG_BLUE, - FG_MAGENTA, - FG_CYAN, - FG_WHITE, - FG_YELLOW - }; - - enum ANSIBgTextAttr - { - BG_BLACK = 40, - BG_RED, - BG_GREEN, - BG_BROWN, - BG_BLUE, - BG_MAGENTA, - BG_CYAN, - BG_WHITE - }; - - static uint8 UnixColorFG[MaxColors] = - { - FG_BLACK, // BLACK - FG_RED, // RED - FG_GREEN, // GREEN - FG_BROWN, // BROWN - FG_BLUE, // BLUE - FG_MAGENTA, // MAGENTA - FG_CYAN, // CYAN - FG_WHITE, // WHITE - FG_YELLOW, // YELLOW - FG_RED, // LRED - FG_GREEN, // LGREEN - FG_BLUE, // LBLUE - FG_MAGENTA, // LMAGENTA - FG_CYAN, // LCYAN - FG_WHITE // LWHITE - }; - - fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < MaxColors ? ";1" : "")); - #endif -} - -void AppenderConsole::ResetColor(bool stdout_stream) -{ - #if PLATFORM == PLATFORM_WINDOWS - HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE); - SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED); - #else - fprintf((stdout_stream ? stdout : stderr), "\x1b[0m"); - #endif -} - -void AppenderConsole::_write(LogMessage const* message) -{ - bool stdout_stream = !(message->level == LOG_LEVEL_ERROR || message->level == LOG_LEVEL_FATAL); - - if (_colored) - { - uint8 index; - switch (message->level) - { - case LOG_LEVEL_TRACE: - index = 5; - break; - case LOG_LEVEL_DEBUG: - index = 4; - break; - case LOG_LEVEL_INFO: - index = 3; - break; - case LOG_LEVEL_WARN: - index = 2; - break; - case LOG_LEVEL_FATAL: - index = 0; - break; - case LOG_LEVEL_ERROR: // No break on purpose - default: - index = 1; - break; - } - - SetColor(stdout_stream, _colors[index]); - utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str()); - ResetColor(stdout_stream); - } - else - utf8printf(stdout_stream ? stdout : stderr, "%s%s\n", message->prefix.c_str(), message->text.c_str()); -} diff --git a/src/server/shared/Logging/AppenderConsole.h b/src/server/shared/Logging/AppenderConsole.h deleted file mode 100644 index 6b30505c6bd..00000000000 --- a/src/server/shared/Logging/AppenderConsole.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 APPENDERCONSOLE_H -#define APPENDERCONSOLE_H - -#include <string> -#include "Appender.h" - -enum ColorTypes -{ - BLACK, - RED, - GREEN, - BROWN, - BLUE, - MAGENTA, - CYAN, - GREY, - YELLOW, - LRED, - LGREEN, - LBLUE, - LMAGENTA, - LCYAN, - WHITE -}; - -const uint8 MaxColors = uint8(WHITE) + 1; - -class 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); - void InitColors(const std::string& init_str); - AppenderType getType() const override { return TypeIndex::value; } - - private: - void SetColor(bool stdout_stream, ColorTypes color); - void ResetColor(bool stdout_stream); - void _write(LogMessage const* message) override; - bool _colored; - ColorTypes _colors[MaxLogLevels]; -}; - -#endif diff --git a/src/server/shared/Logging/AppenderFile.cpp b/src/server/shared/Logging/AppenderFile.cpp deleted file mode 100644 index d33818626fe..00000000000 --- a/src/server/shared/Logging/AppenderFile.cpp +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "AppenderFile.h" -#include "Common.h" -#include "StringFormat.h" -#include "Log.h" - -#if PLATFORM == PLATFORM_WINDOWS -# include <Windows.h> -#endif - -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, ExtraAppenderArgs extraArgs) : - Appender(id, name, level, flags), - logfile(NULL), - _logDir(sLog->GetLogsDir()), - _fileSize(0) -{ - if (extraArgs.empty()) - throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str())); - - _fileName = extraArgs[0]; - - char const* mode = "a"; - if (extraArgs.size() > 1) - mode = extraArgs[1]; - - if (flags & APPENDER_FLAGS_USE_TIMESTAMP) - { - size_t dot_pos = _fileName.find_last_of("."); - if (dot_pos != std::string::npos) - _fileName.insert(dot_pos, sLog->GetLogsTimestamp()); - else - _fileName += sLog->GetLogsTimestamp(); - } - - if (extraArgs.size() > 2) - _maxFileSize = atoi(extraArgs[2]); - - _dynamicName = std::string::npos != _fileName.find("%s"); - _backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0; - - if (!_dynamicName) - logfile = OpenFile(_fileName, mode, !strcmp(mode, "w") && _backup); -} - -AppenderFile::~AppenderFile() -{ - CloseFile(); -} - -void AppenderFile::_write(LogMessage const* message) -{ - bool exceedMaxSize = _maxFileSize > 0 && (_fileSize.load() + message->Size()) > _maxFileSize; - - if (_dynamicName) - { - char namebuf[TRINITY_PATH_MAX]; - snprintf(namebuf, TRINITY_PATH_MAX, _fileName.c_str(), message->param1.c_str()); - // always use "a" with dynamic name otherwise it could delete the log we wrote in last _write() call - FILE* file = OpenFile(namebuf, "a", _backup || exceedMaxSize); - if (!file) - return; - fprintf(file, "%s%s\n", message->prefix.c_str(), message->text.c_str()); - fflush(file); - _fileSize += uint64(message->Size()); - fclose(file); - return; - } - else if (exceedMaxSize) - logfile = OpenFile(_fileName, "w", true); - - if (!logfile) - return; - - fprintf(logfile, "%s%s\n", message->prefix.c_str(), message->text.c_str()); - fflush(logfile); - _fileSize += uint64(message->Size()); -} - -FILE* AppenderFile::OpenFile(std::string const& filename, std::string const& mode, bool backup) -{ - std::string fullName(_logDir + filename); - if (backup) - { - CloseFile(); - std::string newName(fullName); - newName.push_back('.'); - newName.append(LogMessage::getTimeStr(time(NULL))); - 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 - } - - if (FILE* ret = fopen(fullName.c_str(), mode.c_str())) - { - _fileSize = ftell(ret); - return ret; - } - - return NULL; -} - -void AppenderFile::CloseFile() -{ - if (logfile) - { - fclose(logfile); - logfile = NULL; - } -} diff --git a/src/server/shared/Logging/AppenderFile.h b/src/server/shared/Logging/AppenderFile.h deleted file mode 100644 index c2781eb1ee9..00000000000 --- a/src/server/shared/Logging/AppenderFile.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 APPENDERFILE_H -#define APPENDERFILE_H - -#include <atomic> -#include "Appender.h" - -class 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(); - FILE* OpenFile(std::string const& name, std::string const& mode, bool backup); - AppenderType getType() const override { return TypeIndex::value; } - - private: - void CloseFile(); - void _write(LogMessage const* message) override; - FILE* logfile; - std::string _fileName; - std::string _logDir; - bool _dynamicName; - bool _backup; - uint64 _maxFileSize; - std::atomic<uint64> _fileSize; -}; - -#endif diff --git a/src/server/shared/Logging/Log.cpp b/src/server/shared/Logging/Log.cpp deleted file mode 100644 index 5075815ad54..00000000000 --- a/src/server/shared/Logging/Log.cpp +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2008 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 "Log.h" -#include "Common.h" -#include "Config.h" -#include "Util.h" -#include "AppenderConsole.h" -#include "AppenderFile.h" -#include "AppenderDB.h" -#include "LogOperation.h" - -#include <cstdio> -#include <sstream> - -Log::Log() : _ioService(nullptr), _strand(nullptr) -{ - m_logsTimestamp = "_" + GetTimestampStr(); - RegisterAppender<AppenderConsole>(); - RegisterAppender<AppenderFile>(); -} - -Log::~Log() -{ - delete _strand; - Close(); -} - -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(); - while (it != appenders.end() && it->second && it->second->getName() != name) - ++it; - - return it == appenders.end() ? NULL : it->second; -} - -void Log::CreateAppenderFromConfig(std::string const& appenderName) -{ - if (appenderName.empty()) - return; - - // 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(); - - size_t size = tokens.size(); - std::string name = appenderName.substr(9); - - if (size < 2) - { - fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong configuration for appender %s. Config line: %s\n", name.c_str(), options.c_str()); - return; - } - - AppenderFlags flags = APPENDER_FLAGS_NONE; - AppenderType type = AppenderType(atoi(*iter++)); - LogLevel level = LogLevel(atoi(*iter++)); - - if (level > LOG_LEVEL_FATAL) - { - fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %d for appender %s\n", level, name.c_str()); - return; - } - - if (size > 2) - flags = AppenderFlags(atoi(*iter++)); - - auto factoryFunction = appenderFactory.find(type); - if (factoryFunction == appenderFactory.end()) - { - fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str()); - return; - } - - try - { - Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, ExtraAppenderArgs(iter, tokens.end())); - appenders[appender->getId()] = appender; - } - catch (InvalidAppenderArgsException const& iaae) - { - fprintf(stderr, "%s", iaae.what()); - } -} - -void Log::CreateLoggerFromConfig(std::string const& appenderName) -{ - if (appenderName.empty()) - return; - - LogLevel level = LOG_LEVEL_DISABLED; - uint8 type = uint8(-1); - - std::string options = sConfigMgr->GetStringDefault(appenderName.c_str(), ""); - std::string name = appenderName.substr(7); - - if (options.empty()) - { - fprintf(stderr, "Log::CreateLoggerFromConfig: Missing config option Logger.%s\n", name.c_str()); - return; - } - - Tokenizer tokens(options, ','); - Tokenizer::const_iterator iter = tokens.begin(); - - if (tokens.size() != 2) - { - fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong config option Logger.%s=%s\n", name.c_str(), options.c_str()); - return; - } - - Logger& logger = loggers[name]; - if (!logger.getName().empty()) - { - fprintf(stderr, "Error while configuring Logger %s. Already defined\n", name.c_str()); - return; - } - - level = LogLevel(atoi(*iter++)); - if (level > LOG_LEVEL_FATAL) - { - fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level %u for logger %s\n", type, name.c_str()); - return; - } - - if (level < lowestLogLevel) - lowestLogLevel = level; - - logger.Create(name, level); - //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level); - - std::istringstream ss(*iter); - std::string str; - - ss >> str; - while (ss) - { - if (Appender* appender = GetAppenderByName(str)) - { - logger.addAppender(appender->getId(), appender); - //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str()); - } - else - fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name.c_str()); - ss >> str; - } -} - -void Log::ReadAppendersFromConfig() -{ - std::list<std::string> keys = sConfigMgr->GetKeysByString("Appender."); - - while (!keys.empty()) - { - CreateAppenderFromConfig(keys.front()); - keys.pop_front(); - } -} - -void Log::ReadLoggersFromConfig() -{ - std::list<std::string> keys = sConfigMgr->GetKeysByString("Logger."); - - while (!keys.empty()) - { - CreateLoggerFromConfig(keys.front()); - keys.pop_front(); - } - - // Bad config configuration, creating default config - if (loggers.find(LOGGER_ROOT) == loggers.end()) - { - fprintf(stderr, "Wrong Loggers configuration. Review your Logger config section.\n" - "Creating default loggers [root (Error), server (Info)] to console\n"); - - Close(); // Clean any Logger or Appender created - - AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, ExtraAppenderArgs()); - appenders[appender->getId()] = appender; - - Logger& logger = loggers[LOGGER_ROOT]; - logger.Create(LOGGER_ROOT, LOG_LEVEL_ERROR); - logger.addAppender(appender->getId(), appender); - - logger = loggers["server"]; - logger.Create("server", LOG_LEVEL_ERROR); - logger.addAppender(appender->getId(), appender); - } -} - -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))); - - _ioService->post(_strand->wrap([logOperation](){ logOperation->call(); })); - } - else - logger->write(msg.get()); -} - -std::string Log::GetTimestampStr() -{ - time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); - - std::tm aTm; - localtime_r(&tt, &aTm); - - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - return Trinity::StringFormat("%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); -} - -bool Log::SetLogLevel(std::string const& name, const char* newLevelc, bool isLogger /* = true */) -{ - LogLevel newLevel = LogLevel(atoi(newLevelc)); - if (newLevel < 0) - return false; - - if (isLogger) - { - LoggerMap::iterator it = loggers.begin(); - while (it != loggers.end() && it->second.getName() != name) - ++it; - - if (it == loggers.end()) - return false; - - it->second.setLogLevel(newLevel); - - if (newLevel != LOG_LEVEL_DISABLED && newLevel < lowestLogLevel) - lowestLogLevel = newLevel; - } - else - { - Appender* appender = GetAppenderByName(name); - if (!appender) - return false; - - appender->setLogLevel(newLevel); - } - - return true; -} - -void Log::outCharDump(char const* str, uint32 accountId, uint64 guid, char const* name) -{ - if (!str || !ShouldLog("entities.player.dump", LOG_LEVEL_INFO)) - return; - - std::ostringstream ss; - ss << "== START DUMP == (account: " << accountId << " guid: " << guid << " name: " << name - << ")\n" << str << "\n== END DUMP ==\n"; - - std::unique_ptr<LogMessage> msg(new LogMessage(LOG_LEVEL_INFO, "entities.player.dump", ss.str())); - std::ostringstream param; - param << guid << '_' << name; - - msg->param1 = param.str(); - - write(std::move(msg)); -} - -void Log::SetRealmId(uint32 id) -{ - for (AppenderMap::iterator 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(); -} - -void Log::Initialize(boost::asio::io_service* ioService) -{ - if (ioService) - { - _ioService = ioService; - _strand = new boost::asio::strand(*ioService); - } - - LoadFromConfig(); -} - -void Log::LoadFromConfig() -{ - Close(); - - lowestLogLevel = LOG_LEVEL_FATAL; - AppenderId = 0; - m_logsDir = sConfigMgr->GetStringDefault("LogsDir", ""); - if (!m_logsDir.empty()) - if ((m_logsDir.at(m_logsDir.length() - 1) != '/') && (m_logsDir.at(m_logsDir.length() - 1) != '\\')) - m_logsDir.push_back('/'); - - ReadAppendersFromConfig(); - ReadLoggersFromConfig(); -} diff --git a/src/server/shared/Logging/Log.h b/src/server/shared/Logging/Log.h deleted file mode 100644 index a15bb4ad485..00000000000 --- a/src/server/shared/Logging/Log.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITYCORE_LOG_H -#define TRINITYCORE_LOG_H - -#include "Define.h" -#include "Appender.h" -#include "Logger.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> - -#define LOGGER_ROOT "root" - -class Log -{ - typedef std::unordered_map<std::string, Logger> LoggerMap; - - private: - Log(); - ~Log(); - - public: - - static Log* instance() - { - static Log instance; - return &instance; - } - - void Initialize(boost::asio::io_service* ioService); - void LoadFromConfig(); - void Close(); - bool ShouldLog(std::string const& type, LogLevel level) const; - bool SetLogLevel(std::string const& name, char const* level, bool isLogger = true); - - 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)...))); - } - - template<typename Format, typename... Args> - void outCommand(uint32 account, Format&& fmt, Args&&... args) - { - 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)); - } - - void outCharDump(char const* str, uint32 account_id, uint64 guid, char const* name); - - void SetRealmId(uint32 id); - - template<class AppenderImpl> - void RegisterAppender() - { - using Index = typename AppenderImpl::TypeIndex; - auto itr = appenderFactory.find(Index::value); - ASSERT(itr == appenderFactory.end()); - appenderFactory[Index::value] = &CreateAppender<AppenderImpl>; - } - - std::string const& GetLogsDir() const { return m_logsDir; } - std::string const& GetLogsTimestamp() const { return m_logsTimestamp; } - - private: - static std::string GetTimestampStr(); - void write(std::unique_ptr<LogMessage>&& msg) const; - - Logger const* GetLoggerByType(std::string const& type) const; - Appender* GetAppenderByName(std::string const& name); - uint8 NextAppenderId(); - void CreateAppenderFromConfig(std::string const& name); - void CreateLoggerFromConfig(std::string const& name); - void ReadAppendersFromConfig(); - void ReadLoggersFromConfig(); - - AppenderCreatorMap appenderFactory; - AppenderMap appenders; - LoggerMap loggers; - uint8 AppenderId; - LogLevel lowestLogLevel; - - std::string m_logsDir; - std::string m_logsTimestamp; - - boost::asio::io_service* _ioService; - boost::asio::strand* _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__, ...) \ - { \ - try \ - { \ - sLog->outMessage(filterType__, level__, __VA_ARGS__); \ - } \ - catch (std::exception& e) \ - { \ - sLog->outMessage("server", LOG_LEVEL_ERROR, "Wrong format occurred (%s) at %s:%u.", \ - e.what(), __FILE__, __LINE__); \ - } \ - } - -#if PLATFORM != PLATFORM_WINDOWS -void check_args(const char*, ...) ATTR_PRINTF(1, 2); -void check_args(std::string const&, ...); - -// This will catch format errors on build time -#define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \ - do { \ - if (sLog->ShouldLog(filterType__, level__)) \ - { \ - if (false) \ - check_args(__VA_ARGS__); \ - \ - LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \ - } \ - } while (0) -#else -#define TC_LOG_MESSAGE_BODY(filterType__, level__, ...) \ - __pragma(warning(push)) \ - __pragma(warning(disable:4127)) \ - do { \ - if (sLog->ShouldLog(filterType__, level__)) \ - LOG_EXCEPTION_FREE(filterType__, level__, __VA_ARGS__); \ - } while (0) \ - __pragma(warning(pop)) -#endif - -#define TC_LOG_TRACE(filterType__, ...) \ - TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_TRACE, __VA_ARGS__) - -#define TC_LOG_DEBUG(filterType__, ...) \ - TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_DEBUG, __VA_ARGS__) - -#define TC_LOG_INFO(filterType__, ...) \ - TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_INFO, __VA_ARGS__) - -#define TC_LOG_WARN(filterType__, ...) \ - TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_WARN, __VA_ARGS__) - -#define TC_LOG_ERROR(filterType__, ...) \ - TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_ERROR, __VA_ARGS__) - -#define TC_LOG_FATAL(filterType__, ...) \ - TC_LOG_MESSAGE_BODY(filterType__, LOG_LEVEL_FATAL, __VA_ARGS__) - -#endif diff --git a/src/server/shared/Logging/LogOperation.cpp b/src/server/shared/Logging/LogOperation.cpp deleted file mode 100644 index bcd923c705e..00000000000 --- a/src/server/shared/Logging/LogOperation.cpp +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "LogOperation.h" -#include "Logger.h" - -int LogOperation::call() -{ - logger->write(msg.get()); - return 0; -} diff --git a/src/server/shared/Logging/LogOperation.h b/src/server/shared/Logging/LogOperation.h deleted file mode 100644 index ffdd35c3c09..00000000000 --- a/src/server/shared/Logging/LogOperation.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 LOGOPERATION_H -#define LOGOPERATION_H - -#include <memory> - -class Logger; -struct LogMessage; - -class LogOperation -{ - public: - LogOperation(Logger const* _logger, std::unique_ptr<LogMessage>&& _msg) - : logger(_logger), msg(std::forward<std::unique_ptr<LogMessage>>(_msg)) - { } - - ~LogOperation() { } - - int call(); - - protected: - Logger const* logger; - std::unique_ptr<LogMessage> msg; -}; - -#endif diff --git a/src/server/shared/Logging/Logger.cpp b/src/server/shared/Logging/Logger.cpp deleted file mode 100644 index 3b02eb47575..00000000000 --- a/src/server/shared/Logging/Logger.cpp +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "Logger.h" - -Logger::Logger(): name(""), level(LOG_LEVEL_DISABLED) { } - -void Logger::Create(std::string const& _name, LogLevel _level) -{ - name = _name; - level = _level; -} - -std::string const& Logger::getName() const -{ - return name; -} - -LogLevel Logger::getLogLevel() const -{ - return level; -} - -void Logger::addAppender(uint8 id, Appender* appender) -{ - appenders[id] = appender; -} - -void Logger::delAppender(uint8 id) -{ - appenders.erase(id); -} - -void Logger::setLogLevel(LogLevel _level) -{ - level = _level; -} - -void Logger::write(LogMessage* message) const -{ - if (!level || level > message->level || message->text.empty()) - { - //fprintf(stderr, "Logger::write: Logger %s, Level %u. Msg %s Level %u WRONG LEVEL MASK OR EMPTY MSG\n", getName().c_str(), getLogLevel(), message.text.c_str(), message.level); - return; - } - - for (AppenderMap::const_iterator it = appenders.begin(); it != appenders.end(); ++it) - if (it->second) - it->second->write(message); -} diff --git a/src/server/shared/Logging/Logger.h b/src/server/shared/Logging/Logger.h deleted file mode 100644 index 1aee75c5d72..00000000000 --- a/src/server/shared/Logging/Logger.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 LOGGER_H -#define LOGGER_H - -#include "Appender.h" - -class Logger -{ - public: - Logger(); - - void Create(std::string const& name, LogLevel level); - void addAppender(uint8 type, Appender *); - void delAppender(uint8 type); - - std::string const& getName() const; - LogLevel getLogLevel() const; - void setLogLevel(LogLevel level); - void write(LogMessage* message) const; - - private: - std::string name; - LogLevel level; - AppenderMap appenders; -}; - -#endif diff --git a/src/server/shared/PrecompiledHeaders/sharedPCH.h b/src/server/shared/PrecompiledHeaders/sharedPCH.h index f4c18f89ec1..c09b24e6fd9 100644 --- a/src/server/shared/PrecompiledHeaders/sharedPCH.h +++ b/src/server/shared/PrecompiledHeaders/sharedPCH.h @@ -1,11 +1,4 @@ //add here most rarely modified headers to speed up debug build compilation -#include "Common.h" -#include "Log.h" -#include "DatabaseWorker.h" -#include "SQLOperation.h" -#include "Errors.h" #include "TypeList.h" -#include "TaskScheduler.h" -#include "EventMap.h" #include "Revision.h" diff --git a/src/server/shared/Utilities/ServiceWin32.cpp b/src/server/shared/Service/ServiceWin32.cpp index 3e5e416b1a3..3e5e416b1a3 100644 --- a/src/server/shared/Utilities/ServiceWin32.cpp +++ b/src/server/shared/Service/ServiceWin32.cpp diff --git a/src/server/shared/Utilities/ServiceWin32.h b/src/server/shared/Service/ServiceWin32.h index 9d9c732cd20..9d9c732cd20 100644 --- a/src/server/shared/Utilities/ServiceWin32.h +++ b/src/server/shared/Service/ServiceWin32.h diff --git a/src/server/shared/Threading/Callback.h b/src/server/shared/Threading/Callback.h deleted file mode 100644 index 1f4ffc97cfc..00000000000 --- a/src/server/shared/Threading/Callback.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _CALLBACK_H -#define _CALLBACK_H - -#include <future> -#include "QueryResult.h" - -typedef std::future<QueryResult> QueryResultFuture; -typedef std::promise<QueryResult> QueryResultPromise; -typedef std::future<PreparedQueryResult> PreparedQueryResultFuture; -typedef std::promise<PreparedQueryResult> PreparedQueryResultPromise; - -#define CALLBACK_STAGE_INVALID uint8(-1) - -template <typename Result, typename ParamType, bool chain = false> -class QueryCallback -{ - public: - QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) { } - - //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery - void SetFutureResult(std::future<Result> value) - { - _result = std::move(value); - } - - std::future<Result>& GetFutureResult() - { - return _result; - } - - int IsReady() - { - return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready; - } - - void GetResult(Result& res) - { - res = _result.get(); - } - - void FreeResult() - { - // Nothing to do here, the constructor of std::future will take care of the cleanup - } - - void SetParam(ParamType value) - { - _param = value; - } - - ParamType GetParam() - { - return _param; - } - - //! Resets the stage of the callback chain - void ResetStage() - { - if (!chain) - return; - - _stage = 0; - } - - //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly - void NextStage() - { - if (!chain) - return; - - ++_stage; - } - - //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid) - uint8 GetStage() - { - return _stage; - } - - //! Resets all underlying variables (param, result and stage) - void Reset() - { - SetParam(ParamType()); - FreeResult(); - ResetStage(); - } - - private: - std::future<Result> _result; - ParamType _param; - uint8 _stage; - - QueryCallback(QueryCallback const& right) = delete; - QueryCallback& operator=(QueryCallback const& right) = delete; -}; - -template <typename Result, typename ParamType1, typename ParamType2, bool chain = false> -class QueryCallback_2 -{ - public: - QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) { } - - //! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery - void SetFutureResult(std::future<Result> value) - { - _result = std::move(value); - } - - std::future<Result>& GetFutureResult() - { - return _result; - } - - int IsReady() - { - return _result.valid() && _result.wait_for(std::chrono::seconds(0)) == std::future_status::ready; - } - - void GetResult(Result& res) - { - res = _result.get(); - } - - void FreeResult() - { - // Nothing to do here, the constructor of std::future will take care of the cleanup - } - - void SetFirstParam(ParamType1 value) - { - _param_1 = value; - } - - void SetSecondParam(ParamType2 value) - { - _param_2 = value; - } - - ParamType1 GetFirstParam() - { - return _param_1; - } - - ParamType2 GetSecondParam() - { - return _param_2; - } - - //! Resets the stage of the callback chain - void ResetStage() - { - if (!chain) - return; - - _stage = 0; - } - - //! Advances the callback chain to the next stage, so upper level code can act on its results accordingly - void NextStage() - { - if (!chain) - return; - - ++_stage; - } - - //! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid) - uint8 GetStage() - { - return _stage; - } - - //! Resets all underlying variables (param, result and stage) - void Reset() - { - SetFirstParam(NULL); - SetSecondParam(NULL); - FreeResult(); - ResetStage(); - } - - private: - std::future<Result> _result; - ParamType1 _param_1; - ParamType2 _param_2; - uint8 _stage; - - QueryCallback_2(QueryCallback_2 const& right) = delete; - QueryCallback_2& operator=(QueryCallback_2 const& right) = delete; -}; - -#endif diff --git a/src/server/shared/Threading/LockedQueue.h b/src/server/shared/Threading/LockedQueue.h deleted file mode 100644 index 3abb0f4b8bc..00000000000 --- a/src/server/shared/Threading/LockedQueue.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/> - * Copyright (C) 2005-2008 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 LOCKEDQUEUE_H -#define LOCKEDQUEUE_H - -#include <deque> -#include <mutex> - -template <class T, typename StorageType = std::deque<T> > -class LockedQueue -{ - //! Lock access to the queue. - std::mutex _lock; - - //! Storage backing the queue. - StorageType _queue; - - //! Cancellation flag. - volatile bool _canceled; - -public: - - //! Create a LockedQueue. - LockedQueue() - : _canceled(false) - { - } - - //! Destroy a LockedQueue. - virtual ~LockedQueue() - { - } - - //! Adds an item to the queue. - void add(const T& item) - { - lock(); - - _queue.push_back(item); - - unlock(); - } - - //! Gets the next result in the queue, if any. - bool next(T& result) - { - std::lock_guard<std::mutex> lock(_lock); - - if (_queue.empty()) - return false; - - result = _queue.front(); - _queue.pop_front(); - - return true; - } - - template<class Checker> - bool next(T& result, Checker& check) - { - std::lock_guard<std::mutex> lock(_lock); - - if (_queue.empty()) - return false; - - result = _queue.front(); - if (!check.Process(result)) - return false; - - _queue.pop_front(); - return true; - } - - //! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false. - T& peek(bool autoUnlock = false) - { - lock(); - - T& result = _queue.front(); - - if (autoUnlock) - unlock(); - - return result; - } - - //! Cancels the queue. - void cancel() - { - std::lock_guard<std::mutex> lock(_lock); - - _canceled = true; - } - - //! Checks if the queue is cancelled. - bool cancelled() - { - std::lock_guard<std::mutex> lock(_lock); - return _canceled; - } - - //! Locks the queue for access. - void lock() - { - this->_lock.lock(); - } - - //! Unlocks the queue. - void unlock() - { - this->_lock.unlock(); - } - - ///! Calls pop_front of the queue - void pop_front() - { - std::lock_guard<std::mutex> lock(_lock); - _queue.pop_front(); - } - - ///! Checks if we're empty or not with locks held - bool empty() - { - std::lock_guard<std::mutex> lock(_lock); - return _queue.empty(); - } -}; -#endif diff --git a/src/server/shared/Threading/ProcessPriority.h b/src/server/shared/Threading/ProcessPriority.h deleted file mode 100644 index 2a8501a0249..00000000000 --- a/src/server/shared/Threading/ProcessPriority.h +++ /dev/null @@ -1,105 +0,0 @@ -/* -* Copyright (C) 2008-2015 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 _PROCESSPRIO_H -#define _PROCESSPRIO_H - -#include "Configuration/Config.h" - -#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) -{ -// Suppresses Mac OS X Warning since logChannel isn't used. -#if PLATFORM_APPLE - (void)logChannel; -#endif - -#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."); - } - -#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 -#endif -} - -#endif diff --git a/src/server/shared/Threading/ProducerConsumerQueue.h b/src/server/shared/Threading/ProducerConsumerQueue.h deleted file mode 100644 index 96546960393..00000000000 --- a/src/server/shared/Threading/ProducerConsumerQueue.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -* Copyright (C) 2008-2015 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 _PCQ_H -#define _PCQ_H - -#include <condition_variable> -#include <mutex> -#include <queue> -#include <atomic> -#include <type_traits> - -template <typename T> -class ProducerConsumerQueue -{ -private: - std::mutex _queueLock; - std::queue<T> _queue; - std::condition_variable _condition; - std::atomic<bool> _shutdown; - -public: - - ProducerConsumerQueue<T>() : _shutdown(false) { } - - void Push(const T& value) - { - std::lock_guard<std::mutex> lock(_queueLock); - _queue.push(std::move(value)); - - _condition.notify_one(); - } - - bool Empty() - { - std::lock_guard<std::mutex> lock(_queueLock); - - return _queue.empty(); - } - - bool Pop(T& value) - { - std::lock_guard<std::mutex> lock(_queueLock); - - if (_queue.empty() || _shutdown) - return false; - - value = _queue.front(); - - _queue.pop(); - - return true; - } - - void WaitAndPop(T& value) - { - std::unique_lock<std::mutex> lock(_queueLock); - - // we could be using .wait(lock, predicate) overload here but it is broken - // https://connect.microsoft.com/VisualStudio/feedback/details/1098841 - while (_queue.empty() && !_shutdown) - _condition.wait(lock); - - if (_queue.empty() || _shutdown) - return; - - value = _queue.front(); - - _queue.pop(); - } - - void Cancel() - { - std::unique_lock<std::mutex> lock(_queueLock); - - while (!_queue.empty()) - { - T& value = _queue.front(); - - DeleteQueuedObject(value); - - _queue.pop(); - } - - _shutdown = true; - - _condition.notify_all(); - } - -private: - template<typename E = T> - typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; } - - template<typename E = T> - typename std::enable_if<!std::is_pointer<E>::value>::type DeleteQueuedObject(E const& /*packet*/) { } -}; - -#endif diff --git a/src/server/shared/Utilities/ByteConverter.h b/src/server/shared/Utilities/ByteConverter.h deleted file mode 100644 index a077de3eb0b..00000000000 --- a/src/server/shared/Utilities/ByteConverter.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITY_BYTECONVERTER_H -#define TRINITY_BYTECONVERTER_H - -/** ByteConverter reverse your byte order. This is use - for cross platform where they have different endians. - */ - -#include "Define.h" -#include <algorithm> - -namespace ByteConverter -{ - template<size_t T> - inline void convert(char *val) - { - std::swap(*val, *(val + T - 1)); - convert<T - 2>(val + 1); - } - - template<> inline void convert<0>(char *) { } - template<> inline void convert<1>(char *) { } // ignore central byte - - template<typename T> inline void apply(T *val) - { - convert<sizeof(T)>((char *)(val)); - } -} - -#if TRINITY_ENDIAN == TRINITY_BIGENDIAN -template<typename T> inline void EndianConvert(T& val) { ByteConverter::apply<T>(&val); } -template<typename T> inline void EndianConvertReverse(T&) { } -template<typename T> inline void EndianConvertPtr(void* val) { ByteConverter::apply<T>(val); } -template<typename T> inline void EndianConvertPtrReverse(void*) { } -#else -template<typename T> inline void EndianConvert(T&) { } -template<typename T> inline void EndianConvertReverse(T& val) { ByteConverter::apply<T>(&val); } -template<typename T> inline void EndianConvertPtr(void*) { } -template<typename T> inline void EndianConvertPtrReverse(void* val) { ByteConverter::apply<T>(val); } -#endif - -template<typename T> void EndianConvert(T*); // will generate link error -template<typename T> void EndianConvertReverse(T*); // will generate link error - -inline void EndianConvert(uint8&) { } -inline void EndianConvert( int8&) { } -inline void EndianConvertReverse(uint8&) { } -inline void EndianConvertReverse( int8&) { } - -#endif - diff --git a/src/server/shared/Utilities/Duration.h b/src/server/shared/Utilities/Duration.h deleted file mode 100644 index 58a08e5842f..00000000000 --- a/src/server/shared/Utilities/Duration.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _DURATION_H_ -#define _DURATION_H_ - -#include <chrono> - -/// Milliseconds shorthand typedef. -typedef std::chrono::milliseconds Milliseconds; - -/// Seconds shorthand typedef. -typedef std::chrono::seconds Seconds; - -/// Minutes shorthand typedef. -typedef std::chrono::minutes Minutes; - -/// Hours shorthand typedef. -typedef std::chrono::hours Hours; - -/// Makes std::chrono_literals globally available. -// ToDo: Enable this when TC supports C++14. -// using namespace std::chrono_literals; - -#endif // _DURATION_H_ diff --git a/src/server/shared/Utilities/EventMap.cpp b/src/server/shared/Utilities/EventMap.cpp deleted file mode 100644 index 8c3f60afe82..00000000000 --- a/src/server/shared/Utilities/EventMap.cpp +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "EventMap.h" - -void EventMap::Reset() -{ - _eventMap.clear(); - _time = 0; - _phase = 0; -} - -void EventMap::SetPhase(uint8 phase) -{ - if (!phase) - _phase = 0; - else if (phase <= 8) - _phase = uint8(1 << (phase - 1)); -} - -void EventMap::ScheduleEvent(uint32 eventId, uint32 time, uint32 group /*= 0*/, uint8 phase /*= 0*/) -{ - if (group && group <= 8) - eventId |= (1 << (group + 15)); - - if (phase && phase <= 8) - eventId |= (1 << (phase + 23)); - - _eventMap.insert(EventStore::value_type(_time + time, eventId)); -} - -uint32 EventMap::ExecuteEvent() -{ - while (!Empty()) - { - EventStore::iterator itr = _eventMap.begin(); - - if (itr->first > _time) - return 0; - else if (_phase && (itr->second & 0xFF000000) && !((itr->second >> 24) & _phase)) - _eventMap.erase(itr); - else - { - uint32 eventId = (itr->second & 0x0000FFFF); - _lastEvent = itr->second; // include phase/group - _eventMap.erase(itr); - return eventId; - } - } - - return 0; -} - -void EventMap::DelayEvents(uint32 delay, uint32 group) -{ - if (!group || group > 8 || Empty()) - return; - - EventStore delayed; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (itr->second & (1 << (group + 15))) - { - delayed.insert(EventStore::value_type(itr->first + delay, itr->second)); - _eventMap.erase(itr++); - } - else - ++itr; - } - - _eventMap.insert(delayed.begin(), delayed.end()); -} - -void EventMap::CancelEvent(uint32 eventId) -{ - if (Empty()) - return; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (eventId == (itr->second & 0x0000FFFF)) - _eventMap.erase(itr++); - else - ++itr; - } -} - -void EventMap::CancelEventGroup(uint32 group) -{ - if (!group || group > 8 || Empty()) - return; - - for (EventStore::iterator itr = _eventMap.begin(); itr != _eventMap.end();) - { - if (itr->second & (1 << (group + 15))) - _eventMap.erase(itr++); - else - ++itr; - } -} - -uint32 EventMap::GetNextEventTime(uint32 eventId) const -{ - if (Empty()) - return 0; - - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first; - - return 0; -} - -uint32 EventMap::GetTimeUntilEvent(uint32 eventId) const -{ - for (EventStore::const_iterator itr = _eventMap.begin(); itr != _eventMap.end(); ++itr) - if (eventId == (itr->second & 0x0000FFFF)) - return itr->first - _time; - - return std::numeric_limits<uint32>::max(); -} diff --git a/src/server/shared/Utilities/EventMap.h b/src/server/shared/Utilities/EventMap.h deleted file mode 100644 index 021dffc4940..00000000000 --- a/src/server/shared/Utilities/EventMap.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _EVENT_MAP_H_ -#define _EVENT_MAP_H_ - -#include "Common.h" -#include "Duration.h" -#include "Util.h" - -class EventMap -{ - /** - * Internal storage type. - * Key: Time as uint32 when the event should occur. - * Value: The event data as uint32. - * - * Structure of event data: - * - Bit 0 - 15: Event Id. - * - Bit 16 - 23: Group - * - Bit 24 - 31: Phase - * - Pattern: 0xPPGGEEEE - */ - typedef std::multimap<uint32, uint32> EventStore; - -public: - EventMap() : _time(0), _phase(0), _lastEvent(0) { } - - /** - * @name Reset - * @brief Removes all scheduled events and resets time and phase. - */ - void Reset(); - - /** - * @name Update - * @brief Updates the timer of the event map. - * @param time Value in ms to be added to time. - */ - void Update(uint32 time) - { - _time += time; - } - - /** - * @name GetTimer - * @return Current timer in ms value. - */ - uint32 GetTimer() const - { - return _time; - } - - /** - * @name GetPhaseMask - * @return Active phases as mask. - */ - uint8 GetPhaseMask() const - { - return _phase; - } - - /** - * @name Empty - * @return True, if there are no events scheduled. - */ - bool Empty() const - { - return _eventMap.empty(); - } - - /** - * @name SetPhase - * @brief Sets the phase of the map (absolute). - * @param phase Phase which should be set. Values: 1 - 8. 0 resets phase. - */ - void SetPhase(uint8 phase); - - /** - * @name AddPhase - * @brief Activates the given phase (bitwise). - * @param phase Phase which should be activated. Values: 1 - 8 - */ - void AddPhase(uint8 phase) - { - if (phase && phase <= 8) - _phase |= uint8(1 << (phase - 1)); - } - - /** - * @name RemovePhase - * @brief Deactivates the given phase (bitwise). - * @param phase Phase which should be deactivated. Values: 1 - 8. - */ - void RemovePhase(uint8 phase) - { - if (phase && phase <= 8) - _phase &= uint8(~(1 << (phase - 1))); - } - - /** - * @name ScheduleEvent - * @brief Creates new event entry in map. - * @param eventId The id of the new event. - * @param time The time in milliseconds as std::chrono::duration until the event occurs. - * @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& time, uint32 group = 0, uint8 phase = 0) - { - ScheduleEvent(eventId, time.count(), group, phase); - } - - /** - * @name ScheduleEvent - * @brief Creates new event entry in map. - * @param eventId The id of the new event. - * @param time The time in milliseconds until the event occurs. - * @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, uint32 time, uint32 group = 0, uint8 phase = 0); - - /** - * @name RescheduleEvent - * @brief Cancels the given event and reschedules it. - * @param eventId The id of the event. - * @param time The time in milliseconds as std::chrono::duration until the event occurs. - * @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& time, uint32 group = 0, uint8 phase = 0) - { - RescheduleEvent(eventId, time.count(), group, phase); - } - - /** - * @name RescheduleEvent - * @brief Cancels the given event and reschedules it. - * @param eventId The id of the event. - * @param time The time in milliseconds until the event occurs. - * @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, uint32 time, uint32 group = 0, uint8 phase = 0) - { - CancelEvent(eventId); - ScheduleEvent(eventId, time, group, phase); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event. - * @param time Time until in milliseconds as std::chrono::duration the event occurs. - */ - void Repeat(Milliseconds const& time) - { - Repeat(time.count()); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event. - * @param time Time until the event occurs. - */ - void Repeat(uint32 time) - { - _eventMap.insert(EventStore::value_type(_time + time, _lastEvent)); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event. - * @param minTime Minimum time as std::chrono::duration until the event occurs. - * @param maxTime Maximum time as std::chrono::duration until the event occurs. - */ - void Repeat(Milliseconds const& minTime, Milliseconds const& maxTime) - { - Repeat(minTime.count(), maxTime.count()); - } - - /** - * @name RepeatEvent - * @brief Repeats the mostly recently executed event, Equivalent to Repeat(urand(minTime, maxTime). - * @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)); - } - - /** - * @name ExecuteEvent - * @brief Returns the next event to execute and removes it from map. - * @return Id of the event to execute. - */ - uint32 ExecuteEvent(); - - /** - * @name DelayEvents - * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0. - * @param delay Amount of delay in ms as std::chrono::duration. - */ - void DelayEvents(Milliseconds const& delay) - { - DelayEvents(delay.count()); - } - - /** - * @name DelayEvents - * @brief Delays all events in the map. If delay is greater than or equal internal timer, delay will be 0. - * @param delay Amount of delay. - */ - void DelayEvents(uint32 delay) - { - _time = delay < _time ? _time - delay : 0; - } - - /** - * @name DelayEvents - * @brief Delay all events of the same group. - * @param delay Amount of delay in ms as std::chrono::duration. - * @param group Group of the events. - */ - void DelayEvents(Milliseconds const& delay, uint32 group) - { - DelayEvents(delay.count(), group); - } - - /** - * @name DelayEvents - * @brief Delay all events of the same group. - * @param delay Amount of delay. - * @param group Group of the events. - */ - void DelayEvents(uint32 delay, uint32 group); - - /** - * @name CancelEvent - * @brief Cancels all events of the specified id. - * @param eventId Event id to cancel. - */ - void CancelEvent(uint32 eventId); - - /** - * @name CancelEventGroup - * @brief Cancel events belonging to specified group. - * @param group Group to cancel. - */ - void CancelEventGroup(uint32 group); - - /** - * @name GetNextEventTime - * @brief Returns closest occurence of specified event. - * @param eventId Wanted event id. - * @return Time of found event. - */ - uint32 GetNextEventTime(uint32 eventId) const; - - /** - * @name GetNextEventTime - * @return Time of next event. - */ - uint32 GetNextEventTime() const - { - return Empty() ? 0 : _eventMap.begin()->first; - } - - /** - * @name IsInPhase - * @brief Returns whether event map is in specified phase or not. - * @param phase Wanted phase. - * @return True, if phase of event map contains specified phase. - */ - bool IsInPhase(uint8 phase) const - { - return phase <= 8 && (!phase || _phase & (1 << (phase - 1))); - } - - /** - * @name GetTimeUntilEvent - * @brief Returns time in milliseconds until next event. - * @param eventId of the event. - * @return Time of next event. - */ - uint32 GetTimeUntilEvent(uint32 eventId) const; - -private: - /** - * @name _time - * @brief Internal timer. - * - * This does not represent the real date/time value. - * It's more like a stopwatch: It can run, it can be stopped, - * it can be resetted and so on. Events occur when this timer - * has reached their time value. Its value is changed in the - * Update method. - */ - uint32 _time; - - /** - * @name _phase - * @brief Phase mask of the event map. - * - * Contains the phases the event map is in. Multiple - * phases from 1 to 8 can be set with SetPhase or - * AddPhase. RemovePhase deactives a phase. - */ - uint8 _phase; - - /** - * @name _eventMap - * @brief Internal event storage map. Contains the scheduled events. - * - * See typedef at the beginning of the class for more - * details. - */ - EventStore _eventMap; - - /** - * @name _lastEvent - * @brief Stores information on the most recently executed event - */ - uint32 _lastEvent; -}; - -#endif // _EVENT_MAP_H_ diff --git a/src/server/shared/Utilities/EventProcessor.cpp b/src/server/shared/Utilities/EventProcessor.cpp deleted file mode 100644 index 34695665443..00000000000 --- a/src/server/shared/Utilities/EventProcessor.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "EventProcessor.h" - -EventProcessor::EventProcessor() -{ - m_time = 0; - m_aborting = false; -} - -EventProcessor::~EventProcessor() -{ - KillAllEvents(true); -} - -void EventProcessor::Update(uint32 p_time) -{ - // update time - m_time += p_time; - - // main event loop - EventList::iterator i; - while (((i = m_events.begin()) != m_events.end()) && i->first <= m_time) - { - // get and remove event from queue - BasicEvent* Event = i->second; - m_events.erase(i); - - if (!Event->to_Abort) - { - if (Event->Execute(m_time, p_time)) - { - // completely destroy event if it is not re-added - delete Event; - } - } - else - { - Event->Abort(m_time); - delete Event; - } - } -} - -void EventProcessor::KillAllEvents(bool force) -{ - // prevent event insertions - m_aborting = true; - - // first, abort all existing events - for (EventList::iterator i = m_events.begin(); i != m_events.end();) - { - EventList::iterator i_old = i; - ++i; - - i_old->second->to_Abort = true; - i_old->second->Abort(m_time); - if (force || i_old->second->IsDeletable()) - { - delete i_old->second; - - if (!force) // need per-element cleanup - m_events.erase (i_old); - } - } - - // fast clear event list (in force case) - if (force) - m_events.clear(); -} - -void EventProcessor::AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime) -{ - if (set_addtime) Event->m_addTime = m_time; - Event->m_execTime = e_time; - m_events.insert(std::pair<uint64, BasicEvent*>(e_time, Event)); -} - -uint64 EventProcessor::CalculateTime(uint64 t_offset) const -{ - return(m_time + t_offset); -} - diff --git a/src/server/shared/Utilities/EventProcessor.h b/src/server/shared/Utilities/EventProcessor.h deleted file mode 100644 index 3d54bd6f9f2..00000000000 --- a/src/server/shared/Utilities/EventProcessor.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 __EVENTPROCESSOR_H -#define __EVENTPROCESSOR_H - -#include "Define.h" - -#include <map> - -// Note. All times are in milliseconds here. - -class BasicEvent -{ - public: - BasicEvent() - { - to_Abort = false; - m_addTime = 0; - m_execTime = 0; - } - virtual ~BasicEvent() { } // override destructor to perform some actions on event removal - - // this method executes when the event is triggered - // return false if event does not want to be deleted - // e_time is execution time, p_time is update interval - virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; } - - virtual bool IsDeletable() const { return true; } // this event can be safely deleted - - virtual void Abort(uint64 /*e_time*/) { } // this method executes when the event is aborted - - bool to_Abort; // set by externals when the event is aborted, aborted events don't execute - // and get Abort call when deleted - - // these can be used for time offset control - uint64 m_addTime; // time when the event was added to queue, filled by event handler - uint64 m_execTime; // planned time of next execution, filled by event handler -}; - -typedef std::multimap<uint64, BasicEvent*> EventList; - -class EventProcessor -{ - public: - EventProcessor(); - ~EventProcessor(); - - void Update(uint32 p_time); - void KillAllEvents(bool force); - void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true); - uint64 CalculateTime(uint64 t_offset) const; - protected: - uint64 m_time; - EventList m_events; - bool m_aborting; -}; -#endif diff --git a/src/server/shared/Utilities/StringFormat.h b/src/server/shared/Utilities/StringFormat.h deleted file mode 100644 index 67e0100e7c8..00000000000 --- a/src/server/shared/Utilities/StringFormat.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITYCORE_STRING_FORMAT_H -#define TRINITYCORE_STRING_FORMAT_H - -#include "format.h" - -namespace Trinity -{ - /// Default TC string format function. - template<typename Format, typename... Args> - inline std::string StringFormat(Format&& fmt, Args&&... args) - { - return fmt::sprintf(std::forward<Format>(fmt), std::forward<Args>(args)...); - } - - /// Returns true if the given char pointer is null. - inline bool IsFormatEmptyOrNull(const char* fmt) - { - return fmt == nullptr; - } - - /// Returns true if the given std::string is empty. - inline bool IsFormatEmptyOrNull(std::string const& fmt) - { - return fmt.empty(); - } -} - -#endif diff --git a/src/server/shared/Utilities/TaskScheduler.cpp b/src/server/shared/Utilities/TaskScheduler.cpp deleted file mode 100644 index 801cc96cf77..00000000000 --- a/src/server/shared/Utilities/TaskScheduler.cpp +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "TaskScheduler.h" - -TaskScheduler& TaskScheduler::ClearValidator() -{ - _predicate = EmptyValidator; - return *this; -} - -TaskScheduler& TaskScheduler::Update(success_t const& callback) -{ - _now = clock_t::now(); - Dispatch(callback); - return *this; -} - -TaskScheduler& TaskScheduler::Update(size_t const milliseconds, success_t const& callback) -{ - return Update(std::chrono::milliseconds(milliseconds), callback); -} - -TaskScheduler& TaskScheduler::Async(std::function<void()> const& callable) -{ - _asyncHolder.push(callable); - return *this; -} - -TaskScheduler& TaskScheduler::CancelAll() -{ - /// Clear the task holder - _task_holder.Clear(); - _asyncHolder = AsyncHolder(); - return *this; -} - -TaskScheduler& TaskScheduler::CancelGroup(group_t const group) -{ - _task_holder.RemoveIf([group](TaskContainer const& task) -> bool - { - return task->IsInGroup(group); - }); - return *this; -} - -TaskScheduler& TaskScheduler::CancelGroupsOf(std::vector<group_t> const& groups) -{ - std::for_each(groups.begin(), groups.end(), - std::bind(&TaskScheduler::CancelGroup, this, std::placeholders::_1)); - - return *this; -} - -TaskScheduler& TaskScheduler::InsertTask(TaskContainer task) -{ - _task_holder.Push(std::move(task)); - return *this; -} - -void TaskScheduler::Dispatch(success_t const& callback) -{ - // If the validation failed abort the dispatching here. - if (!_predicate()) - return; - - // Process all asyncs - while (!_asyncHolder.empty()) - { - _asyncHolder.front()(); - _asyncHolder.pop(); - - // If the validation failed abort the dispatching here. - if (!_predicate()) - return; - } - - while (!_task_holder.IsEmpty()) - { - if (_task_holder.First()->_end > _now) - break; - - // Perfect forward the context to the handler - // Use weak references to catch destruction before callbacks. - TaskContext context(_task_holder.Pop(), std::weak_ptr<TaskScheduler>(self_reference)); - - // Invoke the context - context.Invoke(); - - // If the validation failed abort the dispatching here. - if (!_predicate()) - return; - } - - // On finish call the final callback - callback(); -} - -void TaskScheduler::TaskQueue::Push(TaskContainer&& task) -{ - container.insert(task); -} - -auto TaskScheduler::TaskQueue::Pop() -> TaskContainer -{ - TaskContainer result = *container.begin(); - container.erase(container.begin()); - return result; -} - -auto TaskScheduler::TaskQueue::First() const -> TaskContainer const& -{ - return *container.begin(); -} - -void TaskScheduler::TaskQueue::Clear() -{ - container.clear(); -} - -void TaskScheduler::TaskQueue::RemoveIf(std::function<bool(TaskContainer const&)> const& filter) -{ - for (auto itr = container.begin(); itr != container.end();) - if (filter(*itr)) - itr = container.erase(itr); - else - ++itr; -} - -void TaskScheduler::TaskQueue::ModifyIf(std::function<bool(TaskContainer const&)> const& filter) -{ - std::vector<TaskContainer> cache; - for (auto itr = container.begin(); itr != container.end();) - if (filter(*itr)) - { - cache.push_back(*itr); - itr = container.erase(itr); - } - else - ++itr; - - container.insert(cache.begin(), cache.end()); -} - -bool TaskScheduler::TaskQueue::IsEmpty() const -{ - return container.empty(); -} - -TaskContext& TaskContext::Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply) -{ - if (auto const owner = _owner.lock()) - apply(*owner); - - return *this; -} - -bool TaskContext::IsExpired() const -{ - return _owner.expired(); -} - -bool TaskContext::IsInGroup(TaskScheduler::group_t const group) const -{ - return _task->IsInGroup(group); -} - -TaskContext& TaskContext::SetGroup(TaskScheduler::group_t const group) -{ - _task->_group = group; - return *this; -} - -TaskContext& TaskContext::ClearGroup() -{ - _task->_group = boost::none; - return *this; -} - -TaskScheduler::repeated_t TaskContext::GetRepeatCounter() const -{ - return _task->_repeated; -} - -TaskContext& TaskContext::Async(std::function<void()> const& callable) -{ - return Dispatch(std::bind(&TaskScheduler::Async, std::placeholders::_1, callable)); -} - -TaskContext& TaskContext::CancelAll() -{ - return Dispatch(std::mem_fn(&TaskScheduler::CancelAll)); -} - -TaskContext& TaskContext::CancelGroup(TaskScheduler::group_t const group) -{ - return Dispatch(std::bind(&TaskScheduler::CancelGroup, std::placeholders::_1, group)); -} - -TaskContext& TaskContext::CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups) -{ - return Dispatch(std::bind(&TaskScheduler::CancelGroupsOf, std::placeholders::_1, std::cref(groups))); -} - -void TaskContext::AssertOnConsumed() const -{ - // This was adapted to TC to prevent static analysis tools from complaining. - // If you encounter this assertion check if you repeat a TaskContext more then 1 time! - ASSERT(!(*_consumed) && "Bad task logic, task context was consumed already!"); -} - -void TaskContext::Invoke() -{ - _task->_task(*this); -} diff --git a/src/server/shared/Utilities/TaskScheduler.h b/src/server/shared/Utilities/TaskScheduler.h deleted file mode 100644 index f1fe7ea0a21..00000000000 --- a/src/server/shared/Utilities/TaskScheduler.h +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _TASK_SCHEDULER_H_ -#define _TASK_SCHEDULER_H_ - -#include <algorithm> -#include <chrono> -#include <vector> -#include <queue> -#include <memory> -#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. -/// Use TaskScheduler::Update to update the scheduler. -/// Popular methods are: -/// * Schedule (Schedules a std::function which will be executed in the near future). -/// * Schedules an asynchronous function which will be executed at the next update tick. -/// * Cancel, Delay & Reschedule (Methods to manipulate already scheduled tasks). -/// Tasks are organized in groups (uint), multiple tasks can have the same group id, -/// you can provide a group or not, but keep in mind that you can only manipulate specific tasks through its group id! -/// Tasks callbacks use the function signature void(TaskContext) where TaskContext provides -/// access to the function schedule plan which makes it possible to repeat the task -/// with the same duration or a new one. -/// It also provides access to the repeat counter which is useful for task that repeat itself often -/// but behave different every time (spoken event dialogs for example). -class TaskScheduler -{ - friend class TaskContext; - - // Time definitions (use steady clock) - typedef std::chrono::steady_clock clock_t; - typedef clock_t::time_point timepoint_t; - typedef clock_t::duration duration_t; - - // Task group type - typedef uint32 group_t; - // Task repeated type - typedef uint32 repeated_t; - // Task handle type - typedef std::function<void(TaskContext)> task_handler_t; - // Predicate type - typedef std::function<bool()> predicate_t; - // Success handle type - typedef std::function<void()> success_t; - - class Task - { - friend class TaskContext; - friend class TaskScheduler; - - timepoint_t _end; - duration_t _duration; - boost::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, - repeated_t const repeated, task_handler_t const& task) - : _end(end), _duration(duration), _group(group), _repeated(repeated), _task(task) { } - - // Minimal Argument construct - Task(timepoint_t const& end, duration_t const& duration, task_handler_t const& task) - : _end(end), _duration(duration), _group(boost::none), _repeated(0), _task(task) { } - - // Copy construct - Task(Task const&) = delete; - // Move construct - Task(Task&&) = delete; - // Copy Assign - Task& operator= (Task const&) = default; - // Move Assign - Task& operator= (Task&& right) = delete; - - // Order tasks by its end - inline bool operator< (Task const& other) const - { - return _end < other._end; - } - - inline bool operator> (Task const& other) const - { - return _end > other._end; - } - - // Compare tasks with its end - inline bool operator== (Task const& other) - { - return _end == other._end; - } - - // Returns true if the task is in the given group - inline bool IsInGroup(group_t const group) const - { - return _group == group; - } - }; - - typedef std::shared_ptr<Task> TaskContainer; - - /// Container which provides Task order, insert and reschedule operations. - struct Compare - { - bool operator() (TaskContainer const& left, TaskContainer const& right) - { - return (*left.get()) < (*right.get()); - }; - }; - - class TaskQueue - { - std::multiset<TaskContainer, Compare> container; - - public: - // Pushes the task in the container - void Push(TaskContainer&& task); - - /// Pops the task out of the container - TaskContainer Pop(); - - TaskContainer const& First() const; - - void Clear(); - - void RemoveIf(std::function<bool(TaskContainer const&)> const& filter); - - void ModifyIf(std::function<bool(TaskContainer const&)> const& filter); - - bool IsEmpty() const; - }; - - /// Contains a self reference to track if this object was deleted or not. - std::shared_ptr<TaskScheduler> self_reference; - - /// The current time point (now) - timepoint_t _now; - - /// The Task Queue which contains all task objects. - TaskQueue _task_holder; - - typedef std::queue<std::function<void()>> AsyncHolder; - - /// Contains all asynchronous tasks which will be invoked at - /// the next update tick. - AsyncHolder _asyncHolder; - - predicate_t _predicate; - - static bool EmptyValidator() - { - return true; - } - - static void EmptyCallback() - { - } - -public: - TaskScheduler() - : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(EmptyValidator) { } - - template<typename P> - TaskScheduler(P&& predicate) - : self_reference(this, [](TaskScheduler const*) { }), _now(clock_t::now()), _predicate(std::forward<P>(predicate)) { } - - TaskScheduler(TaskScheduler const&) = delete; - TaskScheduler(TaskScheduler&&) = delete; - TaskScheduler& operator= (TaskScheduler const&) = delete; - TaskScheduler& operator= (TaskScheduler&&) = delete; - - /// Sets a validator which is asked if tasks are allowed to be executed. - template<typename P> - TaskScheduler& SetValidator(P&& predicate) - { - _predicate = std::forward<P>(predicate); - return *this; - } - - /// Clears the validator which is asked if tasks are allowed to be executed. - TaskScheduler& ClearValidator(); - - /// Update the scheduler to the current time. - /// Calls the optional callback on successfully finish. - TaskScheduler& Update(success_t const& callback = EmptyCallback); - - /// Update the scheduler with a difftime in ms. - /// Calls the optional callback on successfully finish. - TaskScheduler& Update(size_t const milliseconds, success_t const& callback = EmptyCallback); - - /// Update the scheduler with a difftime. - /// Calls the optional callback on successfully finish. - template<class _Rep, class _Period> - TaskScheduler& Update(std::chrono::duration<_Rep, _Period> const& difftime, - success_t const& callback = EmptyCallback) - { - _now += difftime; - Dispatch(callback); - return *this; - } - - /// Schedule an callable function that is executed at the next update tick. - /// Its safe to modify the TaskScheduler from within the callable. - TaskScheduler& Async(std::function<void()> const& callable); - - /// Schedule an event with a fixed rate. - /// Never call this from within a task context! Use TaskContext::Schedule instead! - template<class _Rep, class _Period> - TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time, - task_handler_t const& task) - { - return ScheduleAt(_now, time, task); - } - - /// Schedule an event with a fixed rate. - /// Never call this from within a task context! Use TaskContext::Schedule instead! - template<class _Rep, class _Period> - TaskScheduler& Schedule(std::chrono::duration<_Rep, _Period> const& time, - group_t const group, task_handler_t const& task) - { - return ScheduleAt(_now, time, group, task); - } - - /// Schedule an event with a randomized rate between min and max rate. - /// Never call this from within a task context! Use TaskContext::Schedule instead! - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max, task_handler_t const& task) - { - return Schedule(RandomDurationBetween(min, max), task); - } - - /// Schedule an event with a fixed rate. - /// Never call this from within a task context! Use TaskContext::Schedule instead! - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskScheduler& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max, group_t const group, - task_handler_t const& task) - { - return Schedule(RandomDurationBetween(min, max), group, task); - } - - /// Cancels all tasks. - /// Never call this from within a task context! Use TaskContext::CancelAll instead! - TaskScheduler& CancelAll(); - - /// Cancel all tasks of a single group. - /// Never call this from within a task context! Use TaskContext::CancelGroup instead! - TaskScheduler& CancelGroup(group_t const group); - - /// Cancels all groups in the given std::vector. - /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}" - TaskScheduler& CancelGroupsOf(std::vector<group_t> const& groups); - - /// Delays all tasks with the given duration. - template<class _Rep, class _Period> - TaskScheduler& DelayAll(std::chrono::duration<_Rep, _Period> const& duration) - { - _task_holder.ModifyIf([&duration](TaskContainer const& task) -> bool - { - task->_end += duration; - return true; - }); - return *this; - } - - /// Delays all tasks with a random duration between min and max. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskScheduler& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return DelayAll(RandomDurationBetween(min, max)); - } - - /// Delays all tasks of a group with the given duration. - template<class _Rep, class _Period> - TaskScheduler& DelayGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration) - { - _task_holder.ModifyIf([&duration, group](TaskContainer const& task) -> bool - { - if (task->IsInGroup(group)) - { - task->_end += duration; - return true; - } - else - return false; - }); - return *this; - } - - /// Delays all tasks of a group with a random duration between min and max. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskScheduler& DelayGroup(group_t const group, - std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return DelayGroup(group, RandomDurationBetween(min, max)); - } - - /// Reschedule all tasks with a given duration. - template<class _Rep, class _Period> - TaskScheduler& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration) - { - auto const end = _now + duration; - _task_holder.ModifyIf([end](TaskContainer const& task) -> bool - { - task->_end = end; - return true; - }); - return *this; - } - - /// Reschedule all tasks with a random duration between min and max. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskScheduler& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return RescheduleAll(RandomDurationBetween(min, max)); - } - - /// Reschedule all tasks of a group with the given duration. - template<class _Rep, class _Period> - TaskScheduler& RescheduleGroup(group_t const group, std::chrono::duration<_Rep, _Period> const& duration) - { - auto const end = _now + duration; - _task_holder.ModifyIf([end, group](TaskContainer const& task) -> bool - { - if (task->IsInGroup(group)) - { - task->_end = end; - return true; - } - else - return false; - }); - return *this; - } - - /// Reschedule all tasks of a group with a random duration between min and max. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskScheduler& RescheduleGroup(group_t const group, - std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return RescheduleGroup(group, RandomDurationBetween(min, max)); - } - -private: - /// Insert a new task to the enqueued tasks. - TaskScheduler& InsertTask(TaskContainer task); - - template<class _Rep, class _Period> - TaskScheduler& ScheduleAt(timepoint_t const& end, - std::chrono::duration<_Rep, _Period> const& time, task_handler_t const& task) - { - return InsertTask(TaskContainer(new Task(end + time, time, task))); - } - - /// Schedule an event with a fixed rate. - /// Never call this from within a task context! Use TaskContext::schedule instead! - template<class _Rep, class _Period> - TaskScheduler& ScheduleAt(timepoint_t const& end, - std::chrono::duration<_Rep, _Period> const& time, - group_t const group, task_handler_t const& task) - { - static repeated_t const DEFAULT_REPEATED = 0; - return InsertTask(TaskContainer(new Task(end + time, time, group, DEFAULT_REPEATED, task))); - } - - // Returns a random duration between min and max - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - static std::chrono::milliseconds - RandomDurationBetween(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - auto const milli_min = std::chrono::duration_cast<std::chrono::milliseconds>(min); - auto const milli_max = std::chrono::duration_cast<std::chrono::milliseconds>(max); - - // TC specific: use SFMT URandom - return std::chrono::milliseconds(urand(milli_min.count(), milli_max.count())); - } - - /// Dispatch remaining tasks - void Dispatch(success_t const& callback); -}; - -class TaskContext -{ - friend class TaskScheduler; - - /// Associated task - TaskScheduler::TaskContainer _task; - - /// Owner - std::weak_ptr<TaskScheduler> _owner; - - /// Marks the task as consumed - std::shared_ptr<bool> _consumed; - - /// Dispatches an action safe on the TaskScheduler - TaskContext& Dispatch(std::function<TaskScheduler&(TaskScheduler&)> const& apply); - -public: - // Empty constructor - TaskContext() - : _task(), _owner(), _consumed(std::make_shared<bool>(true)) { } - - // Construct from task and owner - explicit TaskContext(TaskScheduler::TaskContainer&& task, std::weak_ptr<TaskScheduler>&& owner) - : _task(task), _owner(owner), _consumed(std::make_shared<bool>(false)) { } - - // Copy construct - TaskContext(TaskContext const& right) - : _task(right._task), _owner(right._owner), _consumed(right._consumed) { } - - // Move construct - TaskContext(TaskContext&& right) - : _task(std::move(right._task)), _owner(std::move(right._owner)), _consumed(std::move(right._consumed)) { } - - // Copy assign - TaskContext& operator= (TaskContext const& right) - { - _task = right._task; - _owner = right._owner; - _consumed = right._consumed; - return *this; - } - - // Move assign - TaskContext& operator= (TaskContext&& right) - { - _task = std::move(right._task); - _owner = std::move(right._owner); - _consumed = std::move(right._consumed); - return *this; - } - - /// Returns true if the owner was deallocated and this context has expired. - bool IsExpired() const; - - /// Returns true if the event is in the given group - bool IsInGroup(TaskScheduler::group_t const group) const; - - /// Sets the event in the given group - TaskContext& SetGroup(TaskScheduler::group_t const group); - - /// Removes the group from the event - TaskContext& ClearGroup(); - - /// Returns the repeat counter which increases every time the task is repeated. - TaskScheduler::repeated_t GetRepeatCounter() const; - - /// Repeats the event and sets a new duration. - /// std::chrono::seconds(5) for example. - /// This will consume the task context, its not possible to repeat the task again - /// from the same task context! - template<class _Rep, class _Period> - TaskContext& Repeat(std::chrono::duration<_Rep, _Period> const& duration) - { - AssertOnConsumed(); - - // Set new duration, in-context timing and increment repeat counter - _task->_duration = duration; - _task->_end += duration; - _task->_repeated += 1; - (*_consumed) = true; - return Dispatch(std::bind(&TaskScheduler::InsertTask, std::placeholders::_1, _task)); - } - - /// Repeats the event with the same duration. - /// This will consume the task context, its not possible to repeat the task again - /// from the same task context! - TaskContext& Repeat() - { - return Repeat(_task->_duration); - } - - /// Repeats the event and set a new duration that is randomized between min and max. - /// std::chrono::seconds(5) for example. - /// This will consume the task context, its not possible to repeat the task again - /// from the same task context! - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& Repeat(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return Repeat(TaskScheduler::RandomDurationBetween(min, max)); - } - - /// Schedule a callable function that is executed at the next update tick from within the context. - /// Its safe to modify the TaskScheduler from within the callable. - TaskContext& Async(std::function<void()> const& callable); - - /// Schedule an event with a fixed rate from within the context. - /// Its possible that the new event is executed immediately! - /// Use TaskScheduler::Async to create a task - /// which will be called at the next update tick. - template<class _Rep, class _Period> - TaskContext& Schedule(std::chrono::duration<_Rep, _Period> const& time, - TaskScheduler::task_handler_t const& task) - { - auto const end = _task->_end; - return Dispatch([end, time, task](TaskScheduler& scheduler) -> TaskScheduler& - { - return scheduler.ScheduleAt<_Rep, _Period>(end, time, task); - }); - } - - /// Schedule an event with a fixed rate from within the context. - /// Its possible that the new event is executed immediately! - /// Use TaskScheduler::Async to create a task - /// which will be called at the next update tick. - template<class _Rep, class _Period> - TaskContext& Schedule(std::chrono::duration<_Rep, _Period> const& time, - TaskScheduler::group_t const group, TaskScheduler::task_handler_t const& task) - { - auto const end = _task->_end; - return Dispatch([end, time, group, task](TaskScheduler& scheduler) -> TaskScheduler& - { - return scheduler.ScheduleAt<_Rep, _Period>(end, time, group, task); - }); - } - - /// Schedule an event with a randomized rate between min and max rate from within the context. - /// Its possible that the new event is executed immediately! - /// Use TaskScheduler::Async to create a task - /// which will be called at the next update tick. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::task_handler_t const& task) - { - return Schedule(TaskScheduler::RandomDurationBetween(min, max), task); - } - - /// Schedule an event with a randomized rate between min and max rate from within the context. - /// Its possible that the new event is executed immediately! - /// Use TaskScheduler::Async to create a task - /// which will be called at the next update tick. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& Schedule(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max, TaskScheduler::group_t const group, - TaskScheduler::task_handler_t const& task) - { - return Schedule(TaskScheduler::RandomDurationBetween(min, max), group, task); - } - - /// Cancels all tasks from within the context. - TaskContext& CancelAll(); - - /// Cancel all tasks of a single group from within the context. - TaskContext& CancelGroup(TaskScheduler::group_t const group); - - /// Cancels all groups in the given std::vector from within the context. - /// Hint: Use std::initializer_list for this: "{1, 2, 3, 4}" - TaskContext& CancelGroupsOf(std::vector<TaskScheduler::group_t> const& groups); - - /// Delays all tasks with the given duration from within the context. - template<class _Rep, class _Period> - TaskContext& DelayAll(std::chrono::duration<_Rep, _Period> const& duration) - { - return Dispatch(std::bind(&TaskScheduler::DelayAll<_Rep, _Period>, std::placeholders::_1, duration)); - } - - /// Delays all tasks with a random duration between min and max from within the context. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& DelayAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return DelayAll(TaskScheduler::RandomDurationBetween(min, max)); - } - - /// Delays all tasks of a group with the given duration from within the context. - template<class _Rep, class _Period> - TaskContext& DelayGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration) - { - return Dispatch(std::bind(&TaskScheduler::DelayGroup<_Rep, _Period>, std::placeholders::_1, group, duration)); - } - - /// Delays all tasks of a group with a random duration between min and max from within the context. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& DelayGroup(TaskScheduler::group_t const group, - std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return DelayGroup(group, TaskScheduler::RandomDurationBetween(min, max)); - } - - /// Reschedule all tasks with the given duration. - template<class _Rep, class _Period> - TaskContext& RescheduleAll(std::chrono::duration<_Rep, _Period> const& duration) - { - return Dispatch(std::bind(&TaskScheduler::RescheduleAll, std::placeholders::_1, duration)); - } - - /// Reschedule all tasks with a random duration between min and max. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& RescheduleAll(std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return RescheduleAll(TaskScheduler::RandomDurationBetween(min, max)); - } - - /// Reschedule all tasks of a group with the given duration. - template<class _Rep, class _Period> - TaskContext& RescheduleGroup(TaskScheduler::group_t const group, std::chrono::duration<_Rep, _Period> const& duration) - { - return Dispatch(std::bind(&TaskScheduler::RescheduleGroup<_Rep, _Period>, std::placeholders::_1, group, duration)); - } - - /// Reschedule all tasks of a group with a random duration between min and max. - template<class _RepLeft, class _PeriodLeft, class _RepRight, class _PeriodRight> - TaskContext& RescheduleGroup(TaskScheduler::group_t const group, - std::chrono::duration<_RepLeft, _PeriodLeft> const& min, - std::chrono::duration<_RepRight, _PeriodRight> const& max) - { - return RescheduleGroup(group, TaskScheduler::RandomDurationBetween(min, max)); - } - -private: - /// Asserts if the task was consumed already. - void AssertOnConsumed() const; - - /// Invokes the associated hook of the task. - void Invoke(); -}; - -#endif /// _TASK_SCHEDULER_H_ diff --git a/src/server/shared/Utilities/Timer.h b/src/server/shared/Utilities/Timer.h deleted file mode 100644 index c54903d7be2..00000000000 --- a/src/server/shared/Utilities/Timer.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 TRINITY_TIMER_H -#define TRINITY_TIMER_H - -#include <chrono> - -inline uint32 getMSTime() -{ - using namespace std::chrono; - - static const system_clock::time_point ApplicationStartTime = system_clock::now(); - - return uint32(duration_cast<milliseconds>(system_clock::now() - ApplicationStartTime).count()); -} - -inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime) -{ - // getMSTime() have limited data range and this is case when it overflow in this tick - if (oldMSTime > newMSTime) - return (0xFFFFFFFF - oldMSTime) + newMSTime; - else - return newMSTime - oldMSTime; -} - -inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime) -{ - return getMSTimeDiff(oldMSTime, getMSTime()); -} - -struct IntervalTimer -{ -public: - - IntervalTimer() - : _interval(0), _current(0) - { - } - - void Update(time_t diff) - { - _current += diff; - if (_current < 0) - _current = 0; - } - - bool Passed() - { - return _current >= _interval; - } - - void Reset() - { - if (_current >= _interval) - _current %= _interval; - } - - void SetCurrent(time_t current) - { - _current = current; - } - - void SetInterval(time_t interval) - { - _interval = interval; - } - - time_t GetInterval() const - { - return _interval; - } - - time_t GetCurrent() const - { - return _current; - } - -private: - - time_t _interval; - time_t _current; -}; - -struct TimeTracker -{ -public: - - TimeTracker(time_t expiry) - : i_expiryTime(expiry) - { - } - - void Update(time_t diff) - { - i_expiryTime -= diff; - } - - bool Passed() const - { - return i_expiryTime <= 0; - } - - void Reset(time_t interval) - { - i_expiryTime = interval; - } - - time_t GetExpiry() const - { - return i_expiryTime; - } - -private: - - time_t i_expiryTime; -}; - -struct TimeTrackerSmall -{ -public: - - TimeTrackerSmall(uint32 expiry = 0) - : i_expiryTime(expiry) - { - } - - void Update(int32 diff) - { - i_expiryTime -= diff; - } - - bool Passed() const - { - return i_expiryTime <= 0; - } - - void Reset(uint32 interval) - { - i_expiryTime = interval; - } - - int32 GetExpiry() const - { - return i_expiryTime; - } - -private: - - int32 i_expiryTime; -}; - -struct PeriodicTimer -{ -public: - - PeriodicTimer(int32 period, int32 start_time) - : i_period(period), i_expireTime(start_time) - { - } - - bool Update(const uint32 diff) - { - if ((i_expireTime -= diff) > 0) - return false; - - i_expireTime += i_period > int32(diff) ? i_period : diff; - return true; - } - - void SetPeriodic(int32 period, int32 start_time) - { - i_expireTime = start_time; - i_period = period; - } - - // Tracker interface - void TUpdate(int32 diff) { i_expireTime -= diff; } - bool TPassed() const { return i_expireTime <= 0; } - void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; } - -private: - - int32 i_period; - int32 i_expireTime; -}; - -#endif diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp deleted file mode 100644 index 33c273fb05f..00000000000 --- a/src/server/shared/Utilities/Util.cpp +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 "Util.h" -#include "Common.h" -#include "CompilerDefs.h" -#include "utf8.h" -#include "SFMT.h" -#include "Errors.h" // for ASSERT -#include <stdarg.h> -#include <boost/thread/tss.hpp> - -#if COMPILER == COMPILER_GNU - #include <sys/socket.h> - #include <netinet/in.h> - #include <arpa/inet.h> -#endif - -static boost::thread_specific_ptr<SFMTRand> sfmtRand; - -static SFMTRand* GetRng() -{ - SFMTRand* rand = sfmtRand.get(); - - if (!rand) - { - rand = new SFMTRand(); - sfmtRand.reset(rand); - } - - return rand; -} - -int32 irand(int32 min, int32 max) -{ - ASSERT(max >= min); - return int32(GetRng()->IRandom(min, max)); -} - -uint32 urand(uint32 min, uint32 max) -{ - ASSERT(max >= min); - return GetRng()->URandom(min, max); -} - -float frand(float min, float max) -{ - ASSERT(max >= min); - return float(GetRng()->Random() * (max - min) + min); -} - -uint32 rand32() -{ - return GetRng()->BRandom(); -} - -double rand_norm() -{ - return GetRng()->Random(); -} - -double rand_chance() -{ - return GetRng()->Random() * 100.0; -} - -Tokenizer::Tokenizer(const std::string &src, const char sep, uint32 vectorReserve) -{ - m_str = new char[src.length() + 1]; - memcpy(m_str, src.c_str(), src.length() + 1); - - if (vectorReserve) - m_storage.reserve(vectorReserve); - - char* posold = m_str; - char* posnew = m_str; - - for (;;) - { - if (*posnew == sep) - { - m_storage.push_back(posold); - posold = posnew + 1; - - *posnew = '\0'; - } - else if (*posnew == '\0') - { - // Hack like, but the old code accepted these kind of broken strings, - // so changing it would break other things - if (posold != posnew) - m_storage.push_back(posold); - - break; - } - - ++posnew; - } -} - -void stripLineInvisibleChars(std::string &str) -{ - static std::string const invChars = " \t\7\n"; - - size_t wpos = 0; - - bool space = false; - for (size_t pos = 0; pos < str.size(); ++pos) - { - if (invChars.find(str[pos])!=std::string::npos) - { - if (!space) - { - str[wpos++] = ' '; - space = true; - } - } - else - { - if (wpos!=pos) - str[wpos++] = str[pos]; - else - ++wpos; - space = false; - } - } - - if (wpos < str.size()) - str.erase(wpos, str.size()); - if (str.find("|TInterface")!=std::string::npos) - str.clear(); - -} - -#if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) -struct tm* localtime_r(const time_t* time, struct tm *result) -{ - localtime_s(result, time); - return result; -} -#endif - -std::string secsToTimeString(uint64 timeInSecs, bool shortText, bool hoursOnly) -{ - uint64 secs = timeInSecs % MINUTE; - uint64 minutes = timeInSecs % HOUR / MINUTE; - uint64 hours = timeInSecs % DAY / HOUR; - uint64 days = timeInSecs / DAY; - - std::ostringstream ss; - if (days) - ss << days << (shortText ? "d" : " Day(s) "); - if (hours || hoursOnly) - ss << hours << (shortText ? "h" : " Hour(s) "); - if (!hoursOnly) - { - if (minutes) - ss << minutes << (shortText ? "m" : " Minute(s) "); - if (secs || (!days && !hours && !minutes) ) - ss << secs << (shortText ? "s" : " Second(s)."); - } - - return ss.str(); -} - -int32 MoneyStringToMoney(const std::string& moneyString) -{ - int32 money = 0; - - if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 || - std::count(moneyString.begin(), moneyString.end(), 's') == 1 || - std::count(moneyString.begin(), moneyString.end(), 'c') == 1)) - return 0; // Bad format - - Tokenizer tokens(moneyString, ' '); - for (Tokenizer::const_iterator itr = tokens.begin(); itr != tokens.end(); ++itr) - { - std::string tokenString(*itr); - size_t gCount = std::count(tokenString.begin(), tokenString.end(), 'g'); - size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's'); - size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c'); - if (gCount + sCount + cCount != 1) - return 0; - - uint32 amount = atoi(*itr); - if (gCount == 1) - money += amount * 100 * 100; - else if (sCount == 1) - money += amount * 100; - else if (cCount == 1) - money += amount; - } - - return money; -} - -uint32 TimeStringToSecs(const std::string& timestring) -{ - uint32 secs = 0; - uint32 buffer = 0; - uint32 multiplier = 0; - - for (std::string::const_iterator itr = timestring.begin(); itr != timestring.end(); ++itr) - { - if (isdigit(*itr)) - { - buffer*=10; - buffer+= (*itr)-'0'; - } - else - { - switch (*itr) - { - case 'd': multiplier = DAY; break; - case 'h': multiplier = HOUR; break; - case 'm': multiplier = MINUTE; break; - case 's': multiplier = 1; break; - default : return 0; //bad format - } - buffer*=multiplier; - secs+=buffer; - buffer=0; - } - } - - return secs; -} - -std::string TimeToTimestampStr(time_t t) -{ - tm aTm; - localtime_r(&t, &aTm); - // YYYY year - // MM month (2 digits 01-12) - // DD day (2 digits 01-31) - // HH hour (2 digits 00-23) - // MM minutes (2 digits 00-59) - // SS seconds (2 digits 00-59) - char buf[20]; - snprintf(buf, 20, "%04d-%02d-%02d_%02d-%02d-%02d", aTm.tm_year+1900, aTm.tm_mon+1, aTm.tm_mday, aTm.tm_hour, aTm.tm_min, aTm.tm_sec); - return std::string(buf); -} - -/// Check if the string is a valid ip address representation -bool IsIPAddress(char const* ipaddress) -{ - if (!ipaddress) - return false; - - // Let the big boys do it. - // Drawback: all valid ip address formats are recognized e.g.: 12.23, 121234, 0xABCD) - return inet_addr(ipaddress) != INADDR_NONE; -} - -/// create PID file -uint32 CreatePIDFile(const std::string& filename) -{ - FILE* pid_file = fopen (filename.c_str(), "w" ); - if (pid_file == NULL) - return 0; - -#ifdef _WIN32 - DWORD pid = GetCurrentProcessId(); -#else - pid_t pid = getpid(); -#endif - - fprintf(pid_file, "%u", pid ); - fclose(pid_file); - - return (uint32)pid; -} - -size_t utf8length(std::string& utf8str) -{ - try - { - return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size()); - } - catch(std::exception) - { - utf8str.clear(); - return 0; - } -} - -void utf8truncate(std::string& utf8str, size_t len) -{ - try - { - size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size()); - if (wlen <= len) - return; - - std::wstring wstr; - wstr.resize(wlen); - utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]); - wstr.resize(len); - char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]); - utf8str.resize(oend-(&utf8str[0])); // remove unused tail - } - catch(std::exception) - { - utf8str.clear(); - } -} - -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize) -{ - try - { - size_t len = utf8::distance(utf8str, utf8str+csize); - if (len > wsize) - { - if (wsize > 0) - wstr[0] = L'\0'; - wsize = 0; - return false; - } - - wsize = len; - utf8::utf8to16(utf8str, utf8str+csize, wstr); - wstr[len] = L'\0'; - } - catch(std::exception) - { - if (wsize > 0) - wstr[0] = L'\0'; - wsize = 0; - return false; - } - - return true; -} - -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr) -{ - try - { - if (size_t len = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size())) - { - wstr.resize(len); - utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]); - } - } - catch(std::exception) - { - wstr.clear(); - return false; - } - - return true; -} - -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str) -{ - try - { - std::string utf8str2; - utf8str2.resize(size*4); // allocate for most long case - - if (size) - { - char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]); - utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail - } - utf8str = utf8str2; - } - catch(std::exception) - { - utf8str.clear(); - return false; - } - - return true; -} - -bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str) -{ - try - { - std::string utf8str2; - utf8str2.resize(wstr.size()*4); // allocate for most long case - - if (wstr.size()) - { - char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str2[0]); - utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail - } - utf8str = utf8str2; - } - catch(std::exception) - { - utf8str.clear(); - return false; - } - - return true; -} - -typedef wchar_t const* const* wstrlist; - -std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension) -{ - // supported only Cyrillic cases - if (wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5) - return wname; - - // Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently) - - static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430), wchar_t(0x0000)}; - static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E), wchar_t(0x0000)}; - static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F), wchar_t(0x0000)}; - static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435), wchar_t(0x0000)}; - static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438), wchar_t(0x0000)}; - static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B), wchar_t(0x0000)}; - static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443), wchar_t(0x0000)}; - static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E), wchar_t(0x0000)}; - static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E), wchar_t(0x0439), wchar_t(0x0000)}; - static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435), wchar_t(0x0439), wchar_t(0x0000)}; - static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451), wchar_t(0x0439), wchar_t(0x0000)}; - static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E), wchar_t(0x043C), wchar_t(0x0000)}; - static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451), wchar_t(0x043C), wchar_t(0x0000)}; - static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435), wchar_t(0x043C), wchar_t(0x0000)}; - static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C), wchar_t(0x0000)}; - static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439), wchar_t(0x0000)}; - - static wchar_t const* const dropEnds[6][8] = { - { &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL }, - { &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL }, - { &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL }, - { &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL }, - { &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL }, - { &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL } - }; - - for (wchar_t const* const* itr = &dropEnds[declension][0]; *itr; ++itr) - { - size_t len = size_t((*itr)[-1]); // get length from string size field - - if (wname.substr(wname.size()-len, len)==*itr) - return wname.substr(0, wname.size()-len); - } - - return wname; -} - -bool utf8ToConsole(const std::string& utf8str, std::string& conStr) -{ -#if PLATFORM == PLATFORM_WINDOWS - std::wstring wstr; - if (!Utf8toWStr(utf8str, wstr)) - return false; - - conStr.resize(wstr.size()); - CharToOemBuffW(&wstr[0], &conStr[0], wstr.size()); -#else - // not implemented yet - conStr = utf8str; -#endif - - return true; -} - -bool consoleToUtf8(const std::string& conStr, std::string& utf8str) -{ -#if PLATFORM == PLATFORM_WINDOWS - std::wstring wstr; - wstr.resize(conStr.size()); - OemToCharBuffW(&conStr[0], &wstr[0], conStr.size()); - - return WStrToUtf8(wstr, utf8str); -#else - // not implemented yet - utf8str = conStr; - return true; -#endif -} - -bool Utf8FitTo(const std::string& str, std::wstring const& search) -{ - std::wstring temp; - - if (!Utf8toWStr(str, temp)) - return false; - - // converting to lower case - wstrToLower( temp ); - - if (temp.find(search) == std::wstring::npos) - return false; - - return true; -} - -void utf8printf(FILE* out, const char *str, ...) -{ - va_list ap; - va_start(ap, str); - vutf8printf(out, str, &ap); - va_end(ap); -} - -void vutf8printf(FILE* out, const char *str, va_list* ap) -{ -#if PLATFORM == PLATFORM_WINDOWS - char temp_buf[32*1024]; - wchar_t wtemp_buf[32*1024]; - - size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap); - //vsnprintf returns -1 if the buffer is too small - if (temp_len == size_t(-1)) - temp_len = 32*1024-1; - - size_t wtemp_len = 32*1024-1; - Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len); - - CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], wtemp_len+1); - fprintf(out, "%s", temp_buf); -#else - vfprintf(out, str, *ap); -#endif -} - -std::string ByteArrayToHexStr(uint8 const* bytes, uint32 arrayLen, bool reverse /* = false */) -{ - int32 init = 0; - int32 end = arrayLen; - int8 op = 1; - - if (reverse) - { - init = arrayLen - 1; - end = -1; - op = -1; - } - - std::ostringstream ss; - for (int32 i = init; i != end; i += op) - { - char buffer[4]; - sprintf(buffer, "%02X", bytes[i]); - ss << buffer; - } - - return ss.str(); -} diff --git a/src/server/shared/Utilities/Util.h b/src/server/shared/Utilities/Util.h deleted file mode 100644 index 3da1c800410..00000000000 --- a/src/server/shared/Utilities/Util.h +++ /dev/null @@ -1,545 +0,0 @@ -/* - * Copyright (C) 2008-2015 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 _UTIL_H -#define _UTIL_H - -#include "Define.h" -#include "Errors.h" - -#include <algorithm> -#include <string> -#include <vector> -#include <list> -#include <map> - -// 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 Tokenizer -{ -public: - typedef std::vector<char const*> StorageType; - - typedef StorageType::size_type size_type; - - typedef StorageType::const_iterator const_iterator; - typedef StorageType::reference reference; - typedef StorageType::const_reference const_reference; - -public: - Tokenizer(const std::string &src, char const sep, uint32 vectorReserve = 0); - ~Tokenizer() { delete[] m_str; } - - const_iterator begin() const { return m_storage.begin(); } - const_iterator end() const { return m_storage.end(); } - - size_type size() const { return m_storage.size(); } - - reference operator [] (size_type i) { return m_storage[i]; } - const_reference operator [] (size_type i) const { return m_storage[i]; } - -private: - char* m_str; - StorageType m_storage; -}; - -void stripLineInvisibleChars(std::string &src); - -int32 MoneyStringToMoney(const std::string& moneyString); - -struct tm* localtime_r(const time_t* time, struct tm *result); - -std::string secsToTimeString(uint64 timeInSecs, bool shortText = false, bool hoursOnly = false); -uint32 TimeStringToSecs(const std::string& timestring); -std::string TimeToTimestampStr(time_t t); - -/* Return a random number in the range min..max. */ -int32 irand(int32 min, int32 max); - -/* Return a random number in the range min..max (inclusive). */ -uint32 urand(uint32 min, uint32 max); - -/* Return a random number in the range 0 .. UINT32_MAX. */ -uint32 rand32(); - -/* Return a random number in the range min..max */ -float frand(float min, float max); - -/* Return a random double from 0.0 to 1.0 (exclusive). */ -double rand_norm(); - -/* Return a random double from 0.0 to 100.0 (exclusive). */ -double rand_chance(); - -/* Return true if a random roll fits in the specified chance (range 0-100). */ -inline bool roll_chance_f(float chance) -{ - return chance > rand_chance(); -} - -/* Return true if a random roll fits in the specified chance (range 0-100). */ -inline bool roll_chance_i(int chance) -{ - return chance > irand(0, 99); -} - -inline void ApplyPercentModFloatVar(float& var, float val, bool apply) -{ - if (val == -100.0f) // prevent set var to zero - val = -99.99f; - var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val)); -} - -// Percentage calculation -template <class T, class U> -inline T CalculatePct(T base, U pct) -{ - return T(base * static_cast<float>(pct) / 100.0f); -} - -template <class T, class U> -inline T AddPct(T &base, U pct) -{ - return base += CalculatePct(base, pct); -} - -template <class T, class U> -inline T ApplyPct(T &base, U pct) -{ - return base = CalculatePct(base, pct); -} - -template <class T> -inline T RoundToInterval(T& num, T floor, T ceil) -{ - return num = std::min(std::max(num, floor), ceil); -} - -// UTF8 handling -bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr); -// in wsize==max size of buffer, out wsize==real string size -bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize); -inline bool Utf8toWStr(const std::string& utf8str, wchar_t* wstr, size_t& wsize) -{ - return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize); -} - -bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str); -// size==real string size -bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str); - -size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence -void utf8truncate(std::string& utf8str, size_t len); - -inline bool isBasicLatinCharacter(wchar_t wchar) -{ - if (wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z - return true; - if (wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z - return true; - return false; -} - -inline bool isExtendedLatinCharacter(wchar_t wchar) -{ - if (isBasicLatinCharacter(wchar)) - return true; - if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS - return true; - if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN - return true; - if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S - return true; - if (wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS - return true; - if (wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN - return true; - if (wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK - return true; - if (wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S - return true; - return false; -} - -inline bool isCyrillicCharacter(wchar_t wchar) -{ - if (wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA - return true; - if (wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO - return true; - return false; -} - -inline bool isEastAsianCharacter(wchar_t wchar) -{ - if (wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo - return true; - if (wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana - return true; - if (wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo - return true; - if (wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext. - return true; - if (wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A - return true; - if (wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs - return true; - if (wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables - return true; - if (wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms - return true; - return false; -} - -inline bool isNumeric(wchar_t wchar) -{ - return (wchar >= L'0' && wchar <=L'9'); -} - -inline bool isNumeric(char c) -{ - return (c >= '0' && c <='9'); -} - -inline bool isNumeric(char const* str) -{ - for (char const* c = str; *c; ++c) - if (!isNumeric(*c)) - return false; - - return true; -} - -inline bool isNumericOrSpace(wchar_t wchar) -{ - return isNumeric(wchar) || wchar == L' '; -} - -inline bool isBasicLatinString(const std::wstring &wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if (!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isExtendedLatinString(const std::wstring &wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if (!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isCyrillicString(const std::wstring &wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if (!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline bool isEastAsianString(const std::wstring &wstr, bool numericOrSpace) -{ - for (size_t i = 0; i < wstr.size(); ++i) - if (!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i]))) - return false; - return true; -} - -inline wchar_t wcharToUpper(wchar_t wchar) -{ - if (wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z - return wchar_t(uint16(wchar)-0x0020); - if (wchar == 0x00DF) // LATIN SMALL LETTER SHARP S - return wchar_t(0x1E9E); - if (wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS - return wchar_t(uint16(wchar)-0x0020); - if (wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN - return wchar_t(uint16(wchar)-0x0020); - if (wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1) - { - if (wchar % 2 == 1) - return wchar_t(uint16(wchar)-0x0001); - } - if (wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA - return wchar_t(uint16(wchar)-0x0020); - if (wchar == 0x0451) // CYRILLIC SMALL LETTER IO - return wchar_t(0x0401); - - return wchar; -} - -inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar) -{ - return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar; -} - -inline wchar_t wcharToLower(wchar_t wchar) -{ - if (wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z - return wchar_t(uint16(wchar)+0x0020); - if (wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS - return wchar_t(uint16(wchar)+0x0020); - if (wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN - return wchar_t(uint16(wchar)+0x0020); - if (wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0) - { - if (wchar % 2 == 0) - return wchar_t(uint16(wchar)+0x0001); - } - if (wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S - return wchar_t(0x00DF); - if (wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO - return wchar_t(0x0451); - if (wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA - return wchar_t(uint16(wchar)+0x0020); - - return wchar; -} - -inline void wstrToUpper(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToUpper ); -} - -inline void wstrToLower(std::wstring& str) -{ - std::transform( str.begin(), str.end(), str.begin(), wcharToLower ); -} - -std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension); - -bool utf8ToConsole(const std::string& utf8str, std::string& conStr); -bool consoleToUtf8(const std::string& conStr, std::string& utf8str); -bool Utf8FitTo(const std::string& str, std::wstring const& search); -void utf8printf(FILE* out, const char *str, ...); -void vutf8printf(FILE* out, const char *str, va_list* ap); - -bool IsIPAddress(char const* ipaddress); - -uint32 CreatePIDFile(const std::string& filename); - -std::string ByteArrayToHexStr(uint8 const* bytes, uint32 length, bool reverse = false); - -// simple class for not-modifyable list -template <typename T> -class HookList -{ - typedef typename std::list<T>::iterator ListIterator; - private: - typename std::list<T> m_list; - public: - HookList<T> & operator+=(T t) - { - m_list.push_back(t); - return *this; - } - HookList<T> & operator-=(T t) - { - m_list.remove(t); - return *this; - } - size_t size() - { - return m_list.size(); - } - ListIterator begin() - { - return m_list.begin(); - } - ListIterator end() - { - return m_list.end(); - } -}; - -class flag96 -{ -private: - uint32 part[3]; - -public: - flag96(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0) - { - part[0] = p1; - part[1] = p2; - part[2] = p3; - } - - inline bool IsEqual(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0) const - { - return (part[0] == p1 && part[1] == p2 && part[2] == p3); - } - - inline bool HasFlag(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0) const - { - return (part[0] & p1 || part[1] & p2 || part[2] & p3); - } - - inline void Set(uint32 p1 = 0, uint32 p2 = 0, uint32 p3 = 0) - { - part[0] = p1; - part[1] = p2; - part[2] = p3; - } - - inline bool operator <(const flag96 &right) const - { - for (uint8 i = 3; i > 0; --i) - { - if (part[i - 1] < right.part[i - 1]) - return true; - else if (part[i - 1] > right.part[i - 1]) - return false; - } - return false; - } - - inline bool operator ==(const flag96 &right) const - { - return - ( - part[0] == right.part[0] && - part[1] == right.part[1] && - part[2] == right.part[2] - ); - } - - inline bool operator !=(const flag96 &right) const - { - return !this->operator ==(right); - } - - inline flag96 & operator =(const flag96 &right) - { - part[0] = right.part[0]; - part[1] = right.part[1]; - part[2] = right.part[2]; - return *this; - } - - inline flag96 operator &(const flag96 &right) const - { - return flag96(part[0] & right.part[0], part[1] & right.part[1], - part[2] & right.part[2]); - } - - inline flag96 & operator &=(const flag96 &right) - { - part[0] &= right.part[0]; - part[1] &= right.part[1]; - part[2] &= right.part[2]; - return *this; - } - - inline flag96 operator |(const flag96 &right) const - { - return flag96(part[0] | right.part[0], part[1] | right.part[1], - part[2] | right.part[2]); - } - - inline flag96 & operator |=(const flag96 &right) - { - part[0] |= right.part[0]; - part[1] |= right.part[1]; - part[2] |= right.part[2]; - return *this; - } - - inline flag96 operator ~() const - { - return flag96(~part[0], ~part[1], ~part[2]); - } - - inline flag96 operator ^(const flag96 &right) const - { - return flag96(part[0] ^ right.part[0], part[1] ^ right.part[1], - part[2] ^ right.part[2]); - } - - inline flag96 & operator ^=(const flag96 &right) - { - part[0] ^= right.part[0]; - part[1] ^= right.part[1]; - part[2] ^= right.part[2]; - return *this; - } - - inline operator bool() const - { - return (part[0] != 0 || part[1] != 0 || part[2] != 0); - } - - inline bool operator !() const - { - return !this->operator bool(); - } - - inline uint32 & operator [](uint8 el) - { - return part[el]; - } - - inline const uint32 & operator [](uint8 el) const - { - return part[el]; - } -}; - -enum ComparisionType -{ - COMP_TYPE_EQ = 0, - COMP_TYPE_HIGH, - COMP_TYPE_LOW, - COMP_TYPE_HIGH_EQ, - COMP_TYPE_LOW_EQ, - COMP_TYPE_MAX -}; - -template <class T> -bool CompareValues(ComparisionType type, T val1, T val2) -{ - switch (type) - { - case COMP_TYPE_EQ: - return val1 == val2; - case COMP_TYPE_HIGH: - return val1 > val2; - case COMP_TYPE_LOW: - return val1 < val2; - case COMP_TYPE_HIGH_EQ: - return val1 >= val2; - case COMP_TYPE_LOW_EQ: - return val1 <= val2; - default: - // incorrect parameter - ASSERT(false); - return false; - } -} - -#endif diff --git a/src/server/worldserver/CMakeLists.txt b/src/server/worldserver/CMakeLists.txt index a6c76977fe2..f513ba0857f 100644 --- a/src/server/worldserver/CMakeLists.txt +++ b/src/server/worldserver/CMakeLists.txt @@ -49,24 +49,23 @@ include_directories( ${CMAKE_SOURCE_DIR}/dep/SFMT ${CMAKE_SOURCE_DIR}/dep/cppformat ${CMAKE_SOURCE_DIR}/dep/process - ${CMAKE_SOURCE_DIR}/src/server/collision - ${CMAKE_SOURCE_DIR}/src/server/collision/Management - ${CMAKE_SOURCE_DIR}/src/server/collision/Models + ${CMAKE_SOURCE_DIR}/src/server/database + ${CMAKE_SOURCE_DIR}/src/server/database/Database + ${CMAKE_SOURCE_DIR}/src/server/database/Logging + ${CMAKE_SOURCE_DIR}/src/server/database/Updater + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared - ${CMAKE_SOURCE_DIR}/src/server/shared/Configuration ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography ${CMAKE_SOURCE_DIR}/src/server/shared/Cryptography/Authentication - ${CMAKE_SOURCE_DIR}/src/server/shared/Database ${CMAKE_SOURCE_DIR}/src/server/shared/DataStores - ${CMAKE_SOURCE_DIR}/src/server/shared/Debugging ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic/LinkedReference ${CMAKE_SOURCE_DIR}/src/server/shared/Dynamic - ${CMAKE_SOURCE_DIR}/src/server/shared/Logging ${CMAKE_SOURCE_DIR}/src/server/shared/Networking ${CMAKE_SOURCE_DIR}/src/server/shared/Packets - ${CMAKE_SOURCE_DIR}/src/server/shared/Threading - ${CMAKE_SOURCE_DIR}/src/server/shared/Updater - ${CMAKE_SOURCE_DIR}/src/server/shared/Utilities + ${CMAKE_SOURCE_DIR}/src/server/shared/Service ${CMAKE_SOURCE_DIR}/src/server/game ${CMAKE_SOURCE_DIR}/src/server/game/Accounts ${CMAKE_SOURCE_DIR}/src/server/game/Achievements @@ -135,6 +134,14 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/server/game/World ${CMAKE_SOURCE_DIR}/src/server/authserver/Server ${CMAKE_SOURCE_DIR}/src/server/authserver/Realms + ${CMAKE_SOURCE_DIR}/src/common/ + ${CMAKE_SOURCE_DIR}/src/common/Collision + ${CMAKE_SOURCE_DIR}/src/common/Collision/Management + ${CMAKE_SOURCE_DIR}/src/common/Collision/Models + ${CMAKE_SOURCE_DIR}/src/common/Debugging + ${CMAKE_SOURCE_DIR}/src/common/Utilities + ${CMAKE_SOURCE_DIR}/src/common/Threading + ${CMAKE_SOURCE_DIR}/src/common/Logging ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/CommandLine ${CMAKE_CURRENT_SOURCE_DIR}/RemoteAccess @@ -165,9 +172,10 @@ set_target_properties(worldserver PROPERTIES LINK_FLAGS "${worldserver_LINK_FLAG target_link_libraries(worldserver game + common shared + database scripts - collision g3dlib gsoap Detour |
