mirror of
https://github.com/mod-playerbots/azerothcore-wotlk.git
synced 2025-11-29 17:38:24 +08:00
refactor(Core/Common): restyle common lib with astyle (#3461)
This commit is contained in:
@@ -12,30 +12,30 @@
|
|||||||
namespace acore
|
namespace acore
|
||||||
{
|
{
|
||||||
|
|
||||||
template <class Pointer, class Lock>
|
template <class Pointer, class Lock>
|
||||||
class AutoPtr : public ACE_Strong_Bound_Ptr<Pointer, Lock>
|
class AutoPtr : public ACE_Strong_Bound_Ptr<Pointer, Lock>
|
||||||
{
|
|
||||||
typedef ACE_Strong_Bound_Ptr<Pointer, Lock> Base;
|
|
||||||
|
|
||||||
public:
|
|
||||||
AutoPtr()
|
|
||||||
: Base()
|
|
||||||
{ }
|
|
||||||
|
|
||||||
AutoPtr(Pointer* x)
|
|
||||||
: Base(x)
|
|
||||||
{ }
|
|
||||||
|
|
||||||
operator bool() const
|
|
||||||
{
|
{
|
||||||
return !Base::null();
|
typedef ACE_Strong_Bound_Ptr<Pointer, Lock> Base;
|
||||||
}
|
|
||||||
|
|
||||||
bool operator !() const
|
public:
|
||||||
{
|
AutoPtr()
|
||||||
return Base::null();
|
: Base()
|
||||||
}
|
{ }
|
||||||
};
|
|
||||||
|
AutoPtr(Pointer* x)
|
||||||
|
: Base(x)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return !Base::null();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator !() const
|
||||||
|
{
|
||||||
|
return Base::null();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace acore
|
} // namespace acore
|
||||||
|
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
#include "BoundingIntervalHierarchy.h"
|
#include "BoundingIntervalHierarchy.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define isnan _isnan
|
#define isnan _isnan
|
||||||
#else
|
#else
|
||||||
#define isnan std::isnan
|
#define isnan std::isnan
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats)
|
void BIH::buildHierarchy(std::vector<uint32>& tempTree, buildData& dat, BuildStats& stats)
|
||||||
{
|
{
|
||||||
// create space for the first node
|
// create space for the first node
|
||||||
tempTree.push_back(uint32(3 << 30)); // dummy leaf
|
tempTree.push_back(uint32(3 << 30)); // dummy leaf
|
||||||
@@ -26,7 +26,7 @@ void BIH::buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildSta
|
|||||||
subdivide(0, dat.numPrims - 1, tempTree, dat, gridBox, nodeBox, 0, 1, stats);
|
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)
|
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)
|
if ((right - left + 1) <= dat.maxPrims || depth >= MAX_STACK_SIZE)
|
||||||
{
|
{
|
||||||
@@ -121,13 +121,15 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
|
|||||||
if (right == rightOrig)
|
if (right == rightOrig)
|
||||||
{
|
{
|
||||||
// all left
|
// all left
|
||||||
if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) {
|
if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
|
||||||
|
{
|
||||||
// we are stuck here - create a leaf
|
// we are stuck here - create a leaf
|
||||||
stats.updateLeaf(depth, right - left + 1);
|
stats.updateLeaf(depth, right - left + 1);
|
||||||
createNode(tempTree, nodeIndex, left, right);
|
createNode(tempTree, nodeIndex, left, right);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (clipL <= split) {
|
if (clipL <= split)
|
||||||
|
{
|
||||||
// keep looping on left half
|
// keep looping on left half
|
||||||
gridBox.hi[axis] = split;
|
gridBox.hi[axis] = split;
|
||||||
prevClip = clipL;
|
prevClip = clipL;
|
||||||
@@ -140,14 +142,16 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
|
|||||||
else if (left > right)
|
else if (left > right)
|
||||||
{
|
{
|
||||||
// all right
|
// all right
|
||||||
if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split)) {
|
if (prevAxis == axis && G3D::fuzzyEq(prevSplit, split))
|
||||||
|
{
|
||||||
// we are stuck here - create a leaf
|
// we are stuck here - create a leaf
|
||||||
stats.updateLeaf(depth, right - left + 1);
|
stats.updateLeaf(depth, right - left + 1);
|
||||||
createNode(tempTree, nodeIndex, left, right);
|
createNode(tempTree, nodeIndex, left, right);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
right = rightOrig;
|
right = rightOrig;
|
||||||
if (clipR >= split) {
|
if (clipR >= split)
|
||||||
|
{
|
||||||
// keep looping on right half
|
// keep looping on right half
|
||||||
gridBox.lo[axis] = split;
|
gridBox.lo[axis] = split;
|
||||||
prevClip = clipR;
|
prevClip = clipR;
|
||||||
@@ -169,14 +173,17 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
|
|||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
if (wasLeft) {
|
if (wasLeft)
|
||||||
|
{
|
||||||
// create a node with a left child
|
// create a node with a left child
|
||||||
// write leaf node
|
// write leaf node
|
||||||
stats.updateInner();
|
stats.updateInner();
|
||||||
tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex;
|
tempTree[nodeIndex + 0] = (prevAxis << 30) | nextIndex;
|
||||||
tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip);
|
tempTree[nodeIndex + 1] = floatToRawIntBits(prevClip);
|
||||||
tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf());
|
tempTree[nodeIndex + 2] = floatToRawIntBits(G3D::inf());
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
// create a node with a right child
|
// create a node with a right child
|
||||||
// write leaf node
|
// write leaf node
|
||||||
stats.updateInner();
|
stats.updateInner();
|
||||||
@@ -198,14 +205,17 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
|
|||||||
// allocate left node
|
// allocate left node
|
||||||
int nl = right - left + 1;
|
int nl = right - left + 1;
|
||||||
int nr = rightOrig - (right + 1) + 1;
|
int nr = rightOrig - (right + 1) + 1;
|
||||||
if (nl > 0) {
|
if (nl > 0)
|
||||||
|
{
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
} else
|
}
|
||||||
|
else
|
||||||
nextIndex -= 3;
|
nextIndex -= 3;
|
||||||
// allocate right node
|
// allocate right node
|
||||||
if (nr > 0) {
|
if (nr > 0)
|
||||||
|
{
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
tempTree.push_back(0);
|
tempTree.push_back(0);
|
||||||
@@ -235,7 +245,7 @@ void BIH::subdivide(int left, int right, std::vector<uint32> &tempTree, buildDat
|
|||||||
bool BIH::writeToFile(FILE* wf) const
|
bool BIH::writeToFile(FILE* wf) const
|
||||||
{
|
{
|
||||||
uint32 treeSize = tree.size();
|
uint32 treeSize = tree.size();
|
||||||
uint32 check=0, count;
|
uint32 check = 0, count;
|
||||||
check += fwrite(&bounds.low(), sizeof(float), 3, wf);
|
check += fwrite(&bounds.low(), sizeof(float), 3, wf);
|
||||||
check += fwrite(&bounds.high(), sizeof(float), 3, wf);
|
check += fwrite(&bounds.high(), sizeof(float), 3, wf);
|
||||||
check += fwrite(&treeSize, sizeof(uint32), 1, wf);
|
check += fwrite(&treeSize, sizeof(uint32), 1, wf);
|
||||||
@@ -250,7 +260,7 @@ bool BIH::readFromFile(FILE* rf)
|
|||||||
{
|
{
|
||||||
uint32 treeSize;
|
uint32 treeSize;
|
||||||
G3D::Vector3 lo, hi;
|
G3D::Vector3 lo, hi;
|
||||||
uint32 check=0, count=0;
|
uint32 check = 0, count = 0;
|
||||||
check += fread(&lo, sizeof(float), 3, rf);
|
check += fread(&lo, sizeof(float), 3, rf);
|
||||||
check += fread(&hi, sizeof(float), 3, rf);
|
check += fread(&hi, sizeof(float), 3, rf);
|
||||||
bounds = G3D::AABox(lo, hi);
|
bounds = G3D::AABox(lo, hi);
|
||||||
|
|||||||
@@ -54,332 +54,340 @@ struct AABound
|
|||||||
|
|
||||||
class BIH
|
class BIH
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
void init_empty()
|
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)
|
||||||
{
|
{
|
||||||
tree.clear();
|
init_empty();
|
||||||
objects.clear();
|
return;
|
||||||
// create space for the first node
|
|
||||||
tree.push_back(3u << 30u); // dummy leaf
|
|
||||||
tree.insert(tree.end(), 2, 0);
|
|
||||||
}
|
}
|
||||||
public:
|
|
||||||
BIH() { init_empty(); }
|
buildData dat;
|
||||||
template< class BoundsFunc, class PrimArray >
|
dat.maxPrims = leafSize;
|
||||||
void build(const PrimArray &primitives, BoundsFunc &getBounds, uint32 leafSize = 3, bool printStats=false)
|
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)
|
||||||
{
|
{
|
||||||
if (primitives.size() == 0)
|
dat.indices[i] = i;
|
||||||
{
|
getBounds(primitives[i], dat.primBound[i]);
|
||||||
init_empty();
|
bounds.merge(dat.primBound[i]);
|
||||||
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(); }
|
std::vector<uint32> tempTree;
|
||||||
|
BuildStats stats;
|
||||||
|
buildHierarchy(tempTree, dat, stats);
|
||||||
|
if (printStats)
|
||||||
|
stats.printStats();
|
||||||
|
|
||||||
template<typename RayCallback>
|
objects.resize(dat.numPrims);
|
||||||
void intersectRay(const G3D::Ray &r, RayCallback& intersectCallback, float &maxDist, bool stopAtFirstHit) const
|
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 stopAtFirstHit) 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)
|
||||||
{
|
{
|
||||||
float intervalMin = -1.f;
|
invDir[i] = 1.f / dir[i];
|
||||||
float intervalMax = -1.f;
|
if (G3D::fuzzyNe(dir[i], 0.0f))
|
||||||
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];
|
float t1 = (bounds.low()[i] - org[i]) * invDir[i];
|
||||||
if (G3D::fuzzyNe(dir[i], 0.0f))
|
float t2 = (bounds.high()[i] - org[i]) * invDir[i];
|
||||||
{
|
if (t1 > t2)
|
||||||
float t1 = (bounds.low()[i] - org[i]) * invDir[i];
|
std::swap(t1, t2);
|
||||||
float t2 = (bounds.high()[i] - org[i]) * invDir[i];
|
if (t1 > intervalMin)
|
||||||
if (t1 > t2)
|
intervalMin = t1;
|
||||||
std::swap(t1, t2);
|
if (t2 < intervalMax || intervalMax < 0.f)
|
||||||
if (t1 > intervalMin)
|
intervalMax = t2;
|
||||||
intervalMin = t1;
|
// intervalMax can only become smaller for other axis,
|
||||||
if (t2 < intervalMax || intervalMax < 0.f)
|
// and intervalMin only larger respectively, so stop early
|
||||||
intervalMax = t2;
|
if (intervalMax <= 0 || intervalMin >= maxDist)
|
||||||
// intervalMax can only become smaller for other axis,
|
return;
|
||||||
// and intervalMin only larger respectively, so stop early
|
|
||||||
if (intervalMax <= 0 || intervalMin >= maxDist)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (intervalMin > intervalMax)
|
if (intervalMin > intervalMax)
|
||||||
return;
|
return;
|
||||||
intervalMin = std::max(intervalMin, 0.f);
|
intervalMin = std::max(intervalMin, 0.f);
|
||||||
intervalMax = std::min(intervalMax, maxDist);
|
intervalMax = std::min(intervalMax, maxDist);
|
||||||
|
|
||||||
uint32 offsetFront[3];
|
uint32 offsetFront[3];
|
||||||
uint32 offsetBack[3];
|
uint32 offsetBack[3];
|
||||||
uint32 offsetFront3[3];
|
uint32 offsetFront3[3];
|
||||||
uint32 offsetBack3[3];
|
uint32 offsetBack3[3];
|
||||||
// compute custom offsets from direction sign bit
|
// compute custom offsets from direction sign bit
|
||||||
|
|
||||||
for (int i=0; i<3; ++i)
|
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)
|
||||||
{
|
{
|
||||||
offsetFront[i] = floatToRawIntBits(dir[i]) >> 31;
|
uint32 tn = tree[node];
|
||||||
offsetBack[i] = offsetFront[i] ^ 1;
|
uint32 axis = (tn & (3 << 30)) >> 30;
|
||||||
offsetFront3[i] = offsetFront[i] * 3;
|
bool BVH2 = tn & (1 << 29);
|
||||||
offsetBack3[i] = offsetBack[i] * 3;
|
int offset = tn & ~(7 << 29);
|
||||||
|
if (!BVH2)
|
||||||
// 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];
|
if (axis < 3)
|
||||||
uint32 axis = (tn & (3 << 30)) >> 30;
|
|
||||||
bool BVH2 = tn & (1 << 29);
|
|
||||||
int offset = tn & ~(7 << 29);
|
|
||||||
if (!BVH2)
|
|
||||||
{
|
{
|
||||||
if (axis < 3)
|
// "normal" interior node
|
||||||
|
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
|
||||||
|
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
|
||||||
|
// ray passes between clip zones
|
||||||
|
if (tf < intervalMin && tb > intervalMax)
|
||||||
|
break;
|
||||||
|
int back = offset + offsetBack3[axis];
|
||||||
|
node = back;
|
||||||
|
// ray passes through far node only
|
||||||
|
if (tf < intervalMin)
|
||||||
|
{
|
||||||
|
intervalMin = (tb >= intervalMin) ? tb : intervalMin;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
node = offset + offsetFront3[axis]; // front
|
||||||
|
// ray passes through near node only
|
||||||
|
if (tb > intervalMax)
|
||||||
{
|
{
|
||||||
// "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;
|
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else
|
// ray passes through both nodes
|
||||||
{
|
// push back node
|
||||||
// leaf - test some objects
|
stack[stackPos].node = back;
|
||||||
int n = tree[node + 1];
|
stack[stackPos].tnear = (tb >= intervalMin) ? tb : intervalMin;
|
||||||
while (n > 0) {
|
stack[stackPos].tfar = intervalMax;
|
||||||
bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit);
|
stackPos++;
|
||||||
if (stopAtFirstHit && hit) return;
|
// update ray interval for front node
|
||||||
--n;
|
intervalMax = (tf <= intervalMax) ? tf : intervalMax;
|
||||||
++offset;
|
continue;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (axis>2)
|
// leaf - test some objects
|
||||||
return; // should not happen
|
int n = tree[node + 1];
|
||||||
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
|
while (n > 0)
|
||||||
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);
|
|
||||||
int offset = tn & ~(7 << 29);
|
|
||||||
if (!BVH2)
|
|
||||||
{
|
|
||||||
if (axis < 3)
|
|
||||||
{
|
{
|
||||||
// "normal" interior node
|
bool hit = intersectCallback(r, objects[offset], maxDist, stopAtFirstHit);
|
||||||
float tl = intBitsToFloat(tree[node + 1]);
|
if (stopAtFirstHit && hit) return;
|
||||||
float tr = intBitsToFloat(tree[node + 2]);
|
--n;
|
||||||
// point is between clip zones
|
++offset;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else // BVH2 node (empty space cut off left and right)
|
}
|
||||||
{
|
else
|
||||||
if (axis>2)
|
{
|
||||||
return; // should not happen
|
if (axis > 2)
|
||||||
float tl = intBitsToFloat(tree[node + 1]);
|
return; // should not happen
|
||||||
float tr = intBitsToFloat(tree[node + 2]);
|
float tf = (intBitsToFloat(tree[node + offsetFront[axis]]) - org[axis]) * invDir[axis];
|
||||||
node = offset;
|
float tb = (intBitsToFloat(tree[node + offsetBack[axis]]) - org[axis]) * invDir[axis];
|
||||||
if (tl > p[axis] || tr < p[axis])
|
node = offset;
|
||||||
break;
|
intervalMin = (tf >= intervalMin) ? tf : intervalMin;
|
||||||
continue;
|
intervalMax = (tb <= intervalMax) ? tb : intervalMax;
|
||||||
}
|
if (intervalMin > intervalMax)
|
||||||
} // traversal loop
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} // traversal loop
|
||||||
|
do
|
||||||
|
{
|
||||||
// stack is empty?
|
// stack is empty?
|
||||||
if (stackPos == 0)
|
if (stackPos == 0)
|
||||||
return;
|
return;
|
||||||
// move back up the stack
|
// move back up the stack
|
||||||
stackPos--;
|
stackPos--;
|
||||||
|
intervalMin = stack[stackPos].tnear;
|
||||||
|
if (maxDist < intervalMin)
|
||||||
|
continue;
|
||||||
node = stack[stackPos].node;
|
node = stack[stackPos].node;
|
||||||
}
|
intervalMax = stack[stackPos].tfar;
|
||||||
|
break;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool writeToFile(FILE* wf) const;
|
template<typename IsectCallback>
|
||||||
bool readFromFile(FILE* rf);
|
void intersectPoint(const G3D::Vector3& p, IsectCallback& intersectCallback) const
|
||||||
|
{
|
||||||
|
if (!bounds.contains(p))
|
||||||
|
return;
|
||||||
|
|
||||||
protected:
|
StackNode stack[MAX_STACK_SIZE];
|
||||||
std::vector<uint32> tree;
|
int stackPos = 0;
|
||||||
std::vector<uint32> objects;
|
int node = 0;
|
||||||
G3D::AABox bounds;
|
|
||||||
|
|
||||||
struct buildData
|
while (true)
|
||||||
{
|
{
|
||||||
uint32 *indices;
|
while (true)
|
||||||
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;
|
uint32 tn = tree[node];
|
||||||
}
|
uint32 axis = (tn & (3 << 30)) >> 30;
|
||||||
|
bool BVH2 = tn & (1 << 29);
|
||||||
|
int offset = tn & ~(7 << 29);
|
||||||
|
if (!BVH2)
|
||||||
|
{
|
||||||
|
if (axis < 3)
|
||||||
|
{
|
||||||
|
// "normal" interior node
|
||||||
|
float tl = intBitsToFloat(tree[node + 1]);
|
||||||
|
float tr = intBitsToFloat(tree[node + 2]);
|
||||||
|
// point is between clip zones
|
||||||
|
if (tl < p[axis] && tr > p[axis])
|
||||||
|
break;
|
||||||
|
int right = offset + 3;
|
||||||
|
node = right;
|
||||||
|
// point is in right node only
|
||||||
|
if (tl < p[axis])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
node = offset; // left
|
||||||
|
// point is in left node only
|
||||||
|
if (tr > p[axis])
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// point is in both nodes
|
||||||
|
// push back right node
|
||||||
|
stack[stackPos].node = right;
|
||||||
|
stackPos++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// leaf - test some objects
|
||||||
|
int n = tree[node + 1];
|
||||||
|
while (n > 0)
|
||||||
|
{
|
||||||
|
intersectCallback(p, objects[offset]); // !!!
|
||||||
|
--n;
|
||||||
|
++offset;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // BVH2 node (empty space cut off left and right)
|
||||||
|
{
|
||||||
|
if (axis > 2)
|
||||||
|
return; // should not happen
|
||||||
|
float tl = intBitsToFloat(tree[node + 1]);
|
||||||
|
float tr = intBitsToFloat(tree[node + 2]);
|
||||||
|
node = offset;
|
||||||
|
if (tl > p[axis] || tr < p[axis])
|
||||||
|
break;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} // traversal loop
|
||||||
|
|
||||||
void updateInner() { numNodes++; }
|
// stack is empty?
|
||||||
void updateBVH2() { numBVH2++; }
|
if (stackPos == 0)
|
||||||
void updateLeaf(int depth, int n);
|
return;
|
||||||
void printStats();
|
// move back up the stack
|
||||||
};
|
stackPos--;
|
||||||
|
node = stack[stackPos].node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void buildHierarchy(std::vector<uint32> &tempTree, buildData &dat, BuildStats &stats);
|
bool writeToFile(FILE* wf) const;
|
||||||
|
bool readFromFile(FILE* rf);
|
||||||
|
|
||||||
void createNode(std::vector<uint32> &tempTree, int nodeIndex, uint32 left, uint32 right) const
|
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)
|
||||||
{
|
{
|
||||||
// write leaf node
|
for (int i = 0; i < 6; ++i) numLeavesN[i] = 0;
|
||||||
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);
|
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
|
#endif // _BIH_H
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
{
|
{
|
||||||
++unbalanced_times;
|
++unbalanced_times;
|
||||||
uint32 Idx = 0;
|
uint32 Idx = 0;
|
||||||
const T * temp;
|
const T* temp;
|
||||||
if (m_obj2Idx.getRemove(&obj, temp, Idx))
|
if (m_obj2Idx.getRemove(&obj, temp, Idx))
|
||||||
m_objects[Idx] = NULL;
|
m_objects[Idx] = NULL;
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -21,21 +21,25 @@
|
|||||||
|
|
||||||
using VMAP::ModelInstance;
|
using VMAP::ModelInstance;
|
||||||
|
|
||||||
namespace {
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
int CHECK_TREE_PERIOD = 200;
|
int CHECK_TREE_PERIOD = 200;
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
template<> struct HashTrait< GameObjectModel>{
|
template<> struct HashTrait< GameObjectModel>
|
||||||
|
{
|
||||||
static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; }
|
static size_t hashCode(const GameObjectModel& g) { return (size_t)(void*)&g; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct PositionTrait< GameObjectModel> {
|
template<> struct PositionTrait< GameObjectModel>
|
||||||
|
{
|
||||||
static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); }
|
static void getPosition(const GameObjectModel& g, G3D::Vector3& p) { p = g.getPosition(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct BoundsTrait< GameObjectModel> {
|
template<> struct BoundsTrait< GameObjectModel>
|
||||||
|
{
|
||||||
static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();}
|
static void getBounds(const GameObjectModel& g, G3D::AABox& out) { out = g.getBounds();}
|
||||||
static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();}
|
static void getBounds2(const GameObjectModel* g, G3D::AABox& out) { out = g->getBounds();}
|
||||||
};
|
};
|
||||||
@@ -148,7 +152,7 @@ struct DynamicTreeIntersectionCallback
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
|
bool DynamicMapTree::getIntersectionTime(const uint32 phasemask, const G3D::Ray& ray,
|
||||||
const G3D::Vector3& endPos, float& maxDist) const
|
const G3D::Vector3& endPos, float& maxDist) const
|
||||||
{
|
{
|
||||||
float distance = maxDist;
|
float distance = maxDist;
|
||||||
DynamicTreeIntersectionCallback callback(phasemask);
|
DynamicTreeIntersectionCallback callback(phasemask);
|
||||||
@@ -172,7 +176,7 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3&
|
|||||||
resultHit = endPos;
|
resultHit = endPos;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
G3D::Vector3 dir = (endPos - startPos)/maxDist; // direction with length of 1
|
G3D::Vector3 dir = (endPos - startPos) / maxDist; // direction with length of 1
|
||||||
G3D::Ray ray(startPos, dir);
|
G3D::Ray ray(startPos, dir);
|
||||||
float dist = maxDist;
|
float dist = maxDist;
|
||||||
if (getIntersectionTime(phasemask, ray, endPos, dist))
|
if (getIntersectionTime(phasemask, ray, endPos, dist))
|
||||||
@@ -181,12 +185,12 @@ bool DynamicMapTree::getObjectHitPos(const uint32 phasemask, const G3D::Vector3&
|
|||||||
if (modifyDist < 0)
|
if (modifyDist < 0)
|
||||||
{
|
{
|
||||||
if ((resultHit - startPos).magnitude() > -modifyDist)
|
if ((resultHit - startPos).magnitude() > -modifyDist)
|
||||||
resultHit = resultHit + dir*modifyDist;
|
resultHit = resultHit + dir * modifyDist;
|
||||||
else
|
else
|
||||||
resultHit = startPos;
|
resultHit = startPos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
resultHit = resultHit + dir*modifyDist;
|
resultHit = resultHit + dir * modifyDist;
|
||||||
|
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@@ -207,7 +211,7 @@ bool DynamicMapTree::isInLineOfSight(float x1, float y1, float z1, float x2, flo
|
|||||||
if (!G3D::fuzzyGt(maxDist, 0) )
|
if (!G3D::fuzzyGt(maxDist, 0) )
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
G3D::Ray r(v1, (v2-v1) / maxDist);
|
G3D::Ray r(v1, (v2 - v1) / maxDist);
|
||||||
DynamicTreeIntersectionCallback callback(phasemask);
|
DynamicTreeIntersectionCallback callback(phasemask);
|
||||||
impl->intersectRay(r, callback, maxDist, v2, true);
|
impl->intersectRay(r, callback, maxDist, v2, true);
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ struct DynTreeImpl;
|
|||||||
|
|
||||||
class DynamicMapTree
|
class DynamicMapTree
|
||||||
{
|
{
|
||||||
DynTreeImpl *impl;
|
DynTreeImpl* impl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -22,16 +22,16 @@ namespace MMAP
|
|||||||
|
|
||||||
class IMMapManager
|
class IMMapManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool iEnablePathFinding;
|
bool iEnablePathFinding;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IMMapManager() : iEnablePathFinding(true) {}
|
IMMapManager() : iEnablePathFinding(true) {}
|
||||||
virtual ~IMMapManager(void) {}
|
virtual ~IMMapManager(void) {}
|
||||||
|
|
||||||
//Enabled/Disabled Pathfinding
|
//Enabled/Disabled Pathfinding
|
||||||
void setEnablePathFinding(bool value) { iEnablePathFinding = value; }
|
void setEnablePathFinding(bool value) { iEnablePathFinding = value; }
|
||||||
bool isEnablePathFinding() const { return (iEnablePathFinding); }
|
bool isEnablePathFinding() const { return (iEnablePathFinding); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,62 +26,62 @@ namespace VMAP
|
|||||||
VMAP_LOAD_RESULT_IGNORED
|
VMAP_LOAD_RESULT_IGNORED
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VMAP_INVALID_HEIGHT -100000.0f // for check
|
#define VMAP_INVALID_HEIGHT -100000.0f // for check
|
||||||
#define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case
|
#define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case
|
||||||
|
|
||||||
//===========================================================
|
//===========================================================
|
||||||
class IVMapManager
|
class IVMapManager
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
bool iEnableLineOfSightCalc;
|
bool iEnableLineOfSightCalc;
|
||||||
bool iEnableHeightCalc;
|
bool iEnableHeightCalc;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) { }
|
IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) { }
|
||||||
|
|
||||||
virtual ~IVMapManager(void) { }
|
virtual ~IVMapManager(void) { }
|
||||||
|
|
||||||
virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
|
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 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, int x, int y) = 0;
|
||||||
virtual void unloadMap(unsigned int pMapId) = 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 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;
|
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
|
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
|
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;
|
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
|
send debug commands
|
||||||
*/
|
*/
|
||||||
virtual bool processCommand(char *pCommand)= 0;
|
virtual bool processCommand(char* pCommand) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Enable/disable LOS calculation
|
Enable/disable LOS calculation
|
||||||
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
|
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
|
||||||
*/
|
*/
|
||||||
void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; }
|
void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; }
|
||||||
/**
|
/**
|
||||||
Enable/disable model height calculation
|
Enable/disable model height calculation
|
||||||
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
|
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
|
||||||
*/
|
*/
|
||||||
void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; }
|
void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; }
|
||||||
|
|
||||||
bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); }
|
bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); }
|
||||||
bool isHeightCalcEnabled() const { return(iEnableHeightCalc); }
|
bool isHeightCalcEnabled() const { return(iEnableHeightCalc); }
|
||||||
bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); }
|
bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); }
|
||||||
|
|
||||||
virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0;
|
virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const = 0;
|
||||||
/**
|
/**
|
||||||
Query world model area info.
|
Query world model area info.
|
||||||
\param z gets adjusted to the ground height for which this are info is valid
|
\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 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;
|
virtual bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 ReqLiquidType, float& level, float& floor, uint32& type) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace MMAP
|
|||||||
{
|
{
|
||||||
// ######################## MMapFactory ########################
|
// ######################## MMapFactory ########################
|
||||||
// our global singleton copy
|
// our global singleton copy
|
||||||
MMapManager *g_MMapManager = NULL;
|
MMapManager* g_MMapManager = NULL;
|
||||||
bool MMapFactory::forbiddenMaps[1000] = {0};
|
bool MMapFactory::forbiddenMaps[1000] = {0};
|
||||||
|
|
||||||
MMapManager* MMapFactory::createOrGetMMapManager()
|
MMapManager* MMapFactory::createOrGetMMapManager()
|
||||||
|
|||||||
@@ -28,12 +28,12 @@ namespace MMAP
|
|||||||
// access point to MMapManager singleton
|
// access point to MMapManager singleton
|
||||||
class MMapFactory
|
class MMapFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static MMapManager* createOrGetMMapManager();
|
static MMapManager* createOrGetMMapManager();
|
||||||
static void clear();
|
static void clear();
|
||||||
static bool IsPathfindingEnabled(const Map* map);
|
static bool IsPathfindingEnabled(const Map* map);
|
||||||
static void InitializeDisabledMaps();
|
static void InitializeDisabledMaps();
|
||||||
static bool forbiddenMaps[1000];
|
static bool forbiddenMaps[1000];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,9 @@ namespace MMAP
|
|||||||
return true;
|
return true;
|
||||||
|
|
||||||
// load and init dtNavMesh - read parameters from file
|
// load and init dtNavMesh - read parameters from file
|
||||||
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap")+1;
|
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i.mmap") + 1;
|
||||||
char *fileName = new char[pathLen];
|
char* fileName = new char[pathLen];
|
||||||
snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i.mmap").c_str(), mapId);
|
snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i.mmap").c_str(), mapId);
|
||||||
|
|
||||||
FILE* file = fopen(fileName, "rb");
|
FILE* file = fopen(fileName, "rb");
|
||||||
if (!file)
|
if (!file)
|
||||||
@@ -112,11 +112,11 @@ namespace MMAP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// load this tile :: mmaps/MMMXXYY.mmtile
|
// load this tile :: mmaps/MMMXXYY.mmtile
|
||||||
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile")+1;
|
uint32 pathLen = sWorld->GetDataPath().length() + strlen("mmaps/%03i%02i%02i.mmtile") + 1;
|
||||||
char *fileName = new char[pathLen];
|
char* fileName = new char[pathLen];
|
||||||
snprintf(fileName, pathLen, (sWorld->GetDataPath()+"mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
|
snprintf(fileName, pathLen, (sWorld->GetDataPath() + "mmaps/%03i%02i%02i.mmtile").c_str(), mapId, x, y);
|
||||||
|
|
||||||
FILE *file = fopen(fileName, "rb");
|
FILE* file = fopen(fileName, "rb");
|
||||||
if (!file)
|
if (!file)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||||
@@ -139,7 +139,7 @@ namespace MMAP
|
|||||||
if (fileHeader.mmapVersion != MMAP_VERSION)
|
if (fileHeader.mmapVersion != MMAP_VERSION)
|
||||||
{
|
{
|
||||||
sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
|
sLog->outError("MMAP:loadMap: %03u%02i%02i.mmtile was built with generator v%i, expected v%i",
|
||||||
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
|
mapId, x, y, fileHeader.mmapVersion, MMAP_VERSION);
|
||||||
fclose(file);
|
fclose(file);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -345,26 +345,26 @@ namespace MMAP
|
|||||||
MMapData* mmap = loadedMMaps[mapId];
|
MMapData* mmap = loadedMMaps[mapId];
|
||||||
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
||||||
{
|
{
|
||||||
// pussywizard: different instances of the same map shouldn't access this simultaneously
|
// pussywizard: different instances of the same map shouldn't access this simultaneously
|
||||||
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
|
ACORE_WRITE_GUARD(ACE_RW_Thread_Mutex, GetMMapLock(mapId));
|
||||||
// check again after acquiring mutex
|
// check again after acquiring mutex
|
||||||
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
if (mmap->navMeshQueries.find(instanceId) == mmap->navMeshQueries.end())
|
||||||
{
|
|
||||||
// allocate mesh query
|
|
||||||
dtNavMeshQuery* query = dtAllocNavMeshQuery();
|
|
||||||
ASSERT(query);
|
|
||||||
if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
|
|
||||||
{
|
{
|
||||||
dtFreeNavMeshQuery(query);
|
// allocate mesh query
|
||||||
sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
dtNavMeshQuery* query = dtAllocNavMeshQuery();
|
||||||
return NULL;
|
ASSERT(query);
|
||||||
}
|
if (DT_SUCCESS != query->init(mmap->navMesh, 1024))
|
||||||
|
{
|
||||||
|
dtFreeNavMeshQuery(query);
|
||||||
|
sLog->outError("MMAP:GetNavMeshQuery: Failed to initialize dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
|
||||||
sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
sLog->outDetail("MMAP:GetNavMeshQuery: created dtNavMeshQuery for mapId %03u instanceId %u", mapId, instanceId);
|
||||||
#endif
|
#endif
|
||||||
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
|
mmap->navMeshQueries.insert(std::pair<uint32, dtNavMeshQuery*>(instanceId, query));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return mmap->navMeshQueries[instanceId];
|
return mmap->navMeshQueries[instanceId];
|
||||||
|
|||||||
@@ -57,34 +57,34 @@ namespace MMAP
|
|||||||
// holds all all access to mmap loading unloading and meshes
|
// holds all all access to mmap loading unloading and meshes
|
||||||
class MMapManager
|
class MMapManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MMapManager() : loadedTiles(0) {}
|
MMapManager() : loadedTiles(0) {}
|
||||||
~MMapManager();
|
~MMapManager();
|
||||||
|
|
||||||
bool loadMap(uint32 mapId, int32 x, int32 y);
|
bool loadMap(uint32 mapId, int32 x, int32 y);
|
||||||
bool unloadMap(uint32 mapId, int32 x, int32 y);
|
bool unloadMap(uint32 mapId, int32 x, int32 y);
|
||||||
bool unloadMap(uint32 mapId);
|
bool unloadMap(uint32 mapId);
|
||||||
bool unloadMapInstance(uint32 mapId, uint32 instanceId);
|
bool unloadMapInstance(uint32 mapId, uint32 instanceId);
|
||||||
|
|
||||||
// the returned [dtNavMeshQuery const*] is NOT threadsafe
|
// the returned [dtNavMeshQuery const*] is NOT threadsafe
|
||||||
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
|
dtNavMeshQuery const* GetNavMeshQuery(uint32 mapId, uint32 instanceId);
|
||||||
dtNavMesh const* GetNavMesh(uint32 mapId);
|
dtNavMesh const* GetNavMesh(uint32 mapId);
|
||||||
|
|
||||||
uint32 getLoadedTilesCount() const { return loadedTiles; }
|
uint32 getLoadedTilesCount() const { return loadedTiles; }
|
||||||
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
|
uint32 getLoadedMapsCount() const { return loadedMMaps.size(); }
|
||||||
|
|
||||||
ACE_RW_Thread_Mutex& GetMMapLock(uint32 mapId);
|
ACE_RW_Thread_Mutex& GetMMapLock(uint32 mapId);
|
||||||
ACE_RW_Thread_Mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen
|
ACE_RW_Thread_Mutex& GetMMapGeneralLock() { return MMapLock; } // pussywizard: in case a per-map mutex can't be found, should never happen
|
||||||
ACE_RW_Thread_Mutex& GetManagerLock() { return MMapManagerLock; }
|
ACE_RW_Thread_Mutex& GetManagerLock() { return MMapManagerLock; }
|
||||||
private:
|
private:
|
||||||
bool loadMapData(uint32 mapId);
|
bool loadMapData(uint32 mapId);
|
||||||
uint32 packTileID(int32 x, int32 y);
|
uint32 packTileID(int32 x, int32 y);
|
||||||
|
|
||||||
MMapDataSet loadedMMaps;
|
MMapDataSet loadedMMaps;
|
||||||
uint32 loadedTiles;
|
uint32 loadedTiles;
|
||||||
|
|
||||||
ACE_RW_Thread_Mutex MMapManagerLock;
|
ACE_RW_Thread_Mutex MMapManagerLock;
|
||||||
ACE_RW_Thread_Mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen
|
ACE_RW_Thread_Mutex MMapLock; // pussywizard: in case a per-map mutex can't be found, should never happen
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace VMAP
|
|||||||
IVMapManager* VMapFactory::createOrGetVMapManager()
|
IVMapManager* VMapFactory::createOrGetVMapManager()
|
||||||
{
|
{
|
||||||
if (gVMapManager == 0)
|
if (gVMapManager == 0)
|
||||||
gVMapManager= new VMapManager2(); // should be taken from config ... Please change if you like :-)
|
gVMapManager = new VMapManager2(); // should be taken from config ... Please change if you like :-)
|
||||||
return gVMapManager;
|
return gVMapManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,9 @@ namespace VMAP
|
|||||||
|
|
||||||
class VMapFactory
|
class VMapFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static IVMapManager* createOrGetVMapManager();
|
static IVMapManager* createOrGetVMapManager();
|
||||||
static void clear();
|
static void clear();
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,10 +95,10 @@ namespace VMAP
|
|||||||
std::string mapFileName = getMapFileName(mapId);
|
std::string mapFileName = getMapFileName(mapId);
|
||||||
StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
|
StaticMapTree* newTree = new StaticMapTree(mapId, basePath);
|
||||||
if (!newTree->InitMap(mapFileName, this))
|
if (!newTree->InitMap(mapFileName, this))
|
||||||
{
|
{
|
||||||
delete newTree;
|
delete newTree;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first;
|
instanceTree = iInstanceMapTrees.insert(InstanceTreeMap::value_type(mapId, newTree)).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ namespace VMAP
|
|||||||
get the hit position and return true if we hit something
|
get the hit position and return true if we hit something
|
||||||
otherwise the result pos will be the dest pos
|
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)
|
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 defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_VMAP_CHECKS)
|
||||||
if (isLineOfSightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS))
|
if (isLineOfSightCalcEnabled() && !DisableMgr::IsDisabledFor(DISABLE_TYPE_VMAP, mapId, NULL, VMAP_DISABLE_LOS))
|
||||||
@@ -283,7 +283,7 @@ namespace VMAP
|
|||||||
return model->second.getModel();
|
return model->second.getModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VMapManager2::releaseModelInstance(const std::string &filename)
|
void VMapManager2::releaseModelInstance(const std::string& filename)
|
||||||
{
|
{
|
||||||
//! Critical section, thread safe access to iLoadedModelFiles
|
//! Critical section, thread safe access to iLoadedModelFiles
|
||||||
ACORE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
|
ACORE_GUARD(ACE_Thread_Mutex, LoadedModelFilesLock);
|
||||||
|
|||||||
@@ -51,15 +51,15 @@ namespace VMAP
|
|||||||
|
|
||||||
class ManagedModel
|
class ManagedModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ManagedModel() : iModel(0), iRefCount(0) { }
|
ManagedModel() : iModel(0), iRefCount(0) { }
|
||||||
void setModel(WorldModel* model) { iModel = model; }
|
void setModel(WorldModel* model) { iModel = model; }
|
||||||
WorldModel* getModel() { return iModel; }
|
WorldModel* getModel() { return iModel; }
|
||||||
void incRefCount() { ++iRefCount; }
|
void incRefCount() { ++iRefCount; }
|
||||||
int decRefCount() { return --iRefCount; }
|
int decRefCount() { return --iRefCount; }
|
||||||
protected:
|
protected:
|
||||||
WorldModel* iModel;
|
WorldModel* iModel;
|
||||||
int iRefCount;
|
int iRefCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap;
|
typedef std::unordered_map<uint32, StaticMapTree*> InstanceTreeMap;
|
||||||
@@ -67,57 +67,57 @@ namespace VMAP
|
|||||||
|
|
||||||
class VMapManager2 : public IVMapManager
|
class VMapManager2 : public IVMapManager
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
// Tree to check collision
|
// Tree to check collision
|
||||||
ModelFileMap iLoadedModelFiles;
|
ModelFileMap iLoadedModelFiles;
|
||||||
InstanceTreeMap iInstanceMapTrees;
|
InstanceTreeMap iInstanceMapTrees;
|
||||||
// Mutex for iLoadedModelFiles
|
// Mutex for iLoadedModelFiles
|
||||||
ACE_Thread_Mutex LoadedModelFilesLock;
|
ACE_Thread_Mutex LoadedModelFilesLock;
|
||||||
|
|
||||||
bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY);
|
bool _loadMap(uint32 mapId, const std::string& basePath, uint32 tileX, uint32 tileY);
|
||||||
/* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
|
/* void _unloadMap(uint32 pMapId, uint32 x, uint32 y); */
|
||||||
|
|
||||||
static uint32 GetLiquidFlagsDummy(uint32) { return 0; }
|
static uint32 GetLiquidFlagsDummy(uint32) { return 0; }
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// public for debug
|
// public for debug
|
||||||
G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const;
|
G3D::Vector3 convertPositionToInternalRep(float x, float y, float z) const;
|
||||||
static std::string getMapFileName(unsigned int mapId);
|
static std::string getMapFileName(unsigned int mapId);
|
||||||
|
|
||||||
VMapManager2();
|
VMapManager2();
|
||||||
~VMapManager2(void);
|
~VMapManager2(void);
|
||||||
|
|
||||||
int loadMap(const char* pBasePath, unsigned int mapId, int x, int y);
|
int loadMap(const char* pBasePath, unsigned int mapId, int x, int y);
|
||||||
|
|
||||||
void unloadMap(unsigned int mapId, int x, int y);
|
void unloadMap(unsigned int mapId, int x, int y);
|
||||||
void unloadMap(unsigned int mapId);
|
void unloadMap(unsigned int mapId);
|
||||||
|
|
||||||
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) ;
|
bool isInLineOfSight(unsigned int mapId, float x1, float y1, float z1, float x2, float y2, float z2) ;
|
||||||
/**
|
/**
|
||||||
fill the hit pos and return true, if an object was hit
|
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);
|
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);
|
||||||
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist);
|
float getHeight(unsigned int mapId, float x, float y, float z, float maxSearchDist);
|
||||||
|
|
||||||
bool processCommand(char* /*command*/) { return false; } // for debug and extensions
|
bool processCommand(char* /*command*/) { 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;
|
bool getAreaInfo(unsigned int pMapId, float x, float y, float& z, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const;
|
||||||
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const;
|
bool GetLiquidLevel(uint32 pMapId, float x, float y, float z, uint8 reqLiquidType, float& level, float& floor, uint32& type) const;
|
||||||
|
|
||||||
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
|
WorldModel* acquireModelInstance(const std::string& basepath, const std::string& filename);
|
||||||
void releaseModelInstance(const std::string& filename);
|
void releaseModelInstance(const std::string& filename);
|
||||||
|
|
||||||
// what's the use of this? o.O
|
// what's the use of this? o.O
|
||||||
virtual std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const
|
virtual std::string getDirFileName(unsigned int mapId, int /*x*/, int /*y*/) const
|
||||||
{
|
{
|
||||||
return getMapFileName(mapId);
|
return getMapFileName(mapId);
|
||||||
}
|
}
|
||||||
virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y);
|
virtual bool existsMap(const char* basePath, unsigned int mapId, int x, int y);
|
||||||
public:
|
public:
|
||||||
void getInstanceMapTree(InstanceTreeMap &instanceMapTree);
|
void getInstanceMapTree(InstanceTreeMap& instanceMapTree);
|
||||||
|
|
||||||
typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType);
|
typedef uint32(*GetLiquidFlagsFn)(uint32 liquidType);
|
||||||
GetLiquidFlagsFn GetLiquidFlagsPtr;
|
GetLiquidFlagsFn GetLiquidFlagsPtr;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,15 +23,15 @@ namespace VMAP
|
|||||||
|
|
||||||
class MapRayCallback
|
class MapRayCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MapRayCallback(ModelInstance* val): prims(val), hit(false) {}
|
MapRayCallback(ModelInstance* val): prims(val), hit(false) {}
|
||||||
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
|
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
|
||||||
{
|
{
|
||||||
bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit);
|
bool result = prims[entry].intersectRay(ray, distance, StopAtFirstHit);
|
||||||
if (result)
|
if (result)
|
||||||
hit = true;
|
hit = true;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
bool didHit() { return hit; }
|
bool didHit() { return hit; }
|
||||||
protected:
|
protected:
|
||||||
ModelInstance* prims;
|
ModelInstance* prims;
|
||||||
@@ -40,36 +40,36 @@ namespace VMAP
|
|||||||
|
|
||||||
class AreaInfoCallback
|
class AreaInfoCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AreaInfoCallback(ModelInstance* val): prims(val) {}
|
AreaInfoCallback(ModelInstance* val): prims(val) {}
|
||||||
void operator()(const Vector3& point, uint32 entry)
|
void operator()(const Vector3& point, uint32 entry)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
||||||
sLog->outDebug(LOG_FILTER_MAPS, "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
sLog->outDebug(LOG_FILTER_MAPS, "AreaInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
||||||
#endif
|
#endif
|
||||||
prims[entry].intersectPoint(point, aInfo);
|
prims[entry].intersectPoint(point, aInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelInstance* prims;
|
ModelInstance* prims;
|
||||||
AreaInfo aInfo;
|
AreaInfo aInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LocationInfoCallback
|
class LocationInfoCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
LocationInfoCallback(ModelInstance* val, LocationInfo &info): prims(val), locInfo(info), result(false) {}
|
LocationInfoCallback(ModelInstance* val, LocationInfo& info): prims(val), locInfo(info), result(false) {}
|
||||||
void operator()(const Vector3& point, uint32 entry)
|
void operator()(const Vector3& point, uint32 entry)
|
||||||
{
|
{
|
||||||
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS) && defined(VMAP_DEBUG)
|
||||||
sLog->outDebug(LOG_FILTER_MAPS, "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
sLog->outDebug(LOG_FILTER_MAPS, "LocationInfoCallback: trying to intersect '%s'", prims[entry].name.c_str());
|
||||||
#endif
|
#endif
|
||||||
if (prims[entry].GetLocationInfo(point, locInfo))
|
if (prims[entry].GetLocationInfo(point, locInfo))
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelInstance* prims;
|
ModelInstance* prims;
|
||||||
LocationInfo &locInfo;
|
LocationInfo& locInfo;
|
||||||
bool result;
|
bool result;
|
||||||
};
|
};
|
||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
@@ -84,7 +84,7 @@ namespace VMAP
|
|||||||
return tilefilename.str();
|
return tilefilename.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StaticMapTree::getAreaInfo(Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) const
|
bool StaticMapTree::getAreaInfo(Vector3& pos, uint32& flags, int32& adtId, int32& rootId, int32& groupId) const
|
||||||
{
|
{
|
||||||
AreaInfoCallback intersectionCallBack(iTreeValues);
|
AreaInfoCallback intersectionCallBack(iTreeValues);
|
||||||
iTree.intersectPoint(pos, intersectionCallBack);
|
iTree.intersectPoint(pos, intersectionCallBack);
|
||||||
@@ -100,17 +100,17 @@ namespace VMAP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StaticMapTree::GetLocationInfo(const Vector3 &pos, LocationInfo &info) const
|
bool StaticMapTree::GetLocationInfo(const Vector3& pos, LocationInfo& info) const
|
||||||
{
|
{
|
||||||
LocationInfoCallback intersectionCallBack(iTreeValues, info);
|
LocationInfoCallback intersectionCallBack(iTreeValues, info);
|
||||||
iTree.intersectPoint(pos, intersectionCallBack);
|
iTree.intersectPoint(pos, intersectionCallBack);
|
||||||
return intersectionCallBack.result;
|
return intersectionCallBack.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
StaticMapTree::StaticMapTree(uint32 mapID, const std::string &basePath)
|
StaticMapTree::StaticMapTree(uint32 mapID, const std::string& basePath)
|
||||||
: iMapID(mapID), iIsTiled(false), iTreeValues(0), iBasePath(basePath)
|
: iMapID(mapID), iIsTiled(false), iTreeValues(0), iBasePath(basePath)
|
||||||
{
|
{
|
||||||
if (iBasePath.length() > 0 && iBasePath[iBasePath.length()-1] != '/' && iBasePath[iBasePath.length()-1] != '\\')
|
if (iBasePath.length() > 0 && iBasePath[iBasePath.length() - 1] != '/' && iBasePath[iBasePath.length() - 1] != '\\')
|
||||||
{
|
{
|
||||||
iBasePath.push_back('/');
|
iBasePath.push_back('/');
|
||||||
}
|
}
|
||||||
@@ -129,7 +129,7 @@ namespace VMAP
|
|||||||
Else, pMaxDist is not modified and returns false;
|
Else, pMaxDist is not modified and returns false;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool StopAtFirstHit) const
|
bool StaticMapTree::getIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
|
||||||
{
|
{
|
||||||
float distance = pMaxDist;
|
float distance = pMaxDist;
|
||||||
MapRayCallback intersectionCallBack(iTreeValues);
|
MapRayCallback intersectionCallBack(iTreeValues);
|
||||||
@@ -153,7 +153,7 @@ namespace VMAP
|
|||||||
if (maxDist < 1e-10f)
|
if (maxDist < 1e-10f)
|
||||||
return true;
|
return true;
|
||||||
// direction with length of 1
|
// direction with length of 1
|
||||||
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1)/maxDist);
|
G3D::Ray ray = G3D::Ray::fromOriginAndDirection(pos1, (pos2 - pos1) / maxDist);
|
||||||
if (getIntersectionTime(ray, maxDist, true))
|
if (getIntersectionTime(ray, maxDist, true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@@ -167,7 +167,7 @@ namespace VMAP
|
|||||||
|
|
||||||
bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const
|
bool StaticMapTree::getObjectHitPos(const Vector3& pPos1, const Vector3& pPos2, Vector3& pResultHitPos, float pModifyDist) const
|
||||||
{
|
{
|
||||||
bool result=false;
|
bool result = false;
|
||||||
float maxDist = (pPos2 - pPos1).magnitude();
|
float maxDist = (pPos2 - pPos1).magnitude();
|
||||||
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too
|
// valid map coords should *never ever* produce float overflow, but this would produce NaNs too
|
||||||
ASSERT(maxDist < std::numeric_limits<float>::max());
|
ASSERT(maxDist < std::numeric_limits<float>::max());
|
||||||
@@ -177,7 +177,7 @@ namespace VMAP
|
|||||||
pResultHitPos = pPos2;
|
pResultHitPos = pPos2;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
Vector3 dir = (pPos2 - pPos1)/maxDist; // direction with length of 1
|
Vector3 dir = (pPos2 - pPos1) / maxDist; // direction with length of 1
|
||||||
G3D::Ray ray(pPos1, dir);
|
G3D::Ray ray(pPos1, dir);
|
||||||
float dist = maxDist;
|
float dist = maxDist;
|
||||||
if (getIntersectionTime(ray, dist, false))
|
if (getIntersectionTime(ray, dist, false))
|
||||||
@@ -187,7 +187,7 @@ namespace VMAP
|
|||||||
{
|
{
|
||||||
if ((pResultHitPos - pPos1).magnitude() > -pModifyDist)
|
if ((pResultHitPos - pPos1).magnitude() > -pModifyDist)
|
||||||
{
|
{
|
||||||
pResultHitPos = pResultHitPos + dir*pModifyDist;
|
pResultHitPos = pResultHitPos + dir * pModifyDist;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -196,7 +196,7 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pResultHitPos = pResultHitPos + dir*pModifyDist;
|
pResultHitPos = pResultHitPos + dir * pModifyDist;
|
||||||
}
|
}
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
@@ -225,10 +225,10 @@ namespace VMAP
|
|||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
bool StaticMapTree::CanLoadMap(const std::string &vmapPath, uint32 mapID, uint32 tileX, uint32 tileY)
|
bool StaticMapTree::CanLoadMap(const std::string& vmapPath, uint32 mapID, uint32 tileX, uint32 tileY)
|
||||||
{
|
{
|
||||||
std::string basePath = vmapPath;
|
std::string basePath = vmapPath;
|
||||||
if (basePath.length() > 0 && basePath[basePath.length()-1] != '/' && basePath[basePath.length()-1] != '\\')
|
if (basePath.length() > 0 && basePath[basePath.length() - 1] != '/' && basePath[basePath.length() - 1] != '\\')
|
||||||
basePath.push_back('/');
|
basePath.push_back('/');
|
||||||
std::string fullname = basePath + VMapManager2::getMapFileName(mapID);
|
std::string fullname = basePath + VMapManager2::getMapFileName(mapID);
|
||||||
bool success = true;
|
bool success = true;
|
||||||
@@ -262,7 +262,7 @@ namespace VMAP
|
|||||||
|
|
||||||
//=========================================================
|
//=========================================================
|
||||||
|
|
||||||
bool StaticMapTree::InitMap(const std::string &fname, VMapManager2* vm)
|
bool StaticMapTree::InitMap(const std::string& fname, VMapManager2* vm)
|
||||||
{
|
{
|
||||||
//VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str());
|
//VMAP_DEBUG_LOG(LOG_FILTER_MAPS, "StaticMapTree::InitMap() : initializing StaticMapTree '%s'", fname.c_str());
|
||||||
bool success = false;
|
bool success = false;
|
||||||
@@ -275,7 +275,7 @@ namespace VMAP
|
|||||||
char tiled = '\0';
|
char tiled = '\0';
|
||||||
|
|
||||||
if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 &&
|
if (readChunk(rf, chunk, VMAP_MAGIC, 8) && fread(&tiled, sizeof(char), 1, rf) == 1 &&
|
||||||
readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf))
|
readChunk(rf, chunk, "NODE", 4) && iTree.readFromFile(rf))
|
||||||
{
|
{
|
||||||
iNTreeValues = iTree.primCount();
|
iNTreeValues = iTree.primCount();
|
||||||
iTreeValues = new ModelInstance[iNTreeValues];
|
iTreeValues = new ModelInstance[iNTreeValues];
|
||||||
@@ -354,7 +354,7 @@ namespace VMAP
|
|||||||
uint32 numSpawns = 0;
|
uint32 numSpawns = 0;
|
||||||
if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
|
if (result && fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
|
||||||
result = false;
|
result = false;
|
||||||
for (uint32 i=0; i<numSpawns && result; ++i)
|
for (uint32 i = 0; i < numSpawns && result; ++i)
|
||||||
{
|
{
|
||||||
// read model spawns
|
// read model spawns
|
||||||
ModelSpawn spawn;
|
ModelSpawn spawn;
|
||||||
@@ -423,14 +423,14 @@ namespace VMAP
|
|||||||
FILE* tf = fopen(tilefile.c_str(), "rb");
|
FILE* tf = fopen(tilefile.c_str(), "rb");
|
||||||
if (tf)
|
if (tf)
|
||||||
{
|
{
|
||||||
bool result=true;
|
bool result = true;
|
||||||
char chunk[8];
|
char chunk[8];
|
||||||
if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
|
if (!readChunk(tf, chunk, VMAP_MAGIC, 8))
|
||||||
result = false;
|
result = false;
|
||||||
uint32 numSpawns;
|
uint32 numSpawns;
|
||||||
if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
|
if (fread(&numSpawns, sizeof(uint32), 1, tf) != 1)
|
||||||
result = false;
|
result = false;
|
||||||
for (uint32 i=0; i<numSpawns && result; ++i)
|
for (uint32 i = 0; i < numSpawns && result; ++i)
|
||||||
{
|
{
|
||||||
// read model spawns
|
// read model spawns
|
||||||
ModelSpawn spawn;
|
ModelSpawn spawn;
|
||||||
@@ -448,7 +448,7 @@ namespace VMAP
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!iLoadedSpawns.count(referencedNode))
|
if (!iLoadedSpawns.count(referencedNode))
|
||||||
sLog->outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID);
|
sLog->outError("StaticMapTree::UnloadMapTile() : trying to unload non-referenced model '%s' (ID:%u)", spawn.name.c_str(), spawn.ID);
|
||||||
else if (--iLoadedSpawns[referencedNode] == 0)
|
else if (--iLoadedSpawns[referencedNode] == 0)
|
||||||
{
|
{
|
||||||
iTreeValues[referencedNode].setUnloaded();
|
iTreeValues[referencedNode].setUnloaded();
|
||||||
|
|||||||
@@ -29,46 +29,46 @@ namespace VMAP
|
|||||||
{
|
{
|
||||||
typedef std::unordered_map<uint32, bool> loadedTileMap;
|
typedef std::unordered_map<uint32, bool> loadedTileMap;
|
||||||
typedef std::unordered_map<uint32, uint32> loadedSpawnMap;
|
typedef std::unordered_map<uint32, uint32> loadedSpawnMap;
|
||||||
private:
|
private:
|
||||||
uint32 iMapID;
|
uint32 iMapID;
|
||||||
bool iIsTiled;
|
bool iIsTiled;
|
||||||
BIH iTree;
|
BIH iTree;
|
||||||
ModelInstance* iTreeValues; // the tree entries
|
ModelInstance* iTreeValues; // the tree entries
|
||||||
uint32 iNTreeValues;
|
uint32 iNTreeValues;
|
||||||
|
|
||||||
// Store all the map tile idents that are loaded for that map
|
// 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
|
// 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)
|
// empty tiles have no tile file, hence map with bool instead of just a set (consistency check)
|
||||||
loadedTileMap iLoadedTiles;
|
loadedTileMap iLoadedTiles;
|
||||||
// stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors
|
// stores <tree_index, reference_count> to invalidate tree values, unload map, and to be able to report errors
|
||||||
loadedSpawnMap iLoadedSpawns;
|
loadedSpawnMap iLoadedSpawns;
|
||||||
std::string iBasePath;
|
std::string iBasePath;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool getIntersectionTime(const G3D::Ray& pRay, float &pMaxDist, bool StopAtFirstHit) const;
|
bool getIntersectionTime(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
|
||||||
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
|
//bool containsLoadedMapTile(unsigned int pTileIdent) const { return(iLoadedMapTiles.containsKey(pTileIdent)); }
|
||||||
public:
|
public:
|
||||||
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
|
static std::string getTileFileName(uint32 mapID, uint32 tileX, uint32 tileY);
|
||||||
static uint32 packTileID(uint32 tileX, uint32 tileY) { return tileX<<16 | 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 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);
|
static bool CanLoadMap(const std::string& basePath, uint32 mapID, uint32 tileX, uint32 tileY);
|
||||||
|
|
||||||
StaticMapTree(uint32 mapID, const std::string &basePath);
|
StaticMapTree(uint32 mapID, const std::string& basePath);
|
||||||
~StaticMapTree();
|
~StaticMapTree();
|
||||||
|
|
||||||
bool isInLineOfSight(const G3D::Vector3& pos1, const G3D::Vector3& pos2) const;
|
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;
|
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;
|
float getHeight(const G3D::Vector3& pPos, float maxSearchDist) const;
|
||||||
bool getAreaInfo(G3D::Vector3 &pos, uint32 &flags, int32 &adtId, int32 &rootId, int32 &groupId) 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 GetLocationInfo(const G3D::Vector3& pos, LocationInfo& info) const;
|
||||||
|
|
||||||
bool InitMap(const std::string &fname, VMapManager2* vm);
|
bool InitMap(const std::string& fname, VMapManager2* vm);
|
||||||
void UnloadMap(VMapManager2* vm);
|
void UnloadMap(VMapManager2* vm);
|
||||||
bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm);
|
bool LoadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm);
|
||||||
void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm);
|
void UnloadMapTile(uint32 tileX, uint32 tileY, VMapManager2* vm);
|
||||||
bool isTiled() const { return iIsTiled; }
|
bool isTiled() const { return iIsTiled; }
|
||||||
uint32 numLoadedTiles() const { return iLoadedTiles.size(); }
|
uint32 numLoadedTiles() const { return iLoadedTiles.size(); }
|
||||||
void getModelInstances(ModelInstance* &models, uint32 &count);
|
void getModelInstances(ModelInstance*& models, uint32& count);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct AreaInfo
|
struct AreaInfo
|
||||||
|
|||||||
@@ -22,12 +22,12 @@ using std::pair;
|
|||||||
|
|
||||||
template<> struct BoundsTrait<VMAP::ModelSpawn*>
|
template<> struct BoundsTrait<VMAP::ModelSpawn*>
|
||||||
{
|
{
|
||||||
static void getBounds(const VMAP::ModelSpawn* const &obj, G3D::AABox& out) { out = obj->getBounds(); }
|
static void getBounds(const VMAP::ModelSpawn* const& obj, G3D::AABox& out) { out = obj->getBounds(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace VMAP
|
namespace VMAP
|
||||||
{
|
{
|
||||||
bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len)
|
bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len)
|
||||||
{
|
{
|
||||||
if (fread(dest, sizeof(char), len, rf) != len) return false;
|
if (fread(dest, sizeof(char), len, rf) != len) return false;
|
||||||
return memcmp(dest, compare, len) == 0;
|
return memcmp(dest, compare, len) == 0;
|
||||||
@@ -79,7 +79,7 @@ namespace VMAP
|
|||||||
{
|
{
|
||||||
/// @todo remove extractor hack and uncomment below line:
|
/// @todo remove extractor hack and uncomment below line:
|
||||||
//entry->second.iPos += Vector3(533.33333f*32, 533.33333f*32, 0.f);
|
//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);
|
entry->second.iBound = entry->second.iBound + Vector3(533.33333f * 32, 533.33333f * 32, 0.f);
|
||||||
}
|
}
|
||||||
mapSpawns.push_back(&(entry->second));
|
mapSpawns.push_back(&(entry->second));
|
||||||
spawnedModelFiles.insert(entry->second.name);
|
spawnedModelFiles.insert(entry->second.name);
|
||||||
@@ -100,7 +100,7 @@ namespace VMAP
|
|||||||
|
|
||||||
// ===> possibly move this code to StaticMapTree class
|
// ===> possibly move this code to StaticMapTree class
|
||||||
std::map<uint32, uint32> modelNodeIdx;
|
std::map<uint32, uint32> modelNodeIdx;
|
||||||
for (uint32 i=0; i<mapSpawns.size(); ++i)
|
for (uint32 i = 0; i < mapSpawns.size(); ++i)
|
||||||
modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i));
|
modelNodeIdx.insert(pair<uint32, uint32>(mapSpawns[i]->ID, i));
|
||||||
|
|
||||||
// write map tree file
|
// write map tree file
|
||||||
@@ -126,7 +126,7 @@ namespace VMAP
|
|||||||
// global map spawns (WDT), if any (most instances)
|
// global map spawns (WDT), if any (most instances)
|
||||||
if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false;
|
if (success && fwrite("GOBJ", 4, 1, mapfile) != 1) success = false;
|
||||||
|
|
||||||
for (TileMap::iterator glob=globalRange.first; glob != globalRange.second && success; ++glob)
|
for (TileMap::iterator glob = globalRange.first; glob != globalRange.second && success; ++glob)
|
||||||
{
|
{
|
||||||
success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]);
|
success = ModelSpawn::writeToFile(mapfile, map_iter->second->UniqueEntries[glob->second]);
|
||||||
}
|
}
|
||||||
@@ -136,11 +136,11 @@ namespace VMAP
|
|||||||
// <====
|
// <====
|
||||||
|
|
||||||
// write map tile files, similar to ADT files, only with extra BSP tree node info
|
// write map tile files, similar to ADT files, only with extra BSP tree node info
|
||||||
TileMap &tileEntries = map_iter->second->TileEntries;
|
TileMap& tileEntries = map_iter->second->TileEntries;
|
||||||
TileMap::iterator tile;
|
TileMap::iterator tile;
|
||||||
for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile)
|
for (tile = tileEntries.begin(); tile != tileEntries.end(); ++tile)
|
||||||
{
|
{
|
||||||
const ModelSpawn &spawn = map_iter->second->UniqueEntries[tile->second];
|
const ModelSpawn& spawn = map_iter->second->UniqueEntries[tile->second];
|
||||||
if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently...
|
if (spawn.flags & MOD_WORLDSPAWN) // WDT spawn, saved as tile 65/65 currently...
|
||||||
continue;
|
continue;
|
||||||
uint32 nSpawns = tileEntries.count(tile->first);
|
uint32 nSpawns = tileEntries.count(tile->first);
|
||||||
@@ -157,11 +157,11 @@ namespace VMAP
|
|||||||
// write number of tile spawns
|
// write number of tile spawns
|
||||||
if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false;
|
if (success && fwrite(&nSpawns, sizeof(uint32), 1, tilefile) != 1) success = false;
|
||||||
// write tile spawns
|
// write tile spawns
|
||||||
for (uint32 s=0; s<nSpawns; ++s)
|
for (uint32 s = 0; s < nSpawns; ++s)
|
||||||
{
|
{
|
||||||
if (s)
|
if (s)
|
||||||
++tile;
|
++tile;
|
||||||
const ModelSpawn &spawn2 = map_iter->second->UniqueEntries[tile->second];
|
const ModelSpawn& spawn2 = map_iter->second->UniqueEntries[tile->second];
|
||||||
success = success && ModelSpawn::writeToFile(tilefile, spawn2);
|
success = success && ModelSpawn::writeToFile(tilefile, spawn2);
|
||||||
// MapTree nodes to update when loading tile:
|
// MapTree nodes to update when loading tile:
|
||||||
std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID);
|
std::map<uint32, uint32>::iterator nIdx = modelNodeIdx.find(spawn2.ID);
|
||||||
@@ -206,7 +206,7 @@ namespace VMAP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
printf("Read coordinate mapping...\n");
|
printf("Read coordinate mapping...\n");
|
||||||
uint32 mapID, tileX, tileY, check=0;
|
uint32 mapID, tileX, tileY, check = 0;
|
||||||
G3D::Vector3 v1, v2;
|
G3D::Vector3 v1, v2;
|
||||||
ModelSpawn spawn;
|
ModelSpawn spawn;
|
||||||
while (!feof(dirf))
|
while (!feof(dirf))
|
||||||
@@ -221,7 +221,7 @@ namespace VMAP
|
|||||||
if (!ModelSpawn::readFromFile(dirf, spawn))
|
if (!ModelSpawn::readFromFile(dirf, spawn))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
MapSpawns *current;
|
MapSpawns* current;
|
||||||
MapData::iterator map_iter = mapData.find(mapID);
|
MapData::iterator map_iter = mapData.find(mapID);
|
||||||
if (map_iter == mapData.end())
|
if (map_iter == mapData.end())
|
||||||
{
|
{
|
||||||
@@ -237,7 +237,7 @@ namespace VMAP
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TileAssembler::calculateTransformedBound(ModelSpawn &spawn)
|
bool TileAssembler::calculateTransformedBound(ModelSpawn& spawn)
|
||||||
{
|
{
|
||||||
std::string modelFilename(iSrcDir);
|
std::string modelFilename(iSrcDir);
|
||||||
modelFilename.push_back('/');
|
modelFilename.push_back('/');
|
||||||
@@ -257,9 +257,9 @@ namespace VMAP
|
|||||||
printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str());
|
printf("Warning: '%s' does not seem to be a M2 model!\n", modelFilename.c_str());
|
||||||
|
|
||||||
AABox modelBound;
|
AABox modelBound;
|
||||||
bool boundEmpty=true;
|
bool boundEmpty = true;
|
||||||
|
|
||||||
for (uint32 g=0; g<groups; ++g) // should be only one for M2 files...
|
for (uint32 g = 0; g < groups; ++g) // should be only one for M2 files...
|
||||||
{
|
{
|
||||||
std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray;
|
std::vector<Vector3>& vertices = raw_model.groupsArray[g].vertexArray;
|
||||||
|
|
||||||
@@ -275,7 +275,7 @@ namespace VMAP
|
|||||||
Vector3 v = modelPosition.transform(vertices[i]);
|
Vector3 v = modelPosition.transform(vertices[i]);
|
||||||
|
|
||||||
if (boundEmpty)
|
if (boundEmpty)
|
||||||
modelBound = AABox(v, v), boundEmpty=false;
|
modelBound = AABox(v, v), boundEmpty = false;
|
||||||
else
|
else
|
||||||
modelBound.merge(v);
|
modelBound.merge(v);
|
||||||
}
|
}
|
||||||
@@ -298,7 +298,7 @@ namespace VMAP
|
|||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
std::string filename = iSrcDir;
|
std::string filename = iSrcDir;
|
||||||
if (filename.length() >0)
|
if (filename.length() > 0)
|
||||||
filename.push_back('/');
|
filename.push_back('/');
|
||||||
filename.append(pModelFilename);
|
filename.append(pModelFilename);
|
||||||
|
|
||||||
@@ -348,9 +348,9 @@ namespace VMAP
|
|||||||
while (!feof(model_list))
|
while (!feof(model_list))
|
||||||
{
|
{
|
||||||
if (fread(&displayId, sizeof(uint32), 1, model_list) != 1
|
if (fread(&displayId, sizeof(uint32), 1, model_list) != 1
|
||||||
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1
|
|| fread(&name_length, sizeof(uint32), 1, model_list) != 1
|
||||||
|| name_length >= sizeof(buff)
|
|| name_length >= sizeof(buff)
|
||||||
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
|
|| fread(&buff, sizeof(char), name_length, model_list) != name_length)
|
||||||
{
|
{
|
||||||
std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl;
|
std::cout << "\nFile 'temp_gameobject_models' seems to be corrupted" << std::endl;
|
||||||
break;
|
break;
|
||||||
@@ -390,12 +390,12 @@ namespace VMAP
|
|||||||
fclose(model_list);
|
fclose(model_list);
|
||||||
fclose(model_list_copy);
|
fclose(model_list_copy);
|
||||||
}
|
}
|
||||||
// temporary use defines to simplify read/check code (close file and return at fail)
|
// 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) { \
|
#define READ_OR_RETURN(V, S) if (fread((V), (S), 1, rf) != 1) { \
|
||||||
fclose(rf); printf("readfail, op = %i\n", readOperation); return(false); }
|
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) { \
|
#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); };
|
fclose(rf); printf("readfail, op = %i\n", readOperation); delete[] V; return(false); };
|
||||||
#define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \
|
#define CMP_OR_RETURN(V, S) if (strcmp((V), (S)) != 0) { \
|
||||||
fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); }
|
fclose(rf); printf("cmpfail, %s!=%s\n", V, S);return(false); }
|
||||||
|
|
||||||
bool GroupModel_Raw::Read(FILE* rf)
|
bool GroupModel_Raw::Read(FILE* rf)
|
||||||
@@ -423,7 +423,7 @@ namespace VMAP
|
|||||||
CMP_OR_RETURN(blockId, "GRP ");
|
CMP_OR_RETURN(blockId, "GRP ");
|
||||||
READ_OR_RETURN(&blocksize, sizeof(int));
|
READ_OR_RETURN(&blocksize, sizeof(int));
|
||||||
READ_OR_RETURN(&branches, sizeof(uint32));
|
READ_OR_RETURN(&branches, sizeof(uint32));
|
||||||
for (uint32 b=0; b<branches; ++b)
|
for (uint32 b = 0; b < branches; ++b)
|
||||||
{
|
{
|
||||||
uint32 indexes;
|
uint32 indexes;
|
||||||
// indexes for each branch (not used jet)
|
// indexes for each branch (not used jet)
|
||||||
@@ -436,13 +436,13 @@ namespace VMAP
|
|||||||
READ_OR_RETURN(&blocksize, sizeof(int));
|
READ_OR_RETURN(&blocksize, sizeof(int));
|
||||||
uint32 nindexes;
|
uint32 nindexes;
|
||||||
READ_OR_RETURN(&nindexes, sizeof(uint32));
|
READ_OR_RETURN(&nindexes, sizeof(uint32));
|
||||||
if (nindexes >0)
|
if (nindexes > 0)
|
||||||
{
|
{
|
||||||
uint16 *indexarray = new uint16[nindexes];
|
uint16* indexarray = new uint16[nindexes];
|
||||||
READ_OR_RETURN_WITH_DELETE(indexarray, nindexes*sizeof(uint16));
|
READ_OR_RETURN_WITH_DELETE(indexarray, nindexes * sizeof(uint16));
|
||||||
triangles.reserve(nindexes / 3);
|
triangles.reserve(nindexes / 3);
|
||||||
for (uint32 i=0; i<nindexes; i+=3)
|
for (uint32 i = 0; i < nindexes; i += 3)
|
||||||
triangles.push_back(MeshTriangle(indexarray[i], indexarray[i+1], indexarray[i+2]));
|
triangles.push_back(MeshTriangle(indexarray[i], indexarray[i + 1], indexarray[i + 2]));
|
||||||
|
|
||||||
delete[] indexarray;
|
delete[] indexarray;
|
||||||
}
|
}
|
||||||
@@ -454,18 +454,18 @@ namespace VMAP
|
|||||||
uint32 nvectors;
|
uint32 nvectors;
|
||||||
READ_OR_RETURN(&nvectors, sizeof(uint32));
|
READ_OR_RETURN(&nvectors, sizeof(uint32));
|
||||||
|
|
||||||
if (nvectors >0)
|
if (nvectors > 0)
|
||||||
{
|
{
|
||||||
float *vectorarray = new float[nvectors*3];
|
float* vectorarray = new float[nvectors * 3];
|
||||||
READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors*sizeof(float)*3);
|
READ_OR_RETURN_WITH_DELETE(vectorarray, nvectors * sizeof(float) * 3);
|
||||||
for (uint32 i=0; i<nvectors; ++i)
|
for (uint32 i = 0; i < nvectors; ++i)
|
||||||
vertexArray.push_back( Vector3(vectorarray + 3*i) );
|
vertexArray.push_back( Vector3(vectorarray + 3 * i) );
|
||||||
|
|
||||||
delete[] vectorarray;
|
delete[] vectorarray;
|
||||||
}
|
}
|
||||||
// ----- liquid
|
// ----- liquid
|
||||||
liquid = 0;
|
liquid = 0;
|
||||||
if (liquidflags& 1)
|
if (liquidflags & 1)
|
||||||
{
|
{
|
||||||
WMOLiquidHeader hlq;
|
WMOLiquidHeader hlq;
|
||||||
READ_OR_RETURN(&blockId, 4);
|
READ_OR_RETURN(&blockId, 4);
|
||||||
@@ -473,9 +473,9 @@ namespace VMAP
|
|||||||
READ_OR_RETURN(&blocksize, sizeof(int));
|
READ_OR_RETURN(&blocksize, sizeof(int));
|
||||||
READ_OR_RETURN(&hlq, sizeof(WMOLiquidHeader));
|
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);
|
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;
|
uint32 size = hlq.xverts * hlq.yverts;
|
||||||
READ_OR_RETURN(liquid->GetHeightStorage(), size*sizeof(float));
|
READ_OR_RETURN(liquid->GetHeightStorage(), size * sizeof(float));
|
||||||
size = hlq.xtiles*hlq.ytiles;
|
size = hlq.xtiles * hlq.ytiles;
|
||||||
READ_OR_RETURN(liquid->GetFlagsStorage(), size);
|
READ_OR_RETURN(liquid->GetFlagsStorage(), size);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,7 +488,7 @@ namespace VMAP
|
|||||||
delete liquid;
|
delete liquid;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldModel_Raw::Read(const char * path)
|
bool WorldModel_Raw::Read(const char* path)
|
||||||
{
|
{
|
||||||
FILE* rf = fopen(path, "rb");
|
FILE* rf = fopen(path, "rb");
|
||||||
if (!rf)
|
if (!rf)
|
||||||
@@ -523,6 +523,6 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
|
|
||||||
// drop of temporary use defines
|
// drop of temporary use defines
|
||||||
#undef READ_OR_RETURN
|
#undef READ_OR_RETURN
|
||||||
#undef CMP_OR_RETURN
|
#undef CMP_OR_RETURN
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,19 +25,19 @@ namespace VMAP
|
|||||||
|
|
||||||
class ModelPosition
|
class ModelPosition
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
G3D::Matrix3 iRotation;
|
G3D::Matrix3 iRotation;
|
||||||
public:
|
public:
|
||||||
ModelPosition(): iScale(0.0f) { }
|
ModelPosition(): iScale(0.0f) { }
|
||||||
G3D::Vector3 iPos;
|
G3D::Vector3 iPos;
|
||||||
G3D::Vector3 iDir;
|
G3D::Vector3 iDir;
|
||||||
float iScale;
|
float iScale;
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
iRotation = G3D::Matrix3::fromEulerAnglesZYX(G3D::pif()*iDir.y/180.f, G3D::pif()*iDir.x/180.f, G3D::pif()*iDir.z/180.f);
|
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;
|
G3D::Vector3 transform(const G3D::Vector3& pIn) const;
|
||||||
void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; }
|
void moveToBasePos(const G3D::Vector3& pBasePos) { iPos -= pBasePos; }
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<uint32, ModelSpawn> UniqueEntryMap;
|
typedef std::map<uint32, ModelSpawn> UniqueEntryMap;
|
||||||
@@ -75,32 +75,32 @@ namespace VMAP
|
|||||||
uint32 RootWMOID;
|
uint32 RootWMOID;
|
||||||
std::vector<GroupModel_Raw> groupsArray;
|
std::vector<GroupModel_Raw> groupsArray;
|
||||||
|
|
||||||
bool Read(const char * path);
|
bool Read(const char* path);
|
||||||
};
|
};
|
||||||
|
|
||||||
class TileAssembler
|
class TileAssembler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
std::string iDestDir;
|
std::string iDestDir;
|
||||||
std::string iSrcDir;
|
std::string iSrcDir;
|
||||||
bool (*iFilterMethod)(char *pName);
|
bool (*iFilterMethod)(char* pName);
|
||||||
G3D::Table<std::string, unsigned int > iUniqueNameIds;
|
G3D::Table<std::string, unsigned int > iUniqueNameIds;
|
||||||
unsigned int iCurrentUniqueNameId;
|
unsigned int iCurrentUniqueNameId;
|
||||||
MapData mapData;
|
MapData mapData;
|
||||||
std::set<std::string> spawnedModelFiles;
|
std::set<std::string> spawnedModelFiles;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName);
|
TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName);
|
||||||
virtual ~TileAssembler();
|
virtual ~TileAssembler();
|
||||||
|
|
||||||
bool convertWorld2();
|
bool convertWorld2();
|
||||||
bool readMapSpawns();
|
bool readMapSpawns();
|
||||||
bool calculateTransformedBound(ModelSpawn &spawn);
|
bool calculateTransformedBound(ModelSpawn& spawn);
|
||||||
void exportGameobjectModels();
|
void exportGameobjectModels();
|
||||||
|
|
||||||
bool convertRawFile(const std::string& pModelFilename);
|
bool convertRawFile(const std::string& pModelFilename);
|
||||||
void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; }
|
void setModelNameFilterMethod(bool (*pFilterMethod)(char* pName)) { iFilterMethod = pFilterMethod; }
|
||||||
std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName);
|
std::string getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // VMAP
|
} // VMAP
|
||||||
|
|||||||
@@ -36,9 +36,9 @@ ModelList model_list;
|
|||||||
|
|
||||||
void LoadGameObjectModelList()
|
void LoadGameObjectModelList()
|
||||||
{
|
{
|
||||||
//#ifndef NO_CORE_FUNCS
|
//#ifndef NO_CORE_FUNCS
|
||||||
uint32 oldMSTime = getMSTime();
|
uint32 oldMSTime = getMSTime();
|
||||||
//#endif
|
//#endif
|
||||||
|
|
||||||
FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
|
FILE* model_list_file = fopen((sWorld->GetDataPath() + "vmaps/" + VMAP::GAMEOBJECT_MODELS).c_str(), "rb");
|
||||||
if (!model_list_file)
|
if (!model_list_file)
|
||||||
@@ -57,10 +57,10 @@ void LoadGameObjectModelList()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|
if (fread(&name_length, sizeof(uint32), 1, model_list_file) != 1
|
||||||
|| name_length >= sizeof(buff)
|
|| name_length >= sizeof(buff)
|
||||||
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|
|| fread(&buff, sizeof(char), name_length, model_list_file) != name_length
|
||||||
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|
|| fread(&v1, sizeof(Vector3), 1, model_list_file) != 1
|
||||||
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
|
|| fread(&v2, sizeof(Vector3), 1, model_list_file) != 1)
|
||||||
{
|
{
|
||||||
sLog->outError("File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
|
sLog->outError("File '%s' seems to be corrupted!", VMAP::GAMEOBJECT_MODELS);
|
||||||
break;
|
break;
|
||||||
@@ -108,7 +108,7 @@ bool GameObjectModel::initialize(const GameObject& go, const GameObjectDisplayIn
|
|||||||
//ID = 0;
|
//ID = 0;
|
||||||
iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
|
iPos = Vector3(go.GetPositionX(), go.GetPositionY(), go.GetPositionZ());
|
||||||
|
|
||||||
// pussywizard:
|
// pussywizard:
|
||||||
phasemask = (go.GetGoState() == GO_STATE_READY || go.IsTransport()) ? go.GetPhaseMask() : 0;
|
phasemask = (go.GetGoState() == GO_STATE_READY || go.IsTransport()) ? go.GetPhaseMask() : 0;
|
||||||
|
|
||||||
iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X);
|
iScale = go.GetFloatValue(OBJECT_FIELD_SCALE_X);
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ using G3D::Ray;
|
|||||||
|
|
||||||
namespace VMAP
|
namespace VMAP
|
||||||
{
|
{
|
||||||
ModelInstance::ModelInstance(const ModelSpawn &spawn, WorldModel* model): ModelSpawn(spawn), iModel(model)
|
ModelInstance::ModelInstance(const ModelSpawn& spawn, WorldModel* model): ModelSpawn(spawn), iModel(model)
|
||||||
{
|
{
|
||||||
iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi()*iRot.y/180.f, G3D::pi()*iRot.x/180.f, G3D::pi()*iRot.z/180.f).inverse();
|
iInvRot = G3D::Matrix3::fromEulerAnglesZYX(G3D::pi() * iRot.y / 180.f, G3D::pi() * iRot.x / 180.f, G3D::pi() * iRot.z / 180.f).inverse();
|
||||||
iInvScale = 1.f/iScale;
|
iInvScale = 1.f / iScale;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
|
bool ModelInstance::intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const
|
||||||
@@ -30,16 +30,16 @@ namespace VMAP
|
|||||||
float time = pRay.intersectionTime(iBound);
|
float time = pRay.intersectionTime(iBound);
|
||||||
if (time == G3D::inf())
|
if (time == G3D::inf())
|
||||||
{
|
{
|
||||||
// std::cout << "Ray does not hit '" << name << "'\n";
|
// std::cout << "Ray does not hit '" << name << "'\n";
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// std::cout << "Ray crosses bound of '" << name << "'\n";
|
// std::cout << "Ray crosses bound of '" << name << "'\n";
|
||||||
/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z
|
/* std::cout << "ray from:" << pRay.origin().x << ", " << pRay.origin().y << ", " << pRay.origin().z
|
||||||
<< " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z
|
<< " dir:" << pRay.direction().x << ", " << pRay.direction().y << ", " << pRay.direction().z
|
||||||
<< " t/tmax:" << time << '/' << pMaxDist;
|
<< " t/tmax:" << time << '/' << pMaxDist;
|
||||||
std::cout << "\nBound lo:" << iBound.low().x << ", " << iBound.low().y << ", " << iBound.low().z << " hi: "
|
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; */
|
<< iBound.high().x << ", " << iBound.high().y << ", " << iBound.high().z << std::endl; */
|
||||||
// child bounds are defined in object space:
|
// child bounds are defined in object space:
|
||||||
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
|
Vector3 p = iInvRot * (pRay.origin() - iPos) * iInvScale;
|
||||||
Ray modRay(p, iInvRot * pRay.direction());
|
Ray modRay(p, iInvRot * pRay.direction());
|
||||||
@@ -53,7 +53,7 @@ namespace VMAP
|
|||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo &info) const
|
void ModelInstance::intersectPoint(const G3D::Vector3& p, AreaInfo& info) const
|
||||||
{
|
{
|
||||||
if (!iModel)
|
if (!iModel)
|
||||||
{
|
{
|
||||||
@@ -87,7 +87,7 @@ namespace VMAP
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const
|
bool ModelInstance::GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const
|
||||||
{
|
{
|
||||||
if (!iModel)
|
if (!iModel)
|
||||||
{
|
{
|
||||||
@@ -123,7 +123,7 @@ namespace VMAP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const
|
bool ModelInstance::GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const
|
||||||
{
|
{
|
||||||
// child bounds are defined in object space:
|
// child bounds are defined in object space:
|
||||||
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
|
Vector3 pModel = iInvRot * (p - iPos) * iInvScale;
|
||||||
@@ -139,7 +139,7 @@ namespace VMAP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn &spawn)
|
bool ModelSpawn::readFromFile(FILE* rf, ModelSpawn& spawn)
|
||||||
{
|
{
|
||||||
uint32 check = 0, nameLen;
|
uint32 check = 0, nameLen;
|
||||||
check += fread(&spawn.flags, sizeof(uint32), 1, rf);
|
check += fread(&spawn.flags, sizeof(uint32), 1, rf);
|
||||||
@@ -185,9 +185,9 @@ namespace VMAP
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn &spawn)
|
bool ModelSpawn::writeToFile(FILE* wf, const ModelSpawn& spawn)
|
||||||
{
|
{
|
||||||
uint32 check=0;
|
uint32 check = 0;
|
||||||
check += fwrite(&spawn.flags, sizeof(uint32), 1, wf);
|
check += fwrite(&spawn.flags, sizeof(uint32), 1, wf);
|
||||||
check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf);
|
check += fwrite(&spawn.adtId, sizeof(uint16), 1, wf);
|
||||||
check += fwrite(&spawn.ID, sizeof(uint32), 1, wf);
|
check += fwrite(&spawn.ID, sizeof(uint32), 1, wf);
|
||||||
|
|||||||
@@ -23,47 +23,47 @@ namespace VMAP
|
|||||||
enum ModelFlags
|
enum ModelFlags
|
||||||
{
|
{
|
||||||
MOD_M2 = 1,
|
MOD_M2 = 1,
|
||||||
MOD_WORLDSPAWN = 1<<1,
|
MOD_WORLDSPAWN = 1 << 1,
|
||||||
MOD_HAS_BOUND = 1<<2
|
MOD_HAS_BOUND = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModelSpawn
|
class ModelSpawn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
//mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name
|
||||||
uint32 flags;
|
uint32 flags;
|
||||||
uint16 adtId;
|
uint16 adtId;
|
||||||
uint32 ID;
|
uint32 ID;
|
||||||
G3D::Vector3 iPos;
|
G3D::Vector3 iPos;
|
||||||
G3D::Vector3 iRot;
|
G3D::Vector3 iRot;
|
||||||
float iScale;
|
float iScale;
|
||||||
G3D::AABox iBound;
|
G3D::AABox iBound;
|
||||||
std::string name;
|
std::string name;
|
||||||
bool operator==(const ModelSpawn &other) const { return ID == other.ID; }
|
bool operator==(const ModelSpawn& other) const { return ID == other.ID; }
|
||||||
//uint32 hashCode() const { return ID; }
|
//uint32 hashCode() const { return ID; }
|
||||||
// temp?
|
// temp?
|
||||||
const G3D::AABox& getBounds() const { return iBound; }
|
const G3D::AABox& getBounds() const { return iBound; }
|
||||||
|
|
||||||
static bool readFromFile(FILE* rf, ModelSpawn &spawn);
|
static bool readFromFile(FILE* rf, ModelSpawn& spawn);
|
||||||
static bool writeToFile(FILE* rw, const ModelSpawn &spawn);
|
static bool writeToFile(FILE* rw, const ModelSpawn& spawn);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ModelInstance: public ModelSpawn
|
class ModelInstance: public ModelSpawn
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ModelInstance(): iInvScale(0.0f), iModel(0) { }
|
ModelInstance(): iInvScale(0.0f), iModel(0) { }
|
||||||
ModelInstance(const ModelSpawn &spawn, WorldModel* model);
|
ModelInstance(const ModelSpawn& spawn, WorldModel* model);
|
||||||
void setUnloaded() { iModel = 0; }
|
void setUnloaded() { iModel = 0; }
|
||||||
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
|
bool intersectRay(const G3D::Ray& pRay, float& pMaxDist, bool StopAtFirstHit) const;
|
||||||
void intersectPoint(const G3D::Vector3& p, AreaInfo &info) const;
|
void intersectPoint(const G3D::Vector3& p, AreaInfo& info) const;
|
||||||
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo &info) const;
|
bool GetLocationInfo(const G3D::Vector3& p, LocationInfo& info) const;
|
||||||
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo &info, float &liqHeight) const;
|
bool GetLiquidLevel(const G3D::Vector3& p, LocationInfo& info, float& liqHeight) const;
|
||||||
protected:
|
protected:
|
||||||
G3D::Matrix3 iInvRot;
|
G3D::Matrix3 iInvRot;
|
||||||
float iInvScale;
|
float iInvScale;
|
||||||
WorldModel* iModel;
|
WorldModel* iModel;
|
||||||
public:
|
public:
|
||||||
WorldModel* getWorldModel();
|
WorldModel* getWorldModel();
|
||||||
};
|
};
|
||||||
} // namespace VMAP
|
} // namespace VMAP
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ template<> struct BoundsTrait<VMAP::GroupModel>
|
|||||||
|
|
||||||
namespace VMAP
|
namespace VMAP
|
||||||
{
|
{
|
||||||
bool IntersectTriangle(const MeshTriangle &tri, std::vector<Vector3>::const_iterator points, const G3D::Ray &ray, float &distance)
|
bool IntersectTriangle(const MeshTriangle& tri, std::vector<Vector3>::const_iterator points, const G3D::Ray& ray, float& distance)
|
||||||
{
|
{
|
||||||
static const float EPS = 1e-5f;
|
static const float EPS = 1e-5f;
|
||||||
|
|
||||||
@@ -30,7 +30,8 @@ namespace VMAP
|
|||||||
const Vector3 p(ray.direction().cross(e2));
|
const Vector3 p(ray.direction().cross(e2));
|
||||||
const float a = e1.dot(p);
|
const float a = e1.dot(p);
|
||||||
|
|
||||||
if (fabs(a) < EPS) {
|
if (fabs(a) < EPS)
|
||||||
|
{
|
||||||
// Determinant is ill-conditioned; abort early
|
// Determinant is ill-conditioned; abort early
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -39,7 +40,8 @@ namespace VMAP
|
|||||||
const Vector3 s(ray.origin() - points[tri.idx0]);
|
const Vector3 s(ray.origin() - points[tri.idx0]);
|
||||||
const float u = f * s.dot(p);
|
const float u = f * s.dot(p);
|
||||||
|
|
||||||
if ((u < 0.0f) || (u > 1.0f)) {
|
if ((u < 0.0f) || (u > 1.0f))
|
||||||
|
{
|
||||||
// We hit the plane of the m_geometry, but outside the m_geometry
|
// We hit the plane of the m_geometry, but outside the m_geometry
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -47,7 +49,8 @@ namespace VMAP
|
|||||||
const Vector3 q(s.cross(e1));
|
const Vector3 q(s.cross(e1));
|
||||||
const float v = f * ray.direction().dot(q);
|
const float v = f * ray.direction().dot(q);
|
||||||
|
|
||||||
if ((v < 0.0f) || ((u + v) > 1.0f)) {
|
if ((v < 0.0f) || ((u + v) > 1.0f))
|
||||||
|
{
|
||||||
// We hit the plane of the triangle, but outside the triangle
|
// We hit the plane of the triangle, but outside the triangle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -71,32 +74,32 @@ namespace VMAP
|
|||||||
|
|
||||||
class TriBoundFunc
|
class TriBoundFunc
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TriBoundFunc(std::vector<Vector3> &vert): vertices(vert.begin()) { }
|
TriBoundFunc(std::vector<Vector3>& vert): vertices(vert.begin()) { }
|
||||||
void operator()(const MeshTriangle &tri, G3D::AABox &out) const
|
void operator()(const MeshTriangle& tri, G3D::AABox& out) const
|
||||||
{
|
{
|
||||||
G3D::Vector3 lo = vertices[tri.idx0];
|
G3D::Vector3 lo = vertices[tri.idx0];
|
||||||
G3D::Vector3 hi = lo;
|
G3D::Vector3 hi = lo;
|
||||||
|
|
||||||
lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]);
|
lo = (lo.min(vertices[tri.idx1])).min(vertices[tri.idx2]);
|
||||||
hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]);
|
hi = (hi.max(vertices[tri.idx1])).max(vertices[tri.idx2]);
|
||||||
|
|
||||||
out = G3D::AABox(lo, hi);
|
out = G3D::AABox(lo, hi);
|
||||||
}
|
}
|
||||||
protected:
|
protected:
|
||||||
const std::vector<Vector3>::const_iterator vertices;
|
const std::vector<Vector3>::const_iterator vertices;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ===================== WmoLiquid ==================================
|
// ===================== WmoLiquid ==================================
|
||||||
|
|
||||||
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3 &corner, uint32 type):
|
WmoLiquid::WmoLiquid(uint32 width, uint32 height, const Vector3& corner, uint32 type):
|
||||||
iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
|
iTilesX(width), iTilesY(height), iCorner(corner), iType(type)
|
||||||
{
|
{
|
||||||
iHeight = new float[(width+1)*(height+1)];
|
iHeight = new float[(width + 1) * (height + 1)];
|
||||||
iFlags = new uint8[width*height];
|
iFlags = new uint8[width * height];
|
||||||
}
|
}
|
||||||
|
|
||||||
WmoLiquid::WmoLiquid(const WmoLiquid &other): iHeight(0), iFlags(0)
|
WmoLiquid::WmoLiquid(const WmoLiquid& other): iHeight(0), iFlags(0)
|
||||||
{
|
{
|
||||||
*this = other; // use assignment operator...
|
*this = other; // use assignment operator...
|
||||||
}
|
}
|
||||||
@@ -107,7 +110,7 @@ namespace VMAP
|
|||||||
delete[] iFlags;
|
delete[] iFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
WmoLiquid& WmoLiquid::operator=(const WmoLiquid &other)
|
WmoLiquid& WmoLiquid::operator=(const WmoLiquid& other)
|
||||||
{
|
{
|
||||||
if (this == &other)
|
if (this == &other)
|
||||||
return *this;
|
return *this;
|
||||||
@@ -119,8 +122,8 @@ namespace VMAP
|
|||||||
delete[] iFlags;
|
delete[] iFlags;
|
||||||
if (other.iHeight)
|
if (other.iHeight)
|
||||||
{
|
{
|
||||||
iHeight = new float[(iTilesX+1)*(iTilesY+1)];
|
iHeight = new float[(iTilesX + 1) * (iTilesY + 1)];
|
||||||
memcpy(iHeight, other.iHeight, (iTilesX+1)*(iTilesY+1)*sizeof(float));
|
memcpy(iHeight, other.iHeight, (iTilesX + 1) * (iTilesY + 1)*sizeof(float));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
iHeight = 0;
|
iHeight = 0;
|
||||||
@@ -134,20 +137,20 @@ namespace VMAP
|
|||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmoLiquid::GetLiquidHeight(const Vector3 &pos, float &liqHeight) const
|
bool WmoLiquid::GetLiquidHeight(const Vector3& pos, float& liqHeight) const
|
||||||
{
|
{
|
||||||
float tx_f = (pos.x - iCorner.x)/LIQUID_TILE_SIZE;
|
float tx_f = (pos.x - iCorner.x) / LIQUID_TILE_SIZE;
|
||||||
uint32 tx = uint32(tx_f);
|
uint32 tx = uint32(tx_f);
|
||||||
if (tx_f < 0.0f || tx >= iTilesX)
|
if (tx_f < 0.0f || tx >= iTilesX)
|
||||||
return false;
|
return false;
|
||||||
float ty_f = (pos.y - iCorner.y)/LIQUID_TILE_SIZE;
|
float ty_f = (pos.y - iCorner.y) / LIQUID_TILE_SIZE;
|
||||||
uint32 ty = uint32(ty_f);
|
uint32 ty = uint32(ty_f);
|
||||||
if (ty_f < 0.0f || ty >= iTilesY)
|
if (ty_f < 0.0f || ty >= iTilesY)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// check if tile shall be used for liquid level
|
// check if tile shall be used for liquid level
|
||||||
// checking for 0x08 *might* be enough, but disabled tiles always are 0x?F:
|
// checking for 0x08 *might* be enough, but disabled tiles always are 0x?F:
|
||||||
if ((iFlags[tx + ty*iTilesX] & 0x0F) == 0x0F)
|
if ((iFlags[tx + ty * iTilesX] & 0x0F) == 0x0F)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// (dx, dy) coordinates inside tile, in [0, 1]^2
|
// (dx, dy) coordinates inside tile, in [0, 1]^2
|
||||||
@@ -170,14 +173,14 @@ namespace VMAP
|
|||||||
const uint32 rowOffset = iTilesX + 1;
|
const uint32 rowOffset = iTilesX + 1;
|
||||||
if (dx > dy) // case (a)
|
if (dx > dy) // case (a)
|
||||||
{
|
{
|
||||||
float sx = iHeight[tx+1 + ty * rowOffset] - iHeight[tx + ty * rowOffset];
|
float sx = iHeight[tx + 1 + ty * rowOffset] - iHeight[tx + ty * rowOffset];
|
||||||
float sy = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx+1 + ty * rowOffset];
|
float sy = iHeight[tx + 1 + (ty + 1) * rowOffset] - iHeight[tx + 1 + ty * rowOffset];
|
||||||
liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
|
liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
|
||||||
}
|
}
|
||||||
else // case (b)
|
else // case (b)
|
||||||
{
|
{
|
||||||
float sx = iHeight[tx+1 + (ty+1) * rowOffset] - iHeight[tx + (ty+1) * rowOffset];
|
float sx = iHeight[tx + 1 + (ty + 1) * rowOffset] - iHeight[tx + (ty + 1) * rowOffset];
|
||||||
float sy = iHeight[tx + (ty+1) * rowOffset] - iHeight[tx + ty * rowOffset];
|
float sy = iHeight[tx + (ty + 1) * rowOffset] - iHeight[tx + ty * rowOffset];
|
||||||
liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
|
liqHeight = iHeight[tx + ty * rowOffset] + dx * sx + dy * sy;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -186,23 +189,23 @@ namespace VMAP
|
|||||||
uint32 WmoLiquid::GetFileSize()
|
uint32 WmoLiquid::GetFileSize()
|
||||||
{
|
{
|
||||||
return 2 * sizeof(uint32) +
|
return 2 * sizeof(uint32) +
|
||||||
sizeof(Vector3) +
|
sizeof(Vector3) +
|
||||||
(iTilesX + 1)*(iTilesY + 1) * sizeof(float) +
|
(iTilesX + 1) * (iTilesY + 1) * sizeof(float) +
|
||||||
iTilesX * iTilesY;
|
iTilesX * iTilesY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmoLiquid::writeToFile(FILE* wf)
|
bool WmoLiquid::writeToFile(FILE* wf)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 &&
|
if (fwrite(&iTilesX, sizeof(uint32), 1, wf) == 1 &&
|
||||||
fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 &&
|
fwrite(&iTilesY, sizeof(uint32), 1, wf) == 1 &&
|
||||||
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
|
fwrite(&iCorner, sizeof(Vector3), 1, wf) == 1 &&
|
||||||
fwrite(&iType, sizeof(uint32), 1, wf) == 1)
|
fwrite(&iType, sizeof(uint32), 1, wf) == 1)
|
||||||
{
|
{
|
||||||
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
uint32 size = (iTilesX + 1) * (iTilesY + 1);
|
||||||
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
if (fwrite(iHeight, sizeof(float), size, wf) == size)
|
||||||
{
|
{
|
||||||
size = iTilesX*iTilesY;
|
size = iTilesX * iTilesY;
|
||||||
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
result = fwrite(iFlags, sizeof(uint8), size, wf) == size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,15 +213,15 @@ namespace VMAP
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid* &out)
|
bool WmoLiquid::readFromFile(FILE* rf, WmoLiquid*& out)
|
||||||
{
|
{
|
||||||
bool result = false;
|
bool result = false;
|
||||||
WmoLiquid* liquid = new WmoLiquid();
|
WmoLiquid* liquid = new WmoLiquid();
|
||||||
|
|
||||||
if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 &&
|
if (fread(&liquid->iTilesX, sizeof(uint32), 1, rf) == 1 &&
|
||||||
fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 &&
|
fread(&liquid->iTilesY, sizeof(uint32), 1, rf) == 1 &&
|
||||||
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
|
fread(&liquid->iCorner, sizeof(Vector3), 1, rf) == 1 &&
|
||||||
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
|
fread(&liquid->iType, sizeof(uint32), 1, rf) == 1)
|
||||||
{
|
{
|
||||||
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
uint32 size = (liquid->iTilesX + 1) * (liquid->iTilesY + 1);
|
||||||
liquid->iHeight = new float[size];
|
liquid->iHeight = new float[size];
|
||||||
@@ -240,7 +243,7 @@ namespace VMAP
|
|||||||
|
|
||||||
// ===================== GroupModel ==================================
|
// ===================== GroupModel ==================================
|
||||||
|
|
||||||
GroupModel::GroupModel(const GroupModel &other):
|
GroupModel::GroupModel(const GroupModel& other):
|
||||||
iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
|
iBound(other.iBound), iMogpFlags(other.iMogpFlags), iGroupWMOID(other.iGroupWMOID),
|
||||||
vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0)
|
vertices(other.vertices), triangles(other.triangles), meshTree(other.meshTree), iLiquid(0)
|
||||||
{
|
{
|
||||||
@@ -248,7 +251,7 @@ namespace VMAP
|
|||||||
iLiquid = new WmoLiquid(*other.iLiquid);
|
iLiquid = new WmoLiquid(*other.iLiquid);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GroupModel::setMeshData(std::vector<Vector3> &vert, std::vector<MeshTriangle> &tri)
|
void GroupModel::setMeshData(std::vector<Vector3>& vert, std::vector<MeshTriangle>& tri)
|
||||||
{
|
{
|
||||||
vertices.swap(vert);
|
vertices.swap(vert);
|
||||||
triangles.swap(tri);
|
triangles.swap(tri);
|
||||||
@@ -268,7 +271,7 @@ namespace VMAP
|
|||||||
// write vertices
|
// write vertices
|
||||||
if (result && fwrite("VERT", 1, 4, wf) != 4) result = false;
|
if (result && fwrite("VERT", 1, 4, wf) != 4) result = false;
|
||||||
count = vertices.size();
|
count = vertices.size();
|
||||||
chunkSize = sizeof(uint32)+ sizeof(Vector3)*count;
|
chunkSize = sizeof(uint32) + sizeof(Vector3) * count;
|
||||||
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
|
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(&count, sizeof(uint32), 1, wf) != 1) result = false;
|
||||||
if (!count) // models without (collision) geometry end here, unsure if they are useful
|
if (!count) // models without (collision) geometry end here, unsure if they are useful
|
||||||
@@ -278,7 +281,7 @@ namespace VMAP
|
|||||||
// write triangle mesh
|
// write triangle mesh
|
||||||
if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false;
|
if (result && fwrite("TRIM", 1, 4, wf) != 4) result = false;
|
||||||
count = triangles.size();
|
count = triangles.size();
|
||||||
chunkSize = sizeof(uint32)+ sizeof(MeshTriangle)*count;
|
chunkSize = sizeof(uint32) + sizeof(MeshTriangle) * count;
|
||||||
if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
|
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(&count, sizeof(uint32), 1, wf) != 1) result = false;
|
||||||
if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false;
|
if (result && fwrite(&triangles[0], sizeof(MeshTriangle), count, wf) != count) result = false;
|
||||||
@@ -347,12 +350,12 @@ namespace VMAP
|
|||||||
|
|
||||||
struct GModelRayCallback
|
struct GModelRayCallback
|
||||||
{
|
{
|
||||||
GModelRayCallback(const std::vector<MeshTriangle> &tris, const std::vector<Vector3> &vert):
|
GModelRayCallback(const std::vector<MeshTriangle>& tris, const std::vector<Vector3>& vert):
|
||||||
vertices(vert.begin()), triangles(tris.begin()), hit(false) { }
|
vertices(vert.begin()), triangles(tris.begin()), hit(false) { }
|
||||||
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*StopAtFirstHit*/)
|
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool /*StopAtFirstHit*/)
|
||||||
{
|
{
|
||||||
bool result = IntersectTriangle(triangles[entry], vertices, ray, distance);
|
bool result = IntersectTriangle(triangles[entry], vertices, ray, distance);
|
||||||
if (result) hit=true;
|
if (result) hit = true;
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
std::vector<Vector3>::const_iterator vertices;
|
std::vector<Vector3>::const_iterator vertices;
|
||||||
@@ -360,7 +363,7 @@ namespace VMAP
|
|||||||
bool hit;
|
bool hit;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool GroupModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
|
bool GroupModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const
|
||||||
{
|
{
|
||||||
if (triangles.empty())
|
if (triangles.empty())
|
||||||
return false;
|
return false;
|
||||||
@@ -370,7 +373,7 @@ namespace VMAP
|
|||||||
return callback.hit;
|
return callback.hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupModel::IsInsideObject(const Vector3 &pos, const Vector3 &down, float &z_dist) const
|
bool GroupModel::IsInsideObject(const Vector3& pos, const Vector3& down, float& z_dist) const
|
||||||
{
|
{
|
||||||
if (triangles.empty() || !iBound.contains(pos))
|
if (triangles.empty() || !iBound.contains(pos))
|
||||||
return false;
|
return false;
|
||||||
@@ -384,7 +387,7 @@ namespace VMAP
|
|||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GroupModel::GetLiquidLevel(const Vector3 &pos, float &liqHeight) const
|
bool GroupModel::GetLiquidLevel(const Vector3& pos, float& liqHeight) const
|
||||||
{
|
{
|
||||||
if (iLiquid)
|
if (iLiquid)
|
||||||
return iLiquid->GetLiquidHeight(pos, liqHeight);
|
return iLiquid->GetLiquidHeight(pos, liqHeight);
|
||||||
@@ -400,7 +403,7 @@ namespace VMAP
|
|||||||
|
|
||||||
// ===================== WorldModel ==================================
|
// ===================== WorldModel ==================================
|
||||||
|
|
||||||
void WorldModel::setGroupModels(std::vector<GroupModel> &models)
|
void WorldModel::setGroupModels(std::vector<GroupModel>& models)
|
||||||
{
|
{
|
||||||
groupModels.swap(models);
|
groupModels.swap(models);
|
||||||
groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1);
|
groupTree.build(groupModels, BoundsTrait<GroupModel>::getBounds, 1);
|
||||||
@@ -408,18 +411,18 @@ namespace VMAP
|
|||||||
|
|
||||||
struct WModelRayCallBack
|
struct WModelRayCallBack
|
||||||
{
|
{
|
||||||
WModelRayCallBack(const std::vector<GroupModel> &mod): models(mod.begin()), hit(false) { }
|
WModelRayCallBack(const std::vector<GroupModel>& mod): models(mod.begin()), hit(false) { }
|
||||||
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
|
bool operator()(const G3D::Ray& ray, uint32 entry, float& distance, bool StopAtFirstHit)
|
||||||
{
|
{
|
||||||
bool result = models[entry].IntersectRay(ray, distance, StopAtFirstHit);
|
bool result = models[entry].IntersectRay(ray, distance, StopAtFirstHit);
|
||||||
if (result) hit=true;
|
if (result) hit = true;
|
||||||
return hit;
|
return hit;
|
||||||
}
|
}
|
||||||
std::vector<GroupModel>::const_iterator models;
|
std::vector<GroupModel>::const_iterator models;
|
||||||
bool hit;
|
bool hit;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool WorldModel::IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const
|
bool WorldModel::IntersectRay(const G3D::Ray& ray, float& distance, bool stopAtFirstHit) const
|
||||||
{
|
{
|
||||||
// small M2 workaround, maybe better make separate class with virtual intersection funcs
|
// 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
|
// in any case, there's no need to use a bound tree if we only have one submodel
|
||||||
@@ -431,44 +434,45 @@ namespace VMAP
|
|||||||
return isc.hit;
|
return isc.hit;
|
||||||
}
|
}
|
||||||
|
|
||||||
class WModelAreaCallback {
|
class WModelAreaCallback
|
||||||
public:
|
{
|
||||||
WModelAreaCallback(const std::vector<GroupModel> &vals, const Vector3 &down):
|
public:
|
||||||
prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { }
|
WModelAreaCallback(const std::vector<GroupModel>& vals, const Vector3& down):
|
||||||
std::vector<GroupModel>::const_iterator prims;
|
prims(vals.begin()), hit(vals.end()), minVol(G3D::inf()), zDist(G3D::inf()), zVec(down) { }
|
||||||
std::vector<GroupModel>::const_iterator hit;
|
std::vector<GroupModel>::const_iterator prims;
|
||||||
float minVol;
|
std::vector<GroupModel>::const_iterator hit;
|
||||||
float zDist;
|
float minVol;
|
||||||
Vector3 zVec;
|
float zDist;
|
||||||
void operator()(const Vector3& point, uint32 entry)
|
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))
|
||||||
{
|
{
|
||||||
float group_Z;
|
//minVol = pVol;
|
||||||
//float pVol = prims[entry].GetBound().volume();
|
//hit = prims + entry;
|
||||||
//if (pVol < minVol)
|
if (group_Z < zDist)
|
||||||
//{
|
{
|
||||||
/* if (prims[entry].iBound.contains(point)) */
|
zDist = group_Z;
|
||||||
if (prims[entry].IsInsideObject(point, zVec, group_Z))
|
hit = prims + entry;
|
||||||
{
|
}
|
||||||
//minVol = pVol;
|
|
||||||
//hit = prims + entry;
|
|
||||||
if (group_Z < zDist)
|
|
||||||
{
|
|
||||||
zDist = group_Z;
|
|
||||||
hit = prims + entry;
|
|
||||||
}
|
|
||||||
#ifdef VMAP_DEBUG
|
#ifdef VMAP_DEBUG
|
||||||
const GroupModel &gm = prims[entry];
|
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(),
|
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().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);
|
gm.GetBound().high().x, gm.GetBound().high().y, gm.GetBound().high().z, group_Z, point.z);
|
||||||
#endif
|
#endif
|
||||||
}
|
|
||||||
//}
|
|
||||||
//std::cout << "trying to intersect '" << prims[entry].name << "'\n";
|
|
||||||
}
|
}
|
||||||
|
//}
|
||||||
|
//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
|
bool WorldModel::IntersectPoint(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, AreaInfo& info) const
|
||||||
{
|
{
|
||||||
if (groupModels.empty())
|
if (groupModels.empty())
|
||||||
return false;
|
return false;
|
||||||
@@ -487,7 +491,7 @@ namespace VMAP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldModel::GetLocationInfo(const G3D::Vector3 &p, const G3D::Vector3 &down, float &dist, LocationInfo &info) const
|
bool WorldModel::GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const
|
||||||
{
|
{
|
||||||
if (groupModels.empty())
|
if (groupModels.empty())
|
||||||
return false;
|
return false;
|
||||||
@@ -503,7 +507,7 @@ namespace VMAP
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldModel::writeFile(const std::string &filename)
|
bool WorldModel::writeFile(const std::string& filename)
|
||||||
{
|
{
|
||||||
FILE* wf = fopen(filename.c_str(), "wb");
|
FILE* wf = fopen(filename.c_str(), "wb");
|
||||||
if (!wf)
|
if (!wf)
|
||||||
@@ -517,14 +521,14 @@ namespace VMAP
|
|||||||
if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false;
|
if (result && fwrite(&RootWMOID, sizeof(uint32), 1, wf) != 1) result = false;
|
||||||
|
|
||||||
// write group models
|
// write group models
|
||||||
count=groupModels.size();
|
count = groupModels.size();
|
||||||
if (count)
|
if (count)
|
||||||
{
|
{
|
||||||
if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false;
|
if (result && fwrite("GMOD", 1, 4, wf) != 4) result = false;
|
||||||
//chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count;
|
//chunkSize = sizeof(uint32)+ sizeof(GroupModel)*count;
|
||||||
//if (result && fwrite(&chunkSize, sizeof(uint32), 1, wf) != 1) result = false;
|
//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(&count, sizeof(uint32), 1, wf) != 1) result = false;
|
||||||
for (uint32 i=0; i<groupModels.size() && result; ++i)
|
for (uint32 i = 0; i < groupModels.size() && result; ++i)
|
||||||
result = groupModels[i].writeToFile(wf);
|
result = groupModels[i].writeToFile(wf);
|
||||||
|
|
||||||
// write group BIH
|
// write group BIH
|
||||||
@@ -536,7 +540,7 @@ namespace VMAP
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WorldModel::readFile(const std::string &filename)
|
bool WorldModel::readFile(const std::string& filename)
|
||||||
{
|
{
|
||||||
FILE* rf = fopen(filename.c_str(), "rb");
|
FILE* rf = fopen(filename.c_str(), "rb");
|
||||||
if (!rf)
|
if (!rf)
|
||||||
@@ -560,7 +564,7 @@ namespace VMAP
|
|||||||
if (result && fread(&count, 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) groupModels.resize(count);
|
||||||
//if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false;
|
//if (result && fread(&groupModels[0], sizeof(GroupModel), count, rf) != count) result = false;
|
||||||
for (uint32 i=0; i<count && result; ++i)
|
for (uint32 i = 0; i < count && result; ++i)
|
||||||
result = groupModels[i].readFromFile(rf);
|
result = groupModels[i].readFromFile(rf);
|
||||||
|
|
||||||
// read group BIH
|
// read group BIH
|
||||||
|
|||||||
@@ -23,94 +23,94 @@ namespace VMAP
|
|||||||
|
|
||||||
class MeshTriangle
|
class MeshTriangle
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MeshTriangle() : idx0(0), idx1(0), idx2(0) { }
|
MeshTriangle() : idx0(0), idx1(0), idx2(0) { }
|
||||||
MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { }
|
MeshTriangle(uint32 na, uint32 nb, uint32 nc): idx0(na), idx1(nb), idx2(nc) { }
|
||||||
|
|
||||||
uint32 idx0;
|
uint32 idx0;
|
||||||
uint32 idx1;
|
uint32 idx1;
|
||||||
uint32 idx2;
|
uint32 idx2;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WmoLiquid
|
class WmoLiquid
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WmoLiquid(uint32 width, uint32 height, const G3D::Vector3 &corner, uint32 type);
|
WmoLiquid(uint32 width, uint32 height, const G3D::Vector3& corner, uint32 type);
|
||||||
WmoLiquid(const WmoLiquid &other);
|
WmoLiquid(const WmoLiquid& other);
|
||||||
~WmoLiquid();
|
~WmoLiquid();
|
||||||
WmoLiquid& operator=(const WmoLiquid &other);
|
WmoLiquid& operator=(const WmoLiquid& other);
|
||||||
bool GetLiquidHeight(const G3D::Vector3 &pos, float &liqHeight) const;
|
bool GetLiquidHeight(const G3D::Vector3& pos, float& liqHeight) const;
|
||||||
uint32 GetType() const { return iType; }
|
uint32 GetType() const { return iType; }
|
||||||
float *GetHeightStorage() { return iHeight; }
|
float* GetHeightStorage() { return iHeight; }
|
||||||
uint8 *GetFlagsStorage() { return iFlags; }
|
uint8* GetFlagsStorage() { return iFlags; }
|
||||||
uint32 GetFileSize();
|
uint32 GetFileSize();
|
||||||
bool writeToFile(FILE* wf);
|
bool writeToFile(FILE* wf);
|
||||||
static bool readFromFile(FILE* rf, WmoLiquid* &liquid);
|
static bool readFromFile(FILE* rf, WmoLiquid*& liquid);
|
||||||
private:
|
private:
|
||||||
WmoLiquid(): iTilesX(0), iTilesY(0), iType(0), iHeight(0), iFlags(0) { }
|
WmoLiquid(): iTilesX(0), iTilesY(0), iType(0), iHeight(0), iFlags(0) { }
|
||||||
uint32 iTilesX; //!< number of tiles in x direction, each
|
uint32 iTilesX; //!< number of tiles in x direction, each
|
||||||
uint32 iTilesY;
|
uint32 iTilesY;
|
||||||
G3D::Vector3 iCorner; //!< the lower corner
|
G3D::Vector3 iCorner; //!< the lower corner
|
||||||
uint32 iType; //!< liquid type
|
uint32 iType; //!< liquid type
|
||||||
float *iHeight; //!< (tilesX + 1)*(tilesY + 1) height values
|
float* iHeight; //!< (tilesX + 1)*(tilesY + 1) height values
|
||||||
uint8 *iFlags; //!< info if liquid tile is used
|
uint8* iFlags; //!< info if liquid tile is used
|
||||||
public:
|
public:
|
||||||
void getPosInfo(uint32 &tilesX, uint32 &tilesY, G3D::Vector3 &corner) const;
|
void getPosInfo(uint32& tilesX, uint32& tilesY, G3D::Vector3& corner) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/*! holding additional info for WMO group files */
|
/*! holding additional info for WMO group files */
|
||||||
class GroupModel
|
class GroupModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GroupModel(): iMogpFlags(0), iGroupWMOID(0), iLiquid(0) { }
|
GroupModel(): iMogpFlags(0), iGroupWMOID(0), iLiquid(0) { }
|
||||||
GroupModel(const GroupModel &other);
|
GroupModel(const GroupModel& other);
|
||||||
GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox &bound):
|
GroupModel(uint32 mogpFlags, uint32 groupWMOID, const G3D::AABox& bound):
|
||||||
iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) { }
|
iBound(bound), iMogpFlags(mogpFlags), iGroupWMOID(groupWMOID), iLiquid(0) { }
|
||||||
~GroupModel() { delete iLiquid; }
|
~GroupModel() { delete iLiquid; }
|
||||||
|
|
||||||
//! pass mesh data to object and create BIH. Passed vectors get get swapped with old geometry!
|
//! 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 setMeshData(std::vector<G3D::Vector3>& vert, std::vector<MeshTriangle>& tri);
|
||||||
void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; }
|
void setLiquidData(WmoLiquid*& liquid) { iLiquid = liquid; liquid = NULL; }
|
||||||
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const;
|
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 IsInsideObject(const G3D::Vector3& pos, const G3D::Vector3& down, float& z_dist) const;
|
||||||
bool GetLiquidLevel(const G3D::Vector3 &pos, float &liqHeight) const;
|
bool GetLiquidLevel(const G3D::Vector3& pos, float& liqHeight) const;
|
||||||
uint32 GetLiquidType() const;
|
uint32 GetLiquidType() const;
|
||||||
bool writeToFile(FILE* wf);
|
bool writeToFile(FILE* wf);
|
||||||
bool readFromFile(FILE* rf);
|
bool readFromFile(FILE* rf);
|
||||||
const G3D::AABox& GetBound() const { return iBound; }
|
const G3D::AABox& GetBound() const { return iBound; }
|
||||||
uint32 GetMogpFlags() const { return iMogpFlags; }
|
uint32 GetMogpFlags() const { return iMogpFlags; }
|
||||||
uint32 GetWmoID() const { return iGroupWMOID; }
|
uint32 GetWmoID() const { return iGroupWMOID; }
|
||||||
protected:
|
protected:
|
||||||
G3D::AABox iBound;
|
G3D::AABox iBound;
|
||||||
uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor
|
uint32 iMogpFlags;// 0x8 outdor; 0x2000 indoor
|
||||||
uint32 iGroupWMOID;
|
uint32 iGroupWMOID;
|
||||||
std::vector<G3D::Vector3> vertices;
|
std::vector<G3D::Vector3> vertices;
|
||||||
std::vector<MeshTriangle> triangles;
|
std::vector<MeshTriangle> triangles;
|
||||||
BIH meshTree;
|
BIH meshTree;
|
||||||
WmoLiquid* iLiquid;
|
WmoLiquid* iLiquid;
|
||||||
public:
|
public:
|
||||||
void getMeshData(std::vector<G3D::Vector3> &vertices, std::vector<MeshTriangle> &triangles, WmoLiquid* &liquid);
|
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 */
|
/*! Holds a model (converted M2 or WMO) in its original coordinate space */
|
||||||
class WorldModel
|
class WorldModel
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WorldModel(): RootWMOID(0) { }
|
WorldModel(): RootWMOID(0) { }
|
||||||
|
|
||||||
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
|
//! pass group models to WorldModel and create BIH. Passed vector is swapped with old geometry!
|
||||||
void setGroupModels(std::vector<GroupModel> &models);
|
void setGroupModels(std::vector<GroupModel>& models);
|
||||||
void setRootWmoID(uint32 id) { RootWMOID = id; }
|
void setRootWmoID(uint32 id) { RootWMOID = id; }
|
||||||
bool IntersectRay(const G3D::Ray &ray, float &distance, bool stopAtFirstHit) const;
|
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 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 GetLocationInfo(const G3D::Vector3& p, const G3D::Vector3& down, float& dist, LocationInfo& info) const;
|
||||||
bool writeFile(const std::string &filename);
|
bool writeFile(const std::string& filename);
|
||||||
bool readFile(const std::string &filename);
|
bool readFile(const std::string& filename);
|
||||||
protected:
|
protected:
|
||||||
uint32 RootWMOID;
|
uint32 RootWMOID;
|
||||||
std::vector<GroupModel> groupModels;
|
std::vector<GroupModel> groupModels;
|
||||||
BIH groupTree;
|
BIH groupTree;
|
||||||
public:
|
public:
|
||||||
void getGroupModels(std::vector<GroupModel> &groupModels);
|
void getGroupModels(std::vector<GroupModel>& groupModels);
|
||||||
};
|
};
|
||||||
} // namespace VMAP
|
} // namespace VMAP
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ public:
|
|||||||
explicit NodeArray() { memset(&_nodes, 0, sizeof(_nodes)); }
|
explicit NodeArray() { memset(&_nodes, 0, sizeof(_nodes)); }
|
||||||
void AddNode(Node* n)
|
void AddNode(Node* n)
|
||||||
{
|
{
|
||||||
for (uint8 i=0; i<9; ++i)
|
for (uint8 i = 0; i < 9; ++i)
|
||||||
if (_nodes[i] == 0)
|
if (_nodes[i] == 0)
|
||||||
{
|
{
|
||||||
_nodes[i] = n;
|
_nodes[i] = n;
|
||||||
@@ -29,37 +29,41 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<class Node>
|
template<class Node>
|
||||||
struct NodeCreator{
|
struct NodeCreator
|
||||||
static Node * makeNode(int /*x*/, int /*y*/) { return new Node();}
|
{
|
||||||
|
static Node* makeNode(int /*x*/, int /*y*/) { return new Node();}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T,
|
template<class T,
|
||||||
class Node,
|
class Node,
|
||||||
class NodeCreatorFunc = NodeCreator<Node>,
|
class NodeCreatorFunc = NodeCreator<Node>,
|
||||||
/*class BoundsFunc = BoundsTrait<T>,*/
|
/*class BoundsFunc = BoundsTrait<T>,*/
|
||||||
class PositionFunc = PositionTrait<T>
|
class PositionFunc = PositionTrait<T>
|
||||||
>
|
>
|
||||||
class RegularGrid2D
|
class RegularGrid2D
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum{
|
enum
|
||||||
|
{
|
||||||
CELL_NUMBER = 64,
|
CELL_NUMBER = 64,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed
|
#define HGRID_MAP_SIZE (533.33333f * 64.f) // shouldn't be changed
|
||||||
#define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER)
|
#define CELL_SIZE float(HGRID_MAP_SIZE/(float)CELL_NUMBER)
|
||||||
|
|
||||||
typedef G3D::Table<const T*, NodeArray<Node> > MemberTable;
|
typedef G3D::Table<const T*, NodeArray<Node> > MemberTable;
|
||||||
|
|
||||||
MemberTable memberTable;
|
MemberTable memberTable;
|
||||||
Node* nodes[CELL_NUMBER][CELL_NUMBER];
|
Node* nodes[CELL_NUMBER][CELL_NUMBER];
|
||||||
|
|
||||||
RegularGrid2D(){
|
RegularGrid2D()
|
||||||
|
{
|
||||||
memset(nodes, 0, sizeof(nodes));
|
memset(nodes, 0, sizeof(nodes));
|
||||||
}
|
}
|
||||||
|
|
||||||
~RegularGrid2D(){
|
~RegularGrid2D()
|
||||||
|
{
|
||||||
for (int x = 0; x < CELL_NUMBER; ++x)
|
for (int x = 0; x < CELL_NUMBER; ++x)
|
||||||
for (int y = 0; y < CELL_NUMBER; ++y)
|
for (int y = 0; y < CELL_NUMBER; ++y)
|
||||||
delete nodes[x][y];
|
delete nodes[x][y];
|
||||||
@@ -72,14 +76,14 @@ public:
|
|||||||
pos[1] = value.getBounds().corner(1);
|
pos[1] = value.getBounds().corner(1);
|
||||||
pos[2] = value.getBounds().corner(2);
|
pos[2] = value.getBounds().corner(2);
|
||||||
pos[3] = value.getBounds().corner(3);
|
pos[3] = value.getBounds().corner(3);
|
||||||
pos[4] = (pos[0] + pos[1])/2.0f;
|
pos[4] = (pos[0] + pos[1]) / 2.0f;
|
||||||
pos[5] = (pos[1] + pos[2])/2.0f;
|
pos[5] = (pos[1] + pos[2]) / 2.0f;
|
||||||
pos[6] = (pos[2] + pos[3])/2.0f;
|
pos[6] = (pos[2] + pos[3]) / 2.0f;
|
||||||
pos[7] = (pos[3] + pos[0])/2.0f;
|
pos[7] = (pos[3] + pos[0]) / 2.0f;
|
||||||
pos[8] = (pos[0] + pos[2])/2.0f;
|
pos[8] = (pos[0] + pos[2]) / 2.0f;
|
||||||
|
|
||||||
NodeArray<Node> na;
|
NodeArray<Node> na;
|
||||||
for (uint8 i=0; i<9; ++i)
|
for (uint8 i = 0; i < 9; ++i)
|
||||||
{
|
{
|
||||||
Cell c = Cell::ComputeCell(pos[i].x, pos[i].y);
|
Cell c = Cell::ComputeCell(pos[i].x, pos[i].y);
|
||||||
if (!c.isValid())
|
if (!c.isValid())
|
||||||
@@ -88,7 +92,7 @@ public:
|
|||||||
na.AddNode(&node);
|
na.AddNode(&node);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8 i=0; i<9; ++i)
|
for (uint8 i = 0; i < 9; ++i)
|
||||||
{
|
{
|
||||||
if (na._nodes[i])
|
if (na._nodes[i])
|
||||||
na._nodes[i]->insert(value);
|
na._nodes[i]->insert(value);
|
||||||
@@ -102,7 +106,7 @@ public:
|
|||||||
void remove(const T& value)
|
void remove(const T& value)
|
||||||
{
|
{
|
||||||
NodeArray<Node>& na = memberTable[&value];
|
NodeArray<Node>& na = memberTable[&value];
|
||||||
for (uint8 i=0; i<9; ++i)
|
for (uint8 i = 0; i < 9; ++i)
|
||||||
{
|
{
|
||||||
if (na._nodes[i])
|
if (na._nodes[i])
|
||||||
na._nodes[i]->remove(value);
|
na._nodes[i]->remove(value);
|
||||||
@@ -132,7 +136,7 @@ public:
|
|||||||
|
|
||||||
static Cell ComputeCell(float fx, float fy)
|
static Cell ComputeCell(float fx, float fy)
|
||||||
{
|
{
|
||||||
Cell c = { int(fx * (1.f/CELL_SIZE) + (CELL_NUMBER/2)), int(fy * (1.f/CELL_SIZE) + (CELL_NUMBER/2)) };
|
Cell c = { int(fx * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)), int(fy * (1.f / CELL_SIZE) + (CELL_NUMBER / 2)) };
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,26 +189,26 @@ public:
|
|||||||
if (kx_inv >= 0)
|
if (kx_inv >= 0)
|
||||||
{
|
{
|
||||||
stepX = 1;
|
stepX = 1;
|
||||||
float x_border = (cell.x+1) * voxel;
|
float x_border = (cell.x + 1) * voxel;
|
||||||
tMaxX = (x_border - bx) * kx_inv;
|
tMaxX = (x_border - bx) * kx_inv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stepX = -1;
|
stepX = -1;
|
||||||
float x_border = (cell.x-1) * voxel;
|
float x_border = (cell.x - 1) * voxel;
|
||||||
tMaxX = (x_border - bx) * kx_inv;
|
tMaxX = (x_border - bx) * kx_inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ky_inv >= 0)
|
if (ky_inv >= 0)
|
||||||
{
|
{
|
||||||
stepY = 1;
|
stepY = 1;
|
||||||
float y_border = (cell.y+1) * voxel;
|
float y_border = (cell.y + 1) * voxel;
|
||||||
tMaxY = (y_border - by) * ky_inv;
|
tMaxY = (y_border - by) * ky_inv;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stepY = -1;
|
stepY = -1;
|
||||||
float y_border = (cell.y-1) * voxel;
|
float y_border = (cell.y - 1) * voxel;
|
||||||
tMaxY = (y_border - by) * ky_inv;
|
tMaxY = (y_border - by) * ky_inv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,6 @@ namespace VMAP
|
|||||||
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
|
const char GAMEOBJECT_MODELS[] = "GameObjectModels.dtree";
|
||||||
|
|
||||||
// defined in TileAssembler.cpp currently...
|
// defined in TileAssembler.cpp currently...
|
||||||
bool readChunk(FILE* rf, char *dest, const char *compare, uint32 len);
|
bool readChunk(FILE* rf, char* dest, const char* compare, uint32 len);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -21,13 +21,15 @@ The collision detection is modified to return true, if we are inside an object.
|
|||||||
namespace VMAP
|
namespace VMAP
|
||||||
{
|
{
|
||||||
template<class TValue>
|
template<class TValue>
|
||||||
class IntersectionCallBack {
|
class IntersectionCallBack
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
TValue* closestEntity;
|
TValue* closestEntity;
|
||||||
G3D::Vector3 hitLocation;
|
G3D::Vector3 hitLocation;
|
||||||
G3D::Vector3 hitNormal;
|
G3D::Vector3 hitNormal;
|
||||||
|
|
||||||
void operator()(const G3D::Ray& ray, const TValue* entity, bool StopAtFirstHit, float& distance) {
|
void operator()(const G3D::Ray& ray, const TValue* entity, bool StopAtFirstHit, float& distance)
|
||||||
|
{
|
||||||
entity->intersect(ray, distance, StopAtFirstHit, hitLocation, hitNormal);
|
entity->intersect(ray, distance, StopAtFirstHit, hitLocation, hitNormal);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -116,7 +118,7 @@ namespace VMAP
|
|||||||
{
|
{
|
||||||
location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
|
location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
|
||||||
if ((location[i] < MinB[i]) ||
|
if ((location[i] < MinB[i]) ||
|
||||||
(location[i] > MaxB[i]))
|
(location[i] > MaxB[i]))
|
||||||
{
|
{
|
||||||
// On this plane we're outside the box extents, so
|
// On this plane we're outside the box extents, so
|
||||||
// we miss the box
|
// we miss the box
|
||||||
|
|||||||
@@ -6,22 +6,23 @@
|
|||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
|
||||||
char const* localeNames[TOTAL_LOCALES] = {
|
char const* localeNames[TOTAL_LOCALES] =
|
||||||
"enUS",
|
{
|
||||||
"koKR",
|
"enUS",
|
||||||
"frFR",
|
"koKR",
|
||||||
"deDE",
|
"frFR",
|
||||||
"zhCN",
|
"deDE",
|
||||||
"zhTW",
|
"zhCN",
|
||||||
"esES",
|
"zhTW",
|
||||||
"esMX",
|
"esES",
|
||||||
"ruRU"
|
"esMX",
|
||||||
|
"ruRU"
|
||||||
};
|
};
|
||||||
|
|
||||||
LocaleConstant GetLocaleByName(const std::string& name)
|
LocaleConstant GetLocaleByName(const std::string& name)
|
||||||
{
|
{
|
||||||
for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
|
for (uint32 i = 0; i < TOTAL_LOCALES; ++i)
|
||||||
if (name==localeNames[i])
|
if (name == localeNames[i])
|
||||||
return LocaleConstant(i);
|
return LocaleConstant(i);
|
||||||
|
|
||||||
return LOCALE_enUS; // including enGB case
|
return LOCALE_enUS; // including enGB case
|
||||||
@@ -30,8 +31,8 @@ LocaleConstant GetLocaleByName(const std::string& name)
|
|||||||
void CleanStringForMysqlQuery(std::string& str)
|
void CleanStringForMysqlQuery(std::string& str)
|
||||||
{
|
{
|
||||||
std::string::size_type n = 0;
|
std::string::size_type n = 0;
|
||||||
while ((n=str.find('\\')) != str.npos) str.erase(n,1);
|
while ((n = str.find('\\')) != str.npos) str.erase(n, 1);
|
||||||
while ((n=str.find('"')) != str.npos) str.erase(n,1);
|
while ((n = str.find('"')) != str.npos) str.erase(n, 1);
|
||||||
while ((n=str.find('\'')) != str.npos) str.erase(n,1);
|
while ((n = str.find('\'')) != str.npos) str.erase(n, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -136,11 +136,11 @@ inline bool myisfinite(float f) { return isfinite(f) && !isnan(f); }
|
|||||||
enum TimeConstants
|
enum TimeConstants
|
||||||
{
|
{
|
||||||
MINUTE = 60,
|
MINUTE = 60,
|
||||||
HOUR = MINUTE*60,
|
HOUR = MINUTE * 60,
|
||||||
DAY = HOUR*24,
|
DAY = HOUR * 24,
|
||||||
WEEK = DAY*7,
|
WEEK = DAY * 7,
|
||||||
MONTH = DAY*30,
|
MONTH = DAY * 30,
|
||||||
YEAR = MONTH*12,
|
YEAR = MONTH * 12,
|
||||||
IN_MILLISECONDS = 1000
|
IN_MILLISECONDS = 1000
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -36,35 +36,35 @@ namespace acore
|
|||||||
template <class T>
|
template <class T>
|
||||||
class CheckedBufferOutputIterator
|
class CheckedBufferOutputIterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
using iterator_category = std::output_iterator_tag;
|
using iterator_category = std::output_iterator_tag;
|
||||||
using value_type = void;
|
using value_type = void;
|
||||||
using pointer = T*;
|
using pointer = T*;
|
||||||
using reference = T&;
|
using reference = T&;
|
||||||
using difference_type = std::ptrdiff_t;
|
using difference_type = std::ptrdiff_t;
|
||||||
|
|
||||||
CheckedBufferOutputIterator(T* buf, size_t n) : _buf(buf), _end(buf+n) {}
|
CheckedBufferOutputIterator(T* buf, size_t n) : _buf(buf), _end(buf + n) {}
|
||||||
|
|
||||||
T& operator*() const { check(); return *_buf; }
|
T& operator*() const { check(); return *_buf; }
|
||||||
CheckedBufferOutputIterator& operator++() { check(); ++_buf; return *this; }
|
CheckedBufferOutputIterator& operator++() { check(); ++_buf; return *this; }
|
||||||
CheckedBufferOutputIterator operator++(int) { CheckedBufferOutputIterator v = *this; operator++(); return v; }
|
CheckedBufferOutputIterator operator++(int) { CheckedBufferOutputIterator v = *this; operator++(); return v; }
|
||||||
|
|
||||||
size_t remaining() const { return (_end - _buf); }
|
size_t remaining() const { return (_end - _buf); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
T* _buf;
|
T* _buf;
|
||||||
T* _end;
|
T* _end;
|
||||||
void check() const
|
void check() const
|
||||||
{
|
{
|
||||||
if (!(_buf < _end))
|
if (!(_buf < _end))
|
||||||
throw std::out_of_range("index");
|
throw std::out_of_range("index");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Containers
|
namespace Containers
|
||||||
{
|
{
|
||||||
template<class T>
|
template<class T>
|
||||||
void RandomResizeList(std::list<T> &list, uint32 size)
|
void RandomResizeList(std::list<T>& list, uint32 size)
|
||||||
{
|
{
|
||||||
size_t list_size = list.size();
|
size_t list_size = list.size();
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ namespace acore
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class T, class Predicate>
|
template<class T, class Predicate>
|
||||||
void RandomResizeList(std::list<T> &list, Predicate& predicate, uint32 size)
|
void RandomResizeList(std::list<T>& list, Predicate& predicate, uint32 size)
|
||||||
{
|
{
|
||||||
//! First use predicate filter
|
//! First use predicate filter
|
||||||
std::list<T> listCopy;
|
std::list<T> listCopy;
|
||||||
|
|||||||
@@ -12,14 +12,14 @@
|
|||||||
|
|
||||||
class ARC4
|
class ARC4
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ARC4(uint32 len);
|
ARC4(uint32 len);
|
||||||
ARC4(uint8* seed, uint32 len);
|
ARC4(uint8* seed, uint32 len);
|
||||||
~ARC4();
|
~ARC4();
|
||||||
void Init(uint8* seed);
|
void Init(uint8* seed);
|
||||||
void UpdateData(int len, uint8* data);
|
void UpdateData(int len, uint8* data);
|
||||||
private:
|
private:
|
||||||
EVP_CIPHER_CTX* m_ctx;
|
EVP_CIPHER_CTX* m_ctx;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ void AuthCrypt::Init(BigNumber* K)
|
|||||||
{
|
{
|
||||||
uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
|
uint8 ServerEncryptionKey[SEED_KEY_SIZE] = { 0xCC, 0x98, 0xAE, 0x04, 0xE8, 0x97, 0xEA, 0xCA, 0x12, 0xDD, 0xC0, 0x93, 0x42, 0x91, 0x53, 0x57 };
|
||||||
HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey);
|
HmacHash serverEncryptHmac(SEED_KEY_SIZE, (uint8*)ServerEncryptionKey);
|
||||||
uint8 *encryptHash = serverEncryptHmac.ComputeHash(K);
|
uint8* encryptHash = serverEncryptHmac.ComputeHash(K);
|
||||||
|
|
||||||
uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
|
uint8 ServerDecryptionKey[SEED_KEY_SIZE] = { 0xC2, 0xB3, 0x72, 0x3C, 0xC6, 0xAE, 0xD9, 0xB5, 0x34, 0x3C, 0x53, 0xEE, 0x2F, 0x43, 0x67, 0xCE };
|
||||||
HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey);
|
HmacHash clientDecryptHmac(SEED_KEY_SIZE, (uint8*)ServerDecryptionKey);
|
||||||
uint8 *decryptHash = clientDecryptHmac.ComputeHash(K);
|
uint8* decryptHash = clientDecryptHmac.ComputeHash(K);
|
||||||
|
|
||||||
//ARC4 _serverDecrypt(encryptHash);
|
//ARC4 _serverDecrypt(encryptHash);
|
||||||
_clientDecrypt.Init(decryptHash);
|
_clientDecrypt.Init(decryptHash);
|
||||||
@@ -43,7 +43,7 @@ void AuthCrypt::Init(BigNumber* K)
|
|||||||
_initialized = true;
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
void AuthCrypt::DecryptRecv(uint8* data, size_t len)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
return;
|
return;
|
||||||
@@ -51,7 +51,7 @@ void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
|||||||
_clientDecrypt.UpdateData(len, data);
|
_clientDecrypt.UpdateData(len, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AuthCrypt::EncryptSend(uint8 *data, size_t len)
|
void AuthCrypt::EncryptSend(uint8* data, size_t len)
|
||||||
{
|
{
|
||||||
if (!_initialized)
|
if (!_initialized)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -13,18 +13,18 @@ class BigNumber;
|
|||||||
|
|
||||||
class AuthCrypt
|
class AuthCrypt
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AuthCrypt();
|
AuthCrypt();
|
||||||
|
|
||||||
void Init(BigNumber* K);
|
void Init(BigNumber* K);
|
||||||
void DecryptRecv(uint8 *, size_t);
|
void DecryptRecv(uint8*, size_t);
|
||||||
void EncryptSend(uint8 *, size_t);
|
void EncryptSend(uint8*, size_t);
|
||||||
|
|
||||||
bool IsInitialized() const { return _initialized; }
|
bool IsInitialized() const { return _initialized; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ARC4 _clientDecrypt;
|
ARC4 _clientDecrypt;
|
||||||
ARC4 _serverEncrypt;
|
ARC4 _serverEncrypt;
|
||||||
bool _initialized;
|
bool _initialized;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ BigNumber BigNumber::operator-=(BigNumber const& bn)
|
|||||||
|
|
||||||
BigNumber BigNumber::operator*=(BigNumber const& bn)
|
BigNumber BigNumber::operator*=(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BN_CTX *bnctx;
|
BN_CTX* bnctx;
|
||||||
|
|
||||||
bnctx = BN_CTX_new();
|
bnctx = BN_CTX_new();
|
||||||
BN_mul(_bn, _bn, bn._bn, bnctx);
|
BN_mul(_bn, _bn, bn._bn, bnctx);
|
||||||
@@ -98,7 +98,7 @@ BigNumber BigNumber::operator*=(BigNumber const& bn)
|
|||||||
|
|
||||||
BigNumber BigNumber::operator/=(BigNumber const& bn)
|
BigNumber BigNumber::operator/=(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BN_CTX *bnctx;
|
BN_CTX* bnctx;
|
||||||
|
|
||||||
bnctx = BN_CTX_new();
|
bnctx = BN_CTX_new();
|
||||||
BN_div(_bn, NULL, _bn, bn._bn, bnctx);
|
BN_div(_bn, NULL, _bn, bn._bn, bnctx);
|
||||||
@@ -109,7 +109,7 @@ BigNumber BigNumber::operator/=(BigNumber const& bn)
|
|||||||
|
|
||||||
BigNumber BigNumber::operator%=(BigNumber const& bn)
|
BigNumber BigNumber::operator%=(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BN_CTX *bnctx;
|
BN_CTX* bnctx;
|
||||||
|
|
||||||
bnctx = BN_CTX_new();
|
bnctx = BN_CTX_new();
|
||||||
BN_mod(_bn, _bn, bn._bn, bnctx);
|
BN_mod(_bn, _bn, bn._bn, bnctx);
|
||||||
@@ -121,7 +121,7 @@ BigNumber BigNumber::operator%=(BigNumber const& bn)
|
|||||||
BigNumber BigNumber::Exp(BigNumber const& bn)
|
BigNumber BigNumber::Exp(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BigNumber ret;
|
BigNumber ret;
|
||||||
BN_CTX *bnctx;
|
BN_CTX* bnctx;
|
||||||
|
|
||||||
bnctx = BN_CTX_new();
|
bnctx = BN_CTX_new();
|
||||||
BN_exp(ret._bn, _bn, bn._bn, bnctx);
|
BN_exp(ret._bn, _bn, bn._bn, bnctx);
|
||||||
@@ -133,7 +133,7 @@ BigNumber BigNumber::Exp(BigNumber const& bn)
|
|||||||
BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2)
|
BigNumber BigNumber::ModExp(BigNumber const& bn1, BigNumber const& bn2)
|
||||||
{
|
{
|
||||||
BigNumber ret;
|
BigNumber ret;
|
||||||
BN_CTX *bnctx;
|
BN_CTX* bnctx;
|
||||||
|
|
||||||
bnctx = BN_CTX_new();
|
bnctx = BN_CTX_new();
|
||||||
BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
|
BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
|
||||||
@@ -178,12 +178,12 @@ std::unique_ptr<uint8[]> BigNumber::AsByteArray(int32 minSize, bool littleEndian
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
char * BigNumber::AsHexStr() const
|
char* BigNumber::AsHexStr() const
|
||||||
{
|
{
|
||||||
return BN_bn2hex(_bn);
|
return BN_bn2hex(_bn);
|
||||||
}
|
}
|
||||||
|
|
||||||
char * BigNumber::AsDecStr() const
|
char* BigNumber::AsDecStr() const
|
||||||
{
|
{
|
||||||
return BN_bn2dec(_bn);
|
return BN_bn2dec(_bn);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,74 +17,74 @@ struct bignum_st;
|
|||||||
|
|
||||||
class BigNumber
|
class BigNumber
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BigNumber();
|
BigNumber();
|
||||||
BigNumber(BigNumber const& bn);
|
BigNumber(BigNumber const& bn);
|
||||||
BigNumber(uint32);
|
BigNumber(uint32);
|
||||||
~BigNumber();
|
~BigNumber();
|
||||||
|
|
||||||
void SetDword(uint32);
|
void SetDword(uint32);
|
||||||
void SetQword(uint64);
|
void SetQword(uint64);
|
||||||
void SetBinary(uint8 const* bytes, int32 len);
|
void SetBinary(uint8 const* bytes, int32 len);
|
||||||
void SetHexStr(char const* str);
|
void SetHexStr(char const* str);
|
||||||
|
|
||||||
void SetRand(int32 numbits);
|
void SetRand(int32 numbits);
|
||||||
|
|
||||||
BigNumber& operator=(BigNumber const& bn);
|
BigNumber& operator=(BigNumber const& bn);
|
||||||
|
|
||||||
BigNumber operator+=(BigNumber const& bn);
|
BigNumber operator+=(BigNumber const& bn);
|
||||||
BigNumber operator+(BigNumber const& bn)
|
BigNumber operator+(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BigNumber t(*this);
|
BigNumber t(*this);
|
||||||
return t += bn;
|
return t += bn;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigNumber operator-=(BigNumber const& bn);
|
BigNumber operator-=(BigNumber const& bn);
|
||||||
BigNumber operator-(BigNumber const& bn)
|
BigNumber operator-(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BigNumber t(*this);
|
BigNumber t(*this);
|
||||||
return t -= bn;
|
return t -= bn;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigNumber operator*=(BigNumber const& bn);
|
BigNumber operator*=(BigNumber const& bn);
|
||||||
BigNumber operator*(BigNumber const& bn)
|
BigNumber operator*(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BigNumber t(*this);
|
BigNumber t(*this);
|
||||||
return t *= bn;
|
return t *= bn;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigNumber operator/=(BigNumber const& bn);
|
BigNumber operator/=(BigNumber const& bn);
|
||||||
BigNumber operator/(BigNumber const& bn)
|
BigNumber operator/(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BigNumber t(*this);
|
BigNumber t(*this);
|
||||||
return t /= bn;
|
return t /= bn;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigNumber operator%=(BigNumber const& bn);
|
BigNumber operator%=(BigNumber const& bn);
|
||||||
BigNumber operator%(BigNumber const& bn)
|
BigNumber operator%(BigNumber const& bn)
|
||||||
{
|
{
|
||||||
BigNumber t(*this);
|
BigNumber t(*this);
|
||||||
return t %= bn;
|
return t %= bn;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isZero() const;
|
bool isZero() const;
|
||||||
|
|
||||||
BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2);
|
BigNumber ModExp(BigNumber const& bn1, BigNumber const& bn2);
|
||||||
BigNumber Exp(BigNumber const&);
|
BigNumber Exp(BigNumber const&);
|
||||||
|
|
||||||
int32 GetNumBytes(void);
|
int32 GetNumBytes(void);
|
||||||
|
|
||||||
struct bignum_st *BN() { return _bn; }
|
struct bignum_st* BN() { return _bn; }
|
||||||
|
|
||||||
uint32 AsDword();
|
uint32 AsDword();
|
||||||
|
|
||||||
std::unique_ptr<uint8[]> AsByteArray(int32 minSize = 0, bool littleEndian = true);
|
std::unique_ptr<uint8[]> AsByteArray(int32 minSize = 0, bool littleEndian = true);
|
||||||
|
|
||||||
char * AsHexStr() const;
|
char* AsHexStr() const;
|
||||||
char * AsDecStr() const;
|
char* AsDecStr() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct bignum_st *_bn;
|
struct bignum_st* _bn;
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
#if defined(OPENSSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
HMAC_CTX* HMAC_CTX_new()
|
HMAC_CTX* HMAC_CTX_new()
|
||||||
{
|
{
|
||||||
HMAC_CTX *ctx = new HMAC_CTX();
|
HMAC_CTX* ctx = new HMAC_CTX();
|
||||||
HMAC_CTX_init(ctx);
|
HMAC_CTX_init(ctx);
|
||||||
return ctx;
|
return ctx;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,18 +18,18 @@ class BigNumber;
|
|||||||
|
|
||||||
class HmacHash
|
class HmacHash
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
HmacHash(uint32 len, uint8* seed);
|
HmacHash(uint32 len, uint8* seed);
|
||||||
~HmacHash();
|
~HmacHash();
|
||||||
void UpdateData(std::string const& str);
|
void UpdateData(std::string const& str);
|
||||||
void UpdateData(uint8 const* data, size_t len);
|
void UpdateData(uint8 const* data, size_t len);
|
||||||
void Finalize();
|
void Finalize();
|
||||||
uint8* ComputeHash(BigNumber* bn);
|
uint8* ComputeHash(BigNumber* bn);
|
||||||
uint8* GetDigest() { return m_digest; }
|
uint8* GetDigest() { return m_digest; }
|
||||||
int GetLength() const { return SHA_DIGEST_LENGTH; }
|
int GetLength() const { return SHA_DIGEST_LENGTH; }
|
||||||
private:
|
private:
|
||||||
HMAC_CTX* m_ctx;
|
HMAC_CTX* m_ctx;
|
||||||
uint8 m_digest[SHA_DIGEST_LENGTH];
|
uint8 m_digest[SHA_DIGEST_LENGTH];
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ static void lockingCallback(int mode, int type, char const* /*file*/, int /*line
|
|||||||
else
|
else
|
||||||
cryptoLocks[type]->unlock();
|
cryptoLocks[type]->unlock();
|
||||||
}
|
}
|
||||||
static void threadIdCallback(CRYPTO_THREADID * id)
|
static void threadIdCallback(CRYPTO_THREADID* id)
|
||||||
{
|
{
|
||||||
(void)id;
|
(void)id;
|
||||||
CRYPTO_THREADID_set_numeric(id, std::hash<std::thread::id>()(std::this_thread::get_id()));
|
CRYPTO_THREADID_set_numeric(id, std::hash<std::thread::id>()(std::this_thread::get_id()));
|
||||||
|
|||||||
@@ -19,12 +19,12 @@ SHA1Hash::~SHA1Hash()
|
|||||||
SHA1_Init(&mC);
|
SHA1_Init(&mC);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Hash::UpdateData(const uint8 *dta, int len)
|
void SHA1Hash::UpdateData(const uint8* dta, int len)
|
||||||
{
|
{
|
||||||
SHA1_Update(&mC, dta, len);
|
SHA1_Update(&mC, dta, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHA1Hash::UpdateData(const std::string &str)
|
void SHA1Hash::UpdateData(const std::string& str)
|
||||||
{
|
{
|
||||||
UpdateData((uint8 const*)str.c_str(), str.length());
|
UpdateData((uint8 const*)str.c_str(), str.length());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,24 +15,24 @@ class BigNumber;
|
|||||||
|
|
||||||
class SHA1Hash
|
class SHA1Hash
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SHA1Hash();
|
SHA1Hash();
|
||||||
~SHA1Hash();
|
~SHA1Hash();
|
||||||
|
|
||||||
void UpdateBigNumbers(BigNumber* bn0, ...);
|
void UpdateBigNumbers(BigNumber* bn0, ...);
|
||||||
|
|
||||||
void UpdateData(const uint8 *dta, int len);
|
void UpdateData(const uint8* dta, int len);
|
||||||
void UpdateData(const std::string &str);
|
void UpdateData(const std::string& str);
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
void Finalize();
|
void Finalize();
|
||||||
|
|
||||||
uint8 *GetDigest(void) { return mDigest; };
|
uint8* GetDigest(void) { return mDigest; };
|
||||||
int GetLength(void) const { return SHA_DIGEST_LENGTH; };
|
int GetLength(void) const { return SHA_DIGEST_LENGTH; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SHA_CTX mC;
|
SHA_CTX mC;
|
||||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
uint8 mDigest[SHA_DIGEST_LENGTH];
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class SHA1Randx
|
|||||||
public:
|
public:
|
||||||
SHA1Randx(uint8* buff, uint32 size)
|
SHA1Randx(uint8* buff, uint32 size)
|
||||||
{
|
{
|
||||||
uint32 taken = size/2;
|
uint32 taken = size / 2;
|
||||||
|
|
||||||
sh.Initialize();
|
sh.Initialize();
|
||||||
sh.UpdateData(buff, taken);
|
sh.UpdateData(buff, taken);
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ bool DBCFileLoader::Load(char const* filename, char const* fmt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
data = new unsigned char[recordSize * recordCount + stringSize];
|
data = new unsigned char[recordSize * recordCount + stringSize];
|
||||||
stringTable = data + recordSize*recordCount;
|
stringTable = data + recordSize * recordCount;
|
||||||
|
|
||||||
if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1)
|
if (fread(data, recordSize * recordCount + stringSize, 1, f) != 1)
|
||||||
{
|
{
|
||||||
@@ -210,7 +210,7 @@ char* DBCFileLoader::AutoProduceData(char const* format, uint32& records, char**
|
|||||||
else
|
else
|
||||||
indexTable[y] = &dataTable[offset];
|
indexTable[y] = &dataTable[offset];
|
||||||
|
|
||||||
for (uint32 x=0; x < fieldCount; ++x)
|
for (uint32 x = 0; x < fieldCount; ++x)
|
||||||
{
|
{
|
||||||
switch (format[x])
|
switch (format[x])
|
||||||
{
|
{
|
||||||
@@ -275,17 +275,17 @@ char* DBCFileLoader::AutoProduceStrings(char const* format, char* dataTable)
|
|||||||
offset += sizeof(uint8);
|
offset += sizeof(uint8);
|
||||||
break;
|
break;
|
||||||
case FT_STRING:
|
case FT_STRING:
|
||||||
{
|
|
||||||
// fill only not filled entries
|
|
||||||
char** slot = (char**)(&dataTable[offset]);
|
|
||||||
if (!*slot || !**slot)
|
|
||||||
{
|
{
|
||||||
const char * st = getRecord(y).getString(x);
|
// fill only not filled entries
|
||||||
*slot = stringPool + (st - (char const*)stringTable);
|
char** slot = (char**)(&dataTable[offset]);
|
||||||
|
if (!*slot || !** slot)
|
||||||
|
{
|
||||||
|
const char* st = getRecord(y).getString(x);
|
||||||
|
*slot = stringPool + (st - (char const*)stringTable);
|
||||||
|
}
|
||||||
|
offset += sizeof(char*);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
offset += sizeof(char*);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FT_LOGIC:
|
case FT_LOGIC:
|
||||||
ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
|
ASSERT(false && "Attempted to load DBC files that does not have field types that match what is in the core. Check DBCfmt.h or your DBC files.");
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ public:
|
|||||||
DBCFileLoader();
|
DBCFileLoader();
|
||||||
~DBCFileLoader();
|
~DBCFileLoader();
|
||||||
|
|
||||||
bool Load(const char *filename, const char *fmt);
|
bool Load(const char* filename, const char* fmt);
|
||||||
|
|
||||||
class Record
|
class Record
|
||||||
{
|
{
|
||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
float getFloat(size_t field) const
|
float getFloat(size_t field) const
|
||||||
{
|
{
|
||||||
ASSERT(field < file.fieldCount);
|
ASSERT(field < file.fieldCount);
|
||||||
float val = *reinterpret_cast<float*>(offset+file.GetOffset(field));
|
float val = *reinterpret_cast<float*>(offset + file.GetOffset(field));
|
||||||
EndianConvert(val);
|
EndianConvert(val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -46,7 +46,7 @@ public:
|
|||||||
uint32 getUInt(size_t field) const
|
uint32 getUInt(size_t field) const
|
||||||
{
|
{
|
||||||
ASSERT(field < file.fieldCount);
|
ASSERT(field < file.fieldCount);
|
||||||
uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field));
|
uint32 val = *reinterpret_cast<uint32*>(offset + file.GetOffset(field));
|
||||||
EndianConvert(val);
|
EndianConvert(val);
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
@@ -54,10 +54,10 @@ public:
|
|||||||
uint8 getUInt8(size_t field) const
|
uint8 getUInt8(size_t field) const
|
||||||
{
|
{
|
||||||
ASSERT(field < file.fieldCount);
|
ASSERT(field < file.fieldCount);
|
||||||
return *reinterpret_cast<uint8*>(offset+file.GetOffset(field));
|
return *reinterpret_cast<uint8*>(offset + file.GetOffset(field));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getString(size_t field) const
|
const char* getString(size_t field) const
|
||||||
{
|
{
|
||||||
ASSERT(field < file.fieldCount);
|
ASSERT(field < file.fieldCount);
|
||||||
size_t stringOffset = getUInt(field);
|
size_t stringOffset = getUInt(field);
|
||||||
@@ -66,9 +66,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Record(DBCFileLoader &file_, unsigned char *offset_): offset(offset_), file(file_) { }
|
Record(DBCFileLoader& file_, unsigned char* offset_): offset(offset_), file(file_) { }
|
||||||
unsigned char *offset;
|
unsigned char* offset;
|
||||||
DBCFileLoader &file;
|
DBCFileLoader& file;
|
||||||
|
|
||||||
friend class DBCFileLoader;
|
friend class DBCFileLoader;
|
||||||
|
|
||||||
@@ -84,16 +84,16 @@ public:
|
|||||||
bool IsLoaded() const { return data != nullptr; }
|
bool IsLoaded() const { return data != nullptr; }
|
||||||
char* AutoProduceData(char const* fmt, uint32& count, char**& indexTable);
|
char* AutoProduceData(char const* fmt, uint32& count, char**& indexTable);
|
||||||
char* AutoProduceStrings(char const* fmt, char* dataTable);
|
char* AutoProduceStrings(char const* fmt, char* dataTable);
|
||||||
static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = nullptr);
|
static uint32 GetFormatRecordSize(const char* format, int32* index_pos = nullptr);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint32 recordSize;
|
uint32 recordSize;
|
||||||
uint32 recordCount;
|
uint32 recordCount;
|
||||||
uint32 fieldCount;
|
uint32 fieldCount;
|
||||||
uint32 stringSize;
|
uint32 stringSize;
|
||||||
uint32 *fieldsOffset;
|
uint32* fieldsOffset;
|
||||||
unsigned char *data;
|
unsigned char* data;
|
||||||
unsigned char *stringTable;
|
unsigned char* stringTable;
|
||||||
|
|
||||||
DBCFileLoader(DBCFileLoader const& right) = delete;
|
DBCFileLoader(DBCFileLoader const& right) = delete;
|
||||||
DBCFileLoader& operator=(DBCFileLoader const& right) = delete;
|
DBCFileLoader& operator=(DBCFileLoader const& right) = delete;
|
||||||
|
|||||||
@@ -9,14 +9,14 @@
|
|||||||
|
|
||||||
/*! Basic, ad-hoc queries. */
|
/*! Basic, ad-hoc queries. */
|
||||||
BasicStatementTask::BasicStatementTask(const char* sql) :
|
BasicStatementTask::BasicStatementTask(const char* sql) :
|
||||||
m_has_result(false)
|
m_has_result(false)
|
||||||
{
|
{
|
||||||
m_sql = strdup(sql);
|
m_sql = strdup(sql);
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicStatementTask::BasicStatementTask(const char* sql, QueryResultFuture result) :
|
BasicStatementTask::BasicStatementTask(const char* sql, QueryResultFuture result) :
|
||||||
m_has_result(true),
|
m_has_result(true),
|
||||||
m_result(result)
|
m_result(result)
|
||||||
{
|
{
|
||||||
m_sql = strdup(sql);
|
m_sql = strdup(sql);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ typedef ACE_Future<QueryResult> QueryResultFuture;
|
|||||||
/*! Raw, ad-hoc query. */
|
/*! Raw, ad-hoc query. */
|
||||||
class BasicStatementTask : public SQLOperation
|
class BasicStatementTask : public SQLOperation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BasicStatementTask(const char* sql);
|
BasicStatementTask(const char* sql);
|
||||||
BasicStatementTask(const char* sql, QueryResultFuture result);
|
BasicStatementTask(const char* sql, QueryResultFuture result);
|
||||||
~BasicStatementTask();
|
~BasicStatementTask();
|
||||||
|
|
||||||
bool Execute();
|
bool Execute();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const char* m_sql; //- Raw query to be executed
|
const char* m_sql; //- Raw query to be executed
|
||||||
bool m_has_result;
|
bool m_has_result;
|
||||||
QueryResultFuture m_result;
|
QueryResultFuture m_result;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -11,8 +11,8 @@
|
|||||||
#include "MySQLThreading.h"
|
#include "MySQLThreading.h"
|
||||||
|
|
||||||
DatabaseWorker::DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con) :
|
DatabaseWorker::DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con) :
|
||||||
m_queue(new_queue),
|
m_queue(new_queue),
|
||||||
m_conn(con)
|
m_conn(con)
|
||||||
{
|
{
|
||||||
/// Assign thread to task
|
/// Assign thread to task
|
||||||
activate();
|
activate();
|
||||||
@@ -23,7 +23,7 @@ int DatabaseWorker::svc()
|
|||||||
if (!m_queue)
|
if (!m_queue)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
SQLOperation *request = NULL;
|
SQLOperation* request = NULL;
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
request = (SQLOperation*)(m_queue->dequeue());
|
request = (SQLOperation*)(m_queue->dequeue());
|
||||||
|
|||||||
@@ -14,17 +14,17 @@ class MySQLConnection;
|
|||||||
|
|
||||||
class DatabaseWorker : protected ACE_Task_Base
|
class DatabaseWorker : protected ACE_Task_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con);
|
DatabaseWorker(ACE_Activation_Queue* new_queue, MySQLConnection* con);
|
||||||
|
|
||||||
///- Inherited from ACE_Task_Base
|
///- Inherited from ACE_Task_Base
|
||||||
int svc();
|
int svc();
|
||||||
int wait() { return ACE_Task_Base::wait(); }
|
int wait() { return ACE_Task_Base::wait(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DatabaseWorker() : ACE_Task_Base() { }
|
DatabaseWorker() : ACE_Task_Base() { }
|
||||||
ACE_Activation_Queue* m_queue;
|
ACE_Activation_Queue* m_queue;
|
||||||
MySQLConnection* m_conn;
|
MySQLConnection* m_conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -12,8 +12,8 @@
|
|||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
DatabaseWorkerPool<T>::DatabaseWorkerPool() :
|
DatabaseWorkerPool<T>::DatabaseWorkerPool() :
|
||||||
_mqueue(new ACE_Message_Queue<ACE_SYNCH>(2*1024*1024, 2*1024*1024)),
|
_mqueue(new ACE_Message_Queue<ACE_SYNCH>(2 * 1024 * 1024, 2 * 1024 * 1024)),
|
||||||
_queue(new ACE_Activation_Queue(_mqueue))
|
_queue(new ACE_Activation_Queue(_mqueue))
|
||||||
{
|
{
|
||||||
memset(_connectionCount, 0, sizeof(_connectionCount));
|
memset(_connectionCount, 0, sizeof(_connectionCount));
|
||||||
_connections.resize(IDX_SIZE);
|
_connections.resize(IDX_SIZE);
|
||||||
@@ -29,7 +29,7 @@ bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_thre
|
|||||||
_connectionInfo = MySQLConnectionInfo(infoString);
|
_connectionInfo = MySQLConnectionInfo(infoString);
|
||||||
|
|
||||||
sLog->outSQLDriver("Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
|
sLog->outSQLDriver("Opening DatabasePool '%s'. Asynchronous connections: %u, synchronous connections: %u.",
|
||||||
GetDatabaseName(), async_threads, synch_threads);
|
GetDatabaseName(), async_threads, synch_threads);
|
||||||
|
|
||||||
//! Open asynchronous connections (delayed operations)
|
//! Open asynchronous connections (delayed operations)
|
||||||
_connections[IDX_ASYNC].resize(async_threads);
|
_connections[IDX_ASYNC].resize(async_threads);
|
||||||
@@ -39,7 +39,7 @@ bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_thre
|
|||||||
res &= t->Open();
|
res &= t->Open();
|
||||||
if (res) // only check mysql version if connection is valid
|
if (res) // only check mysql version if connection is valid
|
||||||
WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "AzerothCore does not support MySQL versions below 5.6");
|
WPFatal(mysql_get_server_version(t->GetHandle()) >= MIN_MYSQL_SERVER_VERSION, "AzerothCore does not support MySQL versions below 5.6");
|
||||||
|
|
||||||
_connections[IDX_ASYNC][i] = t;
|
_connections[IDX_ASYNC][i] = t;
|
||||||
++_connectionCount[IDX_ASYNC];
|
++_connectionCount[IDX_ASYNC];
|
||||||
}
|
}
|
||||||
@@ -56,11 +56,11 @@ bool DatabaseWorkerPool<T>::Open(const std::string& infoString, uint8 async_thre
|
|||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(),
|
sLog->outSQLDriver("DatabasePool '%s' opened successfully. %u total connections running.", GetDatabaseName(),
|
||||||
(_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
|
(_connectionCount[IDX_SYNCH] + _connectionCount[IDX_ASYNC]));
|
||||||
else
|
else
|
||||||
sLog->outError("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
|
sLog->outError("DatabasePool %s NOT opened. There were errors opening the MySQL connections. Check your SQLDriverLogFile "
|
||||||
"for specific errors.", GetDatabaseName());
|
"for specific errors.", GetDatabaseName());
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ void DatabaseWorkerPool<T>::Close()
|
|||||||
}
|
}
|
||||||
|
|
||||||
sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
|
sLog->outSQLDriver("Asynchronous connections on DatabasePool '%s' terminated. Proceeding with synchronous connections.",
|
||||||
GetDatabaseName());
|
GetDatabaseName());
|
||||||
|
|
||||||
//! Shut down the synchronous connections
|
//! Shut down the synchronous connections
|
||||||
//! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
|
//! There's no need for locking the connection, because DatabaseWorkerPool<>::Close
|
||||||
@@ -212,7 +212,7 @@ SQLTransaction DatabaseWorkerPool<T>::BeginTransaction()
|
|||||||
template <class T>
|
template <class T>
|
||||||
void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction)
|
void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction)
|
||||||
{
|
{
|
||||||
#ifdef ACORE_DEBUG
|
#ifdef ACORE_DEBUG
|
||||||
//! Only analyze transaction weaknesses in Debug mode.
|
//! Only analyze transaction weaknesses in Debug mode.
|
||||||
//! Ideally we catch the faults in Debug mode and then correct them,
|
//! Ideally we catch the faults in Debug mode and then correct them,
|
||||||
//! so there's no need to waste these CPU cycles in Release mode.
|
//! so there's no need to waste these CPU cycles in Release mode.
|
||||||
@@ -227,7 +227,7 @@ void DatabaseWorkerPool<T>::CommitTransaction(SQLTransaction transaction)
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif // ACORE_DEBUG
|
#endif // ACORE_DEBUG
|
||||||
|
|
||||||
Enqueue(new TransactionTask(transaction));
|
Enqueue(new TransactionTask(transaction));
|
||||||
}
|
}
|
||||||
@@ -311,7 +311,7 @@ T* DatabaseWorkerPool<T>::GetFreeConnection()
|
|||||||
uint8 i = 0;
|
uint8 i = 0;
|
||||||
size_t num_cons = _connectionCount[IDX_SYNCH];
|
size_t num_cons = _connectionCount[IDX_SYNCH];
|
||||||
T* t = nullptr;
|
T* t = nullptr;
|
||||||
|
|
||||||
//! Block forever until a connection is free
|
//! Block forever until a connection is free
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -34,211 +34,211 @@ class PingOperation : public SQLOperation
|
|||||||
template <class T>
|
template <class T>
|
||||||
class DatabaseWorkerPool
|
class DatabaseWorkerPool
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Activity state */
|
/* Activity state */
|
||||||
DatabaseWorkerPool();
|
DatabaseWorkerPool();
|
||||||
|
|
||||||
~DatabaseWorkerPool() { }
|
~DatabaseWorkerPool() { }
|
||||||
|
|
||||||
bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads);
|
bool Open(const std::string& infoString, uint8 async_threads, uint8 synch_threads);
|
||||||
|
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Delayed one-way statement methods.
|
Delayed one-way statement methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Enqueues a one-way SQL operation in string format that will be executed asynchronously.
|
//! Enqueues a one-way SQL operation in string format that will be executed asynchronously.
|
||||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||||
void Execute(const char* sql);
|
void Execute(const char* sql);
|
||||||
|
|
||||||
//! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously.
|
//! Enqueues a one-way SQL operation in string format -with variable args- that will be executed asynchronously.
|
||||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||||
template<typename Format, typename... Args>
|
template<typename Format, typename... Args>
|
||||||
void PExecute(Format&& sql, Args&&... args)
|
void PExecute(Format&& sql, Args&& ... args)
|
||||||
{
|
{
|
||||||
if (acore::IsFormatEmptyOrNull(sql))
|
if (acore::IsFormatEmptyOrNull(sql))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Execute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
Execute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously.
|
//! Enqueues a one-way SQL operation in prepared statement format that will be executed asynchronously.
|
||||||
//! Statement must be prepared with CONNECTION_ASYNC flag.
|
//! Statement must be prepared with CONNECTION_ASYNC flag.
|
||||||
void Execute(PreparedStatement* stmt);
|
void Execute(PreparedStatement* stmt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Direct synchronous one-way statement methods.
|
Direct synchronous one-way statement methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Directly executes a one-way SQL operation in string format, that will block the calling thread until finished.
|
//! Directly executes a one-way SQL operation in string format, that will block the calling thread until finished.
|
||||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||||
void DirectExecute(const char* sql);
|
void DirectExecute(const char* sql);
|
||||||
|
|
||||||
//! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished.
|
//! Directly executes a one-way SQL operation in string format -with variable args-, that will block the calling thread until finished.
|
||||||
//! This method should only be used for queries that are only executed once, e.g during startup.
|
//! This method should only be used for queries that are only executed once, e.g during startup.
|
||||||
template<typename Format, typename... Args>
|
template<typename Format, typename... Args>
|
||||||
void DirectPExecute(Format&& sql, Args&&... args)
|
void DirectPExecute(Format&& sql, Args&& ... args)
|
||||||
{
|
{
|
||||||
if (acore::IsFormatEmptyOrNull(sql))
|
if (acore::IsFormatEmptyOrNull(sql))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
DirectExecute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
DirectExecute(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished.
|
//! Directly executes a one-way SQL operation in prepared statement format, that will block the calling thread until finished.
|
||||||
//! Statement must be prepared with the CONNECTION_SYNCH flag.
|
//! Statement must be prepared with the CONNECTION_SYNCH flag.
|
||||||
void DirectExecute(PreparedStatement* stmt);
|
void DirectExecute(PreparedStatement* stmt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Synchronous query (with resultset) methods.
|
Synchronous query (with resultset) methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Directly executes an SQL query in string format that will block the calling thread until finished.
|
//! Directly executes an SQL query in string format that will block the calling thread until finished.
|
||||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||||
QueryResult Query(const char* sql, T* conn = nullptr);
|
QueryResult Query(const char* sql, T* conn = nullptr);
|
||||||
|
|
||||||
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
|
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
|
||||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||||
template<typename Format, typename... Args>
|
template<typename Format, typename... Args>
|
||||||
QueryResult PQuery(Format&& sql, T* conn, Args&&... args)
|
QueryResult PQuery(Format&& sql, T* conn, Args&& ... args)
|
||||||
{
|
{
|
||||||
if (acore::IsFormatEmptyOrNull(sql))
|
if (acore::IsFormatEmptyOrNull(sql))
|
||||||
return QueryResult(nullptr);
|
return QueryResult(nullptr);
|
||||||
|
|
||||||
return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str(), conn);
|
return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str(), conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
|
//! Directly executes an SQL query in string format -with variable args- that will block the calling thread until finished.
|
||||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||||
template<typename Format, typename... Args>
|
template<typename Format, typename... Args>
|
||||||
QueryResult PQuery(Format&& sql, Args&&... args)
|
QueryResult PQuery(Format&& sql, Args&& ... args)
|
||||||
{
|
{
|
||||||
if (acore::IsFormatEmptyOrNull(sql))
|
if (acore::IsFormatEmptyOrNull(sql))
|
||||||
return QueryResult(nullptr);
|
return QueryResult(nullptr);
|
||||||
|
|
||||||
return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
return Query(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Directly executes an SQL query in prepared format that will block the calling thread until finished.
|
//! Directly executes an SQL query in prepared format that will block the calling thread until finished.
|
||||||
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
//! Returns reference counted auto pointer, no need for manual memory management in upper level code.
|
||||||
//! Statement must be prepared with CONNECTION_SYNCH flag.
|
//! Statement must be prepared with CONNECTION_SYNCH flag.
|
||||||
PreparedQueryResult Query(PreparedStatement* stmt);
|
PreparedQueryResult Query(PreparedStatement* stmt);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Asynchronous query (with resultset) methods.
|
Asynchronous query (with resultset) methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed.
|
//! Enqueues a query in string format that will set the value of the QueryResultFuture return object as soon as the query is executed.
|
||||||
//! The return value is then processed in ProcessQueryCallback methods.
|
//! The return value is then processed in ProcessQueryCallback methods.
|
||||||
QueryResultFuture AsyncQuery(const char* sql);
|
QueryResultFuture AsyncQuery(const char* sql);
|
||||||
|
|
||||||
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
|
//! Enqueues a query in string format -with variable args- that will set the value of the QueryResultFuture return object as soon as the query is executed.
|
||||||
//! The return value is then processed in ProcessQueryCallback methods.
|
//! The return value is then processed in ProcessQueryCallback methods.
|
||||||
template<typename Format, typename... Args>
|
template<typename Format, typename... Args>
|
||||||
QueryResultFuture AsyncPQuery(Format&& sql, Args&&... args)
|
QueryResultFuture AsyncPQuery(Format&& sql, Args&& ... args)
|
||||||
{
|
{
|
||||||
if (acore::IsFormatEmptyOrNull(sql))
|
if (acore::IsFormatEmptyOrNull(sql))
|
||||||
return QueryResult(nullptr);
|
return QueryResult(nullptr);
|
||||||
|
|
||||||
return AsyncQuery(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
return AsyncQuery(acore::StringFormat(std::forward<Format>(sql), std::forward<Args>(args)...).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
|
//! Enqueues a query in prepared format that will set the value of the PreparedQueryResultFuture return object as soon as the query is executed.
|
||||||
//! The return value is then processed in ProcessQueryCallback methods.
|
//! The return value is then processed in ProcessQueryCallback methods.
|
||||||
//! Statement must be prepared with CONNECTION_ASYNC flag.
|
//! Statement must be prepared with CONNECTION_ASYNC flag.
|
||||||
PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt);
|
PreparedQueryResultFuture AsyncQuery(PreparedStatement* stmt);
|
||||||
|
|
||||||
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
|
//! Enqueues a vector of SQL operations (can be both adhoc and prepared) that will set the value of the QueryResultHolderFuture
|
||||||
//! return object as soon as the query is executed.
|
//! return object as soon as the query is executed.
|
||||||
//! The return value is then processed in ProcessQueryCallback methods.
|
//! The return value is then processed in ProcessQueryCallback methods.
|
||||||
//! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag.
|
//! Any prepared statements added to this holder need to be prepared with the CONNECTION_ASYNC flag.
|
||||||
QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder);
|
QueryResultHolderFuture DelayQueryHolder(SQLQueryHolder* holder);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Transaction context methods.
|
Transaction context methods.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Begins an automanaged transaction pointer that will automatically rollback if not commited. (Autocommit=0)
|
//! Begins an automanaged transaction pointer that will automatically rollback if not commited. (Autocommit=0)
|
||||||
SQLTransaction BeginTransaction();
|
SQLTransaction BeginTransaction();
|
||||||
|
|
||||||
//! Enqueues a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
|
//! Enqueues a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
|
||||||
//! were appended to the transaction will be respected during execution.
|
//! were appended to the transaction will be respected during execution.
|
||||||
void CommitTransaction(SQLTransaction transaction);
|
void CommitTransaction(SQLTransaction transaction);
|
||||||
|
|
||||||
//! Directly executes a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
|
//! Directly executes a collection of one-way SQL operations (can be both adhoc and prepared). The order in which these operations
|
||||||
//! were appended to the transaction will be respected during execution.
|
//! were appended to the transaction will be respected during execution.
|
||||||
void DirectCommitTransaction(SQLTransaction& transaction);
|
void DirectCommitTransaction(SQLTransaction& transaction);
|
||||||
|
|
||||||
//! Method used to execute prepared statements in a diverse context.
|
//! Method used to execute prepared statements in a diverse context.
|
||||||
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
|
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
|
||||||
void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt);
|
void ExecuteOrAppend(SQLTransaction& trans, PreparedStatement* stmt);
|
||||||
|
|
||||||
//! Method used to execute ad-hoc statements in a diverse context.
|
//! Method used to execute ad-hoc statements in a diverse context.
|
||||||
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
|
//! Will be wrapped in a transaction if valid object is present, otherwise executed standalone.
|
||||||
void ExecuteOrAppend(SQLTransaction& trans, const char* sql);
|
void ExecuteOrAppend(SQLTransaction& trans, const char* sql);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Other
|
Other
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//! Automanaged (internally) pointer to a prepared statement object for usage in upper level code.
|
//! Automanaged (internally) pointer to a prepared statement object for usage in upper level code.
|
||||||
//! Pointer is deleted in this->DirectExecute(PreparedStatement*), this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask.
|
//! Pointer is deleted in this->DirectExecute(PreparedStatement*), this->Query(PreparedStatement*) or PreparedStatementTask::~PreparedStatementTask.
|
||||||
//! This object is not tied to the prepared statement on the MySQL context yet until execution.
|
//! This object is not tied to the prepared statement on the MySQL context yet until execution.
|
||||||
PreparedStatement* GetPreparedStatement(uint32 index);
|
PreparedStatement* GetPreparedStatement(uint32 index);
|
||||||
|
|
||||||
//! Apply escape string'ing for current collation. (utf8)
|
//! Apply escape string'ing for current collation. (utf8)
|
||||||
unsigned long EscapeString(char* to, const char* from, unsigned long length)
|
unsigned long EscapeString(char* to, const char* from, unsigned long length)
|
||||||
{
|
{
|
||||||
if (!to || !from || !length)
|
if (!to || !from || !length)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return mysql_real_escape_string(_connections[IDX_SYNCH][0]->GetHandle(), to, from, length);
|
return mysql_real_escape_string(_connections[IDX_SYNCH][0]->GetHandle(), to, from, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Keeps all our MySQL connections alive, prevent the server from disconnecting us.
|
//! Keeps all our MySQL connections alive, prevent the server from disconnecting us.
|
||||||
void KeepAlive();
|
void KeepAlive();
|
||||||
|
|
||||||
char const* GetDatabaseName() const
|
char const* GetDatabaseName() const
|
||||||
{
|
{
|
||||||
return _connectionInfo.database.c_str();
|
return _connectionInfo.database.c_str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EscapeString(std::string& str)
|
void EscapeString(std::string& str)
|
||||||
{
|
{
|
||||||
if (str.empty())
|
if (str.empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
char* buf = new char[str.size() * 2 + 1];
|
char* buf = new char[str.size() * 2 + 1];
|
||||||
EscapeString(buf, str.c_str(), str.size());
|
EscapeString(buf, str.c_str(), str.size());
|
||||||
str = buf;
|
str = buf;
|
||||||
delete[] buf;
|
delete[] buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void Enqueue(SQLOperation* op)
|
void Enqueue(SQLOperation* op)
|
||||||
{
|
{
|
||||||
_queue->enqueue(op);
|
_queue->enqueue(op);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Gets a free connection in the synchronous connection pool.
|
//! Gets a free connection in the synchronous connection pool.
|
||||||
//! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks.
|
//! Caller MUST call t->Unlock() after touching the MySQL context to prevent deadlocks.
|
||||||
T* GetFreeConnection();
|
T* GetFreeConnection();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum _internalIndex
|
enum _internalIndex
|
||||||
{
|
{
|
||||||
IDX_ASYNC,
|
IDX_ASYNC,
|
||||||
IDX_SYNCH,
|
IDX_SYNCH,
|
||||||
IDX_SIZE
|
IDX_SIZE
|
||||||
};
|
};
|
||||||
|
|
||||||
ACE_Message_Queue<ACE_SYNCH>* _mqueue;
|
ACE_Message_Queue<ACE_SYNCH>* _mqueue;
|
||||||
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
|
ACE_Activation_Queue* _queue; //! Queue shared by async worker threads.
|
||||||
std::vector<std::vector<T*>> _connections;
|
std::vector<std::vector<T*>> _connections;
|
||||||
uint32 _connectionCount[2]; //! Counter of MySQL connections;
|
uint32 _connectionCount[2]; //! Counter of MySQL connections;
|
||||||
MySQLConnectionInfo _connectionInfo;
|
MySQLConnectionInfo _connectionInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ void Field::SetStructuredValue(char* newValue, enum_field_types newType)
|
|||||||
if (newValue)
|
if (newValue)
|
||||||
{
|
{
|
||||||
size_t size = strlen(newValue);
|
size_t size = strlen(newValue);
|
||||||
data.value = new char [size+1];
|
data.value = new char [size + 1];
|
||||||
strcpy((char*)data.value, newValue);
|
strcpy((char*)data.value, newValue);
|
||||||
data.length = size;
|
data.length = size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,369 +17,396 @@ class Field
|
|||||||
friend class ResultSet;
|
friend class ResultSet;
|
||||||
friend class PreparedResultSet;
|
friend class PreparedResultSet;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool GetBool() const // Wrapper, actually gets integer
|
bool GetBool() const // Wrapper, actually gets integer
|
||||||
|
{
|
||||||
|
return (GetUInt8() == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 GetUInt8() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_TINY))
|
||||||
{
|
{
|
||||||
return (GetUInt8() == 1);
|
sLog->outSQLDriver("Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
}
|
return 0;
|
||||||
|
|
||||||
uint8 GetUInt8() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_TINY))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetUInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<uint8*>(data.value);
|
|
||||||
return static_cast<uint8>(atol((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
int8 GetInt8() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_TINY))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<int8*>(data.value);
|
|
||||||
return static_cast<int8>(atol((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ELUNA
|
|
||||||
enum_field_types GetType() const
|
|
||||||
{
|
|
||||||
return data.type;
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint16 GetUInt16() const
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<uint8*>(data.value);
|
||||||
|
return static_cast<uint8>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
int8 GetInt8() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_TINY))
|
||||||
{
|
{
|
||||||
if (!data.value)
|
sLog->outSQLDriver("Warning: GetInt8() on non-tinyint field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<int8*>(data.value);
|
||||||
|
return static_cast<int8>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef ELUNA
|
||||||
|
enum_field_types GetType() const
|
||||||
|
{
|
||||||
|
return data.type;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16 GetUInt16() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<uint16*>(data.value);
|
||||||
|
return static_cast<uint16>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
int16 GetInt16() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<int16*>(data.value);
|
||||||
|
return static_cast<int16>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 GetUInt32() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<uint32*>(data.value);
|
||||||
|
return static_cast<uint32>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 GetInt32() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<int32*>(data.value);
|
||||||
|
return static_cast<int32>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64 GetUInt64() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<uint64*>(data.value);
|
||||||
|
return static_cast<uint64>(atol((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 GetInt64() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<int64*>(data.value);
|
||||||
|
return static_cast<int64>(strtol((char*)data.value, NULL, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
float GetFloat() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_FLOAT))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<float*>(data.value);
|
||||||
|
return static_cast<float>(atof((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
double GetDouble() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return 0.0f;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (!IsType(MYSQL_TYPE_DOUBLE))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return 0.0f;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
return *reinterpret_cast<double*>(data.value);
|
||||||
|
return static_cast<double>(atof((char*)data.value));
|
||||||
|
}
|
||||||
|
|
||||||
|
char const* GetCString() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
if (IsNumeric())
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
return static_cast<char const*>(data.value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetString() const
|
||||||
|
{
|
||||||
|
if (!data.value)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
if (data.raw)
|
||||||
|
{
|
||||||
|
char const* string = GetCString();
|
||||||
|
if (!string)
|
||||||
|
string = "";
|
||||||
|
return std::string(string, data.length);
|
||||||
|
}
|
||||||
|
return std::string((char*)data.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNull() const
|
||||||
|
{
|
||||||
|
return data.value == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Field();
|
||||||
|
~Field();
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma pack(1)
|
||||||
|
#else
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
#endif
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
uint32 length; // Length (prepared strings only)
|
||||||
|
void* value; // Actual data in memory
|
||||||
|
enum_field_types type; // Field type
|
||||||
|
bool raw; // Raw bytes? (Prepared statement or ad hoc)
|
||||||
|
} data;
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma pack()
|
||||||
|
#else
|
||||||
|
#pragma pack(pop)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length);
|
||||||
|
void SetStructuredValue(char* newValue, enum_field_types newType);
|
||||||
|
|
||||||
|
void CleanUp()
|
||||||
|
{
|
||||||
|
delete[] ((char*)data.value);
|
||||||
|
data.value = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t SizeForType(MYSQL_FIELD* field)
|
||||||
|
{
|
||||||
|
switch (field->type)
|
||||||
|
{
|
||||||
|
case MYSQL_TYPE_NULL:
|
||||||
return 0;
|
return 0;
|
||||||
|
case MYSQL_TYPE_TINY:
|
||||||
|
return 1;
|
||||||
|
case MYSQL_TYPE_YEAR:
|
||||||
|
case MYSQL_TYPE_SHORT:
|
||||||
|
return 2;
|
||||||
|
case MYSQL_TYPE_INT24:
|
||||||
|
case MYSQL_TYPE_LONG:
|
||||||
|
case MYSQL_TYPE_FLOAT:
|
||||||
|
return 4;
|
||||||
|
case MYSQL_TYPE_DOUBLE:
|
||||||
|
case MYSQL_TYPE_LONGLONG:
|
||||||
|
case MYSQL_TYPE_BIT:
|
||||||
|
return 8;
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
|
case MYSQL_TYPE_DATE:
|
||||||
{
|
case MYSQL_TYPE_TIME:
|
||||||
sLog->outSQLDriver("Warning: GetUInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
case MYSQL_TYPE_DATETIME:
|
||||||
|
return sizeof(MYSQL_TIME);
|
||||||
|
|
||||||
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||||
|
case MYSQL_TYPE_LONG_BLOB:
|
||||||
|
case MYSQL_TYPE_BLOB:
|
||||||
|
case MYSQL_TYPE_STRING:
|
||||||
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
|
return field->max_length + 1;
|
||||||
|
|
||||||
|
case MYSQL_TYPE_DECIMAL:
|
||||||
|
case MYSQL_TYPE_NEWDECIMAL:
|
||||||
|
return 64;
|
||||||
|
|
||||||
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
|
/*
|
||||||
|
Following types are not sent over the wire:
|
||||||
|
MYSQL_TYPE_ENUM:
|
||||||
|
MYSQL_TYPE_SET:
|
||||||
|
*/
|
||||||
|
default:
|
||||||
|
sLog->outSQLDriver("SQL::SizeForType(): invalid field type %u", uint32(field->type));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<uint16*>(data.value);
|
|
||||||
return static_cast<uint16>(atol((char*)data.value));
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int16 GetInt16() const
|
bool IsType(enum_field_types type) const
|
||||||
|
{
|
||||||
|
return data.type == type;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsNumeric() const
|
||||||
|
{
|
||||||
|
return (data.type == MYSQL_TYPE_TINY ||
|
||||||
|
data.type == MYSQL_TYPE_SHORT ||
|
||||||
|
data.type == MYSQL_TYPE_INT24 ||
|
||||||
|
data.type == MYSQL_TYPE_LONG ||
|
||||||
|
data.type == MYSQL_TYPE_FLOAT ||
|
||||||
|
data.type == MYSQL_TYPE_DOUBLE ||
|
||||||
|
data.type == MYSQL_TYPE_LONGLONG );
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
#ifdef ACORE_DEBUG
|
||||||
|
static char const* FieldTypeToString(enum_field_types type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
{
|
{
|
||||||
if (!data.value)
|
case MYSQL_TYPE_BIT:
|
||||||
return 0;
|
return "BIT";
|
||||||
|
case MYSQL_TYPE_BLOB:
|
||||||
#ifdef ACORE_DEBUG
|
return "BLOB";
|
||||||
if (!IsType(MYSQL_TYPE_SHORT) && !IsType(MYSQL_TYPE_YEAR))
|
case MYSQL_TYPE_DATE:
|
||||||
{
|
return "DATE";
|
||||||
sLog->outSQLDriver("Warning: GetInt16() on non-smallint field. Using type: %s.", FieldTypeToString(data.type));
|
case MYSQL_TYPE_DATETIME:
|
||||||
return 0;
|
return "DATETIME";
|
||||||
}
|
case MYSQL_TYPE_NEWDECIMAL:
|
||||||
#endif
|
return "NEWDECIMAL";
|
||||||
|
case MYSQL_TYPE_DECIMAL:
|
||||||
if (data.raw)
|
return "DECIMAL";
|
||||||
return *reinterpret_cast<int16*>(data.value);
|
case MYSQL_TYPE_DOUBLE:
|
||||||
return static_cast<int16>(atol((char*)data.value));
|
return "DOUBLE";
|
||||||
|
case MYSQL_TYPE_ENUM:
|
||||||
|
return "ENUM";
|
||||||
|
case MYSQL_TYPE_FLOAT:
|
||||||
|
return "FLOAT";
|
||||||
|
case MYSQL_TYPE_GEOMETRY:
|
||||||
|
return "GEOMETRY";
|
||||||
|
case MYSQL_TYPE_INT24:
|
||||||
|
return "INT24";
|
||||||
|
case MYSQL_TYPE_LONG:
|
||||||
|
return "LONG";
|
||||||
|
case MYSQL_TYPE_LONGLONG:
|
||||||
|
return "LONGLONG";
|
||||||
|
case MYSQL_TYPE_LONG_BLOB:
|
||||||
|
return "LONG_BLOB";
|
||||||
|
case MYSQL_TYPE_MEDIUM_BLOB:
|
||||||
|
return "MEDIUM_BLOB";
|
||||||
|
case MYSQL_TYPE_NEWDATE:
|
||||||
|
return "NEWDATE";
|
||||||
|
case MYSQL_TYPE_NULL:
|
||||||
|
return "NULL";
|
||||||
|
case MYSQL_TYPE_SET:
|
||||||
|
return "SET";
|
||||||
|
case MYSQL_TYPE_SHORT:
|
||||||
|
return "SHORT";
|
||||||
|
case MYSQL_TYPE_STRING:
|
||||||
|
return "STRING";
|
||||||
|
case MYSQL_TYPE_TIME:
|
||||||
|
return "TIME";
|
||||||
|
case MYSQL_TYPE_TIMESTAMP:
|
||||||
|
return "TIMESTAMP";
|
||||||
|
case MYSQL_TYPE_TINY:
|
||||||
|
return "TINY";
|
||||||
|
case MYSQL_TYPE_TINY_BLOB:
|
||||||
|
return "TINY_BLOB";
|
||||||
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
|
return "VAR_STRING";
|
||||||
|
case MYSQL_TYPE_YEAR:
|
||||||
|
return "YEAR";
|
||||||
|
default:
|
||||||
|
return "-Unknown-";
|
||||||
}
|
}
|
||||||
|
}
|
||||||
uint32 GetUInt32() const
|
#endif
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetUInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<uint32*>(data.value);
|
|
||||||
return static_cast<uint32>(atol((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 GetInt32() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_INT24) && !IsType(MYSQL_TYPE_LONG))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetInt32() on non-(medium)int field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<int32*>(data.value);
|
|
||||||
return static_cast<int32>(atol((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64 GetUInt64() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetUInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<uint64*>(data.value);
|
|
||||||
return static_cast<uint64>(atol((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
int64 GetInt64() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_LONGLONG) && !IsType(MYSQL_TYPE_BIT))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetInt64() on non-bigint field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<int64*>(data.value);
|
|
||||||
return static_cast<int64>(strtol((char*)data.value, NULL, 10));
|
|
||||||
}
|
|
||||||
|
|
||||||
float GetFloat() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_FLOAT))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetFloat() on non-float field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<float*>(data.value);
|
|
||||||
return static_cast<float>(atof((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
double GetDouble() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return 0.0f;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (!IsType(MYSQL_TYPE_DOUBLE))
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Warning: GetDouble() on non-double field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return 0.0f;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
return *reinterpret_cast<double*>(data.value);
|
|
||||||
return static_cast<double>(atof((char*)data.value));
|
|
||||||
}
|
|
||||||
|
|
||||||
char const* GetCString() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
if (IsNumeric())
|
|
||||||
{
|
|
||||||
sLog->outSQLDriver("Error: GetCString() on numeric field. Using type: %s.", FieldTypeToString(data.type));
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return static_cast<char const*>(data.value);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetString() const
|
|
||||||
{
|
|
||||||
if (!data.value)
|
|
||||||
return "";
|
|
||||||
|
|
||||||
if (data.raw)
|
|
||||||
{
|
|
||||||
char const* string = GetCString();
|
|
||||||
if (!string)
|
|
||||||
string = "";
|
|
||||||
return std::string(string, data.length);
|
|
||||||
}
|
|
||||||
return std::string((char*)data.value);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsNull() const
|
|
||||||
{
|
|
||||||
return data.value == NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
Field();
|
|
||||||
~Field();
|
|
||||||
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#pragma pack(1)
|
|
||||||
#else
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
#endif
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
uint32 length; // Length (prepared strings only)
|
|
||||||
void* value; // Actual data in memory
|
|
||||||
enum_field_types type; // Field type
|
|
||||||
bool raw; // Raw bytes? (Prepared statement or ad hoc)
|
|
||||||
} data;
|
|
||||||
#if defined(__GNUC__)
|
|
||||||
#pragma pack()
|
|
||||||
#else
|
|
||||||
#pragma pack(pop)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SetByteValue(void const* newValue, size_t const newSize, enum_field_types newType, uint32 length);
|
|
||||||
void SetStructuredValue(char* newValue, enum_field_types newType);
|
|
||||||
|
|
||||||
void CleanUp()
|
|
||||||
{
|
|
||||||
delete[] ((char*)data.value);
|
|
||||||
data.value = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t SizeForType(MYSQL_FIELD* field)
|
|
||||||
{
|
|
||||||
switch (field->type)
|
|
||||||
{
|
|
||||||
case MYSQL_TYPE_NULL:
|
|
||||||
return 0;
|
|
||||||
case MYSQL_TYPE_TINY:
|
|
||||||
return 1;
|
|
||||||
case MYSQL_TYPE_YEAR:
|
|
||||||
case MYSQL_TYPE_SHORT:
|
|
||||||
return 2;
|
|
||||||
case MYSQL_TYPE_INT24:
|
|
||||||
case MYSQL_TYPE_LONG:
|
|
||||||
case MYSQL_TYPE_FLOAT:
|
|
||||||
return 4;
|
|
||||||
case MYSQL_TYPE_DOUBLE:
|
|
||||||
case MYSQL_TYPE_LONGLONG:
|
|
||||||
case MYSQL_TYPE_BIT:
|
|
||||||
return 8;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_TIMESTAMP:
|
|
||||||
case MYSQL_TYPE_DATE:
|
|
||||||
case MYSQL_TYPE_TIME:
|
|
||||||
case MYSQL_TYPE_DATETIME:
|
|
||||||
return sizeof(MYSQL_TIME);
|
|
||||||
|
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
||||||
case MYSQL_TYPE_LONG_BLOB:
|
|
||||||
case MYSQL_TYPE_BLOB:
|
|
||||||
case MYSQL_TYPE_STRING:
|
|
||||||
case MYSQL_TYPE_VAR_STRING:
|
|
||||||
return field->max_length + 1;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_DECIMAL:
|
|
||||||
case MYSQL_TYPE_NEWDECIMAL:
|
|
||||||
return 64;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_GEOMETRY:
|
|
||||||
/*
|
|
||||||
Following types are not sent over the wire:
|
|
||||||
MYSQL_TYPE_ENUM:
|
|
||||||
MYSQL_TYPE_SET:
|
|
||||||
*/
|
|
||||||
default:
|
|
||||||
sLog->outSQLDriver("SQL::SizeForType(): invalid field type %u", uint32(field->type));
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsType(enum_field_types type) const
|
|
||||||
{
|
|
||||||
return data.type == type;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool IsNumeric() const
|
|
||||||
{
|
|
||||||
return (data.type == MYSQL_TYPE_TINY ||
|
|
||||||
data.type == MYSQL_TYPE_SHORT ||
|
|
||||||
data.type == MYSQL_TYPE_INT24 ||
|
|
||||||
data.type == MYSQL_TYPE_LONG ||
|
|
||||||
data.type == MYSQL_TYPE_FLOAT ||
|
|
||||||
data.type == MYSQL_TYPE_DOUBLE ||
|
|
||||||
data.type == MYSQL_TYPE_LONGLONG );
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
#ifdef ACORE_DEBUG
|
|
||||||
static char const* FieldTypeToString(enum_field_types type)
|
|
||||||
{
|
|
||||||
switch (type)
|
|
||||||
{
|
|
||||||
case MYSQL_TYPE_BIT: return "BIT";
|
|
||||||
case MYSQL_TYPE_BLOB: return "BLOB";
|
|
||||||
case MYSQL_TYPE_DATE: return "DATE";
|
|
||||||
case MYSQL_TYPE_DATETIME: return "DATETIME";
|
|
||||||
case MYSQL_TYPE_NEWDECIMAL: return "NEWDECIMAL";
|
|
||||||
case MYSQL_TYPE_DECIMAL: return "DECIMAL";
|
|
||||||
case MYSQL_TYPE_DOUBLE: return "DOUBLE";
|
|
||||||
case MYSQL_TYPE_ENUM: return "ENUM";
|
|
||||||
case MYSQL_TYPE_FLOAT: return "FLOAT";
|
|
||||||
case MYSQL_TYPE_GEOMETRY: return "GEOMETRY";
|
|
||||||
case MYSQL_TYPE_INT24: return "INT24";
|
|
||||||
case MYSQL_TYPE_LONG: return "LONG";
|
|
||||||
case MYSQL_TYPE_LONGLONG: return "LONGLONG";
|
|
||||||
case MYSQL_TYPE_LONG_BLOB: return "LONG_BLOB";
|
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB: return "MEDIUM_BLOB";
|
|
||||||
case MYSQL_TYPE_NEWDATE: return "NEWDATE";
|
|
||||||
case MYSQL_TYPE_NULL: return "NULL";
|
|
||||||
case MYSQL_TYPE_SET: return "SET";
|
|
||||||
case MYSQL_TYPE_SHORT: return "SHORT";
|
|
||||||
case MYSQL_TYPE_STRING: return "STRING";
|
|
||||||
case MYSQL_TYPE_TIME: return "TIME";
|
|
||||||
case MYSQL_TYPE_TIMESTAMP: return "TIMESTAMP";
|
|
||||||
case MYSQL_TYPE_TINY: return "TINY";
|
|
||||||
case MYSQL_TYPE_TINY_BLOB: return "TINY_BLOB";
|
|
||||||
case MYSQL_TYPE_VAR_STRING: return "VAR_STRING";
|
|
||||||
case MYSQL_TYPE_YEAR: return "YEAR";
|
|
||||||
default: return "-Unknown-";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -148,8 +148,8 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC); // 0: uint32
|
PrepareStatement(CHAR_DEL_GUILD_MEMBER, "DELETE FROM guild_member WHERE guid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||||
PrepareStatement(CHAR_DEL_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
PrepareStatement(CHAR_DEL_GUILD_MEMBERS, "DELETE FROM guild_member WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||||
PrepareStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED, "SELECT g.guildid, g.name, gr.rname, gm.pnote, gm.offnote "
|
PrepareStatement(CHAR_SEL_GUILD_MEMBER_EXTENDED, "SELECT g.guildid, g.name, gr.rname, gm.pnote, gm.offnote "
|
||||||
"FROM guild g JOIN guild_member gm ON g.guildid = gm.guildid "
|
"FROM guild g JOIN guild_member gm ON g.guildid = gm.guildid "
|
||||||
"JOIN guild_rank gr ON g.guildid = gr.guildid AND gm.`rank` = gr.rid WHERE gm.guid = ?", CONNECTION_BOTH);
|
"JOIN guild_rank gr ON g.guildid = gr.guildid AND gm.`rank` = gr.rid WHERE gm.guid = ?", CONNECTION_BOTH);
|
||||||
// 0: uint32, 1: uint8, 3: string, 4: uint32, 5: uint32
|
// 0: uint32, 1: uint8, 3: string, 4: uint32, 5: uint32
|
||||||
PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights, BankMoneyPerDay) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_INS_GUILD_RANK, "INSERT INTO guild_rank (guildid, rid, rname, rights, BankMoneyPerDay) VALUES (?, ?, ?, ?, ?)", CONNECTION_ASYNC);
|
||||||
PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
PrepareStatement(CHAR_DEL_GUILD_RANKS, "DELETE FROM guild_rank WHERE guildid = ?", CONNECTION_ASYNC); // 0: uint32
|
||||||
@@ -403,7 +403,7 @@ void CharacterDatabaseConnection::DoPrepareStatements()
|
|||||||
PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC);
|
PrepareStatement(CHAR_DEL_CHAR_AURA_FROZEN, "DELETE FROM character_aura WHERE spell = 9454 AND guid = ?", CONNECTION_ASYNC);
|
||||||
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH);
|
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM character_inventory ci INNER JOIN item_instance ii ON ii.guid = ci.item WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
PrepareStatement(CHAR_SEL_MAIL_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM mail_items mi INNER JOIN item_instance ii ON ii.guid = mi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM,"SELECT COUNT(itemEntry) FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
PrepareStatement(CHAR_SEL_AUCTIONHOUSE_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM auctionhouse ah INNER JOIN item_instance ii ON ii.guid = ah.itemguid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM guild_bank_item gbi INNER JOIN item_instance ii ON ii.guid = gbi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
PrepareStatement(CHAR_SEL_GUILD_BANK_COUNT_ITEM, "SELECT COUNT(itemEntry) FROM guild_bank_item gbi INNER JOIN item_instance ii ON ii.guid = gbi.item_guid WHERE itemEntry = ?", CONNECTION_SYNCH);
|
||||||
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY, "SELECT ci.item, cb.slot AS bag, ci.slot, ci.guid, c.account, c.name FROM characters c "
|
PrepareStatement(CHAR_SEL_CHAR_INVENTORY_ITEM_BY_ENTRY, "SELECT ci.item, cb.slot AS bag, ci.slot, ci.guid, c.account, c.name FROM characters c "
|
||||||
"INNER JOIN character_inventory ci ON ci.guid = c.guid "
|
"INNER JOIN character_inventory ci ON ci.guid = c.guid "
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
|
|
||||||
class CharacterDatabaseConnection : public MySQLConnection
|
class CharacterDatabaseConnection : public MySQLConnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//- Constructors for sync and async connections
|
//- Constructors for sync and async connections
|
||||||
CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) {}
|
CharacterDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) {}
|
||||||
CharacterDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) {}
|
CharacterDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) {}
|
||||||
|
|
||||||
//- Loads database type specific prepared statements
|
//- Loads database type specific prepared statements
|
||||||
void DoPrepareStatements();
|
void DoPrepareStatements();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabaseWorkerPool;
|
typedef DatabaseWorkerPool<CharacterDatabaseConnection> CharacterDatabaseWorkerPool;
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
|
|
||||||
class LoginDatabaseConnection : public MySQLConnection
|
class LoginDatabaseConnection : public MySQLConnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//- Constructors for sync and async connections
|
//- Constructors for sync and async connections
|
||||||
LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
LoginDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
||||||
LoginDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
LoginDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
||||||
|
|
||||||
//- Loads database type specific prepared statements
|
//- Loads database type specific prepared statements
|
||||||
void DoPrepareStatements();
|
void DoPrepareStatements();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabaseWorkerPool;
|
typedef DatabaseWorkerPool<LoginDatabaseConnection> LoginDatabaseWorkerPool;
|
||||||
|
|||||||
@@ -12,13 +12,13 @@
|
|||||||
|
|
||||||
class WorldDatabaseConnection : public MySQLConnection
|
class WorldDatabaseConnection : public MySQLConnection
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
//- Constructors for sync and async connections
|
//- Constructors for sync and async connections
|
||||||
WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
WorldDatabaseConnection(MySQLConnectionInfo& connInfo) : MySQLConnection(connInfo) { }
|
||||||
WorldDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
WorldDatabaseConnection(ACE_Activation_Queue* q, MySQLConnectionInfo& connInfo) : MySQLConnection(q, connInfo) { }
|
||||||
|
|
||||||
//- Loads database type specific prepared statements
|
//- Loads database type specific prepared statements
|
||||||
void DoPrepareStatements();
|
void DoPrepareStatements();
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabaseWorkerPool;
|
typedef DatabaseWorkerPool<WorldDatabaseConnection> WorldDatabaseWorkerPool;
|
||||||
|
|||||||
@@ -24,23 +24,23 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) :
|
MySQLConnection::MySQLConnection(MySQLConnectionInfo& connInfo) :
|
||||||
m_reconnecting(false),
|
m_reconnecting(false),
|
||||||
m_prepareError(false),
|
m_prepareError(false),
|
||||||
m_queue(NULL),
|
m_queue(NULL),
|
||||||
m_worker(NULL),
|
m_worker(NULL),
|
||||||
m_Mysql(NULL),
|
m_Mysql(NULL),
|
||||||
m_connectionInfo(connInfo),
|
m_connectionInfo(connInfo),
|
||||||
m_connectionFlags(CONNECTION_SYNCH)
|
m_connectionFlags(CONNECTION_SYNCH)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo) :
|
MySQLConnection::MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo) :
|
||||||
m_reconnecting(false),
|
m_reconnecting(false),
|
||||||
m_prepareError(false),
|
m_prepareError(false),
|
||||||
m_queue(queue),
|
m_queue(queue),
|
||||||
m_Mysql(NULL),
|
m_Mysql(NULL),
|
||||||
m_connectionInfo(connInfo),
|
m_connectionInfo(connInfo),
|
||||||
m_connectionFlags(CONNECTION_ASYNC)
|
m_connectionFlags(CONNECTION_ASYNC)
|
||||||
{
|
{
|
||||||
m_worker = new DatabaseWorker(m_queue, this);
|
m_worker = new DatabaseWorker(m_queue, this);
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ void MySQLConnection::Close()
|
|||||||
|
|
||||||
bool MySQLConnection::Open()
|
bool MySQLConnection::Open()
|
||||||
{
|
{
|
||||||
MYSQL *mysqlInit;
|
MYSQL* mysqlInit;
|
||||||
mysqlInit = mysql_init(NULL);
|
mysqlInit = mysql_init(NULL);
|
||||||
if (!mysqlInit)
|
if (!mysqlInit)
|
||||||
{
|
{
|
||||||
@@ -77,7 +77,7 @@ bool MySQLConnection::Open()
|
|||||||
|
|
||||||
mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");
|
mysql_options(mysqlInit, MYSQL_SET_CHARSET_NAME, "utf8");
|
||||||
//mysql_options(mysqlInit, MYSQL_OPT_READ_TIMEOUT, (char const*)&timeout);
|
//mysql_options(mysqlInit, MYSQL_OPT_READ_TIMEOUT, (char const*)&timeout);
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
if (m_connectionInfo.host == ".") // named pipe use option (Windows)
|
if (m_connectionInfo.host == ".") // named pipe use option (Windows)
|
||||||
{
|
{
|
||||||
unsigned int opt = MYSQL_PROTOCOL_PIPE;
|
unsigned int opt = MYSQL_PROTOCOL_PIPE;
|
||||||
@@ -90,7 +90,7 @@ bool MySQLConnection::Open()
|
|||||||
port = atoi(m_connectionInfo.port_or_socket.c_str());
|
port = atoi(m_connectionInfo.port_or_socket.c_str());
|
||||||
unix_socket = 0;
|
unix_socket = 0;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (m_connectionInfo.host == ".") // socket use option (Unix/Linux)
|
if (m_connectionInfo.host == ".") // socket use option (Unix/Linux)
|
||||||
{
|
{
|
||||||
unsigned int opt = MYSQL_PROTOCOL_SOCKET;
|
unsigned int opt = MYSQL_PROTOCOL_SOCKET;
|
||||||
@@ -104,22 +104,23 @@ bool MySQLConnection::Open()
|
|||||||
port = atoi(m_connectionInfo.port_or_socket.c_str());
|
port = atoi(m_connectionInfo.port_or_socket.c_str());
|
||||||
unix_socket = 0;
|
unix_socket = 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Possible improvement for future: make ATTEMPTS and SECONDS configurable values
|
// Possible improvement for future: make ATTEMPTS and SECONDS configurable values
|
||||||
uint32 const ATTEMPTS = 180;
|
uint32 const ATTEMPTS = 180;
|
||||||
|
|
||||||
uint32 count = 0;
|
uint32 count = 0;
|
||||||
do {
|
do
|
||||||
|
{
|
||||||
m_Mysql = mysql_real_connect(
|
m_Mysql = mysql_real_connect(
|
||||||
mysqlInit,
|
mysqlInit,
|
||||||
m_connectionInfo.host.c_str(),
|
m_connectionInfo.host.c_str(),
|
||||||
m_connectionInfo.user.c_str(),
|
m_connectionInfo.user.c_str(),
|
||||||
m_connectionInfo.password.c_str(),
|
m_connectionInfo.password.c_str(),
|
||||||
m_connectionInfo.database.c_str(),
|
m_connectionInfo.database.c_str(),
|
||||||
port,
|
port,
|
||||||
unix_socket,
|
unix_socket,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (m_Mysql)
|
if (m_Mysql)
|
||||||
{
|
{
|
||||||
@@ -250,7 +251,7 @@ bool MySQLConnection::Execute(PreparedStatement* stmt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount)
|
bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint64* pRowCount, uint32* pFieldCount)
|
||||||
{
|
{
|
||||||
if (!m_Mysql)
|
if (!m_Mysql)
|
||||||
return false;
|
return false;
|
||||||
@@ -287,7 +288,7 @@ bool MySQLConnection::_Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint6
|
|||||||
{
|
{
|
||||||
uint32 lErrno = mysql_errno(m_Mysql);
|
uint32 lErrno = mysql_errno(m_Mysql);
|
||||||
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s",
|
sLog->outSQLDriver("SQL(p): %s\n [ERROR]: [%u] %s",
|
||||||
m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
m_mStmt->getQueryString(m_queries[index].first).c_str(), lErrno, mysql_stmt_error(msql_STMT));
|
||||||
|
|
||||||
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
if (_HandleMySQLErrno(lErrno)) // If it returns true, an error was handled successfully (i.e. reconnection)
|
||||||
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
|
return _Query(stmt, pResult, pRowCount, pFieldCount); // Try again
|
||||||
@@ -315,8 +316,8 @@ ResultSet* MySQLConnection::Query(const char* sql)
|
|||||||
if (!sql)
|
if (!sql)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
MYSQL_RES *result = NULL;
|
MYSQL_RES* result = NULL;
|
||||||
MYSQL_FIELD *fields = NULL;
|
MYSQL_FIELD* fields = NULL;
|
||||||
uint64 rowCount = 0;
|
uint64 rowCount = 0;
|
||||||
uint32 fieldCount = 0;
|
uint32 fieldCount = 0;
|
||||||
|
|
||||||
@@ -326,7 +327,7 @@ ResultSet* MySQLConnection::Query(const char* sql)
|
|||||||
return new ResultSet(result, fields, rowCount, fieldCount);
|
return new ResultSet(result, fields, rowCount, fieldCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MySQLConnection::_Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount)
|
bool MySQLConnection::_Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD** pFields, uint64* pRowCount, uint32* pFieldCount)
|
||||||
{
|
{
|
||||||
if (!m_Mysql)
|
if (!m_Mysql)
|
||||||
return false;
|
return false;
|
||||||
@@ -401,29 +402,29 @@ bool MySQLConnection::ExecuteTransaction(SQLTransaction& transaction)
|
|||||||
switch (itr->type)
|
switch (itr->type)
|
||||||
{
|
{
|
||||||
case SQL_ELEMENT_PREPARED:
|
case SQL_ELEMENT_PREPARED:
|
||||||
{
|
|
||||||
PreparedStatement* stmt = data.element.stmt;
|
|
||||||
ASSERT(stmt);
|
|
||||||
if (!Execute(stmt))
|
|
||||||
{
|
{
|
||||||
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
PreparedStatement* stmt = data.element.stmt;
|
||||||
RollbackTransaction();
|
ASSERT(stmt);
|
||||||
return false;
|
if (!Execute(stmt))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||||
|
RollbackTransaction();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
case SQL_ELEMENT_RAW:
|
case SQL_ELEMENT_RAW:
|
||||||
{
|
|
||||||
const char* sql = data.element.query;
|
|
||||||
ASSERT(sql);
|
|
||||||
if (!Execute(sql))
|
|
||||||
{
|
{
|
||||||
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
const char* sql = data.element.query;
|
||||||
RollbackTransaction();
|
ASSERT(sql);
|
||||||
return false;
|
if (!Execute(sql))
|
||||||
|
{
|
||||||
|
sLog->outSQLDriver("[Warning] Transaction aborted. %u queries not executed.", (uint32)queries.size());
|
||||||
|
RollbackTransaction();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +443,7 @@ MySQLPreparedStatement* MySQLConnection::GetPreparedStatement(uint32 index)
|
|||||||
MySQLPreparedStatement* ret = m_stmts[index];
|
MySQLPreparedStatement* ret = m_stmts[index];
|
||||||
if (!ret)
|
if (!ret)
|
||||||
sLog->outSQLDriver("ERROR: Could not fetch prepared statement %u on database `%s`, connection type: %s.",
|
sLog->outSQLDriver("ERROR: Could not fetch prepared statement %u on database `%s`, connection type: %s.",
|
||||||
index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
index, m_connectionInfo.database.c_str(), (m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -490,7 +491,7 @@ void MySQLConnection::PrepareStatement(uint32 index, const char* sql, Connection
|
|||||||
|
|
||||||
PreparedResultSet* MySQLConnection::Query(PreparedStatement* stmt)
|
PreparedResultSet* MySQLConnection::Query(PreparedStatement* stmt)
|
||||||
{
|
{
|
||||||
MYSQL_RES *result = NULL;
|
MYSQL_RES* result = NULL;
|
||||||
uint64 rowCount = 0;
|
uint64 rowCount = 0;
|
||||||
uint32 fieldCount = 0;
|
uint32 fieldCount = 0;
|
||||||
|
|
||||||
@@ -514,27 +515,27 @@ bool MySQLConnection::_HandleMySQLErrno(uint32 errNo)
|
|||||||
#if !(MARIADB_VERSION_ID >= 100200)
|
#if !(MARIADB_VERSION_ID >= 100200)
|
||||||
case CR_INVALID_CONN_HANDLE:
|
case CR_INVALID_CONN_HANDLE:
|
||||||
#endif
|
#endif
|
||||||
{
|
|
||||||
m_reconnecting = true;
|
|
||||||
uint64 oldThreadId = mysql_thread_id(GetHandle());
|
|
||||||
mysql_close(GetHandle());
|
|
||||||
if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
|
|
||||||
{
|
{
|
||||||
sLog->outSQLDriver("Connection to the MySQL server is active.");
|
m_reconnecting = true;
|
||||||
if (oldThreadId != mysql_thread_id(GetHandle()))
|
uint64 oldThreadId = mysql_thread_id(GetHandle());
|
||||||
sLog->outSQLDriver("Successfully reconnected to %s @%s:%s (%s).",
|
mysql_close(GetHandle());
|
||||||
m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
|
if (this->Open()) // Don't remove 'this' pointer unless you want to skip loading all prepared statements....
|
||||||
(m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
{
|
||||||
|
sLog->outSQLDriver("Connection to the MySQL server is active.");
|
||||||
|
if (oldThreadId != mysql_thread_id(GetHandle()))
|
||||||
|
sLog->outSQLDriver("Successfully reconnected to %s @%s:%s (%s).",
|
||||||
|
m_connectionInfo.database.c_str(), m_connectionInfo.host.c_str(), m_connectionInfo.port_or_socket.c_str(),
|
||||||
|
(m_connectionFlags & CONNECTION_ASYNC) ? "asynchronous" : "synchronous");
|
||||||
|
|
||||||
m_reconnecting = false;
|
m_reconnecting = false;
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
|
||||||
|
std::this_thread::sleep_for(3s); // Sleep 3 seconds
|
||||||
|
return _HandleMySQLErrno(lErrno); // Call self (recursive)
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32 lErrno = mysql_errno(GetHandle()); // It's possible this attempted reconnect throws 2006 at us. To prevent crazy recursive calls, sleep here.
|
|
||||||
std::this_thread::sleep_for(3s); // Sleep 3 seconds
|
|
||||||
return _HandleMySQLErrno(lErrno); // Call self (recursive)
|
|
||||||
}
|
|
||||||
|
|
||||||
case ER_LOCK_DEADLOCK:
|
case ER_LOCK_DEADLOCK:
|
||||||
return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction
|
return false; // Implemented in TransactionTask::Execute and DatabaseWorkerPool<T>::DirectCommitTransaction
|
||||||
// Query related errors - skip query
|
// Query related errors - skip query
|
||||||
|
|||||||
@@ -58,69 +58,69 @@ class MySQLConnection
|
|||||||
template <class T> friend class DatabaseWorkerPool;
|
template <class T> friend class DatabaseWorkerPool;
|
||||||
friend class PingOperation;
|
friend class PingOperation;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MySQLConnection(MySQLConnectionInfo& connInfo); //! Constructor for synchronous connections.
|
MySQLConnection(MySQLConnectionInfo& connInfo); //! Constructor for synchronous connections.
|
||||||
MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections.
|
MySQLConnection(ACE_Activation_Queue* queue, MySQLConnectionInfo& connInfo); //! Constructor for asynchronous connections.
|
||||||
virtual ~MySQLConnection();
|
virtual ~MySQLConnection();
|
||||||
|
|
||||||
virtual bool Open();
|
virtual bool Open();
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool Execute(const char* sql);
|
bool Execute(const char* sql);
|
||||||
bool Execute(PreparedStatement* stmt);
|
bool Execute(PreparedStatement* stmt);
|
||||||
ResultSet* Query(const char* sql);
|
ResultSet* Query(const char* sql);
|
||||||
PreparedResultSet* Query(PreparedStatement* stmt);
|
PreparedResultSet* Query(PreparedStatement* stmt);
|
||||||
bool _Query(const char *sql, MYSQL_RES **pResult, MYSQL_FIELD **pFields, uint64* pRowCount, uint32* pFieldCount);
|
bool _Query(const char* sql, MYSQL_RES** pResult, MYSQL_FIELD** pFields, uint64* pRowCount, uint32* pFieldCount);
|
||||||
bool _Query(PreparedStatement* stmt, MYSQL_RES **pResult, uint64* pRowCount, uint32* pFieldCount);
|
bool _Query(PreparedStatement* stmt, MYSQL_RES** pResult, uint64* pRowCount, uint32* pFieldCount);
|
||||||
|
|
||||||
void BeginTransaction();
|
void BeginTransaction();
|
||||||
void RollbackTransaction();
|
void RollbackTransaction();
|
||||||
void CommitTransaction();
|
void CommitTransaction();
|
||||||
bool ExecuteTransaction(SQLTransaction& transaction);
|
bool ExecuteTransaction(SQLTransaction& transaction);
|
||||||
|
|
||||||
operator bool () const { return m_Mysql != NULL; }
|
operator bool () const { return m_Mysql != NULL; }
|
||||||
void Ping() { mysql_ping(m_Mysql); }
|
void Ping() { mysql_ping(m_Mysql); }
|
||||||
|
|
||||||
uint32 GetLastError() { return mysql_errno(m_Mysql); }
|
uint32 GetLastError() { return mysql_errno(m_Mysql); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool LockIfReady()
|
bool LockIfReady()
|
||||||
{
|
{
|
||||||
/// Tries to acquire lock. If lock is acquired by another thread
|
/// Tries to acquire lock. If lock is acquired by another thread
|
||||||
/// the calling parent will just try another connection
|
/// the calling parent will just try another connection
|
||||||
return m_Mutex.tryacquire() != -1;
|
return m_Mutex.tryacquire() != -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Unlock()
|
void Unlock()
|
||||||
{
|
{
|
||||||
/// Called by parent databasepool. Will let other threads access this connection
|
/// Called by parent databasepool. Will let other threads access this connection
|
||||||
m_Mutex.release();
|
m_Mutex.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
MYSQL* GetHandle() { return m_Mysql; }
|
MYSQL* GetHandle() { return m_Mysql; }
|
||||||
MySQLPreparedStatement* GetPreparedStatement(uint32 index);
|
MySQLPreparedStatement* GetPreparedStatement(uint32 index);
|
||||||
void PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags);
|
void PrepareStatement(uint32 index, const char* sql, ConnectionFlags flags);
|
||||||
|
|
||||||
bool PrepareStatements();
|
bool PrepareStatements();
|
||||||
virtual void DoPrepareStatements() = 0;
|
virtual void DoPrepareStatements() = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<MySQLPreparedStatement*> m_stmts; //! PreparedStatements storage
|
std::vector<MySQLPreparedStatement*> m_stmts; //! PreparedStatements storage
|
||||||
PreparedStatementMap m_queries; //! Query storage
|
PreparedStatementMap m_queries; //! Query storage
|
||||||
bool m_reconnecting; //! Are we reconnecting?
|
bool m_reconnecting; //! Are we reconnecting?
|
||||||
bool m_prepareError; //! Was there any error while preparing statements?
|
bool m_prepareError; //! Was there any error while preparing statements?
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _HandleMySQLErrno(uint32 errNo);
|
bool _HandleMySQLErrno(uint32 errNo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACE_Activation_Queue* m_queue; //! Queue shared with other asynchronous connections.
|
ACE_Activation_Queue* m_queue; //! Queue shared with other asynchronous connections.
|
||||||
DatabaseWorker* m_worker; //! Core worker task.
|
DatabaseWorker* m_worker; //! Core worker task.
|
||||||
MYSQL * m_Mysql; //! MySQL Handle.
|
MYSQL* m_Mysql; //! MySQL Handle.
|
||||||
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
|
MySQLConnectionInfo& m_connectionInfo; //! Connection info (used for logging)
|
||||||
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
|
ConnectionFlags m_connectionFlags; //! Connection flags (for preparing relevant statements)
|
||||||
ACE_Thread_Mutex m_Mutex;
|
ACE_Thread_Mutex m_Mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -11,37 +11,37 @@
|
|||||||
|
|
||||||
class MySQL
|
class MySQL
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*! Create a thread on the MySQL server to mirrior the calling thread,
|
/*! Create a thread on the MySQL server to mirrior the calling thread,
|
||||||
initializes thread-specific variables and allows thread-specific
|
initializes thread-specific variables and allows thread-specific
|
||||||
operations without concurrence from other threads.
|
operations without concurrence from other threads.
|
||||||
This should only be called if multiple core threads are running
|
This should only be called if multiple core threads are running
|
||||||
on the same MySQL connection. Seperate MySQL connections implicitly
|
on the same MySQL connection. Seperate MySQL connections implicitly
|
||||||
create a mirror thread.
|
create a mirror thread.
|
||||||
*/
|
*/
|
||||||
static void Thread_Init()
|
static void Thread_Init()
|
||||||
{
|
{
|
||||||
mysql_thread_init();
|
mysql_thread_init();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! Shuts down MySQL thread and frees resources, should only be called
|
/*! Shuts down MySQL thread and frees resources, should only be called
|
||||||
when we terminate. MySQL threads and connections are not configurable
|
when we terminate. MySQL threads and connections are not configurable
|
||||||
during runtime.
|
during runtime.
|
||||||
*/
|
*/
|
||||||
static void Thread_End()
|
static void Thread_End()
|
||||||
{
|
{
|
||||||
mysql_thread_end();
|
mysql_thread_end();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Library_Init()
|
static void Library_Init()
|
||||||
{
|
{
|
||||||
mysql_library_init(-1, NULL, NULL);
|
mysql_library_init(-1, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Library_End()
|
static void Library_End()
|
||||||
{
|
{
|
||||||
mysql_library_end();
|
mysql_library_end();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
PreparedStatement::PreparedStatement(uint32 index) :
|
PreparedStatement::PreparedStatement(uint32 index) :
|
||||||
m_stmt(NULL),
|
m_stmt(NULL),
|
||||||
m_index(index)
|
m_index(index)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,17 +68,17 @@ void PreparedStatement::BindParameters()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if (i < m_stmt->m_paramCount)
|
if (i < m_stmt->m_paramCount)
|
||||||
sLog->outSQLDriver("[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index);
|
sLog->outSQLDriver("[WARNING]: BindParameters() for statement %u did not bind all allocated parameters", m_index);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//- Bind to buffer
|
//- Bind to buffer
|
||||||
void PreparedStatement::setBool(const uint8 index, const bool value)
|
void PreparedStatement::setBool(const uint8 index, const bool value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.boolean = value;
|
statement_data[index].data.boolean = value;
|
||||||
statement_data[index].type = TYPE_BOOL;
|
statement_data[index].type = TYPE_BOOL;
|
||||||
@@ -87,7 +87,7 @@ void PreparedStatement::setBool(const uint8 index, const bool value)
|
|||||||
void PreparedStatement::setUInt8(const uint8 index, const uint8 value)
|
void PreparedStatement::setUInt8(const uint8 index, const uint8 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.ui8 = value;
|
statement_data[index].data.ui8 = value;
|
||||||
statement_data[index].type = TYPE_UI8;
|
statement_data[index].type = TYPE_UI8;
|
||||||
@@ -96,7 +96,7 @@ void PreparedStatement::setUInt8(const uint8 index, const uint8 value)
|
|||||||
void PreparedStatement::setUInt16(const uint8 index, const uint16 value)
|
void PreparedStatement::setUInt16(const uint8 index, const uint16 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.ui16 = value;
|
statement_data[index].data.ui16 = value;
|
||||||
statement_data[index].type = TYPE_UI16;
|
statement_data[index].type = TYPE_UI16;
|
||||||
@@ -105,7 +105,7 @@ void PreparedStatement::setUInt16(const uint8 index, const uint16 value)
|
|||||||
void PreparedStatement::setUInt32(const uint8 index, const uint32 value)
|
void PreparedStatement::setUInt32(const uint8 index, const uint32 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.ui32 = value;
|
statement_data[index].data.ui32 = value;
|
||||||
statement_data[index].type = TYPE_UI32;
|
statement_data[index].type = TYPE_UI32;
|
||||||
@@ -114,7 +114,7 @@ void PreparedStatement::setUInt32(const uint8 index, const uint32 value)
|
|||||||
void PreparedStatement::setUInt64(const uint8 index, const uint64 value)
|
void PreparedStatement::setUInt64(const uint8 index, const uint64 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.ui64 = value;
|
statement_data[index].data.ui64 = value;
|
||||||
statement_data[index].type = TYPE_UI64;
|
statement_data[index].type = TYPE_UI64;
|
||||||
@@ -123,7 +123,7 @@ void PreparedStatement::setUInt64(const uint8 index, const uint64 value)
|
|||||||
void PreparedStatement::setInt8(const uint8 index, const int8 value)
|
void PreparedStatement::setInt8(const uint8 index, const int8 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.i8 = value;
|
statement_data[index].data.i8 = value;
|
||||||
statement_data[index].type = TYPE_I8;
|
statement_data[index].type = TYPE_I8;
|
||||||
@@ -132,7 +132,7 @@ void PreparedStatement::setInt8(const uint8 index, const int8 value)
|
|||||||
void PreparedStatement::setInt16(const uint8 index, const int16 value)
|
void PreparedStatement::setInt16(const uint8 index, const int16 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.i16 = value;
|
statement_data[index].data.i16 = value;
|
||||||
statement_data[index].type = TYPE_I16;
|
statement_data[index].type = TYPE_I16;
|
||||||
@@ -141,7 +141,7 @@ void PreparedStatement::setInt16(const uint8 index, const int16 value)
|
|||||||
void PreparedStatement::setInt32(const uint8 index, const int32 value)
|
void PreparedStatement::setInt32(const uint8 index, const int32 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.i32 = value;
|
statement_data[index].data.i32 = value;
|
||||||
statement_data[index].type = TYPE_I32;
|
statement_data[index].type = TYPE_I32;
|
||||||
@@ -150,7 +150,7 @@ void PreparedStatement::setInt32(const uint8 index, const int32 value)
|
|||||||
void PreparedStatement::setInt64(const uint8 index, const int64 value)
|
void PreparedStatement::setInt64(const uint8 index, const int64 value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.i64 = value;
|
statement_data[index].data.i64 = value;
|
||||||
statement_data[index].type = TYPE_I64;
|
statement_data[index].type = TYPE_I64;
|
||||||
@@ -159,7 +159,7 @@ void PreparedStatement::setInt64(const uint8 index, const int64 value)
|
|||||||
void PreparedStatement::setFloat(const uint8 index, const float value)
|
void PreparedStatement::setFloat(const uint8 index, const float value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.f = value;
|
statement_data[index].data.f = value;
|
||||||
statement_data[index].type = TYPE_FLOAT;
|
statement_data[index].type = TYPE_FLOAT;
|
||||||
@@ -168,7 +168,7 @@ void PreparedStatement::setFloat(const uint8 index, const float value)
|
|||||||
void PreparedStatement::setDouble(const uint8 index, const double value)
|
void PreparedStatement::setDouble(const uint8 index, const double value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].data.d = value;
|
statement_data[index].data.d = value;
|
||||||
statement_data[index].type = TYPE_DOUBLE;
|
statement_data[index].type = TYPE_DOUBLE;
|
||||||
@@ -177,7 +177,7 @@ void PreparedStatement::setDouble(const uint8 index, const double value)
|
|||||||
void PreparedStatement::setString(const uint8 index, const std::string& value)
|
void PreparedStatement::setString(const uint8 index, const std::string& value)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].str = value;
|
statement_data[index].str = value;
|
||||||
statement_data[index].type = TYPE_STRING;
|
statement_data[index].type = TYPE_STRING;
|
||||||
@@ -186,15 +186,15 @@ void PreparedStatement::setString(const uint8 index, const std::string& value)
|
|||||||
void PreparedStatement::setNull(const uint8 index)
|
void PreparedStatement::setNull(const uint8 index)
|
||||||
{
|
{
|
||||||
if (index >= statement_data.size())
|
if (index >= statement_data.size())
|
||||||
statement_data.resize(index+1);
|
statement_data.resize(index + 1);
|
||||||
|
|
||||||
statement_data[index].type = TYPE_NULL;
|
statement_data[index].type = TYPE_NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
MySQLPreparedStatement::MySQLPreparedStatement(MYSQL_STMT* stmt) :
|
MySQLPreparedStatement::MySQLPreparedStatement(MYSQL_STMT* stmt) :
|
||||||
m_stmt(NULL),
|
m_stmt(NULL),
|
||||||
m_Mstmt(stmt),
|
m_Mstmt(stmt),
|
||||||
m_bind(NULL)
|
m_bind(NULL)
|
||||||
{
|
{
|
||||||
/// Initialize variable parameters
|
/// Initialize variable parameters
|
||||||
m_paramCount = mysql_stmt_param_count(stmt);
|
m_paramCount = mysql_stmt_param_count(stmt);
|
||||||
@@ -221,7 +221,7 @@ MySQLPreparedStatement::~MySQLPreparedStatement()
|
|||||||
|
|
||||||
void MySQLPreparedStatement::ClearParameters()
|
void MySQLPreparedStatement::ClearParameters()
|
||||||
{
|
{
|
||||||
for (uint32 i=0; i < m_paramCount; ++i)
|
for (uint32 i = 0; i < m_paramCount; ++i)
|
||||||
{
|
{
|
||||||
delete m_bind[i].length;
|
delete m_bind[i].length;
|
||||||
m_bind[i].length = NULL;
|
m_bind[i].length = NULL;
|
||||||
@@ -339,12 +339,12 @@ void MySQLPreparedStatement::setString(const uint8 index, const char* value)
|
|||||||
MYSQL_BIND* param = &m_bind[index];
|
MYSQL_BIND* param = &m_bind[index];
|
||||||
size_t len = strlen(value) + 1;
|
size_t len = strlen(value) + 1;
|
||||||
param->buffer_type = MYSQL_TYPE_VAR_STRING;
|
param->buffer_type = MYSQL_TYPE_VAR_STRING;
|
||||||
delete [] static_cast<char *>(param->buffer);
|
delete [] static_cast<char*>(param->buffer);
|
||||||
param->buffer = new char[len];
|
param->buffer = new char[len];
|
||||||
param->buffer_length = len;
|
param->buffer_length = len;
|
||||||
param->is_null_value = 0;
|
param->is_null_value = 0;
|
||||||
delete param->length;
|
delete param->length;
|
||||||
param->length = new unsigned long(len-1);
|
param->length = new unsigned long(len - 1);
|
||||||
|
|
||||||
memcpy(param->buffer, value, len);
|
memcpy(param->buffer, value, len);
|
||||||
}
|
}
|
||||||
@@ -355,7 +355,7 @@ void MySQLPreparedStatement::setNull(const uint8 index)
|
|||||||
m_paramsSet[index] = true;
|
m_paramsSet[index] = true;
|
||||||
MYSQL_BIND* param = &m_bind[index];
|
MYSQL_BIND* param = &m_bind[index];
|
||||||
param->buffer_type = MYSQL_TYPE_NULL;
|
param->buffer_type = MYSQL_TYPE_NULL;
|
||||||
delete [] static_cast<char *>(param->buffer);
|
delete [] static_cast<char*>(param->buffer);
|
||||||
param->buffer = NULL;
|
param->buffer = NULL;
|
||||||
param->buffer_length = 0;
|
param->buffer_length = 0;
|
||||||
param->is_null_value = 1;
|
param->is_null_value = 1;
|
||||||
@@ -366,7 +366,7 @@ void MySQLPreparedStatement::setNull(const uint8 index)
|
|||||||
void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned)
|
void MySQLPreparedStatement::setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned)
|
||||||
{
|
{
|
||||||
param->buffer_type = type;
|
param->buffer_type = type;
|
||||||
delete [] static_cast<char *>(param->buffer);
|
delete [] static_cast<char*>(param->buffer);
|
||||||
param->buffer = new char[len];
|
param->buffer = new char[len];
|
||||||
param->buffer_length = 0;
|
param->buffer_length = 0;
|
||||||
param->is_null_value = 0;
|
param->is_null_value = 0;
|
||||||
@@ -439,15 +439,15 @@ std::string MySQLPreparedStatement::getQueryString(std::string const& sqlPattern
|
|||||||
|
|
||||||
//- Execution
|
//- Execution
|
||||||
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt) :
|
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt) :
|
||||||
m_stmt(stmt),
|
m_stmt(stmt),
|
||||||
m_has_result(false)
|
m_has_result(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result) :
|
PreparedStatementTask::PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result) :
|
||||||
m_stmt(stmt),
|
m_stmt(stmt),
|
||||||
m_has_result(true),
|
m_has_result(true),
|
||||||
m_result(result)
|
m_result(result)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -65,31 +65,31 @@ class PreparedStatement
|
|||||||
friend class MySQLPreparedStatement;
|
friend class MySQLPreparedStatement;
|
||||||
friend class MySQLConnection;
|
friend class MySQLConnection;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit PreparedStatement(uint32 index);
|
explicit PreparedStatement(uint32 index);
|
||||||
~PreparedStatement();
|
~PreparedStatement();
|
||||||
|
|
||||||
void setBool(const uint8 index, const bool value);
|
void setBool(const uint8 index, const bool value);
|
||||||
void setUInt8(const uint8 index, const uint8 value);
|
void setUInt8(const uint8 index, const uint8 value);
|
||||||
void setUInt16(const uint8 index, const uint16 value);
|
void setUInt16(const uint8 index, const uint16 value);
|
||||||
void setUInt32(const uint8 index, const uint32 value);
|
void setUInt32(const uint8 index, const uint32 value);
|
||||||
void setUInt64(const uint8 index, const uint64 value);
|
void setUInt64(const uint8 index, const uint64 value);
|
||||||
void setInt8(const uint8 index, const int8 value);
|
void setInt8(const uint8 index, const int8 value);
|
||||||
void setInt16(const uint8 index, const int16 value);
|
void setInt16(const uint8 index, const int16 value);
|
||||||
void setInt32(const uint8 index, const int32 value);
|
void setInt32(const uint8 index, const int32 value);
|
||||||
void setInt64(const uint8 index, const int64 value);
|
void setInt64(const uint8 index, const int64 value);
|
||||||
void setFloat(const uint8 index, const float value);
|
void setFloat(const uint8 index, const float value);
|
||||||
void setDouble(const uint8 index, const double value);
|
void setDouble(const uint8 index, const double value);
|
||||||
void setString(const uint8 index, const std::string& value);
|
void setString(const uint8 index, const std::string& value);
|
||||||
void setNull(const uint8 index);
|
void setNull(const uint8 index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void BindParameters();
|
void BindParameters();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MySQLPreparedStatement* m_stmt;
|
MySQLPreparedStatement* m_stmt;
|
||||||
uint32 m_index;
|
uint32 m_index;
|
||||||
std::vector<PreparedStatementData> statement_data; //- Buffer of parameters, not tied to MySQL in any way yet
|
std::vector<PreparedStatementData> statement_data; //- Buffer of parameters, not tied to MySQL in any way yet
|
||||||
};
|
};
|
||||||
|
|
||||||
//- Class of which the instances are unique per MySQLConnection
|
//- Class of which the instances are unique per MySQLConnection
|
||||||
@@ -100,40 +100,40 @@ class MySQLPreparedStatement
|
|||||||
friend class MySQLConnection;
|
friend class MySQLConnection;
|
||||||
friend class PreparedStatement;
|
friend class PreparedStatement;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MySQLPreparedStatement(MYSQL_STMT* stmt);
|
MySQLPreparedStatement(MYSQL_STMT* stmt);
|
||||||
~MySQLPreparedStatement();
|
~MySQLPreparedStatement();
|
||||||
|
|
||||||
void setBool(const uint8 index, const bool value);
|
void setBool(const uint8 index, const bool value);
|
||||||
void setUInt8(const uint8 index, const uint8 value);
|
void setUInt8(const uint8 index, const uint8 value);
|
||||||
void setUInt16(const uint8 index, const uint16 value);
|
void setUInt16(const uint8 index, const uint16 value);
|
||||||
void setUInt32(const uint8 index, const uint32 value);
|
void setUInt32(const uint8 index, const uint32 value);
|
||||||
void setUInt64(const uint8 index, const uint64 value);
|
void setUInt64(const uint8 index, const uint64 value);
|
||||||
void setInt8(const uint8 index, const int8 value);
|
void setInt8(const uint8 index, const int8 value);
|
||||||
void setInt16(const uint8 index, const int16 value);
|
void setInt16(const uint8 index, const int16 value);
|
||||||
void setInt32(const uint8 index, const int32 value);
|
void setInt32(const uint8 index, const int32 value);
|
||||||
void setInt64(const uint8 index, const int64 value);
|
void setInt64(const uint8 index, const int64 value);
|
||||||
void setFloat(const uint8 index, const float value);
|
void setFloat(const uint8 index, const float value);
|
||||||
void setDouble(const uint8 index, const double value);
|
void setDouble(const uint8 index, const double value);
|
||||||
void setString(const uint8 index, const char* value);
|
void setString(const uint8 index, const char* value);
|
||||||
void setNull(const uint8 index);
|
void setNull(const uint8 index);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
MYSQL_STMT* GetSTMT() { return m_Mstmt; }
|
MYSQL_STMT* GetSTMT() { return m_Mstmt; }
|
||||||
MYSQL_BIND* GetBind() { return m_bind; }
|
MYSQL_BIND* GetBind() { return m_bind; }
|
||||||
PreparedStatement* m_stmt;
|
PreparedStatement* m_stmt;
|
||||||
void ClearParameters();
|
void ClearParameters();
|
||||||
bool CheckValidIndex(uint8 index);
|
bool CheckValidIndex(uint8 index);
|
||||||
std::string getQueryString(std::string const& sqlPattern) const;
|
std::string getQueryString(std::string const& sqlPattern) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned);
|
void setValue(MYSQL_BIND* param, enum_field_types type, const void* value, uint32 len, bool isUnsigned);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MYSQL_STMT* m_Mstmt;
|
MYSQL_STMT* m_Mstmt;
|
||||||
uint32 m_paramCount;
|
uint32 m_paramCount;
|
||||||
std::vector<bool> m_paramsSet;
|
std::vector<bool> m_paramsSet;
|
||||||
MYSQL_BIND* m_bind;
|
MYSQL_BIND* m_bind;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
|
typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
|
||||||
@@ -141,16 +141,16 @@ typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
|
|||||||
//- Lower-level class, enqueuable operation
|
//- Lower-level class, enqueuable operation
|
||||||
class PreparedStatementTask : public SQLOperation
|
class PreparedStatementTask : public SQLOperation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PreparedStatementTask(PreparedStatement* stmt);
|
PreparedStatementTask(PreparedStatement* stmt);
|
||||||
PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result);
|
PreparedStatementTask(PreparedStatement* stmt, PreparedQueryResultFuture result);
|
||||||
~PreparedStatementTask();
|
~PreparedStatementTask();
|
||||||
|
|
||||||
bool Execute();
|
bool Execute();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PreparedStatement* m_stmt;
|
PreparedStatement* m_stmt;
|
||||||
bool m_has_result;
|
bool m_has_result;
|
||||||
PreparedQueryResultFuture m_result;
|
PreparedQueryResultFuture m_result;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#include "PreparedStatement.h"
|
#include "PreparedStatement.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
|
bool SQLQueryHolder::SetQuery(size_t index, const char* sql)
|
||||||
{
|
{
|
||||||
if (m_queries.size() <= index)
|
if (m_queries.size() <= index)
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,7 @@ bool SQLQueryHolder::SetQuery(size_t index, const char *sql)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SQLQueryHolder::SetPQuery(size_t index, const char *format, ...)
|
bool SQLQueryHolder::SetPQuery(size_t index, const char* format, ...)
|
||||||
{
|
{
|
||||||
if (!format)
|
if (!format)
|
||||||
{
|
{
|
||||||
@@ -165,7 +165,7 @@ bool SQLQueryHolderTask::Execute()
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
/// we can do this, we are friends
|
/// we can do this, we are friends
|
||||||
std::vector<SQLQueryHolder::SQLResultPair> &queries = m_holder->m_queries;
|
std::vector<SQLQueryHolder::SQLResultPair>& queries = m_holder->m_queries;
|
||||||
|
|
||||||
for (size_t i = 0; i < queries.size(); i++)
|
for (size_t i = 0; i < queries.size(); i++)
|
||||||
{
|
{
|
||||||
@@ -175,19 +175,19 @@ bool SQLQueryHolderTask::Execute()
|
|||||||
switch (data->type)
|
switch (data->type)
|
||||||
{
|
{
|
||||||
case SQL_ELEMENT_RAW:
|
case SQL_ELEMENT_RAW:
|
||||||
{
|
{
|
||||||
char const* sql = data->element.query;
|
char const* sql = data->element.query;
|
||||||
if (sql)
|
if (sql)
|
||||||
m_holder->SetResult(i, m_conn->Query(sql));
|
m_holder->SetResult(i, m_conn->Query(sql));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SQL_ELEMENT_PREPARED:
|
case SQL_ELEMENT_PREPARED:
|
||||||
{
|
{
|
||||||
PreparedStatement* stmt = data->element.stmt;
|
PreparedStatement* stmt = data->element.stmt;
|
||||||
if (stmt)
|
if (stmt)
|
||||||
m_holder->SetPreparedResult(i, m_conn->Query(stmt));
|
m_holder->SetPreparedResult(i, m_conn->Query(stmt));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,34 +12,34 @@
|
|||||||
class SQLQueryHolder
|
class SQLQueryHolder
|
||||||
{
|
{
|
||||||
friend class SQLQueryHolderTask;
|
friend class SQLQueryHolderTask;
|
||||||
private:
|
private:
|
||||||
typedef std::pair<SQLElementData, SQLResultSetUnion> SQLResultPair;
|
typedef std::pair<SQLElementData, SQLResultSetUnion> SQLResultPair;
|
||||||
std::vector<SQLResultPair> m_queries;
|
std::vector<SQLResultPair> m_queries;
|
||||||
public:
|
public:
|
||||||
SQLQueryHolder() { }
|
SQLQueryHolder() { }
|
||||||
~SQLQueryHolder();
|
~SQLQueryHolder();
|
||||||
bool SetQuery(size_t index, const char *sql);
|
bool SetQuery(size_t index, const char* sql);
|
||||||
bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3, 4);
|
bool SetPQuery(size_t index, const char* format, ...) ATTR_PRINTF(3, 4);
|
||||||
bool SetPreparedQuery(size_t index, PreparedStatement* stmt);
|
bool SetPreparedQuery(size_t index, PreparedStatement* stmt);
|
||||||
void SetSize(size_t size);
|
void SetSize(size_t size);
|
||||||
QueryResult GetResult(size_t index);
|
QueryResult GetResult(size_t index);
|
||||||
PreparedQueryResult GetPreparedResult(size_t index);
|
PreparedQueryResult GetPreparedResult(size_t index);
|
||||||
void SetResult(size_t index, ResultSet* result);
|
void SetResult(size_t index, ResultSet* result);
|
||||||
void SetPreparedResult(size_t index, PreparedResultSet* result);
|
void SetPreparedResult(size_t index, PreparedResultSet* result);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef ACE_Future<SQLQueryHolder*> QueryResultHolderFuture;
|
typedef ACE_Future<SQLQueryHolder*> QueryResultHolderFuture;
|
||||||
|
|
||||||
class SQLQueryHolderTask : public SQLOperation
|
class SQLQueryHolderTask : public SQLOperation
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SQLQueryHolder * m_holder;
|
SQLQueryHolder* m_holder;
|
||||||
QueryResultHolderFuture m_result;
|
QueryResultHolderFuture m_result;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SQLQueryHolderTask(SQLQueryHolder *holder, QueryResultHolderFuture res)
|
SQLQueryHolderTask(SQLQueryHolder* holder, QueryResultHolderFuture res)
|
||||||
: m_holder(holder), m_result(res){ };
|
: m_holder(holder), m_result(res) { };
|
||||||
bool Execute();
|
bool Execute();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -7,25 +7,25 @@
|
|||||||
#include "DatabaseEnv.h"
|
#include "DatabaseEnv.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
ResultSet::ResultSet(MYSQL_RES *result, MYSQL_FIELD *fields, uint64 rowCount, uint32 fieldCount) :
|
ResultSet::ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount) :
|
||||||
_rowCount(rowCount),
|
_rowCount(rowCount),
|
||||||
_fieldCount(fieldCount),
|
_fieldCount(fieldCount),
|
||||||
_result(result),
|
_result(result),
|
||||||
_fields(fields)
|
_fields(fields)
|
||||||
{
|
{
|
||||||
_currentRow = new Field[_fieldCount];
|
_currentRow = new Field[_fieldCount];
|
||||||
ASSERT(_currentRow);
|
ASSERT(_currentRow);
|
||||||
}
|
}
|
||||||
|
|
||||||
PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES *result, uint64 rowCount, uint32 fieldCount) :
|
PreparedResultSet::PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount) :
|
||||||
m_rowCount(rowCount),
|
m_rowCount(rowCount),
|
||||||
m_rowPosition(0),
|
m_rowPosition(0),
|
||||||
m_fieldCount(fieldCount),
|
m_fieldCount(fieldCount),
|
||||||
m_rBind(NULL),
|
m_rBind(NULL),
|
||||||
m_stmt(stmt),
|
m_stmt(stmt),
|
||||||
m_res(result),
|
m_res(result),
|
||||||
m_isNull(NULL),
|
m_isNull(NULL),
|
||||||
m_length(NULL)
|
m_length(NULL)
|
||||||
{
|
{
|
||||||
if (!m_res)
|
if (!m_res)
|
||||||
return;
|
return;
|
||||||
@@ -94,9 +94,9 @@ m_length(NULL)
|
|||||||
{
|
{
|
||||||
if (!*m_rBind[fIndex].is_null)
|
if (!*m_rBind[fIndex].is_null)
|
||||||
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( m_rBind[fIndex].buffer,
|
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( m_rBind[fIndex].buffer,
|
||||||
m_rBind[fIndex].buffer_length,
|
m_rBind[fIndex].buffer_length,
|
||||||
m_rBind[fIndex].buffer_type,
|
m_rBind[fIndex].buffer_type,
|
||||||
*m_rBind[fIndex].length );
|
*m_rBind[fIndex].length );
|
||||||
else
|
else
|
||||||
switch (m_rBind[fIndex].buffer_type)
|
switch (m_rBind[fIndex].buffer_type)
|
||||||
{
|
{
|
||||||
@@ -106,16 +106,16 @@ m_length(NULL)
|
|||||||
case MYSQL_TYPE_BLOB:
|
case MYSQL_TYPE_BLOB:
|
||||||
case MYSQL_TYPE_STRING:
|
case MYSQL_TYPE_STRING:
|
||||||
case MYSQL_TYPE_VAR_STRING:
|
case MYSQL_TYPE_VAR_STRING:
|
||||||
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( "",
|
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( "",
|
||||||
m_rBind[fIndex].buffer_length,
|
m_rBind[fIndex].buffer_length,
|
||||||
m_rBind[fIndex].buffer_type,
|
m_rBind[fIndex].buffer_type,
|
||||||
*m_rBind[fIndex].length );
|
*m_rBind[fIndex].length );
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( 0,
|
m_rows[uint32(m_rowPosition)][fIndex].SetByteValue( 0,
|
||||||
m_rBind[fIndex].buffer_length,
|
m_rBind[fIndex].buffer_length,
|
||||||
m_rBind[fIndex].buffer_type,
|
m_rBind[fIndex].buffer_type,
|
||||||
*m_rBind[fIndex].length );
|
*m_rBind[fIndex].length );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_rowPosition++;
|
m_rowPosition++;
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
#include "Field.h"
|
#include "Field.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#endif
|
#endif
|
||||||
#include <mysql.h>
|
#include <mysql.h>
|
||||||
|
|
||||||
@@ -24,76 +24,76 @@ typedef bool my_bool;
|
|||||||
|
|
||||||
class ResultSet
|
class ResultSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount);
|
ResultSet(MYSQL_RES* result, MYSQL_FIELD* fields, uint64 rowCount, uint32 fieldCount);
|
||||||
~ResultSet();
|
~ResultSet();
|
||||||
|
|
||||||
bool NextRow();
|
bool NextRow();
|
||||||
uint64 GetRowCount() const { return _rowCount; }
|
uint64 GetRowCount() const { return _rowCount; }
|
||||||
uint32 GetFieldCount() const { return _fieldCount; }
|
uint32 GetFieldCount() const { return _fieldCount; }
|
||||||
#ifdef ELUNA
|
#ifdef ELUNA
|
||||||
std::string GetFieldName(uint32 index) const;
|
std::string GetFieldName(uint32 index) const;
|
||||||
#endif
|
#endif
|
||||||
Field* Fetch() const { return _currentRow; }
|
Field* Fetch() const { return _currentRow; }
|
||||||
const Field & operator [] (uint32 index) const
|
const Field& operator [] (uint32 index) const
|
||||||
{
|
{
|
||||||
ASSERT(index < _fieldCount);
|
ASSERT(index < _fieldCount);
|
||||||
return _currentRow[index];
|
return _currentRow[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint64 _rowCount;
|
uint64 _rowCount;
|
||||||
Field* _currentRow;
|
Field* _currentRow;
|
||||||
uint32 _fieldCount;
|
uint32 _fieldCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CleanUp();
|
void CleanUp();
|
||||||
MYSQL_RES* _result;
|
MYSQL_RES* _result;
|
||||||
MYSQL_FIELD* _fields;
|
MYSQL_FIELD* _fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef acore::AutoPtr<ResultSet, ACE_Thread_Mutex> QueryResult;
|
typedef acore::AutoPtr<ResultSet, ACE_Thread_Mutex> QueryResult;
|
||||||
|
|
||||||
class PreparedResultSet
|
class PreparedResultSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount);
|
PreparedResultSet(MYSQL_STMT* stmt, MYSQL_RES* result, uint64 rowCount, uint32 fieldCount);
|
||||||
~PreparedResultSet();
|
~PreparedResultSet();
|
||||||
|
|
||||||
bool NextRow();
|
bool NextRow();
|
||||||
uint64 GetRowCount() const { return m_rowCount; }
|
uint64 GetRowCount() const { return m_rowCount; }
|
||||||
uint32 GetFieldCount() const { return m_fieldCount; }
|
uint32 GetFieldCount() const { return m_fieldCount; }
|
||||||
|
|
||||||
Field* Fetch() const
|
Field* Fetch() const
|
||||||
{
|
{
|
||||||
ASSERT(m_rowPosition < m_rowCount);
|
ASSERT(m_rowPosition < m_rowCount);
|
||||||
return m_rows[uint32(m_rowPosition)];
|
return m_rows[uint32(m_rowPosition)];
|
||||||
}
|
}
|
||||||
|
|
||||||
const Field & operator [] (uint32 index) const
|
const Field& operator [] (uint32 index) const
|
||||||
{
|
{
|
||||||
ASSERT(m_rowPosition < m_rowCount);
|
ASSERT(m_rowPosition < m_rowCount);
|
||||||
ASSERT(index < m_fieldCount);
|
ASSERT(index < m_fieldCount);
|
||||||
return m_rows[uint32(m_rowPosition)][index];
|
return m_rows[uint32(m_rowPosition)][index];
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Field*> m_rows;
|
std::vector<Field*> m_rows;
|
||||||
uint64 m_rowCount;
|
uint64 m_rowCount;
|
||||||
uint64 m_rowPosition;
|
uint64 m_rowPosition;
|
||||||
uint32 m_fieldCount;
|
uint32 m_fieldCount;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
MYSQL_BIND* m_rBind;
|
MYSQL_BIND* m_rBind;
|
||||||
MYSQL_STMT* m_stmt;
|
MYSQL_STMT* m_stmt;
|
||||||
MYSQL_RES* m_res;
|
MYSQL_RES* m_res;
|
||||||
|
|
||||||
my_bool* m_isNull;
|
my_bool* m_isNull;
|
||||||
unsigned long* m_length;
|
unsigned long* m_length;
|
||||||
|
|
||||||
void FreeBindBuffer();
|
void FreeBindBuffer();
|
||||||
void CleanUp();
|
void CleanUp();
|
||||||
bool _NextRow();
|
bool _NextRow();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -47,17 +47,17 @@ class MySQLConnection;
|
|||||||
|
|
||||||
class SQLOperation : public ACE_Method_Request
|
class SQLOperation : public ACE_Method_Request
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
SQLOperation(): m_conn(NULL) { }
|
SQLOperation(): m_conn(NULL) { }
|
||||||
virtual int call()
|
virtual int call()
|
||||||
{
|
{
|
||||||
Execute();
|
Execute();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual bool Execute() = 0;
|
virtual bool Execute() = 0;
|
||||||
virtual void SetConnection(MySQLConnection* con) { m_conn = con; }
|
virtual void SetConnection(MySQLConnection* con) { m_conn = con; }
|
||||||
|
|
||||||
MySQLConnection* m_conn;
|
MySQLConnection* m_conn;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -44,15 +44,15 @@ void Transaction::Cleanup()
|
|||||||
|
|
||||||
while (!m_queries.empty())
|
while (!m_queries.empty())
|
||||||
{
|
{
|
||||||
SQLElementData const &data = m_queries.front();
|
SQLElementData const& data = m_queries.front();
|
||||||
switch (data.type)
|
switch (data.type)
|
||||||
{
|
{
|
||||||
case SQL_ELEMENT_PREPARED:
|
case SQL_ELEMENT_PREPARED:
|
||||||
delete data.element.stmt;
|
delete data.element.stmt;
|
||||||
break;
|
break;
|
||||||
case SQL_ELEMENT_RAW:
|
case SQL_ELEMENT_RAW:
|
||||||
free((void*)(data.element.query));
|
free((void*)(data.element.query));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_queries.pop_front();
|
m_queries.pop_front();
|
||||||
|
|||||||
@@ -21,22 +21,22 @@ class Transaction
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
friend class DatabaseWorkerPool;
|
friend class DatabaseWorkerPool;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Transaction() : _cleanedUp(false) { }
|
Transaction() : _cleanedUp(false) { }
|
||||||
~Transaction() { Cleanup(); }
|
~Transaction() { Cleanup(); }
|
||||||
|
|
||||||
void Append(PreparedStatement* statement);
|
void Append(PreparedStatement* statement);
|
||||||
void Append(const char* sql);
|
void Append(const char* sql);
|
||||||
void PAppend(const char* sql, ...);
|
void PAppend(const char* sql, ...);
|
||||||
|
|
||||||
size_t GetSize() const { return m_queries.size(); }
|
size_t GetSize() const { return m_queries.size(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
std::list<SQLElementData> m_queries;
|
std::list<SQLElementData> m_queries;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool _cleanedUp;
|
bool _cleanedUp;
|
||||||
|
|
||||||
};
|
};
|
||||||
typedef acore::AutoPtr<Transaction, ACE_Thread_Mutex> SQLTransaction;
|
typedef acore::AutoPtr<Transaction, ACE_Thread_Mutex> SQLTransaction;
|
||||||
@@ -47,14 +47,14 @@ class TransactionTask : public SQLOperation
|
|||||||
template <class T> friend class DatabaseWorkerPool;
|
template <class T> friend class DatabaseWorkerPool;
|
||||||
friend class DatabaseWorker;
|
friend class DatabaseWorker;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TransactionTask(SQLTransaction trans) : m_trans(trans) { } ;
|
TransactionTask(SQLTransaction trans) : m_trans(trans) { } ;
|
||||||
~TransactionTask(){ };
|
~TransactionTask() { };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Execute();
|
bool Execute();
|
||||||
|
|
||||||
SQLTransaction m_trans;
|
SQLTransaction m_trans;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -57,73 +57,73 @@ namespace
|
|||||||
namespace acore
|
namespace acore
|
||||||
{
|
{
|
||||||
|
|
||||||
void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message)
|
void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message)
|
||||||
{
|
{
|
||||||
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + debugInfo + '\n';
|
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + debugInfo + '\n';
|
||||||
fprintf(stderr, "%s", formattedMessage.c_str());
|
fprintf(stderr, "%s", formattedMessage.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
Crash(formattedMessage.c_str());
|
Crash(formattedMessage.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message, char const* format, ...)
|
void Assert(char const* file, int line, char const* function, std::string const& debugInfo, char const* message, char const* format, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, format);
|
va_start(args, format);
|
||||||
|
|
||||||
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n' + debugInfo + '\n';
|
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ASSERTION FAILED:\n %s\n", file, line, function, message) + FormatAssertionMessage(format, args) + '\n' + debugInfo + '\n';
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
fprintf(stderr, "%s", formattedMessage.c_str());
|
fprintf(stderr, "%s", formattedMessage.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
Crash(formattedMessage.c_str());
|
Crash(formattedMessage.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Fatal(char const* file, int line, char const* function, char const* message, ...)
|
void Fatal(char const* file, int line, char const* function, char const* message, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, message);
|
va_start(args, message);
|
||||||
|
|
||||||
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s FATAL ERROR:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n';
|
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s FATAL ERROR:\n", file, line, function) + FormatAssertionMessage(message, args) + '\n';
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
fprintf(stderr, "%s", formattedMessage.c_str());
|
fprintf(stderr, "%s", formattedMessage.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::seconds(10));
|
std::this_thread::sleep_for(std::chrono::seconds(10));
|
||||||
Crash(formattedMessage.c_str());
|
Crash(formattedMessage.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Error(char const* file, int line, char const* function, char const* message)
|
void Error(char const* file, int line, char const* function, char const* message)
|
||||||
{
|
{
|
||||||
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ERROR:\n %s\n", file, line, function, message);
|
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ERROR:\n %s\n", file, line, function, message);
|
||||||
fprintf(stderr, "%s", formattedMessage.c_str());
|
fprintf(stderr, "%s", formattedMessage.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
Crash(formattedMessage.c_str());
|
Crash(formattedMessage.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Warning(char const* file, int line, char const* function, char const* message)
|
void Warning(char const* file, int line, char const* function, char const* message)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n",
|
fprintf(stderr, "\n%s:%i in %s WARNING:\n %s\n",
|
||||||
file, line, function, message);
|
file, line, function, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Abort(char const* file, int line, char const* function)
|
void Abort(char const* file, int line, char const* function)
|
||||||
{
|
{
|
||||||
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ABORTED.\n", file, line, function);
|
std::string formattedMessage = acore::StringFormat("\n%s:%i in %s ABORTED.\n", file, line, function);
|
||||||
fprintf(stderr, "%s", formattedMessage.c_str());
|
fprintf(stderr, "%s", formattedMessage.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
Crash(formattedMessage.c_str());
|
Crash(formattedMessage.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbortHandler(int sigval)
|
void AbortHandler(int sigval)
|
||||||
{
|
{
|
||||||
// nothing useful to log here, no way to pass args
|
// nothing useful to log here, no way to pass args
|
||||||
std::string formattedMessage = acore::StringFormat("Caught signal %i\n", sigval);
|
std::string formattedMessage = acore::StringFormat("Caught signal %i\n", sigval);
|
||||||
fprintf(stderr, "%s", formattedMessage.c_str());
|
fprintf(stderr, "%s", formattedMessage.c_str());
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
Crash(formattedMessage.c_str());
|
Crash(formattedMessage.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace acore
|
} // namespace acore
|
||||||
|
|
||||||
|
|||||||
@@ -33,13 +33,13 @@ inline LPTSTR ErrorMessage(DWORD dw)
|
|||||||
{
|
{
|
||||||
LPVOID lpMsgBuf;
|
LPVOID lpMsgBuf;
|
||||||
DWORD formatResult = FormatMessage(
|
DWORD formatResult = FormatMessage(
|
||||||
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
||||||
FORMAT_MESSAGE_FROM_SYSTEM,
|
FORMAT_MESSAGE_FROM_SYSTEM,
|
||||||
NULL,
|
NULL,
|
||||||
dw,
|
dw,
|
||||||
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||||
(LPTSTR) &lpMsgBuf,
|
(LPTSTR) &lpMsgBuf,
|
||||||
0, NULL);
|
0, NULL);
|
||||||
if (formatResult != 0)
|
if (formatResult != 0)
|
||||||
return (LPTSTR)lpMsgBuf;
|
return (LPTSTR)lpMsgBuf;
|
||||||
else
|
else
|
||||||
@@ -110,7 +110,7 @@ WheatyExceptionReport::~WheatyExceptionReport()
|
|||||||
// Entry point where control comes on an unhandled exception
|
// Entry point where control comes on an unhandled exception
|
||||||
//===========================================================
|
//===========================================================
|
||||||
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
|
LONG WINAPI WheatyExceptionReport::WheatyUnhandledExceptionFilter(
|
||||||
PEXCEPTION_POINTERS pExceptionInfo)
|
PEXCEPTION_POINTERS pExceptionInfo)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> guard(alreadyCrashedLock);
|
std::unique_lock<std::mutex> guard(alreadyCrashedLock);
|
||||||
// Handle only 1 exception in the whole process lifetime
|
// Handle only 1 exception in the whole process lifetime
|
||||||
@@ -141,26 +141,26 @@ PEXCEPTION_POINTERS pExceptionInfo)
|
|||||||
SYSTEMTIME systime;
|
SYSTEMTIME systime;
|
||||||
GetLocalTime(&systime);
|
GetLocalTime(&systime);
|
||||||
sprintf(m_szDumpFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].dmp",
|
sprintf(m_szDumpFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].dmp",
|
||||||
crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
|
crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
|
||||||
|
|
||||||
sprintf(m_szLogFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].txt",
|
sprintf(m_szLogFileName, "%s\\%s_%s_[%u-%u_%u-%u-%u].txt",
|
||||||
crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
|
crash_folder_path, GitRevision::GetHash(), pos, systime.wDay, systime.wMonth, systime.wHour, systime.wMinute, systime.wSecond);
|
||||||
|
|
||||||
m_hDumpFile = CreateFile(m_szDumpFileName,
|
m_hDumpFile = CreateFile(m_szDumpFileName,
|
||||||
GENERIC_WRITE,
|
GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
OPEN_ALWAYS,
|
OPEN_ALWAYS,
|
||||||
FILE_FLAG_WRITE_THROUGH,
|
FILE_FLAG_WRITE_THROUGH,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
m_hReportFile = CreateFile(m_szLogFileName,
|
m_hReportFile = CreateFile(m_szLogFileName,
|
||||||
GENERIC_WRITE,
|
GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
OPEN_ALWAYS,
|
OPEN_ALWAYS,
|
||||||
FILE_FLAG_WRITE_THROUGH,
|
FILE_FLAG_WRITE_THROUGH,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
if (m_hDumpFile)
|
if (m_hDumpFile)
|
||||||
{
|
{
|
||||||
@@ -183,7 +183,7 @@ PEXCEPTION_POINTERS pExceptionInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
|
||||||
m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, &additionalStreamInfo, 0);
|
m_hDumpFile, MiniDumpWithIndirectlyReferencedMemory, &info, &additionalStreamInfo, 0);
|
||||||
|
|
||||||
CloseHandle(m_hDumpFile);
|
CloseHandle(m_hDumpFile);
|
||||||
}
|
}
|
||||||
@@ -217,13 +217,13 @@ BOOL WheatyExceptionReport::_GetProcessorName(TCHAR* sProcessorName, DWORD maxco
|
|||||||
HKEY hKey;
|
HKEY hKey;
|
||||||
LONG lRet;
|
LONG lRet;
|
||||||
lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
|
lRet = ::RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
|
||||||
0, KEY_QUERY_VALUE, &hKey);
|
0, KEY_QUERY_VALUE, &hKey);
|
||||||
if (lRet != ERROR_SUCCESS)
|
if (lRet != ERROR_SUCCESS)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
TCHAR szTmp[2048];
|
TCHAR szTmp[2048];
|
||||||
DWORD cntBytes = sizeof(szTmp);
|
DWORD cntBytes = sizeof(szTmp);
|
||||||
lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL,
|
lRet = ::RegQueryValueEx(hKey, _T("ProcessorNameString"), NULL, NULL,
|
||||||
(LPBYTE)szTmp, &cntBytes);
|
(LPBYTE)szTmp, &cntBytes);
|
||||||
if (lRet != ERROR_SUCCESS)
|
if (lRet != ERROR_SUCCESS)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
::RegCloseKey(hKey);
|
::RegCloseKey(hKey);
|
||||||
@@ -271,150 +271,150 @@ BOOL WheatyExceptionReport::_GetWindowsVersion(TCHAR* szVersion, DWORD cntMax)
|
|||||||
{
|
{
|
||||||
// Windows NT product family.
|
// Windows NT product family.
|
||||||
case VER_PLATFORM_WIN32_NT:
|
case VER_PLATFORM_WIN32_NT:
|
||||||
{
|
{
|
||||||
#if WINVER < 0x0500
|
#if WINVER < 0x0500
|
||||||
BYTE suiteMask = osvi.wReserved[0];
|
BYTE suiteMask = osvi.wReserved[0];
|
||||||
BYTE productType = osvi.wReserved[1];
|
BYTE productType = osvi.wReserved[1];
|
||||||
#else
|
#else
|
||||||
WORD suiteMask = osvi.wSuiteMask;
|
WORD suiteMask = osvi.wSuiteMask;
|
||||||
BYTE productType = osvi.wProductType;
|
BYTE productType = osvi.wProductType;
|
||||||
#endif // WINVER < 0x0500
|
#endif // WINVER < 0x0500
|
||||||
|
|
||||||
// Test for the specific product family.
|
// Test for the specific product family.
|
||||||
if (osvi.dwMajorVersion == 10)
|
if (osvi.dwMajorVersion == 10)
|
||||||
{
|
|
||||||
if (productType == VER_NT_WORKSTATION)
|
|
||||||
_tcsncat(szVersion, _T("Windows 10 "), cntMax);
|
|
||||||
else
|
|
||||||
_tcsncat(szVersion, _T("Windows Server 2016 "), cntMax);
|
|
||||||
}
|
|
||||||
else if (osvi.dwMajorVersion == 6)
|
|
||||||
{
|
|
||||||
if (productType == VER_NT_WORKSTATION)
|
|
||||||
{
|
{
|
||||||
if (osvi.dwMinorVersion == 3)
|
if (productType == VER_NT_WORKSTATION)
|
||||||
_tcsncat(szVersion, _T("Windows 8.1 "), cntMax);
|
_tcsncat(szVersion, _T("Windows 10 "), cntMax);
|
||||||
|
else
|
||||||
|
_tcsncat(szVersion, _T("Windows Server 2016 "), cntMax);
|
||||||
|
}
|
||||||
|
else if (osvi.dwMajorVersion == 6)
|
||||||
|
{
|
||||||
|
if (productType == VER_NT_WORKSTATION)
|
||||||
|
{
|
||||||
|
if (osvi.dwMinorVersion == 3)
|
||||||
|
_tcsncat(szVersion, _T("Windows 8.1 "), cntMax);
|
||||||
|
else 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 == 3)
|
||||||
|
_tcsncat(szVersion, _T("Windows Server 2012 R2 "), cntMax);
|
||||||
else if (osvi.dwMinorVersion == 2)
|
else if (osvi.dwMinorVersion == 2)
|
||||||
_tcsncat(szVersion, _T("Windows 8 "), cntMax);
|
_tcsncat(szVersion, _T("Windows Server 2012 "), cntMax);
|
||||||
else if (osvi.dwMinorVersion == 1)
|
else if (osvi.dwMinorVersion == 1)
|
||||||
_tcsncat(szVersion, _T("Windows 7 "), cntMax);
|
_tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax);
|
||||||
else
|
else
|
||||||
_tcsncat(szVersion, _T("Windows Vista "), cntMax);
|
_tcsncat(szVersion, _T("Windows Server 2008 "), cntMax);
|
||||||
}
|
}
|
||||||
else if (osvi.dwMinorVersion == 3)
|
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2)
|
||||||
_tcsncat(szVersion, _T("Windows Server 2012 R2 "), cntMax);
|
_tcsncat(szVersion, _T("Microsoft Windows Server 2003 "), cntMax);
|
||||||
else if (osvi.dwMinorVersion == 2)
|
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 1)
|
||||||
_tcsncat(szVersion, _T("Windows Server 2012 "), cntMax);
|
_tcsncat(szVersion, _T("Microsoft Windows XP "), cntMax);
|
||||||
else if (osvi.dwMinorVersion == 1)
|
else if (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 0)
|
||||||
_tcsncat(szVersion, _T("Windows Server 2008 R2 "), cntMax);
|
_tcsncat(szVersion, _T("Microsoft Windows 2000 "), cntMax);
|
||||||
else
|
else if (osvi.dwMajorVersion <= 4)
|
||||||
_tcsncat(szVersion, _T("Windows Server 2008 "), cntMax);
|
_tcsncat(szVersion, _T("Microsoft Windows NT "), 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.
|
// Test for specific product on Windows NT 4.0 SP6 and later.
|
||||||
if (bVersionEx >= 0)
|
if (bVersionEx >= 0)
|
||||||
{
|
|
||||||
// Test for the workstation type.
|
|
||||||
if (productType == VER_NT_WORKSTATION)
|
|
||||||
{
|
{
|
||||||
if (osvi.dwMajorVersion == 4)
|
// Test for the workstation type.
|
||||||
_tcsncat(szVersion, _T("Workstation 4.0 "), cntMax);
|
if (productType == VER_NT_WORKSTATION)
|
||||||
else if (suiteMask & VER_SUITE_PERSONAL)
|
{
|
||||||
_tcsncat(szVersion, _T("Home Edition "), cntMax);
|
if (osvi.dwMajorVersion == 4)
|
||||||
else if (suiteMask & VER_SUITE_EMBEDDEDNT)
|
_tcsncat(szVersion, _T("Workstation 4.0 "), cntMax);
|
||||||
_tcsncat(szVersion, _T("Embedded "), 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 == 6 || osvi.dwMajorVersion == 10)
|
||||||
|
{
|
||||||
|
if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
|
||||||
|
_tcsncat(szVersion, _T("Essentials "), cntMax);
|
||||||
|
else if (suiteMask & VER_SUITE_DATACENTER)
|
||||||
|
_tcsncat(szVersion, _T("Datacenter "), cntMax);
|
||||||
|
else if (suiteMask & VER_SUITE_ENTERPRISE)
|
||||||
|
_tcsncat(szVersion, _T("Enterprise "), cntMax);
|
||||||
|
else
|
||||||
|
_tcsncat(szVersion, _T("Standard "), cntMax);
|
||||||
|
}
|
||||||
|
else 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(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)"),
|
||||||
|
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(szCSDVersion))
|
||||||
|
_stprintf(wszTmp, _T("(Version %d.%d, Build %d)"),
|
||||||
|
osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
|
||||||
else
|
else
|
||||||
_tcsncat(szVersion, _T("Professional "), cntMax);
|
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
|
||||||
}
|
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
|
||||||
// Test for the server type.
|
|
||||||
else if (productType == VER_NT_SERVER)
|
|
||||||
{
|
|
||||||
if (osvi.dwMajorVersion == 6 || osvi.dwMajorVersion == 10)
|
|
||||||
{
|
|
||||||
if (suiteMask & VER_SUITE_SMALLBUSINESS_RESTRICTED)
|
|
||||||
_tcsncat(szVersion, _T("Essentials "), cntMax);
|
|
||||||
else if (suiteMask & VER_SUITE_DATACENTER)
|
|
||||||
_tcsncat(szVersion, _T("Datacenter "), cntMax);
|
|
||||||
else if (suiteMask & VER_SUITE_ENTERPRISE)
|
|
||||||
_tcsncat(szVersion, _T("Enterprise "), cntMax);
|
|
||||||
else
|
|
||||||
_tcsncat(szVersion, _T("Standard "), cntMax);
|
|
||||||
}
|
|
||||||
else 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(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);
|
_tcsncat(szVersion, wszTmp, cntMax);
|
||||||
}
|
}
|
||||||
else // Windows NT 4.0 prior to SP6a
|
break;
|
||||||
{
|
|
||||||
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
|
|
||||||
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(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)"),
|
|
||||||
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
|
|
||||||
_tcsncat(szVersion, wszTmp, cntMax);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
|
_stprintf(wszTmp, _T("%s (Version %d.%d, Build %d)"),
|
||||||
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
|
szCSDVersion, osvi.dwMajorVersion, osvi.dwMinorVersion, osvi.dwBuildNumber & 0xFFFF);
|
||||||
_tcsncat(szVersion, wszTmp, cntMax);
|
_tcsncat(szVersion, wszTmp, cntMax);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -434,10 +434,10 @@ void WheatyExceptionReport::PrintSystemInfo()
|
|||||||
Log(_T("//=====================================================\r\n"));
|
Log(_T("//=====================================================\r\n"));
|
||||||
if (_GetProcessorName(sString, countof(sString)))
|
if (_GetProcessorName(sString, countof(sString)))
|
||||||
Log(_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"),
|
Log(_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);
|
sString, SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys / 0x400, MemoryStatus.dwAvailPhys / 0x400, MemoryStatus.dwTotalPageFile / 0x400);
|
||||||
else
|
else
|
||||||
Log(_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"),
|
Log(_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);
|
SystemInfo.dwNumberOfProcessors, MemoryStatus.dwTotalPhys / 0x400, MemoryStatus.dwAvailPhys / 0x400, MemoryStatus.dwTotalPageFile / 0x400);
|
||||||
|
|
||||||
if (_GetWindowsVersion(sString, countof(sString)))
|
if (_GetWindowsVersion(sString, countof(sString)))
|
||||||
Log(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString);
|
Log(_T("\r\n*** Operation System ***\r\n%s\r\n"), sString);
|
||||||
@@ -448,48 +448,48 @@ void WheatyExceptionReport::PrintSystemInfo()
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
|
void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
|
||||||
{
|
{
|
||||||
THREADENTRY32 te32;
|
THREADENTRY32 te32;
|
||||||
|
|
||||||
DWORD dwOwnerPID = GetCurrentProcessId();
|
DWORD dwOwnerPID = GetCurrentProcessId();
|
||||||
m_hProcess = GetCurrentProcess();
|
m_hProcess = GetCurrentProcess();
|
||||||
// Take a snapshot of all running threads
|
// Take a snapshot of all running threads
|
||||||
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
||||||
if (hThreadSnap == INVALID_HANDLE_VALUE)
|
if (hThreadSnap == INVALID_HANDLE_VALUE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Fill in the size of the structure before using it.
|
// Fill in the size of the structure before using it.
|
||||||
te32.dwSize = sizeof(THREADENTRY32);
|
te32.dwSize = sizeof(THREADENTRY32);
|
||||||
|
|
||||||
// Retrieve information about the first thread,
|
// Retrieve information about the first thread,
|
||||||
// and exit if unsuccessful
|
// and exit if unsuccessful
|
||||||
if (!Thread32First(hThreadSnap, &te32))
|
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;
|
CloseHandle(hThreadSnap); // Must clean up the
|
||||||
context.ContextFlags = 0xffffffff;
|
// snapshot object!
|
||||||
HANDLE threadHandle = OpenThread(THREAD_GET_CONTEXT | THREAD_QUERY_INFORMATION, false, te32.th32ThreadID);
|
return;
|
||||||
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.
|
// Now walk the thread list of the system,
|
||||||
CloseHandle(hThreadSnap);
|
// 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@@ -497,7 +497,7 @@ void WheatyExceptionReport::printTracesForAllThreads(bool bWriteVariables)
|
|||||||
// WheatyUnhandledExceptionFilter
|
// WheatyUnhandledExceptionFilter
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
void WheatyExceptionReport::GenerateExceptionReport(
|
void WheatyExceptionReport::GenerateExceptionReport(
|
||||||
PEXCEPTION_POINTERS pExceptionInfo)
|
PEXCEPTION_POINTERS pExceptionInfo)
|
||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
@@ -526,9 +526,9 @@ PEXCEPTION_POINTERS pExceptionInfo)
|
|||||||
DWORD section;
|
DWORD section;
|
||||||
DWORD_PTR offset;
|
DWORD_PTR offset;
|
||||||
GetLogicalAddress(pExceptionRecord->ExceptionAddress,
|
GetLogicalAddress(pExceptionRecord->ExceptionAddress,
|
||||||
szFaultingModule,
|
szFaultingModule,
|
||||||
sizeof(szFaultingModule),
|
sizeof(szFaultingModule),
|
||||||
section, offset);
|
section, offset);
|
||||||
|
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
Log(_T("Fault address: %08X %02X:%08X %s\r\n"),
|
Log(_T("Fault address: %08X %02X:%08X %s\r\n"),
|
||||||
@@ -612,11 +612,11 @@ PEXCEPTION_POINTERS pExceptionInfo)
|
|||||||
//======================================================================
|
//======================================================================
|
||||||
LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
|
LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
|
||||||
{
|
{
|
||||||
#define EXCEPTION(x) case EXCEPTION_##x: return _T(#x);
|
#define EXCEPTION(x) case EXCEPTION_##x: return _T(#x);
|
||||||
|
|
||||||
switch (dwCode)
|
switch (dwCode)
|
||||||
{
|
{
|
||||||
EXCEPTION(ACCESS_VIOLATION)
|
EXCEPTION(ACCESS_VIOLATION)
|
||||||
EXCEPTION(DATATYPE_MISALIGNMENT)
|
EXCEPTION(DATATYPE_MISALIGNMENT)
|
||||||
EXCEPTION(BREAKPOINT)
|
EXCEPTION(BREAKPOINT)
|
||||||
EXCEPTION(SINGLE_STEP)
|
EXCEPTION(SINGLE_STEP)
|
||||||
@@ -646,8 +646,8 @@ LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
|
|||||||
static TCHAR szBuffer[512] = { 0 };
|
static TCHAR szBuffer[512] = { 0 };
|
||||||
|
|
||||||
FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
|
FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_HMODULE,
|
||||||
GetModuleHandle(_T("NTDLL.DLL")),
|
GetModuleHandle(_T("NTDLL.DLL")),
|
||||||
dwCode, 0, szBuffer, sizeof(szBuffer), 0);
|
dwCode, 0, szBuffer, sizeof(szBuffer), 0);
|
||||||
|
|
||||||
return szBuffer;
|
return szBuffer;
|
||||||
}
|
}
|
||||||
@@ -660,7 +660,7 @@ LPTSTR WheatyExceptionReport::GetExceptionString(DWORD dwCode)
|
|||||||
// by the len parameter (in characters!)
|
// by the len parameter (in characters!)
|
||||||
//=============================================================================
|
//=============================================================================
|
||||||
BOOL WheatyExceptionReport::GetLogicalAddress(
|
BOOL WheatyExceptionReport::GetLogicalAddress(
|
||||||
PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
|
PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
|
||||||
{
|
{
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
MEMORY_BASIC_INFORMATION mbi;
|
||||||
|
|
||||||
@@ -688,12 +688,12 @@ PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
|
|||||||
// Iterate through the section table, looking for the one that encompasses
|
// Iterate through the section table, looking for the one that encompasses
|
||||||
// the linear address.
|
// the linear address.
|
||||||
for (unsigned i = 0;
|
for (unsigned i = 0;
|
||||||
i < pNtHdr->FileHeader.NumberOfSections;
|
i < pNtHdr->FileHeader.NumberOfSections;
|
||||||
i++, pSection++)
|
i++, pSection++)
|
||||||
{
|
{
|
||||||
DWORD_PTR sectionStart = pSection->VirtualAddress;
|
DWORD_PTR sectionStart = pSection->VirtualAddress;
|
||||||
DWORD_PTR sectionEnd = sectionStart
|
DWORD_PTR sectionEnd = sectionStart
|
||||||
+ DWORD_PTR(std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize));
|
+ DWORD_PTR(std::max(pSection->SizeOfRawData, pSection->Misc.VirtualSize));
|
||||||
|
|
||||||
// Is the address in this section???
|
// Is the address in this section???
|
||||||
if ((rva >= sectionStart) && (rva <= sectionEnd))
|
if ((rva >= sectionStart) && (rva <= sectionEnd))
|
||||||
@@ -701,7 +701,7 @@ PVOID addr, PTSTR szModule, DWORD len, DWORD& section, DWORD_PTR& offset)
|
|||||||
// Yes, address is in the section. Calculate section and offset,
|
// Yes, address is in the section. Calculate section and offset,
|
||||||
// and store in the "section" & "offset" params, which were
|
// and store in the "section" & "offset" params, which were
|
||||||
// passed by reference.
|
// passed by reference.
|
||||||
section = i+1;
|
section = i + 1;
|
||||||
offset = rva - sectionStart;
|
offset = rva - sectionStart;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@@ -725,8 +725,8 @@ struct CSymbolInfoPackage : public SYMBOL_INFO_PACKAGE
|
|||||||
// Walks the stack, and writes the results to the report file
|
// Walks the stack, and writes the results to the report file
|
||||||
//============================================================
|
//============================================================
|
||||||
void WheatyExceptionReport::WriteStackDetails(
|
void WheatyExceptionReport::WriteStackDetails(
|
||||||
PCONTEXT pContext,
|
PCONTEXT pContext,
|
||||||
bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output
|
bool bWriteVariables, HANDLE pThreadHandle) // true if local/params should be output
|
||||||
{
|
{
|
||||||
Log(_T("\r\nCall stack:\r\n"));
|
Log(_T("\r\nCall stack:\r\n"));
|
||||||
|
|
||||||
@@ -738,7 +738,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
STACKFRAME64 sf;
|
STACKFRAME64 sf;
|
||||||
memset(&sf, 0, sizeof(sf));
|
memset(&sf, 0, sizeof(sf));
|
||||||
|
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
// Initialize the STACKFRAME structure for the first call. This is only
|
// Initialize the STACKFRAME structure for the first call. This is only
|
||||||
// necessary for Intel CPUs, and isn't mentioned in the documentation.
|
// necessary for Intel CPUs, and isn't mentioned in the documentation.
|
||||||
sf.AddrPC.Offset = pContext->Eip;
|
sf.AddrPC.Offset = pContext->Eip;
|
||||||
@@ -749,7 +749,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
sf.AddrFrame.Mode = AddrModeFlat;
|
sf.AddrFrame.Mode = AddrModeFlat;
|
||||||
|
|
||||||
dwMachineType = IMAGE_FILE_MACHINE_I386;
|
dwMachineType = IMAGE_FILE_MACHINE_I386;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _M_X64
|
#ifdef _M_X64
|
||||||
sf.AddrPC.Offset = pContext->Rip;
|
sf.AddrPC.Offset = pContext->Rip;
|
||||||
@@ -765,14 +765,14 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
{
|
{
|
||||||
// Get the next stack frame
|
// Get the next stack frame
|
||||||
if (! StackWalk64(dwMachineType,
|
if (! StackWalk64(dwMachineType,
|
||||||
m_hProcess,
|
m_hProcess,
|
||||||
pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(),
|
pThreadHandle != NULL ? pThreadHandle : GetCurrentThread(),
|
||||||
&sf,
|
&sf,
|
||||||
pContext,
|
pContext,
|
||||||
0,
|
0,
|
||||||
SymFunctionTableAccess64,
|
SymFunctionTableAccess64,
|
||||||
SymGetModuleBase64,
|
SymGetModuleBase64,
|
||||||
0))
|
0))
|
||||||
break;
|
break;
|
||||||
if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure
|
if (0 == sf.AddrFrame.Offset) // Basic sanity check to make sure
|
||||||
break; // the frame is OK. Bail if not.
|
break; // the frame is OK. Bail if not.
|
||||||
@@ -789,10 +789,10 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
// Get the name of the function for this stack frame entry
|
// Get the name of the function for this stack frame entry
|
||||||
CSymbolInfoPackage sip;
|
CSymbolInfoPackage sip;
|
||||||
if (SymFromAddr(
|
if (SymFromAddr(
|
||||||
m_hProcess, // Process handle of the current process
|
m_hProcess, // Process handle of the current process
|
||||||
sf.AddrPC.Offset, // Symbol address
|
sf.AddrPC.Offset, // Symbol address
|
||||||
&symDisplacement, // Address of the variable that will receive the displacement
|
&symDisplacement, // Address of the variable that will receive the displacement
|
||||||
&sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object)
|
&sip.si)) // Address of the SYMBOL_INFO structure (inside "sip" object)
|
||||||
{
|
{
|
||||||
Log(_T("%hs+%I64X"), sip.si.Name, symDisplacement);
|
Log(_T("%hs+%I64X"), sip.si.Name, symDisplacement);
|
||||||
|
|
||||||
@@ -804,7 +804,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
DWORD_PTR offset = 0;
|
DWORD_PTR offset = 0;
|
||||||
|
|
||||||
GetLogicalAddress((PVOID)sf.AddrPC.Offset,
|
GetLogicalAddress((PVOID)sf.AddrPC.Offset,
|
||||||
szModule, sizeof(szModule), section, offset);
|
szModule, sizeof(szModule), section, offset);
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
Log(_T("%04X:%08X %s"), section, offset, szModule);
|
Log(_T("%04X:%08X %s"), section, offset, szModule);
|
||||||
#endif
|
#endif
|
||||||
@@ -817,7 +817,7 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
|
IMAGEHLP_LINE64 lineInfo = { sizeof(IMAGEHLP_LINE64) };
|
||||||
DWORD dwLineDisplacement;
|
DWORD dwLineDisplacement;
|
||||||
if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset,
|
if (SymGetLineFromAddr64(m_hProcess, sf.AddrPC.Offset,
|
||||||
&dwLineDisplacement, &lineInfo))
|
&dwLineDisplacement, &lineInfo))
|
||||||
{
|
{
|
||||||
Log(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber);
|
Log(_T(" %s line %u"), lineInfo.FileName, lineInfo.LineNumber);
|
||||||
}
|
}
|
||||||
@@ -847,9 +847,9 @@ bool bWriteVariables, HANDLE pThreadHandle)
|
|||||||
|
|
||||||
BOOL CALLBACK
|
BOOL CALLBACK
|
||||||
WheatyExceptionReport::EnumerateSymbolsCallback(
|
WheatyExceptionReport::EnumerateSymbolsCallback(
|
||||||
PSYMBOL_INFO pSymInfo,
|
PSYMBOL_INFO pSymInfo,
|
||||||
ULONG /*SymbolSize*/,
|
ULONG /*SymbolSize*/,
|
||||||
PVOID UserContext)
|
PVOID UserContext)
|
||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
@@ -871,8 +871,8 @@ PVOID UserContext)
|
|||||||
// values.
|
// values.
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
bool WheatyExceptionReport::FormatSymbolValue(
|
bool WheatyExceptionReport::FormatSymbolValue(
|
||||||
PSYMBOL_INFO pSym,
|
PSYMBOL_INFO pSym,
|
||||||
STACKFRAME64 * sf)
|
STACKFRAME64* sf)
|
||||||
{
|
{
|
||||||
// If it's a function, don't do anything.
|
// If it's a function, don't do anything.
|
||||||
if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK
|
if (pSym->Tag == SymTagFunction) // SymTagFunction from CVCONST.H from the DIA SDK
|
||||||
@@ -883,7 +883,8 @@ STACKFRAME64 * sf)
|
|||||||
if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
|
if (pSym->Flags & IMAGEHLP_SYMBOL_INFO_REGRELATIVE)
|
||||||
{
|
{
|
||||||
// if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1)
|
// if (pSym->Register == 8) // EBP is the value 8 (in DBGHELP 5.1)
|
||||||
{ // This may change!!!
|
{
|
||||||
|
// This may change!!!
|
||||||
#ifdef _M_IX86
|
#ifdef _M_IX86
|
||||||
pVariable = sf->AddrFrame.Offset;
|
pVariable = sf->AddrFrame.Offset;
|
||||||
#elif _M_X64
|
#elif _M_X64
|
||||||
@@ -942,14 +943,14 @@ STACKFRAME64 * sf)
|
|||||||
// bHandled = false, so that FormatSymbolValue() will format them.
|
// bHandled = false, so that FormatSymbolValue() will format them.
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
void WheatyExceptionReport::DumpTypeIndex(
|
void WheatyExceptionReport::DumpTypeIndex(
|
||||||
DWORD64 modBase,
|
DWORD64 modBase,
|
||||||
DWORD dwTypeIndex,
|
DWORD dwTypeIndex,
|
||||||
DWORD_PTR offset,
|
DWORD_PTR offset,
|
||||||
bool & bHandled,
|
bool& bHandled,
|
||||||
char const* Name,
|
char const* Name,
|
||||||
char* /*suffix*/,
|
char* /*suffix*/,
|
||||||
bool newSymbol,
|
bool newSymbol,
|
||||||
bool logChildren)
|
bool logChildren)
|
||||||
{
|
{
|
||||||
bHandled = false;
|
bHandled = false;
|
||||||
|
|
||||||
@@ -962,9 +963,9 @@ bool logChildren)
|
|||||||
|
|
||||||
// Get the name of the symbol. This will either be a Type name (if a UDT),
|
// Get the name of the symbol. This will either be a Type name (if a UDT),
|
||||||
// or the structure member name.
|
// or the structure member name.
|
||||||
WCHAR * pwszTypeName;
|
WCHAR* pwszTypeName;
|
||||||
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME,
|
if (SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_GET_SYMNAME,
|
||||||
&pwszTypeName))
|
&pwszTypeName))
|
||||||
{
|
{
|
||||||
// handle special cases
|
// handle special cases
|
||||||
if (wcscmp(pwszTypeName, L"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0)
|
if (wcscmp(pwszTypeName, L"std::basic_string<char,std::char_traits<char>,std::allocator<char> >") == 0)
|
||||||
@@ -1085,17 +1086,17 @@ bool logChildren)
|
|||||||
if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL)
|
if (symbolDetails.size() >= WER_MAX_NESTING_LEVEL)
|
||||||
logChildren = false;
|
logChildren = false;
|
||||||
DumpTypeIndex(modBase, innerTypeID,
|
DumpTypeIndex(modBase, innerTypeID,
|
||||||
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
|
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
|
||||||
break;
|
break;
|
||||||
case SymTagPointerType:
|
case SymTagPointerType:
|
||||||
if (Name != NULL && Name[0] != '\0')
|
if (Name != NULL && Name[0] != '\0')
|
||||||
symbolDetails.top().Name = Name;
|
symbolDetails.top().Name = Name;
|
||||||
DumpTypeIndex(modBase, innerTypeID,
|
DumpTypeIndex(modBase, innerTypeID,
|
||||||
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
|
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
|
||||||
break;
|
break;
|
||||||
case SymTagArrayType:
|
case SymTagArrayType:
|
||||||
DumpTypeIndex(modBase, innerTypeID,
|
DumpTypeIndex(modBase, innerTypeID,
|
||||||
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
|
offset, bHandled, symbolDetails.top().Name.c_str(), "", false, logChildren);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -1109,7 +1110,7 @@ bool logChildren)
|
|||||||
|
|
||||||
BasicType basicType = btNoType;
|
BasicType basicType = btNoType;
|
||||||
DumpTypeIndex(modBase, innerTypeID,
|
DumpTypeIndex(modBase, innerTypeID,
|
||||||
offset, bHandled, Name, "", false, false);
|
offset, bHandled, Name, "", false, false);
|
||||||
|
|
||||||
// Set Value back to an empty string since the Array object itself has no value, only its elements have
|
// Set Value back to an empty string since the Array object itself has no value, only its elements have
|
||||||
std::string firstElementValue = symbolDetails.top().Value;
|
std::string firstElementValue = symbolDetails.top().Value;
|
||||||
@@ -1196,16 +1197,16 @@ bool logChildren)
|
|||||||
// TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this.
|
// TI_FINDCHILDREN_PARAMS struct has. Use derivation to accomplish this.
|
||||||
struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
|
struct FINDCHILDREN : TI_FINDCHILDREN_PARAMS
|
||||||
{
|
{
|
||||||
ULONG MoreChildIds[1024*2];
|
ULONG MoreChildIds[1024 * 2];
|
||||||
FINDCHILDREN(){Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);}
|
FINDCHILDREN() {Count = sizeof(MoreChildIds) / sizeof(MoreChildIds[0]);}
|
||||||
} children;
|
} children;
|
||||||
|
|
||||||
children.Count = dwChildrenCount;
|
children.Count = dwChildrenCount;
|
||||||
children.Start= 0;
|
children.Start = 0;
|
||||||
|
|
||||||
// Get the array of TypeIds, one for each child type
|
// Get the array of TypeIds, one for each child type
|
||||||
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN,
|
if (!SymGetTypeInfo(m_hProcess, modBase, dwTypeIndex, TI_FINDCHILDREN,
|
||||||
&children))
|
&children))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1217,17 +1218,17 @@ bool logChildren)
|
|||||||
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag);
|
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_SYMTAG, &symTag);
|
||||||
|
|
||||||
if (symTag == SymTagFunction ||
|
if (symTag == SymTagFunction ||
|
||||||
symTag == SymTagEnum ||
|
symTag == SymTagEnum ||
|
||||||
symTag == SymTagTypedef ||
|
symTag == SymTagTypedef ||
|
||||||
symTag == SymTagVTable)
|
symTag == SymTagVTable)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Ignore static fields
|
// Ignore static fields
|
||||||
DWORD dataKind;
|
DWORD dataKind;
|
||||||
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind);
|
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i], TI_GET_DATAKIND, &dataKind);
|
||||||
if (dataKind == DataIsStaticLocal ||
|
if (dataKind == DataIsStaticLocal ||
|
||||||
dataKind == DataIsGlobal ||
|
dataKind == DataIsGlobal ||
|
||||||
dataKind == DataIsStaticMember)
|
dataKind == DataIsStaticMember)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
||||||
@@ -1245,14 +1246,14 @@ bool logChildren)
|
|||||||
// Get the offset of the child member, relative to its parent
|
// Get the offset of the child member, relative to its parent
|
||||||
DWORD dwMemberOffset;
|
DWORD dwMemberOffset;
|
||||||
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
|
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
|
||||||
TI_GET_OFFSET, &dwMemberOffset);
|
TI_GET_OFFSET, &dwMemberOffset);
|
||||||
|
|
||||||
// Calculate the address of the member
|
// Calculate the address of the member
|
||||||
DWORD_PTR dwFinalOffset = offset + dwMemberOffset;
|
DWORD_PTR dwFinalOffset = offset + dwMemberOffset;
|
||||||
|
|
||||||
DumpTypeIndex(modBase,
|
DumpTypeIndex(modBase,
|
||||||
children.ChildId[i],
|
children.ChildId[i],
|
||||||
dwFinalOffset, bHandled2, ""/*Name */, "", true, true);
|
dwFinalOffset, bHandled2, ""/*Name */, "", true, true);
|
||||||
|
|
||||||
// If the child wasn't a UDT, format it appropriately
|
// If the child wasn't a UDT, format it appropriately
|
||||||
if (!bHandled2)
|
if (!bHandled2)
|
||||||
@@ -1264,7 +1265,7 @@ bool logChildren)
|
|||||||
// SymGetTypeInfo(TI_GET_TYPEID) call below.
|
// SymGetTypeInfo(TI_GET_TYPEID) call below.
|
||||||
DWORD typeId;
|
DWORD typeId;
|
||||||
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
|
SymGetTypeInfo(m_hProcess, modBase, children.ChildId[i],
|
||||||
TI_GET_TYPEID, &typeId);
|
TI_GET_TYPEID, &typeId);
|
||||||
|
|
||||||
// Get the size of the child member
|
// Get the size of the child member
|
||||||
ULONG64 length;
|
ULONG64 length;
|
||||||
@@ -1282,39 +1283,39 @@ bool logChildren)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void WheatyExceptionReport::FormatOutputValue(char * pszCurrBuffer,
|
void WheatyExceptionReport::FormatOutputValue(char* pszCurrBuffer,
|
||||||
BasicType basicType,
|
BasicType basicType,
|
||||||
DWORD64 length,
|
DWORD64 length,
|
||||||
PVOID pAddress,
|
PVOID pAddress,
|
||||||
size_t bufferSize,
|
size_t bufferSize,
|
||||||
size_t countOverride)
|
size_t countOverride)
|
||||||
{
|
{
|
||||||
__try
|
__try
|
||||||
{
|
{
|
||||||
switch (basicType)
|
switch (basicType)
|
||||||
{
|
{
|
||||||
case btChar:
|
case btChar:
|
||||||
{
|
{
|
||||||
// Special case handling for char[] type
|
// Special case handling for char[] type
|
||||||
if (countOverride != 0)
|
if (countOverride != 0)
|
||||||
length = countOverride;
|
length = countOverride;
|
||||||
else
|
else
|
||||||
length = strlen((char*)pAddress);
|
length = strlen((char*)pAddress);
|
||||||
if (length > bufferSize - 6)
|
if (length > bufferSize - 6)
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), (char*)pAddress);
|
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), (char*)pAddress);
|
||||||
else
|
else
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s\"", (DWORD)length, (char*)pAddress);
|
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s\"", (DWORD)length, (char*)pAddress);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case btStdString:
|
case btStdString:
|
||||||
{
|
{
|
||||||
std::string* value = static_cast<std::string*>(pAddress);
|
std::string* value = static_cast<std::string*>(pAddress);
|
||||||
if (value->length() > bufferSize - 6)
|
if (value->length() > bufferSize - 6)
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), value->c_str());
|
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%.*s...\"", (DWORD)(bufferSize - 6), value->c_str());
|
||||||
else
|
else
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", value->c_str());
|
pszCurrBuffer += sprintf(pszCurrBuffer, "\"%s\"", value->c_str());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
// Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!)
|
// Format appropriately (assuming it's a 1, 2, or 4 bytes (!!!)
|
||||||
if (length == 1)
|
if (length == 1)
|
||||||
@@ -1333,19 +1334,19 @@ size_t countOverride)
|
|||||||
if (basicType == btFloat)
|
if (basicType == btFloat)
|
||||||
{
|
{
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "%f",
|
pszCurrBuffer += sprintf(pszCurrBuffer, "%f",
|
||||||
*(double *)pAddress);
|
*(double*)pAddress);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X",
|
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X",
|
||||||
*(DWORD64*)pAddress);
|
*(DWORD64*)pAddress);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
#if _WIN64
|
#if _WIN64
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", (DWORD64)pAddress);
|
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%I64X", (DWORD64)pAddress);
|
||||||
#else
|
#else
|
||||||
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", (DWORD)pAddress);
|
pszCurrBuffer += sprintf(pszCurrBuffer, "0x%X", (DWORD)pAddress);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -1365,7 +1366,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
|
|||||||
{
|
{
|
||||||
BasicType basicType;
|
BasicType basicType;
|
||||||
if (SymGetTypeInfo(m_hProcess, modBase, typeIndex,
|
if (SymGetTypeInfo(m_hProcess, modBase, typeIndex,
|
||||||
TI_GET_BASETYPE, &basicType))
|
TI_GET_BASETYPE, &basicType))
|
||||||
{
|
{
|
||||||
return basicType;
|
return basicType;
|
||||||
}
|
}
|
||||||
@@ -1376,7 +1377,7 @@ WheatyExceptionReport::GetBasicType(DWORD typeIndex, DWORD64 modBase)
|
|||||||
if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, TI_GET_TYPEID, &typeId))
|
if (SymGetTypeInfo(m_hProcess, modBase, typeIndex, TI_GET_TYPEID, &typeId))
|
||||||
{
|
{
|
||||||
if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE,
|
if (SymGetTypeInfo(m_hProcess, modBase, typeId, TI_GET_BASETYPE,
|
||||||
&basicType))
|
&basicType))
|
||||||
{
|
{
|
||||||
return basicType;
|
return basicType;
|
||||||
}
|
}
|
||||||
@@ -1401,12 +1402,12 @@ DWORD_PTR WheatyExceptionReport::DereferenceUnsafePointer(DWORD_PTR address)
|
|||||||
// Helper function that writes to the report file, and allows the user to use
|
// Helper function that writes to the report file, and allows the user to use
|
||||||
// printf style formating
|
// printf style formating
|
||||||
//============================================================================
|
//============================================================================
|
||||||
int __cdecl WheatyExceptionReport::Log(const TCHAR * format, ...)
|
int __cdecl WheatyExceptionReport::Log(const TCHAR* format, ...)
|
||||||
{
|
{
|
||||||
int retValue;
|
int retValue;
|
||||||
va_list argptr;
|
va_list argptr;
|
||||||
va_start(argptr, format);
|
va_start(argptr, format);
|
||||||
|
|
||||||
if (stackOverflowException)
|
if (stackOverflowException)
|
||||||
retValue = HeapLog(format, argptr);
|
retValue = HeapLog(format, argptr);
|
||||||
else
|
else
|
||||||
@@ -1417,7 +1418,7 @@ int __cdecl WheatyExceptionReport::Log(const TCHAR * format, ...)
|
|||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cdecl WheatyExceptionReport::StackLog(const TCHAR * format, va_list argptr)
|
int __cdecl WheatyExceptionReport::StackLog(const TCHAR* format, va_list argptr)
|
||||||
{
|
{
|
||||||
int retValue;
|
int retValue;
|
||||||
DWORD cbWritten;
|
DWORD cbWritten;
|
||||||
@@ -1429,7 +1430,7 @@ int __cdecl WheatyExceptionReport::StackLog(const TCHAR * format, va_list argptr
|
|||||||
return retValue;
|
return retValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
int __cdecl WheatyExceptionReport::HeapLog(const TCHAR * format, va_list argptr)
|
int __cdecl WheatyExceptionReport::HeapLog(const TCHAR* format, va_list argptr)
|
||||||
{
|
{
|
||||||
int retValue = 0;
|
int retValue = 0;
|
||||||
DWORD cbWritten;
|
DWORD cbWritten;
|
||||||
|
|||||||
@@ -103,7 +103,7 @@ struct SymbolPair
|
|||||||
bool operator<(SymbolPair const& other) const
|
bool operator<(SymbolPair const& other) const
|
||||||
{
|
{
|
||||||
return _offset < other._offset ||
|
return _offset < other._offset ||
|
||||||
(_offset == other._offset && _type < other._type);
|
(_offset == other._offset && _type < other._type);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD _type;
|
DWORD _type;
|
||||||
@@ -133,69 +133,69 @@ struct SymbolDetail
|
|||||||
|
|
||||||
class WheatyExceptionReport
|
class WheatyExceptionReport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
WheatyExceptionReport();
|
WheatyExceptionReport();
|
||||||
~WheatyExceptionReport();
|
~WheatyExceptionReport();
|
||||||
|
|
||||||
// entry point where control comes on an unhandled exception
|
// entry point where control comes on an unhandled exception
|
||||||
static LONG WINAPI WheatyUnhandledExceptionFilter(
|
static LONG WINAPI WheatyUnhandledExceptionFilter(
|
||||||
PEXCEPTION_POINTERS pExceptionInfo);
|
PEXCEPTION_POINTERS pExceptionInfo);
|
||||||
|
|
||||||
static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved);
|
static void __cdecl WheatyCrtHandler(wchar_t const* expression, wchar_t const* function, wchar_t const* file, unsigned int line, uintptr_t pReserved);
|
||||||
|
|
||||||
static void printTracesForAllThreads(bool);
|
static void printTracesForAllThreads(bool);
|
||||||
private:
|
private:
|
||||||
// where report info is extracted and generated
|
// where report info is extracted and generated
|
||||||
static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
|
static void GenerateExceptionReport(PEXCEPTION_POINTERS pExceptionInfo);
|
||||||
static void PrintSystemInfo();
|
static void PrintSystemInfo();
|
||||||
static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
|
static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
|
||||||
static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
|
static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
|
||||||
|
|
||||||
// Helper functions
|
// Helper functions
|
||||||
static LPTSTR GetExceptionString(DWORD dwCode);
|
static LPTSTR GetExceptionString(DWORD dwCode);
|
||||||
static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
|
static BOOL GetLogicalAddress(PVOID addr, PTSTR szModule, DWORD len,
|
||||||
DWORD& section, DWORD_PTR& offset);
|
DWORD& section, DWORD_PTR& offset);
|
||||||
|
|
||||||
static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
|
static void WriteStackDetails(PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
|
||||||
|
|
||||||
static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
|
static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO, ULONG, PVOID);
|
||||||
|
|
||||||
static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64 *);
|
static bool FormatSymbolValue(PSYMBOL_INFO, STACKFRAME64*);
|
||||||
|
|
||||||
static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool &, char const*, char*, bool, bool);
|
static void DumpTypeIndex(DWORD64, DWORD, DWORD_PTR, bool&, char const*, char*, bool, bool);
|
||||||
|
|
||||||
static void FormatOutputValue(char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress, size_t bufferSize, size_t countOverride = 0);
|
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 BasicType GetBasicType(DWORD typeIndex, DWORD64 modBase);
|
||||||
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
|
static DWORD_PTR DereferenceUnsafePointer(DWORD_PTR address);
|
||||||
|
|
||||||
static int __cdecl Log(const TCHAR * format, ...);
|
static int __cdecl Log(const TCHAR* format, ...);
|
||||||
static int __cdecl StackLog(const TCHAR * format, va_list argptr);
|
static int __cdecl StackLog(const TCHAR* format, va_list argptr);
|
||||||
static int __cdecl HeapLog(const TCHAR * format, va_list argptr);
|
static int __cdecl HeapLog(const TCHAR* format, va_list argptr);
|
||||||
|
|
||||||
static bool StoreSymbol(DWORD type , DWORD_PTR offset);
|
static bool StoreSymbol(DWORD type, DWORD_PTR offset);
|
||||||
static void ClearSymbols();
|
static void ClearSymbols();
|
||||||
|
|
||||||
// Variables used by the class
|
// Variables used by the class
|
||||||
static TCHAR m_szLogFileName[MAX_PATH];
|
static TCHAR m_szLogFileName[MAX_PATH];
|
||||||
static TCHAR m_szDumpFileName[MAX_PATH];
|
static TCHAR m_szDumpFileName[MAX_PATH];
|
||||||
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
|
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
|
||||||
static _invalid_parameter_handler m_previousCrtHandler;
|
static _invalid_parameter_handler m_previousCrtHandler;
|
||||||
static HANDLE m_hReportFile;
|
static HANDLE m_hReportFile;
|
||||||
static HANDLE m_hDumpFile;
|
static HANDLE m_hDumpFile;
|
||||||
static HANDLE m_hProcess;
|
static HANDLE m_hProcess;
|
||||||
static SymbolPairs symbols;
|
static SymbolPairs symbols;
|
||||||
static std::stack<SymbolDetail> symbolDetails;
|
static std::stack<SymbolDetail> symbolDetails;
|
||||||
static bool stackOverflowException;
|
static bool stackOverflowException;
|
||||||
static bool alreadyCrashed;
|
static bool alreadyCrashed;
|
||||||
static std::mutex alreadyCrashedLock;
|
static std::mutex alreadyCrashedLock;
|
||||||
typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
|
typedef NTSTATUS(NTAPI* pRtlGetVersion)(PRTL_OSVERSIONINFOW lpVersionInformation);
|
||||||
static pRtlGetVersion RtlGetVersion;
|
static pRtlGetVersion RtlGetVersion;
|
||||||
|
|
||||||
static void PushSymbolDetail();
|
static void PushSymbolDetail();
|
||||||
static void PopSymbolDetail();
|
static void PopSymbolDetail();
|
||||||
static void PrintSymbolDetail();
|
static void PrintSymbolDetail();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -41,9 +41,9 @@ private:
|
|||||||
template<class T>
|
template<class T>
|
||||||
class Permissible
|
class Permissible
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Permissible() { }
|
virtual ~Permissible() { }
|
||||||
virtual int Permit(const T *) const = 0;
|
virtual int Permit(const T*) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -15,218 +15,236 @@ class LinkedListHead;
|
|||||||
|
|
||||||
class LinkedListElement
|
class LinkedListElement
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
friend class LinkedListHead;
|
friend class LinkedListHead;
|
||||||
|
|
||||||
LinkedListElement* iNext;
|
LinkedListElement* iNext;
|
||||||
LinkedListElement* iPrev;
|
LinkedListElement* iPrev;
|
||||||
public:
|
public:
|
||||||
LinkedListElement(): iNext(NULL), iPrev(NULL) { }
|
LinkedListElement(): iNext(NULL), iPrev(NULL) { }
|
||||||
~LinkedListElement() { delink(); }
|
~LinkedListElement() { delink(); }
|
||||||
|
|
||||||
bool hasNext() const { return(iNext && iNext->iNext != NULL); }
|
bool hasNext() const { return(iNext && iNext->iNext != NULL); }
|
||||||
bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); }
|
bool hasPrev() const { return(iPrev && iPrev->iPrev != NULL); }
|
||||||
bool isInList() const { return(iNext != NULL && iPrev != NULL); }
|
bool isInList() const { return(iNext != NULL && iPrev != NULL); }
|
||||||
|
|
||||||
LinkedListElement * next() { return hasNext() ? iNext : NULL; }
|
LinkedListElement* next() { return hasNext() ? iNext : NULL; }
|
||||||
LinkedListElement const* next() const { return hasNext() ? iNext : NULL; }
|
LinkedListElement const* next() const { return hasNext() ? iNext : NULL; }
|
||||||
LinkedListElement * prev() { return hasPrev() ? iPrev : NULL; }
|
LinkedListElement* prev() { return hasPrev() ? iPrev : NULL; }
|
||||||
LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; }
|
LinkedListElement const* prev() const { return hasPrev() ? iPrev : NULL; }
|
||||||
|
|
||||||
LinkedListElement * nocheck_next() { return iNext; }
|
LinkedListElement* nocheck_next() { return iNext; }
|
||||||
LinkedListElement const* nocheck_next() const { return iNext; }
|
LinkedListElement const* nocheck_next() const { return iNext; }
|
||||||
LinkedListElement * nocheck_prev() { return iPrev; }
|
LinkedListElement* nocheck_prev() { return iPrev; }
|
||||||
LinkedListElement const* nocheck_prev() const { return iPrev; }
|
LinkedListElement const* nocheck_prev() const { return iPrev; }
|
||||||
|
|
||||||
void delink()
|
void delink()
|
||||||
|
{
|
||||||
|
if (isInList())
|
||||||
{
|
{
|
||||||
if (isInList())
|
iNext->iPrev = iPrev;
|
||||||
{
|
iPrev->iNext = iNext;
|
||||||
iNext->iPrev = iPrev; iPrev->iNext = iNext; iNext = NULL; iPrev = NULL;
|
iNext = NULL;
|
||||||
}
|
iPrev = NULL;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void insertBefore(LinkedListElement* pElem)
|
void insertBefore(LinkedListElement* pElem)
|
||||||
{
|
{
|
||||||
pElem->iNext = this;
|
pElem->iNext = this;
|
||||||
pElem->iPrev = iPrev;
|
pElem->iPrev = iPrev;
|
||||||
iPrev->iNext = pElem;
|
iPrev->iNext = pElem;
|
||||||
iPrev = pElem;
|
iPrev = pElem;
|
||||||
}
|
}
|
||||||
|
|
||||||
void insertAfter(LinkedListElement* pElem)
|
void insertAfter(LinkedListElement* pElem)
|
||||||
{
|
{
|
||||||
pElem->iPrev = this;
|
pElem->iPrev = this;
|
||||||
pElem->iNext = iNext;
|
pElem->iNext = iNext;
|
||||||
iNext->iPrev = pElem;
|
iNext->iPrev = pElem;
|
||||||
iNext = pElem;
|
iNext = pElem;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================
|
//============================================
|
||||||
|
|
||||||
class LinkedListHead
|
class LinkedListHead
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
LinkedListElement iFirst;
|
LinkedListElement iFirst;
|
||||||
LinkedListElement iLast;
|
LinkedListElement iLast;
|
||||||
uint32 iSize;
|
uint32 iSize;
|
||||||
public:
|
public:
|
||||||
LinkedListHead(): iSize(0)
|
LinkedListHead(): iSize(0)
|
||||||
|
{
|
||||||
|
// create empty list
|
||||||
|
|
||||||
|
iFirst.iNext = &iLast;
|
||||||
|
iLast.iPrev = &iFirst;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() const { return(!iFirst.iNext->isInList()); }
|
||||||
|
|
||||||
|
LinkedListElement* getFirst() { return(isEmpty() ? NULL : iFirst.iNext); }
|
||||||
|
LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); }
|
||||||
|
|
||||||
|
LinkedListElement* getLast() { return(isEmpty() ? NULL : iLast.iPrev); }
|
||||||
|
LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); }
|
||||||
|
|
||||||
|
void insertFirst(LinkedListElement* pElem)
|
||||||
|
{
|
||||||
|
iFirst.insertAfter(pElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insertLast(LinkedListElement* pElem)
|
||||||
|
{
|
||||||
|
iLast.insertBefore(pElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32 getSize() const
|
||||||
|
{
|
||||||
|
if (!iSize)
|
||||||
{
|
{
|
||||||
// create empty list
|
uint32 result = 0;
|
||||||
|
LinkedListElement const* e = getFirst();
|
||||||
iFirst.iNext = &iLast;
|
while (e)
|
||||||
iLast.iPrev = &iFirst;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isEmpty() const { return(!iFirst.iNext->isInList()); }
|
|
||||||
|
|
||||||
LinkedListElement * getFirst() { return(isEmpty() ? NULL : iFirst.iNext); }
|
|
||||||
LinkedListElement const* getFirst() const { return(isEmpty() ? NULL : iFirst.iNext); }
|
|
||||||
|
|
||||||
LinkedListElement * getLast() { return(isEmpty() ? NULL : iLast.iPrev); }
|
|
||||||
LinkedListElement const* getLast() const { return(isEmpty() ? NULL : iLast.iPrev); }
|
|
||||||
|
|
||||||
void insertFirst(LinkedListElement* pElem)
|
|
||||||
{
|
|
||||||
iFirst.insertAfter(pElem);
|
|
||||||
}
|
|
||||||
|
|
||||||
void insertLast(LinkedListElement* pElem)
|
|
||||||
{
|
|
||||||
iLast.insertBefore(pElem);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32 getSize() const
|
|
||||||
{
|
|
||||||
if (!iSize)
|
|
||||||
{
|
{
|
||||||
uint32 result = 0;
|
++result;
|
||||||
LinkedListElement const* e = getFirst();
|
e = e->next();
|
||||||
while (e)
|
|
||||||
{
|
|
||||||
++result;
|
|
||||||
e = e->next();
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
else
|
return result;
|
||||||
return iSize;
|
}
|
||||||
|
else
|
||||||
|
return iSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void incSize() { ++iSize; }
|
||||||
|
void decSize() { --iSize; }
|
||||||
|
|
||||||
|
template<class _Ty>
|
||||||
|
class Iterator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef std::bidirectional_iterator_tag iterator_category;
|
||||||
|
typedef _Ty value_type;
|
||||||
|
typedef ptrdiff_t difference_type;
|
||||||
|
typedef ptrdiff_t distance_type;
|
||||||
|
typedef _Ty* pointer;
|
||||||
|
typedef _Ty const* const_pointer;
|
||||||
|
typedef _Ty& reference;
|
||||||
|
typedef _Ty const& const_reference;
|
||||||
|
|
||||||
|
Iterator() : _Ptr(0)
|
||||||
|
{
|
||||||
|
// construct with null node pointer
|
||||||
}
|
}
|
||||||
|
|
||||||
void incSize() { ++iSize; }
|
Iterator(pointer _Pnode) : _Ptr(_Pnode)
|
||||||
void decSize() { --iSize; }
|
|
||||||
|
|
||||||
template<class _Ty>
|
|
||||||
class Iterator
|
|
||||||
{
|
{
|
||||||
public:
|
// construct with node pointer _Pnode
|
||||||
typedef std::bidirectional_iterator_tag iterator_category;
|
}
|
||||||
typedef _Ty value_type;
|
|
||||||
typedef ptrdiff_t difference_type;
|
|
||||||
typedef ptrdiff_t distance_type;
|
|
||||||
typedef _Ty* pointer;
|
|
||||||
typedef _Ty const* const_pointer;
|
|
||||||
typedef _Ty& reference;
|
|
||||||
typedef _Ty const & const_reference;
|
|
||||||
|
|
||||||
Iterator() : _Ptr(0)
|
Iterator& operator=(Iterator const& _Right)
|
||||||
{ // construct with null node pointer
|
{
|
||||||
}
|
_Ptr = _Right._Ptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Iterator(pointer _Pnode) : _Ptr(_Pnode)
|
Iterator& operator=(const_pointer const& _Right)
|
||||||
{ // construct with node pointer _Pnode
|
{
|
||||||
}
|
_Ptr = pointer(_Right);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
Iterator& operator=(Iterator const &_Right)
|
reference operator*()
|
||||||
{
|
{
|
||||||
_Ptr = _Right._Ptr;
|
// return designated value
|
||||||
return *this;
|
return *_Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator& operator=(const_pointer const &_Right)
|
pointer operator->()
|
||||||
{
|
{
|
||||||
_Ptr = pointer(_Right);
|
// return pointer to class object
|
||||||
return *this;
|
return _Ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
reference operator*()
|
Iterator& operator++()
|
||||||
{ // return designated value
|
{
|
||||||
return *_Ptr;
|
// preincrement
|
||||||
}
|
_Ptr = _Ptr->next();
|
||||||
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
pointer operator->()
|
Iterator operator++(int)
|
||||||
{ // return pointer to class object
|
{
|
||||||
return _Ptr;
|
// postincrement
|
||||||
}
|
iterator _Tmp = *this;
|
||||||
|
++*this;
|
||||||
|
return (_Tmp);
|
||||||
|
}
|
||||||
|
|
||||||
Iterator& operator++()
|
Iterator& operator--()
|
||||||
{ // preincrement
|
{
|
||||||
_Ptr = _Ptr->next();
|
// predecrement
|
||||||
return (*this);
|
_Ptr = _Ptr->prev();
|
||||||
}
|
return (*this);
|
||||||
|
}
|
||||||
|
|
||||||
Iterator operator++(int)
|
Iterator operator--(int)
|
||||||
{ // postincrement
|
{
|
||||||
iterator _Tmp = *this;
|
// postdecrement
|
||||||
++*this;
|
iterator _Tmp = *this;
|
||||||
return (_Tmp);
|
--*this;
|
||||||
}
|
return (_Tmp);
|
||||||
|
}
|
||||||
|
|
||||||
Iterator& operator--()
|
bool operator==(Iterator const& _Right) const
|
||||||
{ // predecrement
|
{
|
||||||
_Ptr = _Ptr->prev();
|
// test for iterator equality
|
||||||
return (*this);
|
return (_Ptr == _Right._Ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Iterator operator--(int)
|
bool operator!=(Iterator const& _Right) const
|
||||||
{ // postdecrement
|
{
|
||||||
iterator _Tmp = *this;
|
// test for iterator inequality
|
||||||
--*this;
|
return (!(*this == _Right));
|
||||||
return (_Tmp);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool operator==(Iterator const &_Right) const
|
bool operator==(pointer const& _Right) const
|
||||||
{ // test for iterator equality
|
{
|
||||||
return (_Ptr == _Right._Ptr);
|
// test for pointer equality
|
||||||
}
|
return (_Ptr != _Right);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator!=(Iterator const &_Right) const
|
bool operator!=(pointer const& _Right) const
|
||||||
{ // test for iterator inequality
|
{
|
||||||
return (!(*this == _Right));
|
// test for pointer equality
|
||||||
}
|
return (!(*this == _Right));
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(pointer const &_Right) const
|
bool operator==(const_reference _Right) const
|
||||||
{ // test for pointer equality
|
{
|
||||||
return (_Ptr != _Right);
|
// test for reference equality
|
||||||
}
|
return (_Ptr == &_Right);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator!=(pointer const &_Right) const
|
bool operator!=(const_reference _Right) const
|
||||||
{ // test for pointer equality
|
{
|
||||||
return (!(*this == _Right));
|
// test for reference equality
|
||||||
}
|
return (_Ptr != &_Right);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator==(const_reference _Right) const
|
pointer _Mynode()
|
||||||
{ // test for reference equality
|
{
|
||||||
return (_Ptr == &_Right);
|
// return node pointer
|
||||||
}
|
return (_Ptr);
|
||||||
|
}
|
||||||
|
|
||||||
bool operator!=(const_reference _Right) const
|
protected:
|
||||||
{ // test for reference equality
|
pointer _Ptr; // pointer to node
|
||||||
return (_Ptr != &_Right);
|
};
|
||||||
}
|
|
||||||
|
|
||||||
pointer _Mynode()
|
typedef Iterator<LinkedListElement> iterator;
|
||||||
{ // return node pointer
|
|
||||||
return (_Ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
pointer _Ptr; // pointer to node
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef Iterator<LinkedListElement> iterator;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//============================================
|
//============================================
|
||||||
|
|||||||
@@ -13,30 +13,30 @@
|
|||||||
|
|
||||||
template <class TO, class FROM> class RefManager : public LinkedListHead
|
template <class TO, class FROM> class RefManager : public LinkedListHead
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef LinkedListHead::Iterator< Reference<TO, FROM> > iterator;
|
typedef LinkedListHead::Iterator< Reference<TO, FROM> > iterator;
|
||||||
RefManager() { }
|
RefManager() { }
|
||||||
virtual ~RefManager() { clearReferences(); }
|
virtual ~RefManager() { clearReferences(); }
|
||||||
|
|
||||||
Reference<TO, FROM>* getFirst() { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); }
|
Reference<TO, FROM>* getFirst() { return ((Reference<TO, FROM>*) LinkedListHead::getFirst()); }
|
||||||
Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); }
|
Reference<TO, FROM> const* getFirst() const { return ((Reference<TO, FROM> const*) LinkedListHead::getFirst()); }
|
||||||
Reference<TO, FROM>* getLast() { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); }
|
Reference<TO, FROM>* getLast() { return ((Reference<TO, FROM>*) LinkedListHead::getLast()); }
|
||||||
Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); }
|
Reference<TO, FROM> const* getLast() const { return ((Reference<TO, FROM> const*) LinkedListHead::getLast()); }
|
||||||
|
|
||||||
iterator begin() { return iterator(getFirst()); }
|
iterator begin() { return iterator(getFirst()); }
|
||||||
iterator end() { return iterator(NULL); }
|
iterator end() { return iterator(NULL); }
|
||||||
iterator rbegin() { return iterator(getLast()); }
|
iterator rbegin() { return iterator(getLast()); }
|
||||||
iterator rend() { return iterator(NULL); }
|
iterator rend() { return iterator(NULL); }
|
||||||
|
|
||||||
void clearReferences()
|
void clearReferences()
|
||||||
|
{
|
||||||
|
LinkedListElement* ref;
|
||||||
|
while ((ref = getFirst()) != NULL)
|
||||||
{
|
{
|
||||||
LinkedListElement* ref;
|
((Reference<TO, FROM>*) ref)->invalidate();
|
||||||
while ((ref = getFirst()) != NULL)
|
ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list
|
||||||
{
|
|
||||||
((Reference<TO, FROM>*) ref)->invalidate();
|
|
||||||
ref->delink(); // the delink might be already done by invalidate(), but doing it here again does not hurt and insures an empty list
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//=====================================================
|
//=====================================================
|
||||||
|
|||||||
@@ -14,74 +14,74 @@
|
|||||||
|
|
||||||
template <class TO, class FROM> class Reference : public LinkedListElement
|
template <class TO, class FROM> class Reference : public LinkedListElement
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
TO* iRefTo;
|
TO* iRefTo;
|
||||||
FROM* iRefFrom;
|
FROM* iRefFrom;
|
||||||
protected:
|
protected:
|
||||||
// Tell our refTo (target) object that we have a link
|
// Tell our refTo (target) object that we have a link
|
||||||
virtual void targetObjectBuildLink() = 0;
|
virtual void targetObjectBuildLink() = 0;
|
||||||
|
|
||||||
// Tell our refTo (taget) object, that the link is cut
|
// Tell our refTo (taget) object, that the link is cut
|
||||||
virtual void targetObjectDestroyLink() = 0;
|
virtual void targetObjectDestroyLink() = 0;
|
||||||
|
|
||||||
// Tell our refFrom (source) object, that the link is cut (Target destroyed)
|
// Tell our refFrom (source) object, that the link is cut (Target destroyed)
|
||||||
virtual void sourceObjectDestroyLink() = 0;
|
virtual void sourceObjectDestroyLink() = 0;
|
||||||
public:
|
public:
|
||||||
Reference() { iRefTo = NULL; iRefFrom = NULL; }
|
Reference() { iRefTo = NULL; iRefFrom = NULL; }
|
||||||
virtual ~Reference() { }
|
virtual ~Reference() { }
|
||||||
|
|
||||||
// Create new link
|
// Create new link
|
||||||
void link(TO* toObj, FROM* fromObj)
|
void link(TO* toObj, FROM* fromObj)
|
||||||
|
{
|
||||||
|
ASSERT(fromObj); // fromObj MUST not be NULL
|
||||||
|
if (isValid())
|
||||||
|
unlink();
|
||||||
|
if (toObj != NULL)
|
||||||
{
|
{
|
||||||
ASSERT(fromObj); // fromObj MUST not be NULL
|
iRefTo = toObj;
|
||||||
if (isValid())
|
iRefFrom = fromObj;
|
||||||
unlink();
|
targetObjectBuildLink();
|
||||||
if (toObj != NULL)
|
|
||||||
{
|
|
||||||
iRefTo = toObj;
|
|
||||||
iRefFrom = fromObj;
|
|
||||||
targetObjectBuildLink();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// We don't need the reference anymore. Call comes from the refFrom object
|
// We don't need the reference anymore. Call comes from the refFrom object
|
||||||
// Tell our refTo object, that the link is cut
|
// Tell our refTo object, that the link is cut
|
||||||
void unlink()
|
void unlink()
|
||||||
{
|
{
|
||||||
targetObjectDestroyLink();
|
targetObjectDestroyLink();
|
||||||
delink();
|
delink();
|
||||||
iRefTo = NULL;
|
iRefTo = NULL;
|
||||||
iRefFrom = NULL;
|
iRefFrom = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Link is invalid due to destruction of referenced target object. Call comes from the refTo object
|
// Link is invalid due to destruction of referenced target object. Call comes from the refTo object
|
||||||
// Tell our refFrom object, that the link is cut
|
// Tell our refFrom object, that the link is cut
|
||||||
void invalidate() // the iRefFrom MUST remain!!
|
void invalidate() // the iRefFrom MUST remain!!
|
||||||
{
|
{
|
||||||
sourceObjectDestroyLink();
|
sourceObjectDestroyLink();
|
||||||
delink();
|
delink();
|
||||||
iRefTo = NULL;
|
iRefTo = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValid() const // Only check the iRefTo
|
bool isValid() const // Only check the iRefTo
|
||||||
{
|
{
|
||||||
return iRefTo != NULL;
|
return iRefTo != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference<TO, FROM> * next() { return((Reference<TO, FROM> *) LinkedListElement::next()); }
|
Reference<TO, FROM>* next() { return((Reference<TO, FROM>*) LinkedListElement::next()); }
|
||||||
Reference<TO, FROM> const* next() const { return((Reference<TO, FROM> const*) LinkedListElement::next()); }
|
Reference<TO, FROM> const* next() const { return((Reference<TO, FROM> const*) LinkedListElement::next()); }
|
||||||
Reference<TO, FROM> * prev() { return((Reference<TO, FROM> *) LinkedListElement::prev()); }
|
Reference<TO, FROM>* prev() { return((Reference<TO, FROM>*) LinkedListElement::prev()); }
|
||||||
Reference<TO, FROM> const* prev() const { return((Reference<TO, FROM> const*) LinkedListElement::prev()); }
|
Reference<TO, FROM> const* prev() const { return((Reference<TO, FROM> const*) LinkedListElement::prev()); }
|
||||||
|
|
||||||
Reference<TO, FROM> * nocheck_next() { return((Reference<TO, FROM> *) LinkedListElement::nocheck_next()); }
|
Reference<TO, FROM>* nocheck_next() { return((Reference<TO, FROM>*) LinkedListElement::nocheck_next()); }
|
||||||
Reference<TO, FROM> const* nocheck_next() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_next()); }
|
Reference<TO, FROM> const* nocheck_next() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_next()); }
|
||||||
Reference<TO, FROM> * nocheck_prev() { return((Reference<TO, FROM> *) LinkedListElement::nocheck_prev()); }
|
Reference<TO, FROM>* nocheck_prev() { return((Reference<TO, FROM>*) LinkedListElement::nocheck_prev()); }
|
||||||
Reference<TO, FROM> const* nocheck_prev() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_prev()); }
|
Reference<TO, FROM> const* nocheck_prev() const { return((Reference<TO, FROM> const*) LinkedListElement::nocheck_prev()); }
|
||||||
|
|
||||||
TO* operator ->() const { return iRefTo; }
|
TO* operator ->() const { return iRefTo; }
|
||||||
TO* getTarget() const { return iRefTo; }
|
TO* getTarget() const { return iRefTo; }
|
||||||
|
|
||||||
FROM* GetSource() const { return iRefFrom; }
|
FROM* GetSource() const { return iRefFrom; }
|
||||||
};
|
};
|
||||||
|
|
||||||
//=====================================================
|
//=====================================================
|
||||||
|
|||||||
@@ -18,81 +18,81 @@
|
|||||||
template<class T, class Key = std::string>
|
template<class T, class Key = std::string>
|
||||||
class ObjectRegistry
|
class ObjectRegistry
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef std::map<Key, T *> RegistryMapType;
|
typedef std::map<Key, T*> RegistryMapType;
|
||||||
|
|
||||||
/// Returns a registry item
|
/// Returns a registry item
|
||||||
const T* GetRegistryItem(Key key) const
|
const T* GetRegistryItem(Key key) const
|
||||||
|
{
|
||||||
|
typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key);
|
||||||
|
return( iter == i_registeredObjects.end() ? NULL : iter->second );
|
||||||
|
}
|
||||||
|
|
||||||
|
static ObjectRegistry<T, Key>* instance()
|
||||||
|
{
|
||||||
|
static ObjectRegistry<T, Key>* instance = new ObjectRegistry<T, Key>();
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Inserts a registry item
|
||||||
|
bool InsertItem(T* obj, Key key, bool override = false)
|
||||||
|
{
|
||||||
|
typename RegistryMapType::iterator iter = i_registeredObjects.find(key);
|
||||||
|
if ( iter != i_registeredObjects.end() )
|
||||||
{
|
{
|
||||||
typename RegistryMapType::const_iterator iter = i_registeredObjects.find(key);
|
if ( !override )
|
||||||
return( iter == i_registeredObjects.end() ? NULL : iter->second );
|
return false;
|
||||||
|
delete iter->second;
|
||||||
|
i_registeredObjects.erase(iter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ObjectRegistry<T, Key>* instance()
|
i_registeredObjects[key] = obj;
|
||||||
{
|
return true;
|
||||||
static ObjectRegistry<T, Key>* instance = new ObjectRegistry<T, Key>();
|
}
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Inserts a registry item
|
/// Removes a registry item
|
||||||
bool InsertItem(T *obj, Key key, bool override = false)
|
void RemoveItem(Key key, bool delete_object = true)
|
||||||
|
{
|
||||||
|
typename RegistryMapType::iterator iter = i_registeredObjects.find(key);
|
||||||
|
if ( iter != i_registeredObjects.end() )
|
||||||
{
|
{
|
||||||
typename RegistryMapType::iterator iter = i_registeredObjects.find(key);
|
if ( delete_object )
|
||||||
if ( iter != i_registeredObjects.end() )
|
|
||||||
{
|
|
||||||
if ( !override )
|
|
||||||
return false;
|
|
||||||
delete iter->second;
|
delete iter->second;
|
||||||
i_registeredObjects.erase(iter);
|
i_registeredObjects.erase(iter);
|
||||||
}
|
|
||||||
|
|
||||||
i_registeredObjects[key] = obj;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Removes a registry item
|
/// Returns true if registry contains an item
|
||||||
void RemoveItem(Key key, bool delete_object = true)
|
bool HasItem(Key key) const
|
||||||
{
|
{
|
||||||
typename RegistryMapType::iterator iter = i_registeredObjects.find(key);
|
return (i_registeredObjects.find(key) != i_registeredObjects.end());
|
||||||
if ( iter != i_registeredObjects.end() )
|
}
|
||||||
{
|
|
||||||
if ( delete_object )
|
|
||||||
delete iter->second;
|
|
||||||
i_registeredObjects.erase(iter);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if registry contains an item
|
/// Inefficiently return a vector of registered items
|
||||||
bool HasItem(Key key) const
|
unsigned int GetRegisteredItems(std::vector<Key>& l) const
|
||||||
{
|
{
|
||||||
return (i_registeredObjects.find(key) != i_registeredObjects.end());
|
unsigned int sz = l.size();
|
||||||
}
|
l.resize(sz + i_registeredObjects.size());
|
||||||
|
for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
|
||||||
|
l[sz++] = iter->first;
|
||||||
|
return i_registeredObjects.size();
|
||||||
|
}
|
||||||
|
|
||||||
/// Inefficiently return a vector of registered items
|
/// Return the map of registered items
|
||||||
unsigned int GetRegisteredItems(std::vector<Key> &l) const
|
RegistryMapType const& GetRegisteredItems() const
|
||||||
{
|
{
|
||||||
unsigned int sz = l.size();
|
return i_registeredObjects;
|
||||||
l.resize(sz + i_registeredObjects.size());
|
}
|
||||||
for (typename RegistryMapType::const_iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
|
|
||||||
l[sz++] = iter->first;
|
|
||||||
return i_registeredObjects.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the map of registered items
|
ObjectRegistry() { }
|
||||||
RegistryMapType const &GetRegisteredItems() const
|
~ObjectRegistry()
|
||||||
{
|
{
|
||||||
return i_registeredObjects;
|
for (typename RegistryMapType::iterator iter = i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
|
||||||
}
|
delete iter->second;
|
||||||
|
i_registeredObjects.clear();
|
||||||
ObjectRegistry() { }
|
}
|
||||||
~ObjectRegistry()
|
private:
|
||||||
{
|
RegistryMapType i_registeredObjects;
|
||||||
for (typename RegistryMapType::iterator iter=i_registeredObjects.begin(); iter != i_registeredObjects.end(); ++iter)
|
|
||||||
delete iter->second;
|
|
||||||
i_registeredObjects.clear();
|
|
||||||
}
|
|
||||||
private:
|
|
||||||
RegistryMapType i_registeredObjects;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -85,28 +85,28 @@ template<class H, class T> struct ContainerList<TypeList<H, T> >
|
|||||||
template<class OBJECT_TYPES>
|
template<class OBJECT_TYPES>
|
||||||
class TypeMapContainer
|
class TypeMapContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
template<class SPECIFIC_TYPE> size_t Count() const { return acore::Count(i_elements, (SPECIFIC_TYPE*)NULL); }
|
template<class SPECIFIC_TYPE> size_t Count() const { return acore::Count(i_elements, (SPECIFIC_TYPE*)NULL); }
|
||||||
|
|
||||||
/// inserts a specific object into the container
|
/// inserts a specific object into the container
|
||||||
template<class SPECIFIC_TYPE> bool insert(SPECIFIC_TYPE *obj)
|
template<class SPECIFIC_TYPE> bool insert(SPECIFIC_TYPE* obj)
|
||||||
{
|
{
|
||||||
SPECIFIC_TYPE* t = acore::Insert(i_elements, obj);
|
SPECIFIC_TYPE* t = acore::Insert(i_elements, obj);
|
||||||
return (t != NULL);
|
return (t != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the object from the container, and returns the removed object
|
/// Removes the object from the container, and returns the removed object
|
||||||
//template<class SPECIFIC_TYPE> bool remove(SPECIFIC_TYPE* obj)
|
//template<class SPECIFIC_TYPE> bool remove(SPECIFIC_TYPE* obj)
|
||||||
//{
|
//{
|
||||||
// SPECIFIC_TYPE* t = acore::Remove(i_elements, obj);
|
// SPECIFIC_TYPE* t = acore::Remove(i_elements, obj);
|
||||||
// return (t != NULL);
|
// return (t != NULL);
|
||||||
//}
|
//}
|
||||||
|
|
||||||
ContainerMapList<OBJECT_TYPES> & GetElements(void) { return i_elements; }
|
ContainerMapList<OBJECT_TYPES>& GetElements(void) { return i_elements; }
|
||||||
const ContainerMapList<OBJECT_TYPES> & GetElements(void) const { return i_elements;}
|
const ContainerMapList<OBJECT_TYPES>& GetElements(void) const { return i_elements;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ContainerMapList<OBJECT_TYPES> i_elements;
|
ContainerMapList<OBJECT_TYPES> i_elements;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -21,54 +21,54 @@ namespace acore
|
|||||||
{
|
{
|
||||||
/* ContainerMapList Helpers */
|
/* ContainerMapList Helpers */
|
||||||
// count functions
|
// count functions
|
||||||
template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE* /*fake*/)
|
template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* /*fake*/)
|
||||||
{
|
{
|
||||||
return elements._element.getSize();
|
return elements._element.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE* /*fake*/)
|
template<class SPECIFIC_TYPE> size_t Count(const ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*fake*/)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE* /*fake*/)
|
template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*fake*/)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >&elements, SPECIFIC_TYPE* fake)
|
template<class SPECIFIC_TYPE, class T> size_t Count(const ContainerMapList<TypeList<SPECIFIC_TYPE, T> >& elements, SPECIFIC_TYPE* fake)
|
||||||
{
|
{
|
||||||
return Count(elements._elements, fake);
|
return Count(elements._elements, fake);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class H, class T> size_t Count(const ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE* fake)
|
template<class SPECIFIC_TYPE, class H, class T> size_t Count(const ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* fake)
|
||||||
{
|
{
|
||||||
return Count(elements._TailElements, fake);
|
return Count(elements._TailElements, fake);
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-const insert functions
|
// non-const insert functions
|
||||||
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE> &elements, SPECIFIC_TYPE *obj)
|
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<SPECIFIC_TYPE>& elements, SPECIFIC_TYPE* obj)
|
||||||
{
|
{
|
||||||
//elements._element[hdl] = obj;
|
//elements._element[hdl] = obj;
|
||||||
obj->AddToGrid(elements._element);
|
obj->AddToGrid(elements._element);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull> &/*elements*/, SPECIFIC_TYPE * /*obj*/)
|
template<class SPECIFIC_TYPE> SPECIFIC_TYPE* Insert(ContainerMapList<TypeNull>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a missed
|
// this is a missed
|
||||||
template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Insert(ContainerMapList<T> &/*elements*/, SPECIFIC_TYPE * /*obj*/)
|
template<class SPECIFIC_TYPE, class T> SPECIFIC_TYPE* Insert(ContainerMapList<T>& /*elements*/, SPECIFIC_TYPE* /*obj*/)
|
||||||
{
|
{
|
||||||
return NULL; // a missed
|
return NULL; // a missed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursion
|
// Recursion
|
||||||
template<class SPECIFIC_TYPE, class H, class T> SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T> >&elements, SPECIFIC_TYPE *obj)
|
template<class SPECIFIC_TYPE, class H, class T> SPECIFIC_TYPE* Insert(ContainerMapList<TypeList<H, T> >& elements, SPECIFIC_TYPE* obj)
|
||||||
{
|
{
|
||||||
SPECIFIC_TYPE* t= Insert(elements._elements, obj);
|
SPECIFIC_TYPE* t = Insert(elements._elements, obj);
|
||||||
return (t != NULL ? t : Insert(elements._TailElements, obj));
|
return (t != NULL ? t : Insert(elements._TailElements, obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,48 +47,48 @@ namespace acore
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// non-const find functions
|
// non-const find functions
|
||||||
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<SPECIFIC_TYPE> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<SPECIFIC_TYPE>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
||||||
{
|
{
|
||||||
typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
|
typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
|
||||||
return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
|
return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeNull> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeNull>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
||||||
{
|
{
|
||||||
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// terminate recursion
|
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// terminate recursion
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<T> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<T>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
||||||
{
|
{
|
||||||
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// this is a missed
|
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// this is a missed
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeList<H, T> >&elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
|
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(ContainerMapList<TypeList<H, T> >& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
|
||||||
{
|
{
|
||||||
CountedPtr<SPECIFIC_TYPE> &t = Find(elements._elements, hdl, fake);
|
CountedPtr<SPECIFIC_TYPE>& t = Find(elements._elements, hdl, fake);
|
||||||
return (!t ? Find(elements._TailElements, hdl, fake) : t);
|
return (!t ? Find(elements._TailElements, hdl, fake) : t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// const find functions
|
// const find functions
|
||||||
template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<SPECIFIC_TYPE> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<SPECIFIC_TYPE>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
||||||
{
|
{
|
||||||
typename CountedPtr<SPECIFIC_TYPE>::iterator iter = elements._element.find(hdl);
|
typename CountedPtr<SPECIFIC_TYPE>::iterator iter = elements._element.find(hdl);
|
||||||
return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
|
return (iter == elements._element.end() ? NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL) : iter->second);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeNull> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
template<class SPECIFIC_TYPE> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeNull>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
||||||
{
|
{
|
||||||
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
|
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class T> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<T> &elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
template<class SPECIFIC_TYPE, class T> const CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<T>& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* /*fake*/)
|
||||||
{
|
{
|
||||||
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
|
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeList<H, T> >&elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
|
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Find(const ContainerMapList<TypeList<H, T> >& elements, OBJECT_HANDLE hdl, CountedPtr<SPECIFIC_TYPE>* fake)
|
||||||
{
|
{
|
||||||
CountedPtr<SPECIFIC_TYPE> &t = Find(elements._elements, hdl, fake);
|
CountedPtr<SPECIFIC_TYPE>& t = Find(elements._elements, hdl, fake);
|
||||||
if (!t)
|
if (!t)
|
||||||
t = Find(elements._TailElement, hdl, fake);
|
t = Find(elements._TailElement, hdl, fake);
|
||||||
|
|
||||||
@@ -96,32 +96,32 @@ namespace acore
|
|||||||
}
|
}
|
||||||
|
|
||||||
// non-const insert functions
|
// non-const insert functions
|
||||||
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<SPECIFIC_TYPE>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
elements._element[hdl] = obj;
|
elements._element[hdl] = obj;
|
||||||
return obj;
|
return obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeNull>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
|
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a missed
|
// this is a missed
|
||||||
template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<T>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// a missed
|
return NullPtr<SPECIFIC_TYPE>((SPECIFIC_TYPE*)NULL);// a missed
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recursion
|
// Recursion
|
||||||
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeList<H, T> >&elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE, class H, class T> CountedPtr<SPECIFIC_TYPE>& Insert(ContainerMapList<TypeList<H, T> >& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
CountedPtr<SPECIFIC_TYPE> &t= Insert(elements._elements, obj, hdl);
|
CountedPtr<SPECIFIC_TYPE>& t = Insert(elements._elements, obj, hdl);
|
||||||
return (!t ? Insert(elements._TailElements, obj, hdl) : t);
|
return (!t ? Insert(elements._TailElements, obj, hdl) : t);
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-const remove method
|
// non-const remove method
|
||||||
template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<SPECIFIC_TYPE> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<SPECIFIC_TYPE>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
|
typename std::map<OBJECT_HANDLE, CountedPtr<SPECIFIC_TYPE> >::iterator iter = elements._element.find(hdl);
|
||||||
if ( iter != elements._element.end() )
|
if ( iter != elements._element.end() )
|
||||||
@@ -133,18 +133,18 @@ namespace acore
|
|||||||
return false; // found... terminate the search
|
return false; // found... terminate the search
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<TypeNull> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE> bool Remove(ContainerMapList<TypeNull>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// this is a missed
|
// this is a missed
|
||||||
template<class SPECIFIC_TYPE, class T> bool Remove(ContainerMapList<T> &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE, class T> bool Remove(ContainerMapList<T>& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class SPECIFIC_TYPE, class T, class H> bool Remove(ContainerMapList<TypeList<H, T> > &elements, CountedPtr<SPECIFIC_TYPE> &obj, OBJECT_HANDLE hdl)
|
template<class SPECIFIC_TYPE, class T, class H> bool Remove(ContainerMapList<TypeList<H, T> >& elements, CountedPtr<SPECIFIC_TYPE>& obj, OBJECT_HANDLE hdl)
|
||||||
{
|
{
|
||||||
// The head element is bad
|
// The head element is bad
|
||||||
bool t = Remove(elements._elements, obj, hdl);
|
bool t = Remove(elements._elements, obj, hdl);
|
||||||
|
|||||||
@@ -20,58 +20,58 @@
|
|||||||
template<class T, class Y> class TypeContainerVisitor;
|
template<class T, class Y> class TypeContainerVisitor;
|
||||||
|
|
||||||
// visitor helper
|
// visitor helper
|
||||||
template<class VISITOR, class TYPE_CONTAINER> void VisitorHelper(VISITOR &v, TYPE_CONTAINER &c)
|
template<class VISITOR, class TYPE_CONTAINER> void VisitorHelper(VISITOR& v, TYPE_CONTAINER& c)
|
||||||
{
|
{
|
||||||
v.Visit(c);
|
v.Visit(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminate condition for container list
|
// terminate condition for container list
|
||||||
template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerList<TypeNull> &/*c*/) { }
|
template<class VISITOR> void VisitorHelper(VISITOR& /*v*/, ContainerList<TypeNull>& /*c*/) { }
|
||||||
|
|
||||||
template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerList<T> &c)
|
template<class VISITOR, class T> void VisitorHelper(VISITOR& v, ContainerList<T>& c)
|
||||||
{
|
{
|
||||||
v.Visit(c._element);
|
v.Visit(c._element);
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursion for container list
|
// recursion for container list
|
||||||
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerList<TypeList<H, T> > &c)
|
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR& v, ContainerList<TypeList<H, T> >& c)
|
||||||
{
|
{
|
||||||
VisitorHelper(v, c._elements);
|
VisitorHelper(v, c._elements);
|
||||||
VisitorHelper(v, c._TailElements);
|
VisitorHelper(v, c._TailElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
// terminate condition container map list
|
// terminate condition container map list
|
||||||
template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerMapList<TypeNull> &/*c*/) { }
|
template<class VISITOR> void VisitorHelper(VISITOR& /*v*/, ContainerMapList<TypeNull>& /*c*/) { }
|
||||||
|
|
||||||
template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerMapList<T> &c)
|
template<class VISITOR, class T> void VisitorHelper(VISITOR& v, ContainerMapList<T>& c)
|
||||||
{
|
{
|
||||||
v.Visit(c._element);
|
v.Visit(c._element);
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursion container map list
|
// recursion container map list
|
||||||
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerMapList<TypeList<H, T> > &c)
|
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR& v, ContainerMapList<TypeList<H, T> >& c)
|
||||||
{
|
{
|
||||||
VisitorHelper(v, c._elements);
|
VisitorHelper(v, c._elements);
|
||||||
VisitorHelper(v, c._TailElements);
|
VisitorHelper(v, c._TailElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
// array list
|
// array list
|
||||||
template<class VISITOR, class T> void VisitorHelper(VISITOR &v, ContainerArrayList<T> &c)
|
template<class VISITOR, class T> void VisitorHelper(VISITOR& v, ContainerArrayList<T>& c)
|
||||||
{
|
{
|
||||||
v.Visit(c._element);
|
v.Visit(c._element);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class VISITOR> void VisitorHelper(VISITOR &/*v*/, ContainerArrayList<TypeNull> &/*c*/) { }
|
template<class VISITOR> void VisitorHelper(VISITOR& /*v*/, ContainerArrayList<TypeNull>& /*c*/) { }
|
||||||
|
|
||||||
// recursion
|
// recursion
|
||||||
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR &v, ContainerArrayList<TypeList<H, T> > &c)
|
template<class VISITOR, class H, class T> void VisitorHelper(VISITOR& v, ContainerArrayList<TypeList<H, T> >& c)
|
||||||
{
|
{
|
||||||
VisitorHelper(v, c._elements);
|
VisitorHelper(v, c._elements);
|
||||||
VisitorHelper(v, c._TailElements);
|
VisitorHelper(v, c._TailElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
// for TypeMapContainer
|
// for TypeMapContainer
|
||||||
template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeMapContainer<OBJECT_TYPES> &c)
|
template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR& v, TypeMapContainer<OBJECT_TYPES>& c)
|
||||||
{
|
{
|
||||||
VisitorHelper(v, c.GetElements());
|
VisitorHelper(v, c.GetElements());
|
||||||
}
|
}
|
||||||
@@ -79,21 +79,21 @@ template<class VISITOR, class OBJECT_TYPES> void VisitorHelper(VISITOR &v, TypeM
|
|||||||
template<class VISITOR, class TYPE_CONTAINER>
|
template<class VISITOR, class TYPE_CONTAINER>
|
||||||
class TypeContainerVisitor
|
class TypeContainerVisitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TypeContainerVisitor(VISITOR &v) : i_visitor(v) { }
|
TypeContainerVisitor(VISITOR& v) : i_visitor(v) { }
|
||||||
|
|
||||||
void Visit(TYPE_CONTAINER &c)
|
void Visit(TYPE_CONTAINER& c)
|
||||||
{
|
{
|
||||||
VisitorHelper(i_visitor, c);
|
VisitorHelper(i_visitor, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Visit(const TYPE_CONTAINER &c) const
|
void Visit(const TYPE_CONTAINER& c) const
|
||||||
{
|
{
|
||||||
VisitorHelper(i_visitor, c);
|
VisitorHelper(i_visitor, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VISITOR &i_visitor;
|
VISITOR& i_visitor;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ Log* Log::instance()
|
|||||||
return &instance;
|
return &instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SetLogLevel(char *Level)
|
void Log::SetLogLevel(char* Level)
|
||||||
{
|
{
|
||||||
int32 NewLevel = atoi((char*)Level);
|
int32 NewLevel = atoi((char*)Level);
|
||||||
if (NewLevel < 0)
|
if (NewLevel < 0)
|
||||||
@@ -81,7 +81,7 @@ void Log::SetLogLevel(char *Level)
|
|||||||
outString("LogLevel is %u", m_logLevel);
|
outString("LogLevel is %u", m_logLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::SetLogFileLevel(char *Level)
|
void Log::SetLogFileLevel(char* Level)
|
||||||
{
|
{
|
||||||
int32 NewLevel = atoi((char*)Level);
|
int32 NewLevel = atoi((char*)Level);
|
||||||
if (NewLevel < 0)
|
if (NewLevel < 0)
|
||||||
@@ -126,7 +126,7 @@ void Log::Initialize()
|
|||||||
bool m_gmlog_timestamp = sConfigMgr->GetBoolDefault("GmLogTimestamp", false, false);
|
bool m_gmlog_timestamp = sConfigMgr->GetBoolDefault("GmLogTimestamp", false, false);
|
||||||
|
|
||||||
size_t dot_pos = m_gmlog_filename_format.find_last_of('.');
|
size_t dot_pos = m_gmlog_filename_format.find_last_of('.');
|
||||||
if (dot_pos!=m_gmlog_filename_format.npos)
|
if (dot_pos != m_gmlog_filename_format.npos)
|
||||||
{
|
{
|
||||||
if (m_gmlog_timestamp)
|
if (m_gmlog_timestamp)
|
||||||
m_gmlog_filename_format.insert(dot_pos, m_logsTimestamp);
|
m_gmlog_filename_format.insert(dot_pos, m_logsTimestamp);
|
||||||
@@ -151,7 +151,7 @@ void Log::Initialize()
|
|||||||
chatLogfile = openLogFile("ChatLogFile", "ChatLogTimestamp", "a");
|
chatLogfile = openLogFile("ChatLogFile", "ChatLogTimestamp", "a");
|
||||||
sqlLogFile = openLogFile("SQLDriverLogFile", NULL, "a");
|
sqlLogFile = openLogFile("SQLDriverLogFile", NULL, "a");
|
||||||
sqlDevLogFile = openLogFile("SQLDeveloperLogFile", NULL, "a");
|
sqlDevLogFile = openLogFile("SQLDeveloperLogFile", NULL, "a");
|
||||||
miscLogFile = fopen((m_logsDir+"Misc.log").c_str(), "a");
|
miscLogFile = fopen((m_logsDir + "Misc.log").c_str(), "a");
|
||||||
|
|
||||||
// Main log file settings
|
// Main log file settings
|
||||||
m_logLevel = sConfigMgr->GetIntDefault("LogLevel", LOGL_NORMAL, false);
|
m_logLevel = sConfigMgr->GetIntDefault("LogLevel", LOGL_NORMAL, false);
|
||||||
@@ -184,20 +184,20 @@ void Log::ReloadConfig()
|
|||||||
|
|
||||||
FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode)
|
FILE* Log::openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode)
|
||||||
{
|
{
|
||||||
std::string logfn=sConfigMgr->GetStringDefault(configFileName, "", false);
|
std::string logfn = sConfigMgr->GetStringDefault(configFileName, "", false);
|
||||||
if (logfn.empty())
|
if (logfn.empty())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (configTimeStampFlag && sConfigMgr->GetBoolDefault(configTimeStampFlag, false, false))
|
if (configTimeStampFlag && sConfigMgr->GetBoolDefault(configTimeStampFlag, false, false))
|
||||||
{
|
{
|
||||||
size_t dot_pos = logfn.find_last_of(".");
|
size_t dot_pos = logfn.find_last_of(".");
|
||||||
if (dot_pos!=logfn.npos)
|
if (dot_pos != logfn.npos)
|
||||||
logfn.insert(dot_pos, m_logsTimestamp);
|
logfn.insert(dot_pos, m_logsTimestamp);
|
||||||
else
|
else
|
||||||
logfn += m_logsTimestamp;
|
logfn += m_logsTimestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fopen((m_logsDir+logfn).c_str(), mode);
|
return fopen((m_logsDir + logfn).c_str(), mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* Log::openGmlogPerAccount(uint32 account)
|
FILE* Log::openGmlogPerAccount(uint32 account)
|
||||||
@@ -220,7 +220,7 @@ void Log::outTimestamp(FILE* file)
|
|||||||
// HH hour (2 digits 00-23)
|
// HH hour (2 digits 00-23)
|
||||||
// MM minutes (2 digits 00-59)
|
// MM minutes (2 digits 00-59)
|
||||||
// SS seconds (2 digits 00-59)
|
// SS seconds (2 digits 00-59)
|
||||||
fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year+1900, aTm->tm_mon+1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
|
fprintf(file, "%-4d-%02d-%02d %02d:%02d:%02d ", aTm->tm_year + 1900, aTm->tm_mon + 1, aTm->tm_mday, aTm->tm_hour, aTm->tm_min, aTm->tm_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::InitColors(const std::string& str)
|
void Log::InitColors(const std::string& str)
|
||||||
@@ -254,7 +254,7 @@ void Log::InitColors(const std::string& str)
|
|||||||
|
|
||||||
void Log::SetColor(bool stdout_stream, ColorTypes color)
|
void Log::SetColor(bool stdout_stream, ColorTypes color)
|
||||||
{
|
{
|
||||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||||
static WORD WinColorFG[Colors] =
|
static WORD WinColorFG[Colors] =
|
||||||
{
|
{
|
||||||
0, // BLACK
|
0, // BLACK
|
||||||
@@ -265,41 +265,41 @@ void Log::SetColor(bool stdout_stream, ColorTypes color)
|
|||||||
FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
|
FOREGROUND_RED | FOREGROUND_BLUE, // MAGENTA
|
||||||
FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
|
FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
|
||||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
|
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, // WHITE
|
||||||
// YELLOW
|
// YELLOW
|
||||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||||
// RED_BOLD
|
// RED_BOLD
|
||||||
FOREGROUND_RED | FOREGROUND_INTENSITY,
|
FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||||
// GREEN_BOLD
|
// GREEN_BOLD
|
||||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||||
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
|
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
|
||||||
// MAGENTA_BOLD
|
// MAGENTA_BOLD
|
||||||
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||||
// CYAN_BOLD
|
// CYAN_BOLD
|
||||||
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||||
// WHITE_BOLD
|
// WHITE_BOLD
|
||||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||||
};
|
};
|
||||||
|
|
||||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
|
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
|
||||||
SetConsoleTextAttribute(hConsole, WinColorFG[color]);
|
SetConsoleTextAttribute(hConsole, WinColorFG[color]);
|
||||||
#else
|
#else
|
||||||
enum ANSITextAttr
|
enum ANSITextAttr
|
||||||
{
|
{
|
||||||
TA_NORMAL=0,
|
TA_NORMAL = 0,
|
||||||
TA_BOLD=1,
|
TA_BOLD = 1,
|
||||||
TA_BLINK=5,
|
TA_BLINK = 5,
|
||||||
TA_REVERSE=7
|
TA_REVERSE = 7
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ANSIFgTextAttr
|
enum ANSIFgTextAttr
|
||||||
{
|
{
|
||||||
FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
|
FG_BLACK = 30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
|
||||||
FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
|
FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ANSIBgTextAttr
|
enum ANSIBgTextAttr
|
||||||
{
|
{
|
||||||
BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
|
BG_BLACK = 40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
|
||||||
BG_MAGENTA, BG_CYAN, BG_WHITE
|
BG_MAGENTA, BG_CYAN, BG_WHITE
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -322,18 +322,18 @@ void Log::SetColor(bool stdout_stream, ColorTypes color)
|
|||||||
FG_WHITE // LWHITE
|
FG_WHITE // LWHITE
|
||||||
};
|
};
|
||||||
|
|
||||||
fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : ""));
|
fprintf((stdout_stream ? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < Colors ? ";1" : ""));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::ResetColor(bool stdout_stream)
|
void Log::ResetColor(bool stdout_stream)
|
||||||
{
|
{
|
||||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
|
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
|
||||||
SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED );
|
SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED );
|
||||||
#else
|
#else
|
||||||
fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m");
|
fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Log::GetTimestampStr()
|
std::string Log::GetTimestampStr()
|
||||||
@@ -348,7 +348,7 @@ std::string Log::GetTimestampStr()
|
|||||||
// MM minutes (2 digits 00-59)
|
// MM minutes (2 digits 00-59)
|
||||||
// SS seconds (2 digits 00-59)
|
// SS seconds (2 digits 00-59)
|
||||||
char buf[20];
|
char buf[20];
|
||||||
int ret = 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);
|
int ret = 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);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@@ -358,7 +358,7 @@ std::string Log::GetTimestampStr()
|
|||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outDB(LogTypes type, const char * str)
|
void Log::outDB(LogTypes type, const char* str)
|
||||||
{
|
{
|
||||||
if(!str || std::string(str).empty() || type >= MAX_LOG_TYPES)
|
if(!str || std::string(str).empty() || type >= MAX_LOG_TYPES)
|
||||||
return;
|
return;
|
||||||
@@ -367,10 +367,10 @@ void Log::outDB(LogTypes type, const char * str)
|
|||||||
LoginDatabase.EscapeString(new_str);
|
LoginDatabase.EscapeString(new_str);
|
||||||
|
|
||||||
LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) "
|
LoginDatabase.PExecute("INSERT INTO logs (time, realm, type, string) "
|
||||||
"VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, (uint32)type, new_str.c_str());
|
"VALUES (" UI64FMTD ", %u, %u, '%s');", uint64(time(0)), realm, (uint32)type, new_str.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outString(const char * str, ...)
|
void Log::outString(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -423,7 +423,7 @@ void Log::outString()
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outCrash(const char * err, ...)
|
void Log::outCrash(const char* err, ...)
|
||||||
{
|
{
|
||||||
if (!err)
|
if (!err)
|
||||||
return;
|
return;
|
||||||
@@ -466,7 +466,7 @@ void Log::outCrash(const char * err, ...)
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outError(const char * err, ...)
|
void Log::outError(const char* err, ...)
|
||||||
{
|
{
|
||||||
if (!err)
|
if (!err)
|
||||||
return;
|
return;
|
||||||
@@ -537,7 +537,7 @@ void Log::outSQLDriver(const char* str, ...)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outErrorDb(const char * err, ...)
|
void Log::outErrorDb(const char* err, ...)
|
||||||
{
|
{
|
||||||
if (!err)
|
if (!err)
|
||||||
return;
|
return;
|
||||||
@@ -592,7 +592,7 @@ void Log::outErrorDb(const char * err, ...)
|
|||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outBasic(const char * str, ...)
|
void Log::outBasic(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -636,7 +636,7 @@ void Log::outBasic(const char * str, ...)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outDetail(const char * str, ...)
|
void Log::outDetail(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -708,7 +708,7 @@ void Log::outSQLDev(const char* str, ...)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outDebug(DebugLogFilters f, const char * str, ...)
|
void Log::outDebug(DebugLogFilters f, const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!(m_DebugLogMask & f))
|
if (!(m_DebugLogMask & f))
|
||||||
return;
|
return;
|
||||||
@@ -756,7 +756,7 @@ void Log::outDebug(DebugLogFilters f, const char * str, ...)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outStaticDebug(const char * str, ...)
|
void Log::outStaticDebug(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -801,7 +801,7 @@ void Log::outStaticDebug(const char * str, ...)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outStringInLine(const char * str, ...)
|
void Log::outStringInLine(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -820,7 +820,7 @@ void Log::outStringInLine(const char * str, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outCommand(uint32 account, const char * str, ...)
|
void Log::outCommand(uint32 account, const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -890,7 +890,7 @@ void Log::outCommand(uint32 account, const char * str, ...)
|
|||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outChar(const char * str, ...)
|
void Log::outChar(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -917,7 +917,7 @@ void Log::outChar(const char * str, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name)
|
void Log::outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name)
|
||||||
{
|
{
|
||||||
FILE* file = NULL;
|
FILE* file = NULL;
|
||||||
if (m_charLog_Dump_Separate)
|
if (m_charLog_Dump_Separate)
|
||||||
@@ -933,14 +933,14 @@ void Log::outCharDump(const char * str, uint32 account_id, uint32 guid, const ch
|
|||||||
if (file)
|
if (file)
|
||||||
{
|
{
|
||||||
fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",
|
fprintf(file, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",
|
||||||
account_id, guid, name, str);
|
account_id, guid, name, str);
|
||||||
fflush(file);
|
fflush(file);
|
||||||
if (m_charLog_Dump_Separate)
|
if (m_charLog_Dump_Separate)
|
||||||
fclose(file);
|
fclose(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outChat(const char * str, ...)
|
void Log::outChat(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -967,7 +967,7 @@ void Log::outChat(const char * str, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outRemote(const char * str, ...)
|
void Log::outRemote(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
@@ -994,7 +994,7 @@ void Log::outRemote(const char * str, ...)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Log::outMisc(const char * str, ...)
|
void Log::outMisc(const char* str, ...)
|
||||||
{
|
{
|
||||||
if (!str)
|
if (!str)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ enum LogTypes
|
|||||||
LOG_TYPE_CRASH = 9,
|
LOG_TYPE_CRASH = 9,
|
||||||
LOG_TYPE_CHAT = 10,
|
LOG_TYPE_CHAT = 10,
|
||||||
LOG_TYPE_PERF = 11,
|
LOG_TYPE_PERF = 11,
|
||||||
LOG_TYPE_MULTITH= 12,
|
LOG_TYPE_MULTITH = 12,
|
||||||
MAX_LOG_TYPES
|
MAX_LOG_TYPES
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ enum LogLevel
|
|||||||
LOGL_DEBUG
|
LOGL_DEBUG
|
||||||
};
|
};
|
||||||
|
|
||||||
const int LogLevels = int(LOGL_DEBUG)+1;
|
const int LogLevels = int(LOGL_DEBUG) + 1;
|
||||||
|
|
||||||
enum ColorTypes
|
enum ColorTypes
|
||||||
{
|
{
|
||||||
@@ -91,110 +91,110 @@ enum ColorTypes
|
|||||||
WHITE
|
WHITE
|
||||||
};
|
};
|
||||||
|
|
||||||
const int Colors = int(WHITE)+1;
|
const int Colors = int(WHITE) + 1;
|
||||||
|
|
||||||
class Log
|
class Log
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
Log();
|
Log();
|
||||||
~Log();
|
~Log();
|
||||||
Log(Log const&) = delete;
|
Log(Log const&) = delete;
|
||||||
Log(Log&&) = delete;
|
Log(Log&&) = delete;
|
||||||
Log& operator=(Log const&) = delete;
|
Log& operator=(Log const&) = delete;
|
||||||
Log& operator=(Log&&) = delete;
|
Log& operator=(Log&&) = delete;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Log* instance();
|
static Log* instance();
|
||||||
|
|
||||||
void Initialize();
|
|
||||||
|
|
||||||
void ReloadConfig();
|
void Initialize();
|
||||||
|
|
||||||
void InitColors(const std::string& init_str);
|
void ReloadConfig();
|
||||||
void SetColor(bool stdout_stream, ColorTypes color);
|
|
||||||
void ResetColor(bool stdout_stream);
|
|
||||||
|
|
||||||
void outDB(LogTypes type, const char * str);
|
void InitColors(const std::string& init_str);
|
||||||
void outString(const char * str, ...) ATTR_PRINTF(2, 3);
|
void SetColor(bool stdout_stream, ColorTypes color);
|
||||||
void outString();
|
void ResetColor(bool stdout_stream);
|
||||||
void outStringInLine(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outError(const char * err, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outCrash(const char * err, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outBasic(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outDetail(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outSQLDev(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4);
|
|
||||||
void outStaticDebug(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outErrorDb(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outChar(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outCommand(uint32 account, const char * str, ...) ATTR_PRINTF(3, 4);
|
|
||||||
void outChat(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outRemote(const char * str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3);
|
|
||||||
void outMisc(const char * str, ...) ATTR_PRINTF(2, 3); // pussywizard
|
|
||||||
void outCharDump(const char * str, uint32 account_id, uint32 guid, const char * name);
|
|
||||||
|
|
||||||
static void outTimestamp(FILE* file);
|
void outDB(LogTypes type, const char* str);
|
||||||
static std::string GetTimestampStr();
|
void outString(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outString();
|
||||||
|
void outStringInLine(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outError(const char* err, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outCrash(const char* err, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outBasic(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outDetail(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outSQLDev(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outDebug(DebugLogFilters f, const char* str, ...) ATTR_PRINTF(3, 4);
|
||||||
|
void outStaticDebug(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outErrorDb(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outChar(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outCommand(uint32 account, const char* str, ...) ATTR_PRINTF(3, 4);
|
||||||
|
void outChat(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outRemote(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outSQLDriver(const char* str, ...) ATTR_PRINTF(2, 3);
|
||||||
|
void outMisc(const char* str, ...) ATTR_PRINTF(2, 3); // pussywizard
|
||||||
|
void outCharDump(const char* str, uint32 account_id, uint32 guid, const char* name);
|
||||||
|
|
||||||
void SetLogLevel(char * Level);
|
static void outTimestamp(FILE* file);
|
||||||
void SetLogFileLevel(char * Level);
|
static std::string GetTimestampStr();
|
||||||
void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; }
|
|
||||||
void SetRealmID(uint32 id) { realm = id; }
|
|
||||||
|
|
||||||
bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
|
void SetLogLevel(char* Level);
|
||||||
bool IsOutCharDump() const { return m_charLog_Dump; }
|
void SetLogFileLevel(char* Level);
|
||||||
|
void SetSQLDriverQueryLogging(bool newStatus) { m_sqlDriverQueryLogging = newStatus; }
|
||||||
|
void SetRealmID(uint32 id) { realm = id; }
|
||||||
|
|
||||||
bool GetLogDB() const { return m_enableLogDB; }
|
bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
|
||||||
void SetLogDB(bool enable) { m_enableLogDB = enable; }
|
bool IsOutCharDump() const { return m_charLog_Dump; }
|
||||||
bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; }
|
|
||||||
private:
|
|
||||||
FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
|
|
||||||
FILE* openGmlogPerAccount(uint32 account);
|
|
||||||
|
|
||||||
FILE* raLogfile;
|
bool GetLogDB() const { return m_enableLogDB; }
|
||||||
FILE* logfile;
|
void SetLogDB(bool enable) { m_enableLogDB = enable; }
|
||||||
FILE* gmLogfile;
|
bool GetSQLDriverQueryLogging() const { return m_sqlDriverQueryLogging; }
|
||||||
FILE* charLogfile;
|
private:
|
||||||
FILE* dberLogfile;
|
FILE* openLogFile(char const* configFileName, char const* configTimeStampFlag, char const* mode);
|
||||||
FILE* chatLogfile;
|
FILE* openGmlogPerAccount(uint32 account);
|
||||||
FILE* sqlLogFile;
|
|
||||||
FILE* sqlDevLogFile;
|
|
||||||
FILE* miscLogFile;
|
|
||||||
|
|
||||||
// cache values for after initilization use (like gm log per account case)
|
FILE* raLogfile;
|
||||||
std::string m_logsDir;
|
FILE* logfile;
|
||||||
std::string m_logsTimestamp;
|
FILE* gmLogfile;
|
||||||
|
FILE* charLogfile;
|
||||||
|
FILE* dberLogfile;
|
||||||
|
FILE* chatLogfile;
|
||||||
|
FILE* sqlLogFile;
|
||||||
|
FILE* sqlDevLogFile;
|
||||||
|
FILE* miscLogFile;
|
||||||
|
|
||||||
// gm log control
|
// cache values for after initilization use (like gm log per account case)
|
||||||
bool m_gmlog_per_account;
|
std::string m_logsDir;
|
||||||
std::string m_gmlog_filename_format;
|
std::string m_logsTimestamp;
|
||||||
|
|
||||||
bool m_enableLogDB;
|
// gm log control
|
||||||
uint32 realm;
|
bool m_gmlog_per_account;
|
||||||
|
std::string m_gmlog_filename_format;
|
||||||
|
|
||||||
// log coloring
|
bool m_enableLogDB;
|
||||||
bool m_colored;
|
uint32 realm;
|
||||||
ColorTypes m_colors[4];
|
|
||||||
|
|
||||||
// log levels:
|
// log coloring
|
||||||
// false: errors only, true: full query logging
|
bool m_colored;
|
||||||
bool m_sqlDriverQueryLogging;
|
ColorTypes m_colors[4];
|
||||||
|
|
||||||
// log levels:
|
// log levels:
|
||||||
// 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug
|
// false: errors only, true: full query logging
|
||||||
uint8 m_dbLogLevel;
|
bool m_sqlDriverQueryLogging;
|
||||||
uint8 m_logLevel;
|
|
||||||
uint8 m_logFileLevel;
|
|
||||||
bool m_dbChar;
|
|
||||||
bool m_dbRA;
|
|
||||||
bool m_dbGM;
|
|
||||||
bool m_dbChat;
|
|
||||||
bool m_charLog_Dump;
|
|
||||||
bool m_charLog_Dump_Separate;
|
|
||||||
std::string m_dumpsDir;
|
|
||||||
|
|
||||||
DebugLogFilters m_DebugLogMask;
|
// log levels:
|
||||||
|
// 0 minimum/string, 1 basic/error, 2 detail, 3 full/debug
|
||||||
|
uint8 m_dbLogLevel;
|
||||||
|
uint8 m_logLevel;
|
||||||
|
uint8 m_logFileLevel;
|
||||||
|
bool m_dbChar;
|
||||||
|
bool m_dbRA;
|
||||||
|
bool m_dbGM;
|
||||||
|
bool m_dbChat;
|
||||||
|
bool m_charLog_Dump;
|
||||||
|
bool m_charLog_Dump_Separate;
|
||||||
|
std::string m_dumpsDir;
|
||||||
|
|
||||||
|
DebugLogFilters m_DebugLogMask;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define sLog Log::instance()
|
#define sLog Log::instance()
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
|
ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
|
||||||
size_t size, size_t valueSize)
|
size_t size, size_t valueSize)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ ByteBufferPositionException::ByteBufferPositionException(bool add, size_t pos,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size,
|
ByteBufferSourceException::ByteBufferSourceException(size_t pos, size_t size,
|
||||||
size_t valueSize)
|
size_t valueSize)
|
||||||
{
|
{
|
||||||
std::ostringstream ss;
|
std::ostringstream ss;
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public:
|
|||||||
char const* what() const throw() { return msg_.c_str(); }
|
char const* what() const throw() { return msg_.c_str(); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::string & message() throw() { return msg_; }
|
std::string& message() throw() { return msg_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string msg_;
|
std::string msg_;
|
||||||
@@ -51,466 +51,466 @@ public:
|
|||||||
|
|
||||||
class ByteBuffer
|
class ByteBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
const static size_t DEFAULT_SIZE = 0x1000;
|
const static size_t DEFAULT_SIZE = 0x1000;
|
||||||
|
|
||||||
// constructor
|
// constructor
|
||||||
ByteBuffer() : _rpos(0), _wpos(0)
|
ByteBuffer() : _rpos(0), _wpos(0)
|
||||||
|
{
|
||||||
|
_storage.reserve(DEFAULT_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
|
||||||
|
{
|
||||||
|
_storage.reserve(reserve);
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy constructor
|
||||||
|
ByteBuffer(const ByteBuffer& buf) : _rpos(buf._rpos), _wpos(buf._wpos),
|
||||||
|
_storage(buf._storage)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
/* requried as of C++ 11 */
|
||||||
|
#if __cplusplus >= 201103L
|
||||||
|
ByteBuffer(ByteBuffer&&) = default;
|
||||||
|
ByteBuffer& operator=(const ByteBuffer&) = default;
|
||||||
|
ByteBuffer& operator=(ByteBuffer&&) = default;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
_storage.clear();
|
||||||
|
_rpos = _wpos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void append(T value)
|
||||||
|
{
|
||||||
|
EndianConvert(value);
|
||||||
|
append((uint8*)&value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T> void put(size_t pos, T value)
|
||||||
|
{
|
||||||
|
EndianConvert(value);
|
||||||
|
put(pos, (uint8*)&value, sizeof(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(uint8 value)
|
||||||
|
{
|
||||||
|
append<uint8>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(uint16 value)
|
||||||
|
{
|
||||||
|
append<uint16>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(uint32 value)
|
||||||
|
{
|
||||||
|
append<uint32>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(uint64 value)
|
||||||
|
{
|
||||||
|
append<uint64>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// signed as in 2e complement
|
||||||
|
ByteBuffer& operator<<(int8 value)
|
||||||
|
{
|
||||||
|
append<int8>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(int16 value)
|
||||||
|
{
|
||||||
|
append<int16>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(int32 value)
|
||||||
|
{
|
||||||
|
append<int32>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(int64 value)
|
||||||
|
{
|
||||||
|
append<int64>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// floating points
|
||||||
|
ByteBuffer& operator<<(float value)
|
||||||
|
{
|
||||||
|
append<float>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(double value)
|
||||||
|
{
|
||||||
|
append<double>(value);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(const std::string& value)
|
||||||
|
{
|
||||||
|
if (size_t len = value.length())
|
||||||
|
append((uint8 const*)value.c_str(), len);
|
||||||
|
append((uint8)0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator<<(const char* str)
|
||||||
|
{
|
||||||
|
if (size_t len = (str ? strlen(str) : 0))
|
||||||
|
append((uint8 const*)str, len);
|
||||||
|
append((uint8)0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(bool& value)
|
||||||
|
{
|
||||||
|
value = (read<char>() > 0);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(uint8& value)
|
||||||
|
{
|
||||||
|
value = read<uint8>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(uint16& value)
|
||||||
|
{
|
||||||
|
value = read<uint16>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(uint32& value)
|
||||||
|
{
|
||||||
|
value = read<uint32>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(uint64& value)
|
||||||
|
{
|
||||||
|
value = read<uint64>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
//signed as in 2e complement
|
||||||
|
ByteBuffer& operator>>(int8& value)
|
||||||
|
{
|
||||||
|
value = read<int8>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(int16& value)
|
||||||
|
{
|
||||||
|
value = read<int16>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(int32& value)
|
||||||
|
{
|
||||||
|
value = read<int32>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(int64& value)
|
||||||
|
{
|
||||||
|
value = read<int64>();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& operator>>(float& value)
|
||||||
|
{
|
||||||
|
value = read<float>();
|
||||||
|
if (!myisfinite(value))
|
||||||
{
|
{
|
||||||
_storage.reserve(DEFAULT_SIZE);
|
value = 0.0f;
|
||||||
|
//throw ByteBufferException();
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer(size_t reserve) : _rpos(0), _wpos(0)
|
ByteBuffer& operator>>(double& value)
|
||||||
|
{
|
||||||
|
value = read<double>();
|
||||||
|
if (!myisfinite(value))
|
||||||
{
|
{
|
||||||
_storage.reserve(reserve);
|
value = 0.0f;
|
||||||
|
//throw ByteBufferException();
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
// copy constructor
|
ByteBuffer& operator>>(std::string& value)
|
||||||
ByteBuffer(const ByteBuffer &buf) : _rpos(buf._rpos), _wpos(buf._wpos),
|
{
|
||||||
_storage(buf._storage)
|
value.clear();
|
||||||
|
while (rpos() < size()) // prevent crash at wrong string format in packet
|
||||||
{
|
{
|
||||||
|
char c = read<char>();
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
value += c;
|
||||||
}
|
}
|
||||||
/* requried as of C++ 11 */
|
return *this;
|
||||||
#if __cplusplus >= 201103L
|
}
|
||||||
ByteBuffer(ByteBuffer&&) = default;
|
|
||||||
ByteBuffer& operator=(const ByteBuffer&) = default;
|
|
||||||
ByteBuffer& operator=(ByteBuffer&&) = default;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void clear()
|
uint8& operator[](size_t const pos)
|
||||||
{
|
{
|
||||||
_storage.clear();
|
if (pos >= size())
|
||||||
_rpos = _wpos = 0;
|
throw ByteBufferPositionException(false, pos, 1, size());
|
||||||
}
|
return _storage[pos];
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> void append(T value)
|
uint8 const& operator[](size_t const pos) const
|
||||||
{
|
{
|
||||||
EndianConvert(value);
|
if (pos >= size())
|
||||||
append((uint8 *)&value, sizeof(value));
|
throw ByteBufferPositionException(false, pos, 1, size());
|
||||||
}
|
return _storage[pos];
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> void put(size_t pos, T value)
|
size_t rpos() const { return _rpos; }
|
||||||
{
|
|
||||||
EndianConvert(value);
|
|
||||||
put(pos, (uint8 *)&value, sizeof(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator<<(uint8 value)
|
size_t rpos(size_t rpos_)
|
||||||
{
|
{
|
||||||
append<uint8>(value);
|
_rpos = rpos_;
|
||||||
return *this;
|
return _rpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer &operator<<(uint16 value)
|
void rfinish()
|
||||||
{
|
{
|
||||||
append<uint16>(value);
|
_rpos = wpos();
|
||||||
return *this;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator<<(uint32 value)
|
size_t wpos() const { return _wpos; }
|
||||||
{
|
|
||||||
append<uint32>(value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator<<(uint64 value)
|
size_t wpos(size_t wpos_)
|
||||||
{
|
{
|
||||||
append<uint64>(value);
|
_wpos = wpos_;
|
||||||
return *this;
|
return _wpos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// signed as in 2e complement
|
template<typename T>
|
||||||
ByteBuffer &operator<<(int8 value)
|
void read_skip() { read_skip(sizeof(T)); }
|
||||||
{
|
|
||||||
append<int8>(value);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator<<(int16 value)
|
void read_skip(size_t skip)
|
||||||
{
|
{
|
||||||
append<int16>(value);
|
if (_rpos + skip > size())
|
||||||
return *this;
|
throw ByteBufferPositionException(false, _rpos, skip, size());
|
||||||
}
|
_rpos += skip;
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer &operator<<(int32 value)
|
template <typename T> T read()
|
||||||
{
|
{
|
||||||
append<int32>(value);
|
T r = read<T>(_rpos);
|
||||||
return *this;
|
_rpos += sizeof(T);
|
||||||
}
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer &operator<<(int64 value)
|
template <typename T> T read(size_t pos) const
|
||||||
{
|
{
|
||||||
append<int64>(value);
|
if (pos + sizeof(T) > size())
|
||||||
return *this;
|
throw ByteBufferPositionException(false, pos, sizeof(T), size());
|
||||||
}
|
T val = *((T const*)&_storage[pos]);
|
||||||
|
EndianConvert(val);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
// floating points
|
void read(uint8* dest, size_t len)
|
||||||
ByteBuffer &operator<<(float value)
|
{
|
||||||
{
|
if (_rpos + len > size())
|
||||||
append<float>(value);
|
throw ByteBufferPositionException(false, _rpos, len, size());
|
||||||
return *this;
|
std::memcpy(dest, &_storage[_rpos], len);
|
||||||
}
|
_rpos += len;
|
||||||
|
}
|
||||||
|
|
||||||
ByteBuffer &operator<<(double value)
|
void readPackGUID(uint64& guid)
|
||||||
{
|
{
|
||||||
append<double>(value);
|
if (rpos() + 1 > size())
|
||||||
return *this;
|
throw ByteBufferPositionException(false, _rpos, 1, size());
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator<<(const std::string &value)
|
guid = 0;
|
||||||
{
|
|
||||||
if (size_t len = value.length())
|
|
||||||
append((uint8 const*)value.c_str(), len);
|
|
||||||
append((uint8)0);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator<<(const char *str)
|
uint8 guidmark = 0;
|
||||||
{
|
(*this) >> guidmark;
|
||||||
if (size_t len = (str ? strlen(str) : 0))
|
|
||||||
append((uint8 const*)str, len);
|
|
||||||
append((uint8)0);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(bool &value)
|
for (int i = 0; i < 8; ++i)
|
||||||
{
|
{
|
||||||
value = (read<char>() > 0);
|
if (guidmark & (uint8(1) << i))
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(uint8 &value)
|
|
||||||
{
|
|
||||||
value = read<uint8>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(uint16 &value)
|
|
||||||
{
|
|
||||||
value = read<uint16>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(uint32 &value)
|
|
||||||
{
|
|
||||||
value = read<uint32>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(uint64 &value)
|
|
||||||
{
|
|
||||||
value = read<uint64>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
//signed as in 2e complement
|
|
||||||
ByteBuffer &operator>>(int8 &value)
|
|
||||||
{
|
|
||||||
value = read<int8>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(int16 &value)
|
|
||||||
{
|
|
||||||
value = read<int16>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(int32 &value)
|
|
||||||
{
|
|
||||||
value = read<int32>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(int64 &value)
|
|
||||||
{
|
|
||||||
value = read<int64>();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(float &value)
|
|
||||||
{
|
|
||||||
value = read<float>();
|
|
||||||
if (!myisfinite(value))
|
|
||||||
{
|
{
|
||||||
value = 0.0f;
|
if (rpos() + 1 > size())
|
||||||
//throw ByteBufferException();
|
throw ByteBufferPositionException(false, _rpos, 1, size());
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(double &value)
|
uint8 bit;
|
||||||
{
|
(*this) >> bit;
|
||||||
value = read<double>();
|
guid |= (uint64(bit) << (i * 8));
|
||||||
if (!myisfinite(value))
|
|
||||||
{
|
|
||||||
value = 0.0f;
|
|
||||||
//throw ByteBufferException();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteBuffer &operator>>(std::string& value)
|
|
||||||
{
|
|
||||||
value.clear();
|
|
||||||
while (rpos() < size()) // prevent crash at wrong string format in packet
|
|
||||||
{
|
|
||||||
char c = read<char>();
|
|
||||||
if (c == 0)
|
|
||||||
break;
|
|
||||||
value += c;
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8& operator[](size_t const pos)
|
|
||||||
{
|
|
||||||
if (pos >= size())
|
|
||||||
throw ByteBufferPositionException(false, pos, 1, size());
|
|
||||||
return _storage[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 const& operator[](size_t const pos) const
|
|
||||||
{
|
|
||||||
if (pos >= size())
|
|
||||||
throw ByteBufferPositionException(false, pos, 1, size());
|
|
||||||
return _storage[pos];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t rpos() const { return _rpos; }
|
|
||||||
|
|
||||||
size_t rpos(size_t rpos_)
|
|
||||||
{
|
|
||||||
_rpos = rpos_;
|
|
||||||
return _rpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void rfinish()
|
|
||||||
{
|
|
||||||
_rpos = wpos();
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t wpos() const { return _wpos; }
|
|
||||||
|
|
||||||
size_t wpos(size_t wpos_)
|
|
||||||
{
|
|
||||||
_wpos = wpos_;
|
|
||||||
return _wpos;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void read_skip() { read_skip(sizeof(T)); }
|
|
||||||
|
|
||||||
void read_skip(size_t skip)
|
|
||||||
{
|
|
||||||
if (_rpos + skip > size())
|
|
||||||
throw ByteBufferPositionException(false, _rpos, skip, size());
|
|
||||||
_rpos += skip;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> T read()
|
|
||||||
{
|
|
||||||
T r = read<T>(_rpos);
|
|
||||||
_rpos += sizeof(T);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> T read(size_t pos) const
|
|
||||||
{
|
|
||||||
if (pos + sizeof(T) > size())
|
|
||||||
throw ByteBufferPositionException(false, pos, sizeof(T), size());
|
|
||||||
T val = *((T const*)&_storage[pos]);
|
|
||||||
EndianConvert(val);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint8 *dest, size_t len)
|
|
||||||
{
|
|
||||||
if (_rpos + len > size())
|
|
||||||
throw ByteBufferPositionException(false, _rpos, len, size());
|
|
||||||
std::memcpy(dest, &_storage[_rpos], len);
|
|
||||||
_rpos += len;
|
|
||||||
}
|
|
||||||
|
|
||||||
void readPackGUID(uint64& guid)
|
|
||||||
{
|
|
||||||
if (rpos() + 1 > size())
|
|
||||||
throw ByteBufferPositionException(false, _rpos, 1, size());
|
|
||||||
|
|
||||||
guid = 0;
|
|
||||||
|
|
||||||
uint8 guidmark = 0;
|
|
||||||
(*this) >> guidmark;
|
|
||||||
|
|
||||||
for (int i = 0; i < 8; ++i)
|
|
||||||
{
|
|
||||||
if (guidmark & (uint8(1) << i))
|
|
||||||
{
|
|
||||||
if (rpos() + 1 > size())
|
|
||||||
throw ByteBufferPositionException(false, _rpos, 1, size());
|
|
||||||
|
|
||||||
uint8 bit;
|
|
||||||
(*this) >> bit;
|
|
||||||
guid |= (uint64(bit) << (i * 8));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uint32 ReadPackedTime()
|
uint32 ReadPackedTime()
|
||||||
|
{
|
||||||
|
uint32 packedDate = read<uint32>();
|
||||||
|
tm lt = tm();
|
||||||
|
|
||||||
|
lt.tm_min = packedDate & 0x3F;
|
||||||
|
lt.tm_hour = (packedDate >> 6) & 0x1F;
|
||||||
|
//lt.tm_wday = (packedDate >> 11) & 7;
|
||||||
|
lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1;
|
||||||
|
lt.tm_mon = (packedDate >> 20) & 0xF;
|
||||||
|
lt.tm_year = ((packedDate >> 24) & 0x1F) + 100;
|
||||||
|
|
||||||
|
return uint32(mktime(<));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ByteBuffer& ReadPackedTime(uint32& time)
|
||||||
|
{
|
||||||
|
time = ReadPackedTime();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8* contents()
|
||||||
|
{
|
||||||
|
if (_storage.empty())
|
||||||
|
throw ByteBufferException();
|
||||||
|
return &_storage[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8* contents() const
|
||||||
|
{
|
||||||
|
if (_storage.empty())
|
||||||
|
throw ByteBufferException();
|
||||||
|
return &_storage[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t size() const { return _storage.size(); }
|
||||||
|
bool empty() const { return _storage.empty(); }
|
||||||
|
|
||||||
|
void resize(size_t newsize)
|
||||||
|
{
|
||||||
|
_storage.resize(newsize, 0);
|
||||||
|
_rpos = 0;
|
||||||
|
_wpos = size();
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t ressize)
|
||||||
|
{
|
||||||
|
if (ressize > size())
|
||||||
|
_storage.reserve(ressize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const char* src, size_t cnt)
|
||||||
|
{
|
||||||
|
return append((const uint8*)src, cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T> void append(const T* src, size_t cnt)
|
||||||
|
{
|
||||||
|
return append((const uint8*)src, cnt * sizeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const uint8* src, size_t cnt)
|
||||||
|
{
|
||||||
|
if (!cnt)
|
||||||
|
throw ByteBufferSourceException(_wpos, size(), cnt);
|
||||||
|
|
||||||
|
if (!src)
|
||||||
|
throw ByteBufferSourceException(_wpos, size(), cnt);
|
||||||
|
|
||||||
|
ASSERT(size() < 10000000);
|
||||||
|
|
||||||
|
size_t newsize = _wpos + cnt;
|
||||||
|
|
||||||
|
if (_storage.capacity() < newsize) // pussywizard
|
||||||
{
|
{
|
||||||
uint32 packedDate = read<uint32>();
|
if (newsize < 100)
|
||||||
tm lt = tm();
|
_storage.reserve(300);
|
||||||
|
else if (newsize < 750)
|
||||||
lt.tm_min = packedDate & 0x3F;
|
_storage.reserve(2500);
|
||||||
lt.tm_hour = (packedDate >> 6) & 0x1F;
|
else if (newsize < 6000)
|
||||||
//lt.tm_wday = (packedDate >> 11) & 7;
|
_storage.reserve(10000);
|
||||||
lt.tm_mday = ((packedDate >> 14) & 0x3F) + 1;
|
else
|
||||||
lt.tm_mon = (packedDate >> 20) & 0xF;
|
_storage.reserve(400000);
|
||||||
lt.tm_year = ((packedDate >> 24) & 0x1F) + 100;
|
|
||||||
|
|
||||||
return uint32(mktime(<));
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteBuffer& ReadPackedTime(uint32& time)
|
if (_storage.size() < newsize)
|
||||||
|
_storage.resize(newsize);
|
||||||
|
|
||||||
|
memcpy(&_storage[_wpos], src, cnt);
|
||||||
|
_wpos = newsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void append(const ByteBuffer& buffer)
|
||||||
|
{
|
||||||
|
if (buffer.wpos())
|
||||||
|
append(buffer.contents(), buffer.wpos());
|
||||||
|
}
|
||||||
|
|
||||||
|
// can be used in SMSG_MONSTER_MOVE opcode
|
||||||
|
void appendPackXYZ(float x, float y, float z)
|
||||||
|
{
|
||||||
|
uint32 packed = 0;
|
||||||
|
packed |= ((int)(x / 0.25f) & 0x7FF);
|
||||||
|
packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
|
||||||
|
packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
|
||||||
|
*this << packed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void appendPackGUID(uint64 guid)
|
||||||
|
{
|
||||||
|
uint8 packGUID[8 + 1];
|
||||||
|
packGUID[0] = 0;
|
||||||
|
size_t size = 1;
|
||||||
|
for (uint8 i = 0; guid != 0; ++i)
|
||||||
{
|
{
|
||||||
time = ReadPackedTime();
|
if (guid & 0xFF)
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8 * contents()
|
|
||||||
{
|
|
||||||
if (_storage.empty())
|
|
||||||
throw ByteBufferException();
|
|
||||||
return &_storage[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint8 *contents() const
|
|
||||||
{
|
|
||||||
if (_storage.empty())
|
|
||||||
throw ByteBufferException();
|
|
||||||
return &_storage[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t size() const { return _storage.size(); }
|
|
||||||
bool empty() const { return _storage.empty(); }
|
|
||||||
|
|
||||||
void resize(size_t newsize)
|
|
||||||
{
|
|
||||||
_storage.resize(newsize, 0);
|
|
||||||
_rpos = 0;
|
|
||||||
_wpos = size();
|
|
||||||
}
|
|
||||||
|
|
||||||
void reserve(size_t ressize)
|
|
||||||
{
|
|
||||||
if (ressize > size())
|
|
||||||
_storage.reserve(ressize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const char *src, size_t cnt)
|
|
||||||
{
|
|
||||||
return append((const uint8 *)src, cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class T> void append(const T *src, size_t cnt)
|
|
||||||
{
|
|
||||||
return append((const uint8 *)src, cnt * sizeof(T));
|
|
||||||
}
|
|
||||||
|
|
||||||
void append(const uint8 *src, size_t cnt)
|
|
||||||
{
|
|
||||||
if (!cnt)
|
|
||||||
throw ByteBufferSourceException(_wpos, size(), cnt);
|
|
||||||
|
|
||||||
if (!src)
|
|
||||||
throw ByteBufferSourceException(_wpos, size(), cnt);
|
|
||||||
|
|
||||||
ASSERT(size() < 10000000);
|
|
||||||
|
|
||||||
size_t newsize = _wpos + cnt;
|
|
||||||
|
|
||||||
if (_storage.capacity() < newsize) // pussywizard
|
|
||||||
{
|
{
|
||||||
if (newsize < 100)
|
packGUID[0] |= uint8(1 << i);
|
||||||
_storage.reserve(300);
|
packGUID[size] = uint8(guid & 0xFF);
|
||||||
else if (newsize < 750)
|
++size;
|
||||||
_storage.reserve(2500);
|
|
||||||
else if (newsize < 6000)
|
|
||||||
_storage.reserve(10000);
|
|
||||||
else
|
|
||||||
_storage.reserve(400000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_storage.size() < newsize)
|
guid >>= 8;
|
||||||
_storage.resize(newsize);
|
|
||||||
|
|
||||||
memcpy(&_storage[_wpos], src, cnt);
|
|
||||||
_wpos = newsize;
|
|
||||||
}
|
}
|
||||||
|
append(packGUID, size);
|
||||||
|
}
|
||||||
|
|
||||||
void append(const ByteBuffer& buffer)
|
void AppendPackedTime(time_t time)
|
||||||
{
|
{
|
||||||
if (buffer.wpos())
|
tm lt;
|
||||||
append(buffer.contents(), buffer.wpos());
|
localtime_r(&time, <);
|
||||||
}
|
append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);
|
||||||
|
}
|
||||||
|
|
||||||
// can be used in SMSG_MONSTER_MOVE opcode
|
void put(size_t pos, const uint8* src, size_t cnt)
|
||||||
void appendPackXYZ(float x, float y, float z)
|
{
|
||||||
{
|
if (pos + cnt > size())
|
||||||
uint32 packed = 0;
|
throw ByteBufferPositionException(true, pos, cnt, size());
|
||||||
packed |= ((int)(x / 0.25f) & 0x7FF);
|
|
||||||
packed |= ((int)(y / 0.25f) & 0x7FF) << 11;
|
|
||||||
packed |= ((int)(z / 0.25f) & 0x3FF) << 22;
|
|
||||||
*this << packed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void appendPackGUID(uint64 guid)
|
if (!src)
|
||||||
{
|
throw ByteBufferSourceException(_wpos, size(), cnt);
|
||||||
uint8 packGUID[8+1];
|
|
||||||
packGUID[0] = 0;
|
|
||||||
size_t size = 1;
|
|
||||||
for (uint8 i = 0;guid != 0;++i)
|
|
||||||
{
|
|
||||||
if (guid & 0xFF)
|
|
||||||
{
|
|
||||||
packGUID[0] |= uint8(1 << i);
|
|
||||||
packGUID[size] = uint8(guid & 0xFF);
|
|
||||||
++size;
|
|
||||||
}
|
|
||||||
|
|
||||||
guid >>= 8;
|
std::memcpy(&_storage[pos], src, cnt);
|
||||||
}
|
}
|
||||||
append(packGUID, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AppendPackedTime(time_t time)
|
void hexlike(bool outString = false) const;
|
||||||
{
|
|
||||||
tm lt;
|
|
||||||
localtime_r(&time, <);
|
|
||||||
append<uint32>((lt.tm_year - 100) << 24 | lt.tm_mon << 20 | (lt.tm_mday - 1) << 14 | lt.tm_wday << 11 | lt.tm_hour << 6 | lt.tm_min);
|
|
||||||
}
|
|
||||||
|
|
||||||
void put(size_t pos, const uint8 *src, size_t cnt)
|
protected:
|
||||||
{
|
size_t _rpos, _wpos;
|
||||||
if (pos + cnt > size())
|
std::vector<uint8> _storage;
|
||||||
throw ByteBufferPositionException(true, pos, cnt, size());
|
|
||||||
|
|
||||||
if (!src)
|
|
||||||
throw ByteBufferSourceException(_wpos, size(), cnt);
|
|
||||||
|
|
||||||
std::memcpy(&_storage[pos], src, cnt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hexlike(bool outString = false) const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
size_t _rpos, _wpos;
|
|
||||||
std::vector<uint8> _storage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
|
inline ByteBuffer& operator<<(ByteBuffer& b, std::vector<T> v)
|
||||||
{
|
{
|
||||||
b << (uint32)v.size();
|
b << (uint32)v.size();
|
||||||
for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
|
for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); ++i)
|
||||||
@@ -521,7 +521,7 @@ inline ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
|
inline ByteBuffer& operator>>(ByteBuffer& b, std::vector<T>& v)
|
||||||
{
|
{
|
||||||
uint32 vsize;
|
uint32 vsize;
|
||||||
b >> vsize;
|
b >> vsize;
|
||||||
@@ -536,7 +536,7 @@ inline ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
|
inline ByteBuffer& operator<<(ByteBuffer& b, std::list<T> v)
|
||||||
{
|
{
|
||||||
b << (uint32)v.size();
|
b << (uint32)v.size();
|
||||||
for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
|
for (typename std::list<T>::iterator i = v.begin(); i != v.end(); ++i)
|
||||||
@@ -547,7 +547,7 @@ inline ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
|
inline ByteBuffer& operator>>(ByteBuffer& b, std::list<T>& v)
|
||||||
{
|
{
|
||||||
uint32 vsize;
|
uint32 vsize;
|
||||||
b >> vsize;
|
b >> vsize;
|
||||||
@@ -562,7 +562,7 @@ inline ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename V>
|
template <typename K, typename V>
|
||||||
inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
|
inline ByteBuffer& operator<<(ByteBuffer& b, std::map<K, V>& m)
|
||||||
{
|
{
|
||||||
b << (uint32)m.size();
|
b << (uint32)m.size();
|
||||||
for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
|
for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); ++i)
|
||||||
@@ -573,7 +573,7 @@ inline ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename K, typename V>
|
template <typename K, typename V>
|
||||||
inline ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
|
inline ByteBuffer& operator>>(ByteBuffer& b, std::map<K, V>& m)
|
||||||
{
|
{
|
||||||
uint32 msize;
|
uint32 msize;
|
||||||
b >> msize;
|
b >> msize;
|
||||||
|
|||||||
@@ -12,34 +12,34 @@
|
|||||||
|
|
||||||
class WorldPacket : public ByteBuffer
|
class WorldPacket : public ByteBuffer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// just container for later use
|
// just container for later use
|
||||||
WorldPacket() : ByteBuffer(0), m_opcode(0)
|
WorldPacket() : ByteBuffer(0), m_opcode(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { }
|
explicit WorldPacket(uint16 opcode, size_t res = 200) : ByteBuffer(res), m_opcode(opcode) { }
|
||||||
// copy constructor
|
// copy constructor
|
||||||
WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
|
WorldPacket(const WorldPacket& packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
/* requried as of C++ 11 */
|
/* requried as of C++ 11 */
|
||||||
#if __cplusplus >= 201103L
|
#if __cplusplus >= 201103L
|
||||||
WorldPacket(WorldPacket&&) = default;
|
WorldPacket(WorldPacket&&) = default;
|
||||||
WorldPacket& operator=(const WorldPacket&) = default;
|
WorldPacket& operator=(const WorldPacket&) = default;
|
||||||
WorldPacket& operator=(WorldPacket&&) = default;
|
WorldPacket& operator=(WorldPacket&&) = default;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void Initialize(uint16 opcode, size_t newres=200)
|
void Initialize(uint16 opcode, size_t newres = 200)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
_storage.reserve(newres);
|
_storage.reserve(newres);
|
||||||
m_opcode = opcode;
|
m_opcode = opcode;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16 GetOpcode() const { return m_opcode; }
|
uint16 GetOpcode() const { return m_opcode; }
|
||||||
void SetOpcode(uint16 opcode) { m_opcode = opcode; }
|
void SetOpcode(uint16 opcode) { m_opcode = opcode; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint16 m_opcode;
|
uint16 m_opcode;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,277 +23,277 @@ typedef ACE_Future<PreparedQueryResult> PreparedQueryResultFuture;
|
|||||||
template <typename Result, typename ParamType, bool chain = false>
|
template <typename Result, typename ParamType, bool chain = false>
|
||||||
class QueryCallback
|
class QueryCallback
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
|
QueryCallback() : _param(), _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
|
||||||
|
|
||||||
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
|
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
|
||||||
void SetFutureResult(ACE_Future<Result> value)
|
void SetFutureResult(ACE_Future<Result> value)
|
||||||
{
|
{
|
||||||
_result = value;
|
_result = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACE_Future<Result> GetFutureResult()
|
ACE_Future<Result> GetFutureResult()
|
||||||
{
|
{
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsReady()
|
int IsReady()
|
||||||
{
|
{
|
||||||
return _result.ready();
|
return _result.ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetResult(Result& res)
|
void GetResult(Result& res)
|
||||||
{
|
{
|
||||||
_result.get(res);
|
_result.get(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeResult()
|
void FreeResult()
|
||||||
{
|
{
|
||||||
_result.cancel();
|
_result.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetParam(ParamType value)
|
void SetParam(ParamType value)
|
||||||
{
|
{
|
||||||
_param = value;
|
_param = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamType GetParam()
|
ParamType GetParam()
|
||||||
{
|
{
|
||||||
return _param;
|
return _param;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets the stage of the callback chain
|
//! Resets the stage of the callback chain
|
||||||
void ResetStage()
|
void ResetStage()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_stage = 0;
|
_stage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
|
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
|
||||||
void NextStage()
|
void NextStage()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++_stage;
|
++_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
|
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
|
||||||
uint8 GetStage()
|
uint8 GetStage()
|
||||||
{
|
{
|
||||||
return _stage;
|
return _stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets all underlying variables (param, result and stage)
|
//! Resets all underlying variables (param, result and stage)
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
SetParam(NULL);
|
SetParam(NULL);
|
||||||
FreeResult();
|
FreeResult();
|
||||||
ResetStage();
|
ResetStage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACE_Future<Result> _result;
|
ACE_Future<Result> _result;
|
||||||
ParamType _param;
|
ParamType _param;
|
||||||
uint8 _stage;
|
uint8 _stage;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
|
template <typename Result, typename ParamType1, typename ParamType2, bool chain = false>
|
||||||
class QueryCallback_2
|
class QueryCallback_2
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
|
QueryCallback_2() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
|
||||||
|
|
||||||
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
|
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
|
||||||
void SetFutureResult(ACE_Future<Result> value)
|
void SetFutureResult(ACE_Future<Result> value)
|
||||||
{
|
{
|
||||||
_result = value;
|
_result = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACE_Future<Result> GetFutureResult()
|
ACE_Future<Result> GetFutureResult()
|
||||||
{
|
{
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsReady()
|
int IsReady()
|
||||||
{
|
{
|
||||||
return _result.ready();
|
return _result.ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetResult(Result& res)
|
void GetResult(Result& res)
|
||||||
{
|
{
|
||||||
_result.get(res);
|
_result.get(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeResult()
|
void FreeResult()
|
||||||
{
|
{
|
||||||
_result.cancel();
|
_result.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstParam(ParamType1 value)
|
void SetFirstParam(ParamType1 value)
|
||||||
{
|
{
|
||||||
_param_1 = value;
|
_param_1 = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSecondParam(ParamType2 value)
|
void SetSecondParam(ParamType2 value)
|
||||||
{
|
{
|
||||||
_param_2 = value;
|
_param_2 = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamType1 GetFirstParam()
|
ParamType1 GetFirstParam()
|
||||||
{
|
{
|
||||||
return _param_1;
|
return _param_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamType2 GetSecondParam()
|
ParamType2 GetSecondParam()
|
||||||
{
|
{
|
||||||
return _param_2;
|
return _param_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets the stage of the callback chain
|
//! Resets the stage of the callback chain
|
||||||
void ResetStage()
|
void ResetStage()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_stage = 0;
|
_stage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
|
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
|
||||||
void NextStage()
|
void NextStage()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++_stage;
|
++_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
|
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
|
||||||
uint8 GetStage()
|
uint8 GetStage()
|
||||||
{
|
{
|
||||||
return _stage;
|
return _stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets all underlying variables (param, result and stage)
|
//! Resets all underlying variables (param, result and stage)
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
SetFirstParam(0);
|
SetFirstParam(0);
|
||||||
SetSecondParam(NULL);
|
SetSecondParam(NULL);
|
||||||
FreeResult();
|
FreeResult();
|
||||||
ResetStage();
|
ResetStage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACE_Future<Result> _result;
|
ACE_Future<Result> _result;
|
||||||
ParamType1 _param_1;
|
ParamType1 _param_1;
|
||||||
ParamType2 _param_2;
|
ParamType2 _param_2;
|
||||||
uint8 _stage;
|
uint8 _stage;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Result, typename ParamType1, typename ParamType2, typename ParamType3, bool chain = false>
|
template <typename Result, typename ParamType1, typename ParamType2, typename ParamType3, bool chain = false>
|
||||||
class QueryCallback_3
|
class QueryCallback_3
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QueryCallback_3() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
|
QueryCallback_3() : _stage(chain ? 0 : CALLBACK_STAGE_INVALID) {}
|
||||||
|
|
||||||
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
|
//! The parameter of this function should be a resultset returned from either .AsyncQuery or .AsyncPQuery
|
||||||
void SetFutureResult(ACE_Future<Result> value)
|
void SetFutureResult(ACE_Future<Result> value)
|
||||||
{
|
{
|
||||||
_result = value;
|
_result = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ACE_Future<Result> GetFutureResult()
|
ACE_Future<Result> GetFutureResult()
|
||||||
{
|
{
|
||||||
return _result;
|
return _result;
|
||||||
}
|
}
|
||||||
|
|
||||||
int IsReady()
|
int IsReady()
|
||||||
{
|
{
|
||||||
return _result.ready();
|
return _result.ready();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetResult(Result& res)
|
void GetResult(Result& res)
|
||||||
{
|
{
|
||||||
_result.get(res);
|
_result.get(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FreeResult()
|
void FreeResult()
|
||||||
{
|
{
|
||||||
_result.cancel();
|
_result.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFirstParam(ParamType1 value)
|
void SetFirstParam(ParamType1 value)
|
||||||
{
|
{
|
||||||
_param_1 = value;
|
_param_1 = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSecondParam(ParamType2 value)
|
void SetSecondParam(ParamType2 value)
|
||||||
{
|
{
|
||||||
_param_2 = value;
|
_param_2 = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetThirdParam(ParamType3 value)
|
void SetThirdParam(ParamType3 value)
|
||||||
{
|
{
|
||||||
_param_3 = value;
|
_param_3 = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamType1 GetFirstParam()
|
ParamType1 GetFirstParam()
|
||||||
{
|
{
|
||||||
return _param_1;
|
return _param_1;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamType2 GetSecondParam()
|
ParamType2 GetSecondParam()
|
||||||
{
|
{
|
||||||
return _param_2;
|
return _param_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ParamType3 GetThirdParam()
|
ParamType3 GetThirdParam()
|
||||||
{
|
{
|
||||||
return _param_3;
|
return _param_3;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets the stage of the callback chain
|
//! Resets the stage of the callback chain
|
||||||
void ResetStage()
|
void ResetStage()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
_stage = 0;
|
_stage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
|
//! Advances the callback chain to the next stage, so upper level code can act on its results accordingly
|
||||||
void NextStage()
|
void NextStage()
|
||||||
{
|
{
|
||||||
if (!chain)
|
if (!chain)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
++_stage;
|
++_stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
|
//! Returns the callback stage (or CALLBACK_STAGE_INVALID if invalid)
|
||||||
uint8 GetStage()
|
uint8 GetStage()
|
||||||
{
|
{
|
||||||
return _stage;
|
return _stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Resets all underlying variables (param, result and stage)
|
//! Resets all underlying variables (param, result and stage)
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
SetFirstParam(NULL);
|
SetFirstParam(NULL);
|
||||||
SetSecondParam(NULL);
|
SetSecondParam(NULL);
|
||||||
SetThirdParam(NULL);
|
SetThirdParam(NULL);
|
||||||
FreeResult();
|
FreeResult();
|
||||||
ResetStage();
|
ResetStage();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ACE_Future<Result> _result;
|
ACE_Future<Result> _result;
|
||||||
ParamType1 _param_1;
|
ParamType1 _param_1;
|
||||||
ParamType2 _param_2;
|
ParamType2 _param_2;
|
||||||
ParamType3 _param_3;
|
ParamType3 _param_3;
|
||||||
uint8 _stage;
|
uint8 _stage;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -10,7 +10,7 @@ DelayExecutor* DelayExecutor::instance()
|
|||||||
}
|
}
|
||||||
|
|
||||||
DelayExecutor::DelayExecutor()
|
DelayExecutor::DelayExecutor()
|
||||||
: pre_svc_hook_(0), post_svc_hook_(0), activated_(false), mqueue_(1*1024*1024, 1*1024*1024), queue_(&mqueue_)
|
: pre_svc_hook_(0), post_svc_hook_(0), activated_(false), mqueue_(1 * 1024 * 1024, 1 * 1024 * 1024), queue_(&mqueue_)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,33 +7,33 @@
|
|||||||
|
|
||||||
class DelayExecutor : protected ACE_Task_Base
|
class DelayExecutor : protected ACE_Task_Base
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
DelayExecutor();
|
DelayExecutor();
|
||||||
virtual ~DelayExecutor();
|
virtual ~DelayExecutor();
|
||||||
|
|
||||||
static DelayExecutor* instance();
|
static DelayExecutor* instance();
|
||||||
|
|
||||||
int execute(ACE_Method_Request* new_req);
|
int execute(ACE_Method_Request* new_req);
|
||||||
|
|
||||||
int start(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL);
|
int start(int num_threads = 1, ACE_Method_Request* pre_svc_hook = NULL, ACE_Method_Request* post_svc_hook = NULL);
|
||||||
|
|
||||||
int deactivate();
|
int deactivate();
|
||||||
|
|
||||||
bool activated();
|
bool activated();
|
||||||
|
|
||||||
virtual int svc();
|
virtual int svc();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
ACE_Method_Request* pre_svc_hook_;
|
ACE_Method_Request* pre_svc_hook_;
|
||||||
ACE_Method_Request* post_svc_hook_;
|
ACE_Method_Request* post_svc_hook_;
|
||||||
bool activated_;
|
bool activated_;
|
||||||
ACE_Message_Queue<ACE_SYNCH> mqueue_;
|
ACE_Message_Queue<ACE_SYNCH> mqueue_;
|
||||||
ACE_Activation_Queue queue_;
|
ACE_Activation_Queue queue_;
|
||||||
|
|
||||||
|
|
||||||
void activated(bool s);
|
void activated(bool s);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _M_DELAY_EXECUTOR_H
|
#endif // _M_DELAY_EXECUTOR_H
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
|
|
||||||
namespace ACE_Based
|
namespace ACE_Based
|
||||||
{
|
{
|
||||||
template <class T, class LockType, typename StorageType=std::deque<T> >
|
template <class T, class LockType, typename StorageType = std::deque<T> >
|
||||||
class LockedQueue
|
class LockedQueue
|
||||||
{
|
{
|
||||||
//! Lock access to the queue.
|
//! Lock access to the queue.
|
||||||
LockType _lock;
|
LockType _lock;
|
||||||
@@ -27,120 +27,120 @@ namespace ACE_Based
|
|||||||
//! Cancellation flag.
|
//! Cancellation flag.
|
||||||
volatile bool _canceled;
|
volatile bool _canceled;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//! Create a LockedQueue.
|
//! Create a LockedQueue.
|
||||||
LockedQueue()
|
LockedQueue()
|
||||||
: _canceled(false)
|
: _canceled(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Destroy a LockedQueue.
|
//! Destroy a LockedQueue.
|
||||||
virtual ~LockedQueue()
|
virtual ~LockedQueue()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Adds an item to the queue.
|
//! Adds an item to the queue.
|
||||||
void add(const T& item)
|
void add(const T& item)
|
||||||
{
|
{
|
||||||
lock();
|
lock();
|
||||||
|
|
||||||
//ASSERT(!this->_canceled);
|
//ASSERT(!this->_canceled);
|
||||||
// throw Cancellation_Exception();
|
// throw Cancellation_Exception();
|
||||||
|
|
||||||
_queue.push_back(item);
|
_queue.push_back(item);
|
||||||
|
|
||||||
|
unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
//! Gets the next result in the queue, if any.
|
||||||
|
bool next(T& result)
|
||||||
|
{
|
||||||
|
// ACE_Guard<LockType> g(this->_lock);
|
||||||
|
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
|
||||||
|
|
||||||
|
if (_queue.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
//ASSERT (!_queue.empty() || !this->_canceled);
|
||||||
|
// throw Cancellation_Exception();
|
||||||
|
result = _queue.front();
|
||||||
|
_queue.pop_front();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Checker>
|
||||||
|
bool next(T& result, Checker& check)
|
||||||
|
{
|
||||||
|
ACE_Guard<LockType> g(this->_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();
|
unlock();
|
||||||
}
|
|
||||||
|
|
||||||
//! Gets the next result in the queue, if any.
|
return result;
|
||||||
bool next(T& result)
|
}
|
||||||
{
|
|
||||||
// ACE_Guard<LockType> g(this->_lock);
|
|
||||||
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
|
|
||||||
|
|
||||||
if (_queue.empty())
|
//! Cancels the queue.
|
||||||
return false;
|
void cancel()
|
||||||
|
{
|
||||||
|
lock();
|
||||||
|
|
||||||
//ASSERT (!_queue.empty() || !this->_canceled);
|
_canceled = true;
|
||||||
// throw Cancellation_Exception();
|
|
||||||
result = _queue.front();
|
|
||||||
_queue.pop_front();
|
|
||||||
|
|
||||||
return true;
|
unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Checker>
|
//! Checks if the queue is cancelled.
|
||||||
bool next(T& result, Checker& check)
|
bool cancelled()
|
||||||
{
|
{
|
||||||
ACE_Guard<LockType> g(this->_lock);
|
ACE_Guard<LockType> g(this->_lock);
|
||||||
|
return _canceled;
|
||||||
|
}
|
||||||
|
|
||||||
if (_queue.empty())
|
//! Locks the queue for access.
|
||||||
return false;
|
void lock()
|
||||||
|
{
|
||||||
|
this->_lock.acquire();
|
||||||
|
}
|
||||||
|
|
||||||
result = _queue.front();
|
//! Unlocks the queue.
|
||||||
if (!check.Process(result))
|
void unlock()
|
||||||
return false;
|
{
|
||||||
|
this->_lock.release();
|
||||||
|
}
|
||||||
|
|
||||||
_queue.pop_front();
|
///! Calls pop_front of the queue
|
||||||
return true;
|
void pop_front()
|
||||||
}
|
{
|
||||||
|
ACE_GUARD (LockType, g, this->_lock);
|
||||||
|
_queue.pop_front();
|
||||||
|
}
|
||||||
|
|
||||||
//! Peeks at the top of the queue. Check if the queue is empty before calling! Remember to unlock after use if autoUnlock == false.
|
///! Checks if we're empty or not with locks held
|
||||||
T& peek(bool autoUnlock = false)
|
bool empty()
|
||||||
{
|
{
|
||||||
lock();
|
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
|
||||||
|
return _queue.empty();
|
||||||
T& result = _queue.front();
|
}
|
||||||
|
|
||||||
if (autoUnlock)
|
|
||||||
unlock();
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Cancels the queue.
|
|
||||||
void cancel()
|
|
||||||
{
|
|
||||||
lock();
|
|
||||||
|
|
||||||
_canceled = true;
|
|
||||||
|
|
||||||
unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Checks if the queue is cancelled.
|
|
||||||
bool cancelled()
|
|
||||||
{
|
|
||||||
ACE_Guard<LockType> g(this->_lock);
|
|
||||||
return _canceled;
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Locks the queue for access.
|
|
||||||
void lock()
|
|
||||||
{
|
|
||||||
this->_lock.acquire();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! Unlocks the queue.
|
|
||||||
void unlock()
|
|
||||||
{
|
|
||||||
this->_lock.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
///! Calls pop_front of the queue
|
|
||||||
void pop_front()
|
|
||||||
{
|
|
||||||
ACE_GUARD (LockType, g, this->_lock);
|
|
||||||
_queue.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
///! Checks if we're empty or not with locks held
|
|
||||||
bool empty()
|
|
||||||
{
|
|
||||||
ACE_GUARD_RETURN (LockType, g, this->_lock, false);
|
|
||||||
return _queue.empty();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ private:
|
|||||||
typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; }
|
typename std::enable_if<std::is_pointer<E>::value>::type DeleteQueuedObject(E& obj) { delete obj; }
|
||||||
|
|
||||||
template<typename E = T>
|
template<typename E = T>
|
||||||
typename std::enable_if<!std::is_pointer<E>::value>::type DeleteQueuedObject(E const& /*packet*/) { }
|
typename std::enable_if < !std::is_pointer<E>::value >::type DeleteQueuedObject(E const& /*packet*/) { }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -88,13 +88,27 @@ void Thread::setPriority(Priority priority)
|
|||||||
switch (priority)
|
switch (priority)
|
||||||
{
|
{
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
case Priority_Realtime: _ok = SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL); break;
|
case Priority_Realtime:
|
||||||
case Priority_Highest: _ok = SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST); break;
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_TIME_CRITICAL);
|
||||||
case Priority_High: _ok = SetThreadPriority(handle, THREAD_PRIORITY_ABOVE_NORMAL); break;
|
break;
|
||||||
case Priority_Normal: _ok = SetThreadPriority(handle, THREAD_PRIORITY_NORMAL); break;
|
case Priority_Highest:
|
||||||
case Priority_Low: _ok = SetThreadPriority(handle, THREAD_PRIORITY_BELOW_NORMAL); break;
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_HIGHEST);
|
||||||
case Priority_Lowest: _ok = SetThreadPriority(handle, THREAD_PRIORITY_LOWEST); break;
|
break;
|
||||||
case Priority_Idle: _ok = SetThreadPriority(handle, THREAD_PRIORITY_IDLE); break;
|
case Priority_High:
|
||||||
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_ABOVE_NORMAL);
|
||||||
|
break;
|
||||||
|
case Priority_Normal:
|
||||||
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_NORMAL);
|
||||||
|
break;
|
||||||
|
case Priority_Low:
|
||||||
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_BELOW_NORMAL);
|
||||||
|
break;
|
||||||
|
case Priority_Lowest:
|
||||||
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_LOWEST);
|
||||||
|
break;
|
||||||
|
case Priority_Idle:
|
||||||
|
_ok = SetThreadPriority(handle, THREAD_PRIORITY_IDLE);
|
||||||
|
break;
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -17,18 +17,18 @@ namespace acore
|
|||||||
{
|
{
|
||||||
class Runnable
|
class Runnable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Runnable() {}
|
virtual ~Runnable() {}
|
||||||
virtual void run() = 0;
|
virtual void run() = 0;
|
||||||
|
|
||||||
void incReference() { ++m_refs; }
|
void incReference() { ++m_refs; }
|
||||||
void decReference()
|
void decReference()
|
||||||
{
|
{
|
||||||
if (!--m_refs)
|
if (!--m_refs)
|
||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
std::atomic_long m_refs;
|
std::atomic_long m_refs;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Priority
|
enum Priority
|
||||||
@@ -44,28 +44,28 @@ namespace acore
|
|||||||
|
|
||||||
class Thread
|
class Thread
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Thread();
|
Thread();
|
||||||
explicit Thread(Runnable* instance);
|
explicit Thread(Runnable* instance);
|
||||||
~Thread();
|
~Thread();
|
||||||
|
|
||||||
bool wait();
|
bool wait();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
void setPriority(Priority type);
|
void setPriority(Priority type);
|
||||||
|
|
||||||
static void Sleep(unsigned long msecs);
|
static void Sleep(unsigned long msecs);
|
||||||
static std::thread::id currentId();
|
static std::thread::id currentId();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Thread(const Thread&);
|
Thread(const Thread&);
|
||||||
Thread& operator=(const Thread&);
|
Thread& operator=(const Thread&);
|
||||||
|
|
||||||
static void ThreadTask(void* param);
|
static void ThreadTask(void* param);
|
||||||
|
|
||||||
Runnable* const m_task;
|
Runnable* const m_task;
|
||||||
std::thread::id m_iThreadId;
|
std::thread::id m_iThreadId;
|
||||||
std::thread m_ThreadImp;
|
std::thread m_ThreadImp;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,120 +19,120 @@ namespace acore
|
|||||||
template<typename MUTEX>
|
template<typename MUTEX>
|
||||||
class GeneralLock
|
class GeneralLock
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
GeneralLock(MUTEX& m)
|
GeneralLock(MUTEX& m)
|
||||||
: i_mutex(m)
|
: i_mutex(m)
|
||||||
{
|
{
|
||||||
i_mutex.lock();
|
i_mutex.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
~GeneralLock()
|
~GeneralLock()
|
||||||
{
|
{
|
||||||
i_mutex.unlock();
|
i_mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
GeneralLock(const GeneralLock&);
|
GeneralLock(const GeneralLock&);
|
||||||
GeneralLock& operator=(const GeneralLock&);
|
GeneralLock& operator=(const GeneralLock&);
|
||||||
MUTEX& i_mutex;
|
MUTEX& i_mutex;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T>
|
template<class T>
|
||||||
class SingleThreaded
|
class SingleThreaded
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct Lock // empty object
|
struct Lock // empty object
|
||||||
|
{
|
||||||
|
Lock()
|
||||||
{
|
{
|
||||||
Lock()
|
}
|
||||||
{
|
Lock(const T&)
|
||||||
}
|
{
|
||||||
Lock(const T&)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Lock(const SingleThreaded<T>&) // for single threaded we ignore this
|
Lock(const SingleThreaded<T>&) // for single threaded we ignore this
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T, class MUTEX>
|
template<class T, class MUTEX>
|
||||||
class ObjectLevelLockable
|
class ObjectLevelLockable
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ObjectLevelLockable()
|
||||||
|
: i_mtx()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class Lock;
|
||||||
|
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ObjectLevelLockable()
|
Lock(ObjectLevelLockable<T, MUTEX>& host)
|
||||||
: i_mtx()
|
: i_lock(host.i_mtx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class Lock;
|
|
||||||
|
|
||||||
class Lock
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
Lock(ObjectLevelLockable<T, MUTEX>& host)
|
|
||||||
: i_lock(host.i_mtx)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
GeneralLock<MUTEX> i_lock;
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// prevent the compiler creating a copy construct
|
GeneralLock<MUTEX> i_lock;
|
||||||
ObjectLevelLockable(const ObjectLevelLockable<T, MUTEX>&);
|
};
|
||||||
ObjectLevelLockable<T, MUTEX>& operator=(const ObjectLevelLockable<T, MUTEX>&);
|
|
||||||
|
|
||||||
MUTEX i_mtx;
|
private:
|
||||||
|
|
||||||
|
// prevent the compiler creating a copy construct
|
||||||
|
ObjectLevelLockable(const ObjectLevelLockable<T, MUTEX>&);
|
||||||
|
ObjectLevelLockable<T, MUTEX>& operator=(const ObjectLevelLockable<T, MUTEX>&);
|
||||||
|
|
||||||
|
MUTEX i_mtx;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class T, class MUTEX>
|
template<class T, class MUTEX>
|
||||||
class ClassLevelLockable
|
class ClassLevelLockable
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
ClassLevelLockable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
friend class Lock;
|
||||||
|
|
||||||
|
class Lock
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
ClassLevelLockable()
|
Lock(const T& /*host*/)
|
||||||
{
|
{
|
||||||
|
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
friend class Lock;
|
Lock(const ClassLevelLockable<T, MUTEX>&)
|
||||||
|
|
||||||
class Lock
|
|
||||||
{
|
{
|
||||||
public:
|
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
|
||||||
|
}
|
||||||
|
|
||||||
Lock(const T& /*host*/)
|
Lock()
|
||||||
{
|
{
|
||||||
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
|
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
|
||||||
}
|
}
|
||||||
|
|
||||||
Lock(const ClassLevelLockable<T, MUTEX>&)
|
~Lock()
|
||||||
{
|
{
|
||||||
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
|
ClassLevelLockable<T, MUTEX>::si_mtx.unlock();
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
Lock()
|
private:
|
||||||
{
|
|
||||||
ClassLevelLockable<T, MUTEX>::si_mtx.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
~Lock()
|
static MUTEX si_mtx;
|
||||||
{
|
|
||||||
ClassLevelLockable<T, MUTEX>::si_mtx.unlock();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
static MUTEX si_mtx;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,18 +17,18 @@
|
|||||||
namespace ByteConverter
|
namespace ByteConverter
|
||||||
{
|
{
|
||||||
template<size_t T>
|
template<size_t T>
|
||||||
inline void convert(char *val)
|
inline void convert(char* val)
|
||||||
{
|
{
|
||||||
std::swap(*val, *(val + T - 1));
|
std::swap(*val, *(val + T - 1));
|
||||||
convert<T - 2>(val + 1);
|
convert < T - 2 > (val + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<> inline void convert<0>(char *) { }
|
template<> inline void convert<0>(char*) { }
|
||||||
template<> inline void convert<1>(char *) { } // ignore central byte
|
template<> inline void convert<1>(char*) { } // ignore central byte
|
||||||
|
|
||||||
template<typename T> inline void apply(T *val)
|
template<typename T> inline void apply(T* val)
|
||||||
{
|
{
|
||||||
convert<sizeof(T)>((char *)(val));
|
convert<sizeof(T)>((char*)(val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,8 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns a pointer to object of requested type stored with given key or nullptr
|
* Returns a pointer to object of requested type stored with given key or nullptr
|
||||||
*/
|
*/
|
||||||
template<class T> T* Get(std::string const & k) const {
|
template<class T> T* Get(std::string const& k) const
|
||||||
|
{
|
||||||
static_assert(std::is_base_of<Base, T>::value, "T must derive from Base");
|
static_assert(std::is_base_of<Base, T>::value, "T must derive from Base");
|
||||||
if (Container.empty())
|
if (Container.empty())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -36,13 +37,14 @@ public:
|
|||||||
return dynamic_cast<T*>(it->second.get());
|
return dynamic_cast<T*>(it->second.get());
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a pointer to object of requested type stored with given key
|
* Returns a pointer to object of requested type stored with given key
|
||||||
* or default constructs one and returns that one
|
* or default constructs one and returns that one
|
||||||
*/
|
*/
|
||||||
template<class T, typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0>
|
template<class T, typename std::enable_if<std::is_default_constructible<T>::value, int>::type = 0>
|
||||||
T* GetDefault(std::string const & k) {
|
T * GetDefault(std::string const& k)
|
||||||
|
{
|
||||||
static_assert(std::is_base_of<Base, T>::value, "T must derive from Base");
|
static_assert(std::is_base_of<Base, T>::value, "T must derive from Base");
|
||||||
if (T* v = Get<T>(k))
|
if (T* v = Get<T>(k))
|
||||||
return v;
|
return v;
|
||||||
@@ -50,16 +52,16 @@ public:
|
|||||||
Container.emplace(k, std::unique_ptr<T>(v));
|
Container.emplace(k, std::unique_ptr<T>(v));
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores a new object that inherits the Base class with the given key
|
* Stores a new object that inherits the Base class with the given key
|
||||||
*/
|
*/
|
||||||
void Set(std::string const & k, Base* v) { Container[k] = std::unique_ptr<Base>(v); }
|
void Set(std::string const& k, Base* v) { Container[k] = std::unique_ptr<Base>(v); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes objects with given key and returns true if one was removed, false otherwise
|
* Removes objects with given key and returns true if one was removed, false otherwise
|
||||||
*/
|
*/
|
||||||
bool Erase(std::string const & k) { return Container.erase(k) != 0; }
|
bool Erase(std::string const& k) { return Container.erase(k) != 0; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, std::unique_ptr<Base>> Container;
|
std::unordered_map<std::string, std::unique_ptr<Base>> Container;
|
||||||
|
|||||||
@@ -15,51 +15,51 @@
|
|||||||
|
|
||||||
class BasicEvent
|
class BasicEvent
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BasicEvent()
|
BasicEvent()
|
||||||
{
|
{
|
||||||
to_Abort = false;
|
to_Abort = false;
|
||||||
m_addTime = 0;
|
m_addTime = 0;
|
||||||
m_execTime = 0;
|
m_execTime = 0;
|
||||||
}
|
}
|
||||||
virtual ~BasicEvent() { } // override destructor to perform some actions on event removal
|
virtual ~BasicEvent() { } // override destructor to perform some actions on event removal
|
||||||
|
|
||||||
// this method executes when the event is triggered
|
// this method executes when the event is triggered
|
||||||
// return false if event does not want to be deleted
|
// return false if event does not want to be deleted
|
||||||
// e_time is execution time, p_time is update interval
|
// e_time is execution time, p_time is update interval
|
||||||
virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; }
|
virtual bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) { return true; }
|
||||||
|
|
||||||
virtual bool IsDeletable() const { return true; } // this event can be safely deleted
|
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
|
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
|
bool to_Abort; // set by externals when the event is aborted, aborted events don't execute
|
||||||
// and get Abort call when deleted
|
// and get Abort call when deleted
|
||||||
|
|
||||||
// these can be used for time offset control
|
// 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_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
|
uint64 m_execTime; // planned time of next execution, filled by event handler
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::multimap<uint64, BasicEvent*> EventList;
|
typedef std::multimap<uint64, BasicEvent*> EventList;
|
||||||
|
|
||||||
class EventProcessor
|
class EventProcessor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
EventProcessor();
|
EventProcessor();
|
||||||
~EventProcessor();
|
~EventProcessor();
|
||||||
|
|
||||||
void Update(uint32 p_time);
|
void Update(uint32 p_time);
|
||||||
void KillAllEvents(bool force);
|
void KillAllEvents(bool force);
|
||||||
void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true);
|
void AddEvent(BasicEvent* Event, uint64 e_time, bool set_addtime = true);
|
||||||
uint64 CalculateTime(uint64 t_offset) const;
|
uint64 CalculateTime(uint64 t_offset) const;
|
||||||
|
|
||||||
// Xinef: calculates next queue tick time
|
// Xinef: calculates next queue tick time
|
||||||
uint64 CalculateQueueTime(uint64 delay) const;
|
uint64 CalculateQueueTime(uint64 delay) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
uint64 m_time;
|
uint64 m_time;
|
||||||
EventList m_events;
|
EventList m_events;
|
||||||
bool m_aborting;
|
bool m_aborting;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int main(int argc, char ** argv);
|
extern int main(int argc, char** argv);
|
||||||
extern char serviceLongName[];
|
extern char serviceLongName[];
|
||||||
extern char serviceName[];
|
extern char serviceName[];
|
||||||
extern char serviceDescription[];
|
extern char serviceDescription[];
|
||||||
@@ -36,7 +36,7 @@ SERVICE_STATUS serviceStatus;
|
|||||||
|
|
||||||
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
|
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
|
||||||
|
|
||||||
typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
|
typedef WINADVAPI BOOL (WINAPI* CSD_T)(SC_HANDLE, DWORD, LPCVOID);
|
||||||
|
|
||||||
bool WinServiceInstall()
|
bool WinServiceInstall()
|
||||||
{
|
{
|
||||||
@@ -45,24 +45,24 @@ bool WinServiceInstall()
|
|||||||
if (serviceControlManager)
|
if (serviceControlManager)
|
||||||
{
|
{
|
||||||
char path[_MAX_PATH + 10];
|
char path[_MAX_PATH + 10];
|
||||||
if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
|
if (GetModuleFileName( 0, path, sizeof(path) / sizeof(path[0]) ) > 0)
|
||||||
{
|
{
|
||||||
SC_HANDLE service;
|
SC_HANDLE service;
|
||||||
std::strcat(path, " --service");
|
std::strcat(path, " --service");
|
||||||
service = CreateService(serviceControlManager,
|
service = CreateService(serviceControlManager,
|
||||||
serviceName, // name of service
|
serviceName, // name of service
|
||||||
serviceLongName, // service name to display
|
serviceLongName, // service name to display
|
||||||
SERVICE_ALL_ACCESS, // desired access
|
SERVICE_ALL_ACCESS, // desired access
|
||||||
// service type
|
// service type
|
||||||
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
||||||
SERVICE_AUTO_START, // start type
|
SERVICE_AUTO_START, // start type
|
||||||
SERVICE_ERROR_IGNORE, // error control type
|
SERVICE_ERROR_IGNORE, // error control type
|
||||||
path, // service's binary
|
path, // service's binary
|
||||||
0, // no load ordering group
|
0, // no load ordering group
|
||||||
0, // no tag identifier
|
0, // no tag identifier
|
||||||
0, // no dependencies
|
0, // no dependencies
|
||||||
0, // LocalSystem account
|
0, // LocalSystem account
|
||||||
0); // no password
|
0); // no password
|
||||||
if (service)
|
if (service)
|
||||||
{
|
{
|
||||||
HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL");
|
HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL");
|
||||||
@@ -95,7 +95,7 @@ bool WinServiceInstall()
|
|||||||
ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
|
ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
|
||||||
sfa.lpsaActions = _action;
|
sfa.lpsaActions = _action;
|
||||||
sfa.cActions = 1;
|
sfa.cActions = 1;
|
||||||
sfa.dwResetPeriod =INFINITE;
|
sfa.dwResetPeriod = INFINITE;
|
||||||
ChangeService_Config2(
|
ChangeService_Config2(
|
||||||
service, // handle to service
|
service, // handle to service
|
||||||
SERVICE_CONFIG_FAILURE_ACTIONS, // information level
|
SERVICE_CONFIG_FAILURE_ACTIONS, // information level
|
||||||
@@ -117,7 +117,7 @@ bool WinServiceUninstall()
|
|||||||
if (serviceControlManager)
|
if (serviceControlManager)
|
||||||
{
|
{
|
||||||
SC_HANDLE service = OpenService(serviceControlManager,
|
SC_HANDLE service = OpenService(serviceControlManager,
|
||||||
serviceName, SERVICE_QUERY_STATUS | DELETE);
|
serviceName, SERVICE_QUERY_STATUS | DELETE);
|
||||||
if (service)
|
if (service)
|
||||||
{
|
{
|
||||||
SERVICE_STATUS serviceStatus2;
|
SERVICE_STATUS serviceStatus2;
|
||||||
@@ -173,7 +173,7 @@ void WINAPI ServiceControlHandler(DWORD controlCode)
|
|||||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WINAPI ServiceMain(DWORD argc, char *argv[])
|
void WINAPI ServiceMain(DWORD argc, char* argv[])
|
||||||
{
|
{
|
||||||
// initialise service status
|
// initialise service status
|
||||||
serviceStatus.dwServiceType = SERVICE_WIN32;
|
serviceStatus.dwServiceType = SERVICE_WIN32;
|
||||||
@@ -191,7 +191,7 @@ void WINAPI ServiceMain(DWORD argc, char *argv[])
|
|||||||
char path[_MAX_PATH + 1];
|
char path[_MAX_PATH + 1];
|
||||||
unsigned int i, last_slash = 0;
|
unsigned int i, last_slash = 0;
|
||||||
|
|
||||||
GetModuleFileName(0, path, sizeof(path)/sizeof(path[0]));
|
GetModuleFileName(0, path, sizeof(path) / sizeof(path[0]));
|
||||||
|
|
||||||
for (i = 0; i < std::strlen(path); i++)
|
for (i = 0; i < std::strlen(path); i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,9 +12,9 @@
|
|||||||
namespace acore
|
namespace acore
|
||||||
{
|
{
|
||||||
|
|
||||||
/// Handle termination signals
|
/// Handle termination signals
|
||||||
class SignalHandler : public ACE_Event_Handler
|
class SignalHandler : public ACE_Event_Handler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL)
|
int handle_signal(int SigNum, siginfo_t* = NULL, ucontext_t* = NULL)
|
||||||
{
|
{
|
||||||
@@ -22,7 +22,7 @@ class SignalHandler : public ACE_Event_Handler
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual void HandleSignal(int /*SigNum*/) { };
|
virtual void HandleSignal(int /*SigNum*/) { };
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,158 +50,158 @@ inline uint32 GetMSTimeDiffToNow(uint32 oldMSTime)
|
|||||||
|
|
||||||
struct IntervalTimer
|
struct IntervalTimer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
IntervalTimer()
|
IntervalTimer()
|
||||||
: _interval(0), _current(0)
|
: _interval(0), _current(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(time_t diff)
|
void Update(time_t diff)
|
||||||
{
|
{
|
||||||
_current += diff;
|
_current += diff;
|
||||||
if (_current < 0)
|
if (_current < 0)
|
||||||
_current = 0;
|
_current = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Passed()
|
bool Passed()
|
||||||
{
|
{
|
||||||
return _current >= _interval;
|
return _current >= _interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset()
|
void Reset()
|
||||||
{
|
{
|
||||||
if (_current >= _interval)
|
if (_current >= _interval)
|
||||||
_current %= _interval;
|
_current %= _interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetCurrent(time_t current)
|
void SetCurrent(time_t current)
|
||||||
{
|
{
|
||||||
_current = current;
|
_current = current;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetInterval(time_t interval)
|
void SetInterval(time_t interval)
|
||||||
{
|
{
|
||||||
_interval = interval;
|
_interval = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t GetInterval() const
|
time_t GetInterval() const
|
||||||
{
|
{
|
||||||
return _interval;
|
return _interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t GetCurrent() const
|
time_t GetCurrent() const
|
||||||
{
|
{
|
||||||
return _current;
|
return _current;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
time_t _interval;
|
time_t _interval;
|
||||||
time_t _current;
|
time_t _current;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimeTracker
|
struct TimeTracker
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TimeTracker(time_t expiry)
|
TimeTracker(time_t expiry)
|
||||||
: i_expiryTime(expiry)
|
: i_expiryTime(expiry)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(time_t diff)
|
void Update(time_t diff)
|
||||||
{
|
{
|
||||||
i_expiryTime -= diff;
|
i_expiryTime -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Passed() const
|
bool Passed() const
|
||||||
{
|
{
|
||||||
return i_expiryTime <= 0;
|
return i_expiryTime <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset(time_t interval)
|
void Reset(time_t interval)
|
||||||
{
|
{
|
||||||
i_expiryTime = interval;
|
i_expiryTime = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t GetExpiry() const
|
time_t GetExpiry() const
|
||||||
{
|
{
|
||||||
return i_expiryTime;
|
return i_expiryTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
time_t i_expiryTime;
|
time_t i_expiryTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct TimeTrackerSmall
|
struct TimeTrackerSmall
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TimeTrackerSmall(uint32 expiry = 0)
|
TimeTrackerSmall(uint32 expiry = 0)
|
||||||
: i_expiryTime(expiry)
|
: i_expiryTime(expiry)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Update(int32 diff)
|
void Update(int32 diff)
|
||||||
{
|
{
|
||||||
i_expiryTime -= diff;
|
i_expiryTime -= diff;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Passed() const
|
bool Passed() const
|
||||||
{
|
{
|
||||||
return i_expiryTime <= 0;
|
return i_expiryTime <= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reset(uint32 interval)
|
void Reset(uint32 interval)
|
||||||
{
|
{
|
||||||
i_expiryTime = interval;
|
i_expiryTime = interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 GetExpiry() const
|
int32 GetExpiry() const
|
||||||
{
|
{
|
||||||
return i_expiryTime;
|
return i_expiryTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int32 i_expiryTime;
|
int32 i_expiryTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PeriodicTimer
|
struct PeriodicTimer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
PeriodicTimer(int32 period, int32 start_time)
|
PeriodicTimer(int32 period, int32 start_time)
|
||||||
: i_period(period), i_expireTime(start_time)
|
: i_period(period), i_expireTime(start_time)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Update(const uint32 diff)
|
bool Update(const uint32 diff)
|
||||||
{
|
{
|
||||||
if ((i_expireTime -= diff) > 0)
|
if ((i_expireTime -= diff) > 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
i_expireTime += i_period > int32(diff) ? i_period : diff;
|
i_expireTime += i_period > int32(diff) ? i_period : diff;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPeriodic(int32 period, int32 start_time)
|
void SetPeriodic(int32 period, int32 start_time)
|
||||||
{
|
{
|
||||||
i_expireTime = start_time;
|
i_expireTime = start_time;
|
||||||
i_period = period;
|
i_period = period;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tracker interface
|
// Tracker interface
|
||||||
void TUpdate(int32 diff) { i_expireTime -= diff; }
|
void TUpdate(int32 diff) { i_expireTime -= diff; }
|
||||||
bool TPassed() const { return i_expireTime <= 0; }
|
bool TPassed() const { return i_expireTime <= 0; }
|
||||||
void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; }
|
void TReset(int32 diff, int32 period) { i_expireTime += period > diff ? period : diff; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
int32 i_period;
|
int32 i_period;
|
||||||
int32 i_expireTime;
|
int32 i_expireTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ SFMTEngine& SFMTEngine::Instance()
|
|||||||
return engine;
|
return engine;
|
||||||
}
|
}
|
||||||
|
|
||||||
Tokenizer::Tokenizer(const std::string &src, const char sep, uint32 vectorReserve)
|
Tokenizer::Tokenizer(const std::string& src, const char sep, uint32 vectorReserve)
|
||||||
{
|
{
|
||||||
m_str = new char[src.length() + 1];
|
m_str = new char[src.length() + 1];
|
||||||
memcpy(m_str, src.c_str(), src.length() + 1);
|
memcpy(m_str, src.c_str(), src.length() + 1);
|
||||||
@@ -141,7 +141,7 @@ time_t GetLocalHourTimestamp(time_t time, uint8 hour, bool onlyAfterTime)
|
|||||||
return hourLocal;
|
return hourLocal;
|
||||||
}
|
}
|
||||||
|
|
||||||
void stripLineInvisibleChars(std::string &str)
|
void stripLineInvisibleChars(std::string& str)
|
||||||
{
|
{
|
||||||
static std::string const invChars = " \t\7\n";
|
static std::string const invChars = " \t\7\n";
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ void stripLineInvisibleChars(std::string &str)
|
|||||||
bool space = false;
|
bool space = false;
|
||||||
for (size_t pos = 0; pos < str.size(); ++pos)
|
for (size_t pos = 0; pos < str.size(); ++pos)
|
||||||
{
|
{
|
||||||
if (invChars.find(str[pos])!=std::string::npos)
|
if (invChars.find(str[pos]) != std::string::npos)
|
||||||
{
|
{
|
||||||
if (!space)
|
if (!space)
|
||||||
{
|
{
|
||||||
@@ -160,7 +160,7 @@ void stripLineInvisibleChars(std::string &str)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (wpos!=pos)
|
if (wpos != pos)
|
||||||
str[wpos++] = str[pos];
|
str[wpos++] = str[pos];
|
||||||
else
|
else
|
||||||
++wpos;
|
++wpos;
|
||||||
@@ -170,7 +170,7 @@ void stripLineInvisibleChars(std::string &str)
|
|||||||
|
|
||||||
if (wpos < str.size())
|
if (wpos < str.size())
|
||||||
str.erase(wpos, str.size());
|
str.erase(wpos, str.size());
|
||||||
if (str.find("|TInterface")!=std::string::npos)
|
if (str.find("|TInterface") != std::string::npos)
|
||||||
str.clear();
|
str.clear();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -194,8 +194,8 @@ std::string secsToTimeString(uint64 timeInSecs, bool shortText)
|
|||||||
|
|
||||||
std::string str = ss.str();
|
std::string str = ss.str();
|
||||||
|
|
||||||
if (!shortText && !str.empty() && str[str.size()-1] == ' ')
|
if (!shortText && !str.empty() && str[str.size() - 1] == ' ')
|
||||||
str.resize(str.size()-1);
|
str.resize(str.size() - 1);
|
||||||
|
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
@@ -205,8 +205,8 @@ int32 MoneyStringToMoney(const std::string& moneyString)
|
|||||||
int32 money = 0;
|
int32 money = 0;
|
||||||
|
|
||||||
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
|
if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 ||
|
||||||
std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
|
std::count(moneyString.begin(), moneyString.end(), 's') == 1 ||
|
||||||
std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
|
std::count(moneyString.begin(), moneyString.end(), 'c') == 1))
|
||||||
return 0; // Bad format
|
return 0; // Bad format
|
||||||
|
|
||||||
Tokenizer tokens(moneyString, ' ');
|
Tokenizer tokens(moneyString, ' ');
|
||||||
@@ -241,22 +241,31 @@ uint32 TimeStringToSecs(const std::string& timestring)
|
|||||||
{
|
{
|
||||||
if (isdigit(*itr))
|
if (isdigit(*itr))
|
||||||
{
|
{
|
||||||
buffer*=10;
|
buffer *= 10;
|
||||||
buffer+= (*itr)-'0';
|
buffer += (*itr) - '0';
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
switch (*itr)
|
switch (*itr)
|
||||||
{
|
{
|
||||||
case 'd': multiplier = DAY; break;
|
case 'd':
|
||||||
case 'h': multiplier = HOUR; break;
|
multiplier = DAY;
|
||||||
case 'm': multiplier = MINUTE; break;
|
break;
|
||||||
case 's': multiplier = 1; break;
|
case 'h':
|
||||||
default : return 0; //bad format
|
multiplier = HOUR;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
multiplier = MINUTE;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
multiplier = 1;
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
return 0; //bad format
|
||||||
}
|
}
|
||||||
buffer*=multiplier;
|
buffer *= multiplier;
|
||||||
secs+=buffer;
|
secs += buffer;
|
||||||
buffer=0;
|
buffer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -274,7 +283,7 @@ std::string TimeToTimestampStr(time_t t)
|
|||||||
// MM minutes (2 digits 00-59)
|
// MM minutes (2 digits 00-59)
|
||||||
// SS seconds (2 digits 00-59)
|
// SS seconds (2 digits 00-59)
|
||||||
char buf[20];
|
char buf[20];
|
||||||
int ret = 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);
|
int ret = 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);
|
||||||
|
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
{
|
{
|
||||||
@@ -349,7 +358,7 @@ size_t utf8length(std::string& utf8str)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
|
return utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
|
||||||
}
|
}
|
||||||
catch(std::exception const&)
|
catch(std::exception const&)
|
||||||
{
|
{
|
||||||
@@ -362,16 +371,16 @@ void utf8truncate(std::string& utf8str, size_t len)
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str()+utf8str.size());
|
size_t wlen = utf8::distance(utf8str.c_str(), utf8str.c_str() + utf8str.size());
|
||||||
if (wlen <= len)
|
if (wlen <= len)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
std::wstring wstr;
|
std::wstring wstr;
|
||||||
wstr.resize(wlen);
|
wstr.resize(wlen);
|
||||||
utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), &wstr[0]);
|
utf8::utf8to16(utf8str.c_str(), utf8str.c_str() + utf8str.size(), &wstr[0]);
|
||||||
wstr.resize(len);
|
wstr.resize(len);
|
||||||
char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str[0]);
|
char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str() + wstr.size(), &utf8str[0]);
|
||||||
utf8str.resize(oend-(&utf8str[0])); // remove unused tail
|
utf8str.resize(oend - (&utf8str[0])); // remove unused tail
|
||||||
}
|
}
|
||||||
catch(std::exception const&)
|
catch(std::exception const&)
|
||||||
{
|
{
|
||||||
@@ -384,7 +393,7 @@ bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
acore::CheckedBufferOutputIterator<wchar_t> out(wstr, wsize);
|
acore::CheckedBufferOutputIterator<wchar_t> out(wstr, wsize);
|
||||||
out = utf8::utf8to16(utf8str, utf8str+csize, out);
|
out = utf8::utf8to16(utf8str, utf8str + csize, out);
|
||||||
wsize -= out.remaining(); // remaining unused space
|
wsize -= out.remaining(); // remaining unused space
|
||||||
wstr[wsize] = L'\0';
|
wstr[wsize] = L'\0';
|
||||||
}
|
}
|
||||||
@@ -418,7 +427,7 @@ bool Utf8toWStr(const std::string& utf8str, std::wstring& wstr)
|
|||||||
wstr.clear();
|
wstr.clear();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
utf8::utf8to16(utf8str.c_str(), utf8str.c_str()+utf8str.size(), std::back_inserter(wstr));
|
utf8::utf8to16(utf8str.c_str(), utf8str.c_str() + utf8str.size(), std::back_inserter(wstr));
|
||||||
}
|
}
|
||||||
catch(std::exception const&)
|
catch(std::exception const&)
|
||||||
{
|
{
|
||||||
@@ -434,12 +443,12 @@ bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::string utf8str2;
|
std::string utf8str2;
|
||||||
utf8str2.resize(size*4); // allocate for most long case
|
utf8str2.resize(size * 4); // allocate for most long case
|
||||||
|
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
char* oend = utf8::utf16to8(wstr, wstr+size, &utf8str2[0]);
|
char* oend = utf8::utf16to8(wstr, wstr + size, &utf8str2[0]);
|
||||||
utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
|
utf8str2.resize(oend - (&utf8str2[0])); // remove unused tail
|
||||||
}
|
}
|
||||||
utf8str = utf8str2;
|
utf8str = utf8str2;
|
||||||
}
|
}
|
||||||
@@ -457,12 +466,12 @@ bool WStrToUtf8(std::wstring const& wstr, std::string& utf8str)
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
std::string utf8str2;
|
std::string utf8str2;
|
||||||
utf8str2.resize(wstr.size()*4); // allocate for most long case
|
utf8str2.resize(wstr.size() * 4); // allocate for most long case
|
||||||
|
|
||||||
if (wstr.size())
|
if (wstr.size())
|
||||||
{
|
{
|
||||||
char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str()+wstr.size(), &utf8str2[0]);
|
char* oend = utf8::utf16to8(wstr.c_str(), wstr.c_str() + wstr.size(), &utf8str2[0]);
|
||||||
utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
|
utf8str2.resize(oend - (&utf8str2[0])); // remove unused tail
|
||||||
}
|
}
|
||||||
utf8str = utf8str2;
|
utf8str = utf8str2;
|
||||||
}
|
}
|
||||||
@@ -512,13 +521,14 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
|
|||||||
static std::wstring const j_End = { wchar_t(0x0439), wchar_t(0x0000) };
|
static std::wstring const j_End = { wchar_t(0x0439), wchar_t(0x0000) };
|
||||||
|
|
||||||
static std::array<std::array<std::wstring const*, 7>, 6> const dropEnds = {{
|
static std::array<std::array<std::wstring const*, 7>, 6> const dropEnds = {{
|
||||||
{ &a_End, &o_End, &ya_End, &ie_End, &soft_End, &j_End, nullptr },
|
{ &a_End, &o_End, &ya_End, &ie_End, &soft_End, &j_End, nullptr },
|
||||||
{ &a_End, &ya_End, &yeru_End, &i_End, nullptr, nullptr, nullptr },
|
{ &a_End, &ya_End, &yeru_End, &i_End, nullptr, nullptr, nullptr },
|
||||||
{ &ie_End, &u_End, &yu_End, &i_End, nullptr, nullptr, nullptr },
|
{ &ie_End, &u_End, &yu_End, &i_End, nullptr, nullptr, nullptr },
|
||||||
{ &u_End, &yu_End, &o_End, &ie_End, &soft_End, &ya_End, &a_End },
|
{ &u_End, &yu_End, &o_End, &ie_End, &soft_End, &ya_End, &a_End },
|
||||||
{ &oj_End, &io_j_End, &ie_j_End, &o_m_End, &io_m_End, &ie_m_End, &yu_End },
|
{ &oj_End, &io_j_End, &ie_j_End, &o_m_End, &io_m_End, &ie_m_End, &yu_End },
|
||||||
{ &ie_End, &i_End, nullptr, nullptr, nullptr, nullptr, nullptr }
|
{ &ie_End, &i_End, nullptr, nullptr, nullptr, nullptr, nullptr }
|
||||||
}};
|
}
|
||||||
|
};
|
||||||
|
|
||||||
std::size_t const thisLen = wname.length();
|
std::size_t const thisLen = wname.length();
|
||||||
std::array<std::wstring const*, 7> const& endings = dropEnds[declension];
|
std::array<std::wstring const*, 7> const& endings = dropEnds[declension];
|
||||||
@@ -529,8 +539,8 @@ std::wstring GetMainPartOfName(std::wstring const& wname, uint32 declension)
|
|||||||
if (!(endLen <= thisLen))
|
if (!(endLen <= thisLen))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wname.substr(thisLen-endLen, thisLen) == ending)
|
if (wname.substr(thisLen - endLen, thisLen) == ending)
|
||||||
return wname.substr(0, thisLen-endLen);
|
return wname.substr(0, thisLen - endLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
return wname;
|
return wname;
|
||||||
@@ -584,7 +594,7 @@ bool Utf8FitTo(const std::string& str, std::wstring const& search)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void utf8printf(FILE* out, const char *str, ...)
|
void utf8printf(FILE* out, const char* str, ...)
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, str);
|
va_start(ap, str);
|
||||||
@@ -592,7 +602,7 @@ void utf8printf(FILE* out, const char *str, ...)
|
|||||||
va_end(ap);
|
va_end(ap);
|
||||||
}
|
}
|
||||||
|
|
||||||
void vutf8printf(FILE* out, const char *str, va_list* ap)
|
void vutf8printf(FILE* out, const char* str, va_list* ap)
|
||||||
{
|
{
|
||||||
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
#if AC_PLATFORM == AC_PLATFORM_WINDOWS
|
||||||
char temp_buf[32 * 1024];
|
char temp_buf[32 * 1024];
|
||||||
@@ -601,9 +611,9 @@ void vutf8printf(FILE* out, const char *str, va_list* ap)
|
|||||||
size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
|
size_t temp_len = vsnprintf(temp_buf, 32 * 1024, str, *ap);
|
||||||
//vsnprintf returns -1 if the buffer is too small
|
//vsnprintf returns -1 if the buffer is too small
|
||||||
if (temp_len == size_t(-1))
|
if (temp_len == size_t(-1))
|
||||||
temp_len = 32*1024-1;
|
temp_len = 32 * 1024 - 1;
|
||||||
|
|
||||||
size_t wtemp_len = 32*1024-1;
|
size_t wtemp_len = 32 * 1024 - 1;
|
||||||
Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
|
Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
|
||||||
|
|
||||||
CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1));
|
CharToOemBuffW(&wtemp_buf[0], &temp_buf[0], uint32(wtemp_len + 1));
|
||||||
@@ -683,5 +693,5 @@ bool StringToBool(std::string const& str)
|
|||||||
bool StringContainsStringI(std::string const& haystack, std::string const& needle)
|
bool StringContainsStringI(std::string const& haystack, std::string const& needle)
|
||||||
{
|
{
|
||||||
return haystack.end() !=
|
return haystack.end() !=
|
||||||
std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); });
|
std::search(haystack.begin(), haystack.end(), needle.begin(), needle.end(), [](char c1, char c2) { return std::toupper(c1) == std::toupper(c2); });
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user