mirror of
https://github.com/mangosfour/server.git
synced 2025-12-25 13:37:02 +00:00
Imported MaNGOS revision 6767 from http://mangos.svn.sourceforge.net/svnroot/mangos/trunk/
This commit is contained in:
parent
d767495d5b
commit
800ee76535
3322 changed files with 903437 additions and 0 deletions
81
src/shared/Auth/AuthCrypt.cpp
Normal file
81
src/shared/Auth/AuthCrypt.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "AuthCrypt.h"
|
||||
#include "Hmac.h"
|
||||
|
||||
AuthCrypt::AuthCrypt()
|
||||
{
|
||||
_initialized = false;
|
||||
}
|
||||
|
||||
void AuthCrypt::Init()
|
||||
{
|
||||
_send_i = _send_j = _recv_i = _recv_j = 0;
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
void AuthCrypt::DecryptRecv(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized) return;
|
||||
if (len < CRYPTED_RECV_LEN) return;
|
||||
|
||||
for (size_t t = 0; t < CRYPTED_RECV_LEN; t++)
|
||||
{
|
||||
_recv_i %= _key.size();
|
||||
uint8 x = (data[t] - _recv_j) ^ _key[_recv_i];
|
||||
++_recv_i;
|
||||
_recv_j = data[t];
|
||||
data[t] = x;
|
||||
}
|
||||
}
|
||||
|
||||
void AuthCrypt::EncryptSend(uint8 *data, size_t len)
|
||||
{
|
||||
if (!_initialized) return;
|
||||
if (len < CRYPTED_SEND_LEN) return;
|
||||
|
||||
for (size_t t = 0; t < CRYPTED_SEND_LEN; t++)
|
||||
{
|
||||
_send_i %= _key.size();
|
||||
uint8 x = (data[t] ^ _key[_send_i]) + _send_j;
|
||||
++_send_i;
|
||||
data[t] = _send_j = x;
|
||||
}
|
||||
}
|
||||
|
||||
void AuthCrypt::SetKey(BigNumber *bn)
|
||||
{
|
||||
uint8 *key = new uint8[SHA_DIGEST_LENGTH];
|
||||
GenerateKey(key, bn);
|
||||
_key.resize(SHA_DIGEST_LENGTH);
|
||||
std::copy(key, key + SHA_DIGEST_LENGTH, _key.begin());
|
||||
delete key;
|
||||
}
|
||||
|
||||
AuthCrypt::~AuthCrypt()
|
||||
{
|
||||
}
|
||||
|
||||
void AuthCrypt::GenerateKey(uint8 *key, BigNumber *bn)
|
||||
{
|
||||
HmacHash hash;
|
||||
hash.UpdateBigNumber(bn);
|
||||
hash.Finalize();
|
||||
memcpy(key, hash.GetDigest(), SHA_DIGEST_LENGTH);
|
||||
}
|
||||
52
src/shared/Auth/AuthCrypt.h
Normal file
52
src/shared/Auth/AuthCrypt.h
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _AUTHCRYPT_H
|
||||
#define _AUTHCRYPT_H
|
||||
|
||||
#include <Common.h>
|
||||
#include <vector>
|
||||
|
||||
class BigNumber;
|
||||
|
||||
class AuthCrypt
|
||||
{
|
||||
public:
|
||||
AuthCrypt();
|
||||
~AuthCrypt();
|
||||
|
||||
const static size_t CRYPTED_SEND_LEN = 4;
|
||||
const static size_t CRYPTED_RECV_LEN = 6;
|
||||
|
||||
void Init();
|
||||
|
||||
void SetKey(BigNumber *);
|
||||
|
||||
void DecryptRecv(uint8 *, size_t);
|
||||
void EncryptSend(uint8 *, size_t);
|
||||
|
||||
bool IsInitialized() { return _initialized; }
|
||||
|
||||
static void GenerateKey(uint8 *, BigNumber *);
|
||||
|
||||
private:
|
||||
std::vector<uint8> _key;
|
||||
uint8 _send_i, _send_j, _recv_i, _recv_j;
|
||||
bool _initialized;
|
||||
};
|
||||
#endif
|
||||
207
src/shared/Auth/BigNumber.cpp
Normal file
207
src/shared/Auth/BigNumber.cpp
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Auth/BigNumber.h"
|
||||
#include <openssl/bn.h>
|
||||
#include <algorithm>
|
||||
|
||||
BigNumber::BigNumber()
|
||||
{
|
||||
_bn = BN_new();
|
||||
_array = NULL;
|
||||
}
|
||||
|
||||
BigNumber::BigNumber(const BigNumber &bn)
|
||||
{
|
||||
_bn = BN_dup(bn._bn);
|
||||
_array = NULL;
|
||||
}
|
||||
|
||||
BigNumber::BigNumber(uint32 val)
|
||||
{
|
||||
_bn = BN_new();
|
||||
BN_set_word(_bn, val);
|
||||
_array = NULL;
|
||||
}
|
||||
|
||||
BigNumber::~BigNumber()
|
||||
{
|
||||
BN_free(_bn);
|
||||
if(_array) delete[] _array;
|
||||
}
|
||||
|
||||
void BigNumber::SetDword(uint32 val)
|
||||
{
|
||||
BN_set_word(_bn, val);
|
||||
}
|
||||
|
||||
void BigNumber::SetQword(uint64 val)
|
||||
{
|
||||
BN_add_word(_bn, (uint32)(val >> 32));
|
||||
BN_lshift(_bn, _bn, 32);
|
||||
BN_add_word(_bn, (uint32)(val & 0xFFFFFFFF));
|
||||
}
|
||||
|
||||
void BigNumber::SetBinary(const uint8 *bytes, int len)
|
||||
{
|
||||
uint8 t[1000];
|
||||
for (int i = 0; i < len; i++) t[i] = bytes[len - 1 - i];
|
||||
BN_bin2bn(t, len, _bn);
|
||||
}
|
||||
|
||||
void BigNumber::SetHexStr(const char *str)
|
||||
{
|
||||
BN_hex2bn(&_bn, str);
|
||||
}
|
||||
|
||||
void BigNumber::SetRand(int numbits)
|
||||
{
|
||||
BN_rand(_bn, numbits, 0, 1);
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator=(const BigNumber &bn)
|
||||
{
|
||||
BN_copy(_bn, bn._bn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator+=(const BigNumber &bn)
|
||||
{
|
||||
BN_add(_bn, _bn, bn._bn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator-=(const BigNumber &bn)
|
||||
{
|
||||
BN_sub(_bn, _bn, bn._bn);
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator*=(const BigNumber &bn)
|
||||
{
|
||||
BN_CTX *bnctx;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
BN_mul(_bn, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator/=(const BigNumber &bn)
|
||||
{
|
||||
BN_CTX *bnctx;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
BN_div(_bn, NULL, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::operator%=(const BigNumber &bn)
|
||||
{
|
||||
BN_CTX *bnctx;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
BN_mod(_bn, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::Exp(const BigNumber &bn)
|
||||
{
|
||||
BigNumber ret;
|
||||
BN_CTX *bnctx;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
BN_exp(ret._bn, _bn, bn._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BigNumber BigNumber::ModExp(const BigNumber &bn1, const BigNumber &bn2)
|
||||
{
|
||||
BigNumber ret;
|
||||
BN_CTX *bnctx;
|
||||
|
||||
bnctx = BN_CTX_new();
|
||||
BN_mod_exp(ret._bn, _bn, bn1._bn, bn2._bn, bnctx);
|
||||
BN_CTX_free(bnctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BigNumber::GetNumBytes(void)
|
||||
{
|
||||
return BN_num_bytes(_bn);
|
||||
}
|
||||
|
||||
uint32 BigNumber::AsDword()
|
||||
{
|
||||
return (uint32)BN_get_word(_bn);
|
||||
}
|
||||
|
||||
uint8 *BigNumber::AsByteArray(int minSize)
|
||||
{
|
||||
int length = (minSize >= GetNumBytes()) ? minSize : GetNumBytes();
|
||||
|
||||
if (_array)
|
||||
{
|
||||
delete[] _array;
|
||||
_array = NULL;
|
||||
}
|
||||
_array = new uint8[length];
|
||||
|
||||
// If we need more bytes than length of BigNumber set the rest to 0
|
||||
if (length > GetNumBytes())
|
||||
memset((void*)_array, 0, length);
|
||||
|
||||
BN_bn2bin(_bn, (unsigned char *)_array);
|
||||
|
||||
std::reverse(_array, _array + length);
|
||||
|
||||
return _array;
|
||||
}
|
||||
|
||||
ByteBuffer BigNumber::AsByteBuffer()
|
||||
{
|
||||
ByteBuffer ret(GetNumBytes());
|
||||
ret.append(AsByteArray(), GetNumBytes());
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<uint8> BigNumber::AsByteVector()
|
||||
{
|
||||
std::vector<uint8> ret;
|
||||
ret.resize(GetNumBytes());
|
||||
memcpy(&ret[0], AsByteArray(), GetNumBytes());
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *BigNumber::AsHexStr()
|
||||
{
|
||||
return BN_bn2hex(_bn);
|
||||
}
|
||||
|
||||
const char *BigNumber::AsDecStr()
|
||||
{
|
||||
return BN_bn2dec(_bn);
|
||||
}
|
||||
94
src/shared/Auth/BigNumber.h
Normal file
94
src/shared/Auth/BigNumber.h
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_BIGNUMBER_H
|
||||
#define _AUTH_BIGNUMBER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
struct bignum_st;
|
||||
|
||||
class BigNumber
|
||||
{
|
||||
public:
|
||||
BigNumber();
|
||||
BigNumber(const BigNumber &bn);
|
||||
BigNumber(uint32);
|
||||
~BigNumber();
|
||||
|
||||
void SetDword(uint32);
|
||||
void SetQword(uint64);
|
||||
void SetBinary(const uint8 *bytes, int len);
|
||||
void SetHexStr(const char *str);
|
||||
|
||||
void SetRand(int numbits);
|
||||
|
||||
BigNumber operator=(const BigNumber &bn);
|
||||
|
||||
BigNumber operator+=(const BigNumber &bn);
|
||||
BigNumber operator+(const BigNumber &bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t += bn;
|
||||
}
|
||||
BigNumber operator-=(const BigNumber &bn);
|
||||
BigNumber operator-(const BigNumber &bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t -= bn;
|
||||
}
|
||||
BigNumber operator*=(const BigNumber &bn);
|
||||
BigNumber operator*(const BigNumber &bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t *= bn;
|
||||
}
|
||||
BigNumber operator/=(const BigNumber &bn);
|
||||
BigNumber operator/(const BigNumber &bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t /= bn;
|
||||
}
|
||||
BigNumber operator%=(const BigNumber &bn);
|
||||
BigNumber operator%(const BigNumber &bn)
|
||||
{
|
||||
BigNumber t(*this);
|
||||
return t %= bn;
|
||||
}
|
||||
|
||||
BigNumber ModExp(const BigNumber &bn1, const BigNumber &bn2);
|
||||
BigNumber Exp(const BigNumber &);
|
||||
|
||||
int GetNumBytes(void);
|
||||
|
||||
struct bignum_st *BN() { return _bn; }
|
||||
|
||||
uint32 AsDword();
|
||||
uint8* AsByteArray(int minSize = 0);
|
||||
ByteBuffer AsByteBuffer();
|
||||
std::vector<uint8> AsByteVector();
|
||||
|
||||
const char *AsHexStr();
|
||||
const char *AsDecStr();
|
||||
|
||||
private:
|
||||
struct bignum_st *_bn;
|
||||
uint8 *_array;
|
||||
};
|
||||
#endif
|
||||
56
src/shared/Auth/Hmac.cpp
Normal file
56
src/shared/Auth/Hmac.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Auth/Hmac.h"
|
||||
#include "BigNumber.h"
|
||||
|
||||
HmacHash::HmacHash()
|
||||
{
|
||||
uint8 temp[SEED_KEY_SIZE] = { 0x38, 0xA7, 0x83, 0x15, 0xF8, 0x92, 0x25, 0x30, 0x71, 0x98, 0x67, 0xB1, 0x8C, 0x4, 0xE2, 0xAA };
|
||||
memcpy(&m_key, &temp, SEED_KEY_SIZE);
|
||||
HMAC_CTX_init(&m_ctx);
|
||||
HMAC_Init_ex(&m_ctx, &m_key, SEED_KEY_SIZE, EVP_sha1(), NULL);
|
||||
}
|
||||
|
||||
HmacHash::~HmacHash()
|
||||
{
|
||||
memset(&m_key, 0x00, SEED_KEY_SIZE);
|
||||
HMAC_CTX_cleanup(&m_ctx);
|
||||
}
|
||||
|
||||
void HmacHash::UpdateBigNumber(BigNumber *bn)
|
||||
{
|
||||
UpdateData(bn->AsByteArray(), bn->GetNumBytes());
|
||||
}
|
||||
|
||||
void HmacHash::UpdateData(const uint8 *data, int length)
|
||||
{
|
||||
HMAC_Update(&m_ctx, data, length);
|
||||
}
|
||||
|
||||
void HmacHash::Initialize()
|
||||
{
|
||||
HMAC_Init_ex(&m_ctx, &m_key, SEED_KEY_SIZE, EVP_sha1(), NULL);
|
||||
}
|
||||
|
||||
void HmacHash::Finalize()
|
||||
{
|
||||
uint32 length = 0;
|
||||
HMAC_Final(&m_ctx, m_digest, &length);
|
||||
ASSERT(length == SHA_DIGEST_LENGTH)
|
||||
}
|
||||
46
src/shared/Auth/Hmac.h
Normal file
46
src/shared/Auth/Hmac.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_HMAC_H
|
||||
#define _AUTH_HMAC_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <openssl/hmac.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
class BigNumber;
|
||||
|
||||
#define SEED_KEY_SIZE 16
|
||||
|
||||
class HmacHash
|
||||
{
|
||||
public:
|
||||
HmacHash();
|
||||
~HmacHash();
|
||||
void UpdateBigNumber(BigNumber *bn);
|
||||
void UpdateData(const uint8 *data, int length);
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
uint8 *GetDigest() { return m_digest; };
|
||||
int GetLength() { return SHA_DIGEST_LENGTH; };
|
||||
private:
|
||||
HMAC_CTX m_ctx;
|
||||
uint8 m_key[SEED_KEY_SIZE];
|
||||
uint8 m_digest[SHA_DIGEST_LENGTH];
|
||||
};
|
||||
#endif
|
||||
39
src/shared/Auth/Makefile.am
Normal file
39
src/shared/Auth/Makefile.am
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
# Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
## Sub-directories to parse
|
||||
|
||||
## CPP flags for includes, defines, etc.
|
||||
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite
|
||||
|
||||
## Build MaNGOS shared library and its parts as convenience library.
|
||||
# All libraries will be convenience libraries. Might be changed to shared
|
||||
# later.
|
||||
noinst_LIBRARIES = libmangosauth.a
|
||||
|
||||
libmangosauth_a_SOURCES = \
|
||||
AuthCrypt.cpp \
|
||||
AuthCrypt.h \
|
||||
BigNumber.cpp \
|
||||
BigNumber.h \
|
||||
Hmac.cpp \
|
||||
Hmac.h \
|
||||
Sha1.cpp \
|
||||
Sha1.h \
|
||||
md5.c \
|
||||
md5.h
|
||||
65
src/shared/Auth/Sha1.cpp
Normal file
65
src/shared/Auth/Sha1.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Auth/Sha1.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
Sha1Hash::Sha1Hash()
|
||||
{
|
||||
SHA1_Init(&mC);
|
||||
}
|
||||
|
||||
Sha1Hash::~Sha1Hash()
|
||||
{
|
||||
SHA1_Init(&mC);
|
||||
}
|
||||
|
||||
void Sha1Hash::UpdateData(const uint8 *dta, int len)
|
||||
{
|
||||
SHA1_Update(&mC, dta, len);
|
||||
}
|
||||
|
||||
void Sha1Hash::UpdateData(const std::string &str)
|
||||
{
|
||||
UpdateData((uint8 const*)str.c_str(), str.length());
|
||||
}
|
||||
|
||||
void Sha1Hash::UpdateBigNumbers(BigNumber *bn0, ...)
|
||||
{
|
||||
va_list v;
|
||||
BigNumber *bn;
|
||||
|
||||
va_start(v, bn0);
|
||||
bn = bn0;
|
||||
while (bn)
|
||||
{
|
||||
UpdateData(bn->AsByteArray(), bn->GetNumBytes());
|
||||
bn = va_arg(v, BigNumber *);
|
||||
}
|
||||
va_end(v);
|
||||
}
|
||||
|
||||
void Sha1Hash::Initialize()
|
||||
{
|
||||
SHA1_Init(&mC);
|
||||
}
|
||||
|
||||
void Sha1Hash::Finalize(void)
|
||||
{
|
||||
SHA1_Final(mDigest, &mC);
|
||||
}
|
||||
51
src/shared/Auth/Sha1.h
Normal file
51
src/shared/Auth/Sha1.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _AUTH_SHA1_H
|
||||
#define _AUTH_SHA1_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <openssl/sha.h>
|
||||
#include <openssl/crypto.h>
|
||||
#include "Auth/BigNumber.h"
|
||||
|
||||
class Sha1Hash
|
||||
{
|
||||
public:
|
||||
Sha1Hash();
|
||||
~Sha1Hash();
|
||||
|
||||
void UpdateFinalizeBigNumbers(BigNumber *bn0, ...);
|
||||
void UpdateBigNumbers(BigNumber *bn0, ...);
|
||||
|
||||
void UpdateData(const uint8 *dta, int len);
|
||||
void UpdateData(const std::string &str);
|
||||
|
||||
void Initialize();
|
||||
void Finalize();
|
||||
|
||||
uint8 *GetDigest(void) { return mDigest; };
|
||||
int GetLength(void) { return SHA_DIGEST_LENGTH; };
|
||||
|
||||
BigNumber GetBigNumber();
|
||||
|
||||
private:
|
||||
SHA_CTX mC;
|
||||
uint8 mDigest[SHA_DIGEST_LENGTH];
|
||||
};
|
||||
#endif
|
||||
385
src/shared/Auth/md5.c
Normal file
385
src/shared/Auth/md5.c
Normal file
|
|
@ -0,0 +1,385 @@
|
|||
/*
|
||||
Copyright (C) 1999, 2000, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.c,v 1.6 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.c is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
|
||||
either statically or dynamically; added missing #include <string.h>
|
||||
in library.
|
||||
2002-03-11 lpd Corrected argument list for main(), and added int return
|
||||
type, in test program and T value program.
|
||||
2002-02-21 lpd Added missing #include <stdio.h> in test program.
|
||||
2000-07-03 lpd Patched to eliminate warnings about "constant is
|
||||
unsigned in ANSI C, signed in traditional"; made test program
|
||||
self-checking.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#include "md5.h"
|
||||
#include <string.h>
|
||||
|
||||
#undef BYTE_ORDER /* 1 = big-endian, -1 = little-endian, 0 = unknown */
|
||||
#ifdef ARCH_IS_BIG_ENDIAN
|
||||
# define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
|
||||
#else
|
||||
# define BYTE_ORDER 0
|
||||
#endif
|
||||
|
||||
#define T_MASK ((md5_word_t)~0)
|
||||
#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
|
||||
#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
|
||||
#define T3 0x242070db
|
||||
#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
|
||||
#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
|
||||
#define T6 0x4787c62a
|
||||
#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
|
||||
#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
|
||||
#define T9 0x698098d8
|
||||
#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
|
||||
#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
|
||||
#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
|
||||
#define T13 0x6b901122
|
||||
#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
|
||||
#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
|
||||
#define T16 0x49b40821
|
||||
#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
|
||||
#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
|
||||
#define T19 0x265e5a51
|
||||
#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
|
||||
#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
|
||||
#define T22 0x02441453
|
||||
#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
|
||||
#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
|
||||
#define T25 0x21e1cde6
|
||||
#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
|
||||
#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
|
||||
#define T28 0x455a14ed
|
||||
#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
|
||||
#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
|
||||
#define T31 0x676f02d9
|
||||
#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
|
||||
#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
|
||||
#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
|
||||
#define T35 0x6d9d6122
|
||||
#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
|
||||
#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
|
||||
#define T38 0x4bdecfa9
|
||||
#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
|
||||
#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
|
||||
#define T41 0x289b7ec6
|
||||
#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
|
||||
#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
|
||||
#define T44 0x04881d05
|
||||
#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
|
||||
#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
|
||||
#define T47 0x1fa27cf8
|
||||
#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
|
||||
#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
|
||||
#define T50 0x432aff97
|
||||
#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
|
||||
#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
|
||||
#define T53 0x655b59c3
|
||||
#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
|
||||
#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
|
||||
#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
|
||||
#define T57 0x6fa87e4f
|
||||
#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
|
||||
#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
|
||||
#define T60 0x4e0811a1
|
||||
#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
|
||||
#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
|
||||
#define T63 0x2ad7d2bb
|
||||
#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
|
||||
|
||||
static void
|
||||
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
|
||||
{
|
||||
md5_word_t
|
||||
a = pms->abcd[0], b = pms->abcd[1],
|
||||
c = pms->abcd[2], d = pms->abcd[3];
|
||||
md5_word_t t;
|
||||
#if BYTE_ORDER > 0
|
||||
/* Define storage only for big-endian CPUs. */
|
||||
md5_word_t X[16];
|
||||
#else
|
||||
/* Define storage for little-endian or both types of CPUs. */
|
||||
md5_word_t xbuf[16];
|
||||
const md5_word_t *X;
|
||||
#endif
|
||||
|
||||
{
|
||||
#if BYTE_ORDER == 0
|
||||
/*
|
||||
* Determine dynamically whether this is a big-endian or
|
||||
* little-endian machine, since we can use a more efficient
|
||||
* algorithm on the latter.
|
||||
*/
|
||||
static const int w = 1;
|
||||
|
||||
if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER <= 0 /* little-endian */
|
||||
{
|
||||
/*
|
||||
* On little-endian machines, we can process properly aligned
|
||||
* data without copying it.
|
||||
*/
|
||||
if (!((data - (const md5_byte_t *)0) & 3))
|
||||
{
|
||||
/* data are properly aligned */
|
||||
X = (const md5_word_t *)data;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* not aligned */
|
||||
memcpy(xbuf, data, 64);
|
||||
X = xbuf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if BYTE_ORDER == 0
|
||||
else /* dynamic big-endian */
|
||||
#endif
|
||||
#if BYTE_ORDER >= 0 /* big-endian */
|
||||
{
|
||||
/*
|
||||
* On big-endian machines, we must arrange the bytes in the
|
||||
* right order.
|
||||
*/
|
||||
const md5_byte_t *xp = data;
|
||||
int i;
|
||||
|
||||
# if BYTE_ORDER == 0
|
||||
X = xbuf; /* (dynamic only) */
|
||||
# else
|
||||
# define xbuf X /* (static only) */
|
||||
# endif
|
||||
for (i = 0; i < 16; ++i, xp += 4)
|
||||
xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
|
||||
|
||||
/* Round 1. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + F(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 7, T1);
|
||||
SET(d, a, b, c, 1, 12, T2);
|
||||
SET(c, d, a, b, 2, 17, T3);
|
||||
SET(b, c, d, a, 3, 22, T4);
|
||||
SET(a, b, c, d, 4, 7, T5);
|
||||
SET(d, a, b, c, 5, 12, T6);
|
||||
SET(c, d, a, b, 6, 17, T7);
|
||||
SET(b, c, d, a, 7, 22, T8);
|
||||
SET(a, b, c, d, 8, 7, T9);
|
||||
SET(d, a, b, c, 9, 12, T10);
|
||||
SET(c, d, a, b, 10, 17, T11);
|
||||
SET(b, c, d, a, 11, 22, T12);
|
||||
SET(a, b, c, d, 12, 7, T13);
|
||||
SET(d, a, b, c, 13, 12, T14);
|
||||
SET(c, d, a, b, 14, 17, T15);
|
||||
SET(b, c, d, a, 15, 22, T16);
|
||||
#undef SET
|
||||
|
||||
/* Round 2. */
|
||||
/* Let [abcd k s i] denote the operation
|
||||
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + G(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 1, 5, T17);
|
||||
SET(d, a, b, c, 6, 9, T18);
|
||||
SET(c, d, a, b, 11, 14, T19);
|
||||
SET(b, c, d, a, 0, 20, T20);
|
||||
SET(a, b, c, d, 5, 5, T21);
|
||||
SET(d, a, b, c, 10, 9, T22);
|
||||
SET(c, d, a, b, 15, 14, T23);
|
||||
SET(b, c, d, a, 4, 20, T24);
|
||||
SET(a, b, c, d, 9, 5, T25);
|
||||
SET(d, a, b, c, 14, 9, T26);
|
||||
SET(c, d, a, b, 3, 14, T27);
|
||||
SET(b, c, d, a, 8, 20, T28);
|
||||
SET(a, b, c, d, 13, 5, T29);
|
||||
SET(d, a, b, c, 2, 9, T30);
|
||||
SET(c, d, a, b, 7, 14, T31);
|
||||
SET(b, c, d, a, 12, 20, T32);
|
||||
#undef SET
|
||||
|
||||
/* Round 3. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define H(x, y, z) ((x) ^ (y) ^ (z))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + H(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 5, 4, T33);
|
||||
SET(d, a, b, c, 8, 11, T34);
|
||||
SET(c, d, a, b, 11, 16, T35);
|
||||
SET(b, c, d, a, 14, 23, T36);
|
||||
SET(a, b, c, d, 1, 4, T37);
|
||||
SET(d, a, b, c, 4, 11, T38);
|
||||
SET(c, d, a, b, 7, 16, T39);
|
||||
SET(b, c, d, a, 10, 23, T40);
|
||||
SET(a, b, c, d, 13, 4, T41);
|
||||
SET(d, a, b, c, 0, 11, T42);
|
||||
SET(c, d, a, b, 3, 16, T43);
|
||||
SET(b, c, d, a, 6, 23, T44);
|
||||
SET(a, b, c, d, 9, 4, T45);
|
||||
SET(d, a, b, c, 12, 11, T46);
|
||||
SET(c, d, a, b, 15, 16, T47);
|
||||
SET(b, c, d, a, 2, 23, T48);
|
||||
#undef SET
|
||||
|
||||
/* Round 4. */
|
||||
/* Let [abcd k s t] denote the operation
|
||||
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
|
||||
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
|
||||
#define SET(a, b, c, d, k, s, Ti)\
|
||||
t = a + I(b,c,d) + X[k] + Ti;\
|
||||
a = ROTATE_LEFT(t, s) + b
|
||||
/* Do the following 16 operations. */
|
||||
SET(a, b, c, d, 0, 6, T49);
|
||||
SET(d, a, b, c, 7, 10, T50);
|
||||
SET(c, d, a, b, 14, 15, T51);
|
||||
SET(b, c, d, a, 5, 21, T52);
|
||||
SET(a, b, c, d, 12, 6, T53);
|
||||
SET(d, a, b, c, 3, 10, T54);
|
||||
SET(c, d, a, b, 10, 15, T55);
|
||||
SET(b, c, d, a, 1, 21, T56);
|
||||
SET(a, b, c, d, 8, 6, T57);
|
||||
SET(d, a, b, c, 15, 10, T58);
|
||||
SET(c, d, a, b, 6, 15, T59);
|
||||
SET(b, c, d, a, 13, 21, T60);
|
||||
SET(a, b, c, d, 4, 6, T61);
|
||||
SET(d, a, b, c, 11, 10, T62);
|
||||
SET(c, d, a, b, 2, 15, T63);
|
||||
SET(b, c, d, a, 9, 21, T64);
|
||||
#undef SET
|
||||
|
||||
/* Then perform the following additions. (That is increment each
|
||||
of the four registers by the value it had before this block
|
||||
was started.) */
|
||||
pms->abcd[0] += a;
|
||||
pms->abcd[1] += b;
|
||||
pms->abcd[2] += c;
|
||||
pms->abcd[3] += d;
|
||||
}
|
||||
|
||||
void
|
||||
md5_init(md5_state_t *pms)
|
||||
{
|
||||
pms->count[0] = pms->count[1] = 0;
|
||||
pms->abcd[0] = 0x67452301;
|
||||
pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
|
||||
pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
|
||||
pms->abcd[3] = 0x10325476;
|
||||
}
|
||||
|
||||
void
|
||||
md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
|
||||
{
|
||||
const md5_byte_t *p = data;
|
||||
int left = nbytes;
|
||||
int offset = (pms->count[0] >> 3) & 63;
|
||||
md5_word_t nbits = (md5_word_t)(nbytes << 3);
|
||||
|
||||
if (nbytes <= 0)
|
||||
return;
|
||||
|
||||
/* Update the message length. */
|
||||
pms->count[1] += nbytes >> 29;
|
||||
pms->count[0] += nbits;
|
||||
if (pms->count[0] < nbits)
|
||||
++pms->count[1];
|
||||
|
||||
/* Process an initial partial block. */
|
||||
if (offset)
|
||||
{
|
||||
int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
|
||||
|
||||
memcpy(pms->buf + offset, p, copy);
|
||||
if (offset + copy < 64)
|
||||
return;
|
||||
p += copy;
|
||||
left -= copy;
|
||||
md5_process(pms, pms->buf);
|
||||
}
|
||||
|
||||
/* Process full blocks. */
|
||||
for (; left >= 64; p += 64, left -= 64)
|
||||
md5_process(pms, p);
|
||||
|
||||
/* Process a final partial block. */
|
||||
if (left)
|
||||
memcpy(pms->buf, p, left);
|
||||
}
|
||||
|
||||
void
|
||||
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
|
||||
{
|
||||
static const md5_byte_t pad[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
md5_byte_t data[8];
|
||||
int i;
|
||||
|
||||
/* Save the length before padding. */
|
||||
for (i = 0; i < 8; ++i)
|
||||
data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
|
||||
/* Pad to 56 bytes mod 64. */
|
||||
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
|
||||
/* Append the length. */
|
||||
md5_append(pms, data, 8);
|
||||
for (i = 0; i < 16; ++i)
|
||||
digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
|
||||
}
|
||||
91
src/shared/Auth/md5.h
Normal file
91
src/shared/Auth/md5.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/*
|
||||
Copyright (C) 1999, 2002 Aladdin Enterprises. All rights reserved.
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
L. Peter Deutsch
|
||||
ghost@aladdin.com
|
||||
|
||||
*/
|
||||
/* $Id: md5.h,v 1.4 2002/04/13 19:20:28 lpd Exp $ */
|
||||
/*
|
||||
Independent implementation of MD5 (RFC 1321).
|
||||
|
||||
This code implements the MD5 Algorithm defined in RFC 1321, whose
|
||||
text is available at
|
||||
http://www.ietf.org/rfc/rfc1321.txt
|
||||
The code is derived from the text of the RFC, including the test suite
|
||||
(section A.5) but excluding the rest of Appendix A. It does not include
|
||||
any code or documentation that is identified in the RFC as being
|
||||
copyrighted.
|
||||
|
||||
The original and principal author of md5.h is L. Peter Deutsch
|
||||
<ghost@aladdin.com>. Other authors are noted in the change history
|
||||
that follows (in reverse chronological order):
|
||||
|
||||
2002-04-13 lpd Removed support for non-ANSI compilers; removed
|
||||
references to Ghostscript; clarified derivation from RFC 1321;
|
||||
now handles byte order either statically or dynamically.
|
||||
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
|
||||
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
|
||||
added conditionalization for C++ compilation from Martin
|
||||
Purschke <purschke@bnl.gov>.
|
||||
1999-05-03 lpd Original version.
|
||||
*/
|
||||
|
||||
#ifndef md5_INCLUDED
|
||||
# define md5_INCLUDED
|
||||
|
||||
/*
|
||||
* This package supports both compile-time and run-time determination of CPU
|
||||
* byte order. If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
|
||||
* compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
|
||||
* defined as non-zero, the code will be compiled to run only on big-endian
|
||||
* CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
|
||||
* run on either big- or little-endian CPUs, but will run slightly less
|
||||
* efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
|
||||
*/
|
||||
|
||||
typedef unsigned char md5_byte_t; /* 8-bit byte */
|
||||
typedef unsigned int md5_word_t; /* 32-bit word */
|
||||
|
||||
/* Define the state of the MD5 Algorithm. */
|
||||
typedef struct md5_state_s
|
||||
{
|
||||
md5_word_t count[2]; /* message length in bits, lsw first */
|
||||
md5_word_t abcd[4]; /* digest buffer */
|
||||
md5_byte_t buf[64]; /* accumulate block */
|
||||
} md5_state_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/* Initialize the algorithm. */
|
||||
void md5_init(md5_state_t *pms);
|
||||
|
||||
/* Append a string to the message. */
|
||||
void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
|
||||
|
||||
/* Finish the message and return the digest. */
|
||||
void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* end extern "C" */
|
||||
#endif
|
||||
#endif /* md5_INCLUDED */
|
||||
67
src/shared/Base.cpp
Normal file
67
src/shared/Base.cpp
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
Base class interface
|
||||
Copyright (C) 1998,1999 by Andrew Zabolotny
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Base.h"
|
||||
|
||||
Base::~Base ()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrement object's reference count; as soon as the last reference
|
||||
* to the object is removed, it is destroyed.
|
||||
*/
|
||||
|
||||
void Base::DecRef ()
|
||||
{
|
||||
if (!--RefCount)
|
||||
delete this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Object initialization. The initial reference count is set to one;
|
||||
* this means if you call DecRef() immediately after creating the object,
|
||||
* it will be destroyed.
|
||||
*/
|
||||
Base::Base ()
|
||||
{
|
||||
RefCount = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment reference count.
|
||||
* Every time when you copy a pointer to a object and store it for
|
||||
* later use you MUST call IncRef() on it; this will allow to keep
|
||||
* objects as long as they are referenced by some entity.
|
||||
*/
|
||||
void Base::IncRef ()
|
||||
{
|
||||
++RefCount;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Query number of references to this object.
|
||||
* I would rather prefer to have the reference counter strictly private,
|
||||
* but sometimes, mostly for debugging, such a function can help.
|
||||
*/
|
||||
int Base::GetRefCount ()
|
||||
{
|
||||
return RefCount;
|
||||
}
|
||||
54
src/shared/Base.h
Normal file
54
src/shared/Base.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Base class interface
|
||||
Copyright (C) 1998,1999 by Andrew Zabolotny
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef __BASE_H__
|
||||
#define __BASE_H__
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
/**
|
||||
* This class is intended to be a base class for every other class.
|
||||
* It defines the basic interface available for any object.
|
||||
*/
|
||||
class Base
|
||||
{
|
||||
private:
|
||||
/// Object reference count
|
||||
int RefCount;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Destroy this object. Destructor is virtual, because class contains
|
||||
* virtual methods; also it is private because it is never intended
|
||||
* to be called directly; use DecRef() instead: when reference counter
|
||||
* reaches zero, the object will be destroyed.
|
||||
*/
|
||||
virtual ~Base ();
|
||||
|
||||
public:
|
||||
|
||||
Base ();
|
||||
|
||||
void IncRef ();
|
||||
|
||||
void DecRef ();
|
||||
int GetRefCount ();
|
||||
|
||||
};
|
||||
#endif // __BASE_H__
|
||||
479
src/shared/ByteBuffer.h
Normal file
479
src/shared/ByteBuffer.h
Normal file
|
|
@ -0,0 +1,479 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _BYTEBUFFER_H
|
||||
#define _BYTEBUFFER_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Errors.h"
|
||||
#include "Log.h"
|
||||
#include "Utilities/ByteConverter.h"
|
||||
|
||||
class ByteBuffer
|
||||
{
|
||||
public:
|
||||
const static size_t DEFAULT_SIZE = 0x1000;
|
||||
|
||||
// constructor
|
||||
ByteBuffer(): _rpos(0), _wpos(0)
|
||||
{
|
||||
_storage.reserve(DEFAULT_SIZE);
|
||||
}
|
||||
// constructor
|
||||
ByteBuffer(size_t res): _rpos(0), _wpos(0)
|
||||
{
|
||||
_storage.reserve(res);
|
||||
}
|
||||
// copy constructor
|
||||
ByteBuffer(const ByteBuffer &buf): _rpos(buf._rpos), _wpos(buf._wpos), _storage(buf._storage) { }
|
||||
|
||||
void clear()
|
||||
{
|
||||
_storage.clear();
|
||||
_rpos = _wpos = 0;
|
||||
}
|
||||
|
||||
template <typename T> void append(T value)
|
||||
{
|
||||
EndianConvert(value);
|
||||
append((uint8 *)&value, sizeof(value));
|
||||
}
|
||||
|
||||
template <typename T> void put(size_t pos,T value)
|
||||
{
|
||||
EndianConvert(value);
|
||||
put(pos,(uint8 *)&value,sizeof(value));
|
||||
}
|
||||
|
||||
ByteBuffer &operator<<(uint8 value)
|
||||
{
|
||||
append<uint8>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(uint16 value)
|
||||
{
|
||||
append<uint16>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(uint32 value)
|
||||
{
|
||||
append<uint32>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(uint64 value)
|
||||
{
|
||||
append<uint64>(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// signed as in 2e complement
|
||||
ByteBuffer &operator<<(int8 value)
|
||||
{
|
||||
append<int8>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(int16 value)
|
||||
{
|
||||
append<int16>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(int32 value)
|
||||
{
|
||||
append<int32>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(int64 value)
|
||||
{
|
||||
append<int64>(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// floating points
|
||||
ByteBuffer &operator<<(float value)
|
||||
{
|
||||
append<float>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(double value)
|
||||
{
|
||||
append<double>(value);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(const std::string &value)
|
||||
{
|
||||
append((uint8 const *)value.c_str(), value.length());
|
||||
append((uint8)0);
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator<<(const char *str)
|
||||
{
|
||||
append((uint8 const *)str, str ? strlen(str) : 0);
|
||||
append((uint8)0);
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteBuffer &operator>>(bool &value)
|
||||
{
|
||||
value = read<char>() > 0 ? true : false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteBuffer &operator>>(uint8 &value)
|
||||
{
|
||||
value = read<uint8>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(uint16 &value)
|
||||
{
|
||||
value = read<uint16>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(uint32 &value)
|
||||
{
|
||||
value = read<uint32>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(uint64 &value)
|
||||
{
|
||||
value = read<uint64>();
|
||||
return *this;
|
||||
}
|
||||
|
||||
//signed as in 2e complement
|
||||
ByteBuffer &operator>>(int8 &value)
|
||||
{
|
||||
value = read<int8>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(int16 &value)
|
||||
{
|
||||
value = read<int16>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(int32 &value)
|
||||
{
|
||||
value = read<int32>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(int64 &value)
|
||||
{
|
||||
value = read<int64>();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ByteBuffer &operator>>(float &value)
|
||||
{
|
||||
value = read<float>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(double &value)
|
||||
{
|
||||
value = read<double>();
|
||||
return *this;
|
||||
}
|
||||
ByteBuffer &operator>>(std::string& value)
|
||||
{
|
||||
value.clear();
|
||||
while (rpos() < size()) // prevent crash at wrong string format in packet
|
||||
{
|
||||
char c=read<char>();
|
||||
if (c==0)
|
||||
break;
|
||||
value+=c;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8 operator[](size_t pos) const
|
||||
{
|
||||
return read<uint8>(pos);
|
||||
}
|
||||
|
||||
size_t rpos() const { return _rpos; }
|
||||
|
||||
size_t rpos(size_t rpos_)
|
||||
{
|
||||
_rpos = rpos_;
|
||||
return _rpos;
|
||||
};
|
||||
|
||||
size_t wpos() const { return _wpos; }
|
||||
|
||||
size_t wpos(size_t wpos_)
|
||||
{
|
||||
_wpos = wpos_;
|
||||
return _wpos;
|
||||
}
|
||||
|
||||
template <typename T> T read()
|
||||
{
|
||||
T r=read<T>(_rpos);
|
||||
_rpos += sizeof(T);
|
||||
return r;
|
||||
};
|
||||
template <typename T> T read(size_t pos) const
|
||||
{
|
||||
ASSERT(pos + sizeof(T) <= size() || PrintPosError(false,pos,sizeof(T)));
|
||||
T val = *((T const*)&_storage[pos]);
|
||||
EndianConvert(val);
|
||||
return val;
|
||||
}
|
||||
|
||||
void read(uint8 *dest, size_t len)
|
||||
{
|
||||
ASSERT(_rpos + len <= size() || PrintPosError(false,_rpos,len));
|
||||
memcpy(dest, &_storage[_rpos], len);
|
||||
_rpos += len;
|
||||
}
|
||||
|
||||
const uint8 *contents() const { return &_storage[0]; }
|
||||
|
||||
size_t size() const { return _storage.size(); }
|
||||
bool empty() const { return _storage.empty(); }
|
||||
|
||||
void resize(size_t newsize)
|
||||
{
|
||||
_storage.resize(newsize);
|
||||
_rpos = 0;
|
||||
_wpos = size();
|
||||
};
|
||||
void reserve(size_t ressize)
|
||||
{
|
||||
if (ressize > size()) _storage.reserve(ressize);
|
||||
};
|
||||
|
||||
void append(const std::string& str)
|
||||
{
|
||||
append((uint8 const*)str.c_str(),str.size() + 1);
|
||||
}
|
||||
void append(const char *src, size_t cnt)
|
||||
{
|
||||
return append((const uint8 *)src, cnt);
|
||||
}
|
||||
template<class T>
|
||||
void append(const T *src, size_t cnt)
|
||||
{
|
||||
return append((const uint8 *)src, cnt*sizeof(T));
|
||||
}
|
||||
void append(const uint8 *src, size_t cnt)
|
||||
{
|
||||
if (!cnt) return;
|
||||
|
||||
ASSERT(size() < 10000000);
|
||||
|
||||
if (_storage.size() < _wpos + cnt)
|
||||
_storage.resize(_wpos + cnt);
|
||||
memcpy(&_storage[_wpos], src, cnt);
|
||||
_wpos += cnt;
|
||||
}
|
||||
void append(const ByteBuffer& buffer)
|
||||
{
|
||||
if(buffer.size()) append(buffer.contents(),buffer.size());
|
||||
}
|
||||
|
||||
void appendPackGUID(uint64 guid)
|
||||
{
|
||||
size_t mask_position = wpos();
|
||||
*this << uint8(0);
|
||||
for(uint8 i = 0; i < 8; i++)
|
||||
{
|
||||
if(guid & 0xFF)
|
||||
{
|
||||
_storage[mask_position] |= uint8(1<<i);
|
||||
*this << uint8(guid & 0xFF);
|
||||
}
|
||||
|
||||
guid >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void put(size_t pos, const uint8 *src, size_t cnt)
|
||||
{
|
||||
ASSERT(pos + cnt <= size() || PrintPosError(true,pos,cnt));
|
||||
memcpy(&_storage[pos], src, cnt);
|
||||
}
|
||||
void print_storage() const
|
||||
{
|
||||
if(!sLog.IsOutDebug()) // optimize disabled debug output
|
||||
return;
|
||||
|
||||
sLog.outDebug("STORAGE_SIZE: %u", size() );
|
||||
for(uint32 i = 0; i < size(); i++)
|
||||
sLog.outDebugInLine("%u - ", read<uint8>(i) );
|
||||
sLog.outDebug(" ");
|
||||
}
|
||||
|
||||
void textlike() const
|
||||
{
|
||||
if(!sLog.IsOutDebug()) // optimize disabled debug output
|
||||
return;
|
||||
|
||||
sLog.outDebug("STORAGE_SIZE: %u", size() );
|
||||
for(uint32 i = 0; i < size(); i++)
|
||||
sLog.outDebugInLine("%c", read<uint8>(i) );
|
||||
sLog.outDebug(" ");
|
||||
}
|
||||
|
||||
void hexlike() const
|
||||
{
|
||||
if(!sLog.IsOutDebug()) // optimize disabled debug output
|
||||
return;
|
||||
|
||||
uint32 j = 1, k = 1;
|
||||
sLog.outDebug("STORAGE_SIZE: %u", size() );
|
||||
|
||||
if(sLog.IsIncludeTime())
|
||||
sLog.outDebugInLine(" ");
|
||||
|
||||
for(uint32 i = 0; i < size(); i++)
|
||||
{
|
||||
if ((i == (j*8)) && ((i != (k*16))))
|
||||
{
|
||||
if (read<uint8>(i) < 0x0F)
|
||||
{
|
||||
sLog.outDebugInLine("| 0%X ", read<uint8>(i) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outDebugInLine("| %X ", read<uint8>(i) );
|
||||
}
|
||||
++j;
|
||||
}
|
||||
else if (i == (k*16))
|
||||
{
|
||||
if (read<uint8>(i) < 0x0F)
|
||||
{
|
||||
sLog.outDebugInLine("\n");
|
||||
if(sLog.IsIncludeTime())
|
||||
sLog.outDebugInLine(" ");
|
||||
|
||||
sLog.outDebugInLine("0%X ", read<uint8>(i) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outDebugInLine("\n");
|
||||
if(sLog.IsIncludeTime())
|
||||
sLog.outDebugInLine(" ");
|
||||
|
||||
sLog.outDebugInLine("%X ", read<uint8>(i) );
|
||||
}
|
||||
|
||||
++k;
|
||||
++j;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (read<uint8>(i) < 0x0F)
|
||||
{
|
||||
sLog.outDebugInLine("0%X ", read<uint8>(i) );
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outDebugInLine("%X ", read<uint8>(i) );
|
||||
}
|
||||
}
|
||||
}
|
||||
sLog.outDebugInLine("\n");
|
||||
}
|
||||
|
||||
protected:
|
||||
bool PrintPosError(bool add, size_t pos, size_t esize) const
|
||||
{
|
||||
sLog.outError("ERROR: Attempt %s in ByteBuffer (pos: %u size: %u) value with size: %u",(add ? "put" : "get"),pos, size(), esize);
|
||||
|
||||
// assert must fail after function call
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t _rpos, _wpos;
|
||||
std::vector<uint8> _storage;
|
||||
};
|
||||
|
||||
template <typename T> ByteBuffer &operator<<(ByteBuffer &b, std::vector<T> v)
|
||||
{
|
||||
b << (uint32)v.size();
|
||||
for (typename std::vector<T>::iterator i = v.begin(); i != v.end(); i++)
|
||||
{
|
||||
b << *i;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::vector<T> &v)
|
||||
{
|
||||
uint32 vsize;
|
||||
b >> vsize;
|
||||
v.clear();
|
||||
while(vsize--)
|
||||
{
|
||||
T t;
|
||||
b >> t;
|
||||
v.push_back(t);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T> ByteBuffer &operator<<(ByteBuffer &b, std::list<T> v)
|
||||
{
|
||||
b << (uint32)v.size();
|
||||
for (typename std::list<T>::iterator i = v.begin(); i != v.end(); i++)
|
||||
{
|
||||
b << *i;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename T> ByteBuffer &operator>>(ByteBuffer &b, std::list<T> &v)
|
||||
{
|
||||
uint32 vsize;
|
||||
b >> vsize;
|
||||
v.clear();
|
||||
while(vsize--)
|
||||
{
|
||||
T t;
|
||||
b >> t;
|
||||
v.push_back(t);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename K, typename V> ByteBuffer &operator<<(ByteBuffer &b, std::map<K, V> &m)
|
||||
{
|
||||
b << (uint32)m.size();
|
||||
for (typename std::map<K, V>::iterator i = m.begin(); i != m.end(); i++)
|
||||
{
|
||||
b << i->first << i->second;
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
template <typename K, typename V> ByteBuffer &operator>>(ByteBuffer &b, std::map<K, V> &m)
|
||||
{
|
||||
uint32 msize;
|
||||
b >> msize;
|
||||
m.clear();
|
||||
while(msize--)
|
||||
{
|
||||
K k;
|
||||
V v;
|
||||
b >> k >> v;
|
||||
m.insert(make_pair(k, v));
|
||||
}
|
||||
return b;
|
||||
}
|
||||
#endif
|
||||
40
src/shared/Common.cpp
Normal file
40
src/shared/Common.cpp
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
char const* localeNames[MAX_LOCALE] = {
|
||||
"enUS",
|
||||
"koKR",
|
||||
"frFR",
|
||||
"deDE",
|
||||
"zhCN",
|
||||
"zhTW",
|
||||
"esES",
|
||||
"esMX",
|
||||
"ruRU"
|
||||
};
|
||||
|
||||
LocaleConstant GetLocaleByName(std::string name)
|
||||
{
|
||||
for(uint32 i = 0; i < MAX_LOCALE; ++i)
|
||||
if(name==localeNames[i])
|
||||
return LocaleConstant(i);
|
||||
|
||||
return LOCALE_enUS; // including enGB case
|
||||
}
|
||||
203
src/shared/Common.h
Normal file
203
src/shared/Common.h
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOSSERVER_COMMON_H
|
||||
#define MANGOSSERVER_COMMON_H
|
||||
|
||||
// config.h needs to be included 1st
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#ifdef PACKAGE
|
||||
#undef PACKAGE
|
||||
#endif //PACKAGE
|
||||
#ifdef PACKAGE_BUGREPORT
|
||||
#undef PACKAGE_BUGREPORT
|
||||
#endif //PACKAGE_BUGREPORT
|
||||
#ifdef PACKAGE_NAME
|
||||
#undef PACKAGE_NAME
|
||||
#endif //PACKAGE_NAME
|
||||
#ifdef PACKAGE_STRING
|
||||
#undef PACKAGE_STRING
|
||||
#endif //PACKAGE_STRING
|
||||
#ifdef PACKAGE_TARNAME
|
||||
#undef PACKAGE_TARNAME
|
||||
#endif //PACKAGE_TARNAME
|
||||
#ifdef PACKAGE_VERSION
|
||||
#undef PACKAGE_VERSION
|
||||
#endif //PACKAGE_VERSION
|
||||
#ifdef VERSION
|
||||
#undef VERSION
|
||||
#endif //VERSION
|
||||
# include "config.h"
|
||||
#undef PACKAGE
|
||||
#undef PACKAGE_BUGREPORT
|
||||
#undef PACKAGE_NAME
|
||||
#undef PACKAGE_STRING
|
||||
#undef PACKAGE_TARNAME
|
||||
#undef PACKAGE_VERSION
|
||||
#undef VERSION
|
||||
#endif //HAVE_CONFIG_H
|
||||
|
||||
#include "Platform/Define.h"
|
||||
|
||||
#if COMPILER == COMPILER_MICROSOFT
|
||||
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
#ifndef __SHOW_STUPID_WARNINGS__
|
||||
|
||||
#pragma warning(disable:4244)
|
||||
|
||||
#pragma warning(disable:4267)
|
||||
|
||||
#pragma warning(disable:4800)
|
||||
|
||||
#pragma warning(disable:4018)
|
||||
|
||||
#pragma warning(disable:4311)
|
||||
|
||||
#pragma warning(disable:4305)
|
||||
|
||||
#pragma warning(disable:4005)
|
||||
#endif // __SHOW_STUPID_WARNINGS__
|
||||
#endif // __GNUC__
|
||||
|
||||
// must be the first thing to include for it to work
|
||||
#include "MemoryLeaks.h"
|
||||
|
||||
#include "Utilities/HashMap.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
#define STRCASECMP stricmp
|
||||
#else
|
||||
#define STRCASECMP strcasecmp
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <zthread/FastMutex.h>
|
||||
#include <zthread/LockedQueue.h>
|
||||
#include <zthread/Runnable.h>
|
||||
#include <zthread/Thread.h>
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
# define FD_SETSIZE 4096
|
||||
# include <ace/config-all.h>
|
||||
// XP winver - needed to compile with standard leak check in MemoryLeaks.h
|
||||
// uncomment later if needed
|
||||
//#define _WIN32_WINNT 0x0501
|
||||
# include <ws2tcpip.h>
|
||||
//#undef WIN32_WINNT
|
||||
#else
|
||||
# include <sys/types.h>
|
||||
# include <sys/ioctl.h>
|
||||
# include <sys/socket.h>
|
||||
# include <netinet/in.h>
|
||||
# include <unistd.h>
|
||||
# include <netdb.h>
|
||||
#endif
|
||||
|
||||
#if COMPILER == COMPILER_MICROSOFT
|
||||
|
||||
#include <float.h>
|
||||
|
||||
#define I64FMT "%016I64X"
|
||||
#define I64FMTD "%I64u"
|
||||
#define SI64FMTD "%I64d"
|
||||
#define snprintf _snprintf
|
||||
#define atoll __atoi64
|
||||
#define vsnprintf _vsnprintf
|
||||
#define strdup _strdup
|
||||
#define finite(X) _finite(X)
|
||||
|
||||
#else
|
||||
|
||||
#define stricmp strcasecmp
|
||||
#define strnicmp strncasecmp
|
||||
#define I64FMT "%016llX"
|
||||
#define I64FMTD "%llu"
|
||||
#define SI64FMTD "%lld"
|
||||
#endif
|
||||
|
||||
inline float finiteAlways(float f) { return finite(f) ? f : 0.0f; }
|
||||
|
||||
#define atol(a) strtoul( a, NULL, 10)
|
||||
|
||||
#define STRINGIZE(a) #a
|
||||
|
||||
enum TimeConstants
|
||||
{
|
||||
MINUTE = 60,
|
||||
HOUR = MINUTE*60,
|
||||
DAY = HOUR*24,
|
||||
MONTH = DAY*30
|
||||
};
|
||||
|
||||
enum AccountTypes
|
||||
{
|
||||
SEC_PLAYER = 0,
|
||||
SEC_MODERATOR = 1,
|
||||
SEC_GAMEMASTER = 2,
|
||||
SEC_ADMINISTRATOR = 3
|
||||
};
|
||||
|
||||
enum LocaleConstant
|
||||
{
|
||||
LOCALE_enUS = 0,
|
||||
LOCALE_koKR = 1,
|
||||
LOCALE_frFR = 2,
|
||||
LOCALE_deDE = 3,
|
||||
LOCALE_zhCN = 4,
|
||||
LOCALE_zhTW = 5,
|
||||
LOCALE_esES = 6,
|
||||
LOCALE_esMX = 7,
|
||||
LOCALE_ruRU = 8
|
||||
};
|
||||
|
||||
#define MAX_LOCALE 9
|
||||
|
||||
extern char const* localeNames[MAX_LOCALE];
|
||||
|
||||
LocaleConstant GetLocaleByName(std::string name);
|
||||
|
||||
// we always use stdlibc++ std::max/std::min, undefine some not C++ standard defines (Win API and some pother platforms)
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
#endif
|
||||
174
src/shared/Config/Config.cpp
Normal file
174
src/shared/Config/Config.cpp
Normal file
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ConfigEnv.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1(Config);
|
||||
|
||||
Config::Config() : mIgnoreCase(true), mConf(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Config::~Config()
|
||||
{
|
||||
delete mConf;
|
||||
}
|
||||
|
||||
|
||||
bool Config::SetSource(const char *file, bool ignorecase)
|
||||
{
|
||||
mIgnoreCase = ignorecase;
|
||||
mFilename = file;
|
||||
|
||||
return Reload();
|
||||
}
|
||||
|
||||
bool Config::Reload()
|
||||
{
|
||||
delete mConf;
|
||||
|
||||
mConf = new DOTCONFDocument(mIgnoreCase ?
|
||||
DOTCONFDocument::CASEINSENSETIVE :
|
||||
DOTCONFDocument::CASESENSETIVE);
|
||||
|
||||
if (mConf->setContent(mFilename.c_str()) == -1)
|
||||
{
|
||||
delete mConf;
|
||||
mConf = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Config::GetString(const char* name, std::string *value)
|
||||
{
|
||||
if(!mConf)
|
||||
return false;
|
||||
|
||||
DOTCONFDocumentNode const *node = mConf->findNode(name);
|
||||
if(!node || !node->getValue())
|
||||
return false;
|
||||
|
||||
*value = node->getValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Config::GetString(const char* name, char const **value)
|
||||
{
|
||||
if(!mConf)
|
||||
return false;
|
||||
|
||||
DOTCONFDocumentNode const *node = mConf->findNode(name);
|
||||
if(!node || !node->getValue())
|
||||
return false;
|
||||
|
||||
*value = node->getValue();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string Config::GetStringDefault(const char* name, const char* def)
|
||||
{
|
||||
if(!mConf)
|
||||
return std::string(def);
|
||||
|
||||
DOTCONFDocumentNode const *node = mConf->findNode(name);
|
||||
if(!node || !node->getValue())
|
||||
return std::string(def);
|
||||
|
||||
return std::string(node->getValue());
|
||||
}
|
||||
|
||||
|
||||
bool Config::GetBool(const char* name, bool *value)
|
||||
{
|
||||
if(!mConf)
|
||||
return false;
|
||||
|
||||
DOTCONFDocumentNode const *node = mConf->findNode(name);
|
||||
if(!node || !node->getValue())
|
||||
return false;
|
||||
|
||||
const char* str = node->getValue();
|
||||
if(strcmp(str, "true") == 0 || strcmp(str, "TRUE") == 0 ||
|
||||
strcmp(str, "yes") == 0 || strcmp(str, "YES") == 0 ||
|
||||
strcmp(str, "1") == 0)
|
||||
{
|
||||
*value = true;
|
||||
}
|
||||
else
|
||||
*value = false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Config::GetBoolDefault(const char* name, const bool def)
|
||||
{
|
||||
bool val;
|
||||
return GetBool(name, &val) ? val : def;
|
||||
}
|
||||
|
||||
|
||||
bool Config::GetInt(const char* name, int *value)
|
||||
{
|
||||
if(!mConf)
|
||||
return false;
|
||||
|
||||
DOTCONFDocumentNode const *node = mConf->findNode(name);
|
||||
if(!node || !node->getValue())
|
||||
return false;
|
||||
|
||||
*value = atoi(node->getValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Config::GetFloat(const char* name, float *value)
|
||||
{
|
||||
if(!mConf)
|
||||
return false;
|
||||
|
||||
DOTCONFDocumentNode const *node = mConf->findNode(name);
|
||||
if(!node || !node->getValue())
|
||||
return false;
|
||||
|
||||
*value = atof(node->getValue());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
int Config::GetIntDefault(const char* name, const int def)
|
||||
{
|
||||
int val;
|
||||
return GetInt(name, &val) ? val : def;
|
||||
}
|
||||
|
||||
|
||||
float Config::GetFloatDefault(const char* name, const float def)
|
||||
{
|
||||
float val;
|
||||
return (GetFloat(name, &val) ? val : def);
|
||||
}
|
||||
58
src/shared/Config/Config.h
Normal file
58
src/shared/Config/Config.h
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#include <Policies/Singleton.h>
|
||||
#include "Platform/Define.h"
|
||||
|
||||
class DOTCONFDocument;
|
||||
|
||||
class MANGOS_DLL_SPEC Config
|
||||
{
|
||||
public:
|
||||
Config();
|
||||
~Config();
|
||||
|
||||
bool SetSource(const char *file, bool ignorecase = true);
|
||||
bool Reload();
|
||||
|
||||
bool GetString(const char* name, std::string *value);
|
||||
bool GetString(const char* name, char const **value);
|
||||
std::string GetStringDefault(const char* name, const char* def);
|
||||
|
||||
bool GetBool(const char* name, bool *value);
|
||||
bool GetBoolDefault(const char* name, const bool def = false);
|
||||
|
||||
bool GetInt(const char* name, int *value);
|
||||
int GetIntDefault(const char* name, const int def);
|
||||
|
||||
bool GetFloat(const char* name, float *value);
|
||||
float GetFloatDefault(const char* name, const float def);
|
||||
|
||||
std::string GetFilename() const { return mFilename; }
|
||||
private:
|
||||
std::string mFilename;
|
||||
bool mIgnoreCase;
|
||||
DOTCONFDocument *mConf;
|
||||
};
|
||||
|
||||
#define sConfig MaNGOS::Singleton<Config>::Instance()
|
||||
|
||||
#endif
|
||||
28
src/shared/Config/ConfigEnv.h
Normal file
28
src/shared/Config/ConfigEnv.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if !defined(CONFIGENVIRONMENT_H)
|
||||
|
||||
#define CONFIGENVIRONMENT_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "dotconfpp/dotconfpp.h"
|
||||
#include "Config.h"
|
||||
#include "Log.h"
|
||||
|
||||
#endif
|
||||
137
src/shared/Config/ConfigLibrary.vcproj
Normal file
137
src/shared/Config/ConfigLibrary.vcproj
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
<?xml version="1.0" encoding="Windows-1252"?>
|
||||
<VisualStudioProject
|
||||
ProjectType="Visual C++"
|
||||
Version="7.10"
|
||||
Name="ConfigLibrary"
|
||||
ProjectGUID="{C849D54F-32A6-4025-95BE-E64D1CF0686E}"
|
||||
Keyword="Win32Proj">
|
||||
<Platforms>
|
||||
<Platform
|
||||
Name="Win32"/>
|
||||
</Platforms>
|
||||
<Configurations>
|
||||
<Configuration
|
||||
Name="Debug|Win32"
|
||||
OutputDirectory="Debug"
|
||||
IntermediateDirectory="Debug"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
Optimization="0"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
|
||||
MinimalRebuild="TRUE"
|
||||
BasicRuntimeChecks="3"
|
||||
RuntimeLibrary="1"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="4"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/ConfigLibrary.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
<Configuration
|
||||
Name="Release|Win32"
|
||||
OutputDirectory="Release"
|
||||
IntermediateDirectory="Release"
|
||||
ConfigurationType="4"
|
||||
CharacterSet="2">
|
||||
<Tool
|
||||
Name="VCCLCompilerTool"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
|
||||
RuntimeLibrary="0"
|
||||
UsePrecompiledHeader="0"
|
||||
WarningLevel="3"
|
||||
Detect64BitPortabilityProblems="TRUE"
|
||||
DebugInformationFormat="3"/>
|
||||
<Tool
|
||||
Name="VCCustomBuildTool"/>
|
||||
<Tool
|
||||
Name="VCLibrarianTool"
|
||||
OutputFile="$(OutDir)/ConfigLibrary.lib"/>
|
||||
<Tool
|
||||
Name="VCMIDLTool"/>
|
||||
<Tool
|
||||
Name="VCPostBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreBuildEventTool"/>
|
||||
<Tool
|
||||
Name="VCPreLinkEventTool"/>
|
||||
<Tool
|
||||
Name="VCResourceCompilerTool"/>
|
||||
<Tool
|
||||
Name="VCWebServiceProxyGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCXMLDataGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCManagedWrapperGeneratorTool"/>
|
||||
<Tool
|
||||
Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
|
||||
</Configuration>
|
||||
</Configurations>
|
||||
<References>
|
||||
</References>
|
||||
<Files>
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
|
||||
UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
|
||||
<File
|
||||
RelativePath=".\Config.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dotconfpp\dotconfpp.cpp">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dotconfpp\mempool.cpp">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Header Files"
|
||||
Filter="h;hpp;hxx;hm;inl;inc;xsd"
|
||||
UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
|
||||
<File
|
||||
RelativePath=".\Config.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\ConfigEnv.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dotconfpp\dotconfpp.h">
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\dotconfpp\mempool.h">
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Resource Files"
|
||||
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
|
||||
UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
|
||||
</Filter>
|
||||
</Files>
|
||||
<Globals>
|
||||
</Globals>
|
||||
</VisualStudioProject>
|
||||
40
src/shared/Config/Makefile.am
Normal file
40
src/shared/Config/Makefile.am
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
# Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
## Sub-directories to parse
|
||||
|
||||
## CPP flags for includes, defines, etc.
|
||||
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite
|
||||
|
||||
## Build MaNGOS shared library and its parts as convenience library.
|
||||
# All libraries will be convenience libraries. Might be changed to shared
|
||||
# later.
|
||||
noinst_LIBRARIES = libmangosconfig.a
|
||||
|
||||
libmangosconfig_a_SOURCES = \
|
||||
dotconfpp/dotconfpp.cpp \
|
||||
dotconfpp/dotconfpp.h \
|
||||
dotconfpp/mempool.cpp \
|
||||
dotconfpp/mempool.h \
|
||||
Config.cpp \
|
||||
Config.h \
|
||||
ConfigEnv.h
|
||||
|
||||
# VC++ project workspace for dotconfpp
|
||||
EXTRA_DIST = \
|
||||
ConfigLibrary.vcproj
|
||||
583
src/shared/Config/dotconfpp/dotconfpp.cpp
Normal file
583
src/shared/Config/dotconfpp/dotconfpp.cpp
Normal file
|
|
@ -0,0 +1,583 @@
|
|||
|
||||
#include "Common.h"
|
||||
|
||||
#include "dotconfpp.h"
|
||||
|
||||
#if !defined(R_OK)
|
||||
#define R_OK 04
|
||||
#endif
|
||||
|
||||
DOTCONFDocumentNode::DOTCONFDocumentNode():previousNode(NULL), nextNode(NULL), parentNode(NULL), childNode(NULL),
|
||||
values(NULL), valuesCount(0),
|
||||
name(NULL), lineNum(0), fileName(NULL), closed(true)
|
||||
{
|
||||
}
|
||||
|
||||
DOTCONFDocumentNode::~DOTCONFDocumentNode()
|
||||
{
|
||||
free(name);
|
||||
if(values != NULL){
|
||||
for(int i = 0 ; i < valuesCount; i++){
|
||||
free(values[i]);
|
||||
}
|
||||
free(values);
|
||||
}
|
||||
}
|
||||
|
||||
void DOTCONFDocumentNode::pushValue(char * _value)
|
||||
{
|
||||
++valuesCount;
|
||||
values = (char**)realloc(values, valuesCount*sizeof(char*));
|
||||
values[valuesCount-1] = strdup(_value);
|
||||
}
|
||||
|
||||
const char* DOTCONFDocumentNode::getValue(int index) const
|
||||
{
|
||||
if(index >= valuesCount){
|
||||
return NULL;
|
||||
}
|
||||
return values[index];
|
||||
}
|
||||
|
||||
DOTCONFDocument::DOTCONFDocument(DOTCONFDocument::CaseSensitive caseSensitivity):
|
||||
mempool(NULL),
|
||||
curParent(NULL), curPrev(NULL), curLine(0), file(NULL), fileName(NULL)
|
||||
{
|
||||
if(caseSensitivity == CASESENSETIVE){
|
||||
cmp_func = strcmp;
|
||||
} else {
|
||||
cmp_func = strcasecmp;
|
||||
}
|
||||
|
||||
mempool = new AsyncDNSMemPool(1024);
|
||||
mempool->initialize();
|
||||
}
|
||||
|
||||
DOTCONFDocument::~DOTCONFDocument()
|
||||
{
|
||||
for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i != nodeTree.end(); i++){
|
||||
delete(*i);
|
||||
}
|
||||
for(std::list<char*>::iterator i = requiredOptions.begin(); i != requiredOptions.end(); i++){
|
||||
free(*i);
|
||||
}
|
||||
for(std::list<char*>::iterator i = processedFiles.begin(); i != processedFiles.end(); i++){
|
||||
free(*i);
|
||||
}
|
||||
free(fileName);
|
||||
delete mempool;
|
||||
}
|
||||
|
||||
int DOTCONFDocument::cleanupLine(char * line)
|
||||
{
|
||||
char * start = line;
|
||||
char * bg = line;
|
||||
bool multiline = false;
|
||||
bool concat = false;
|
||||
char * word = NULL;
|
||||
|
||||
if(!words.empty() && quoted)
|
||||
concat = true;
|
||||
|
||||
while(*line){
|
||||
if((*line == '#' || *line == ';') && !quoted){
|
||||
*bg = 0;
|
||||
if(strlen(start)){
|
||||
|
||||
if(concat){
|
||||
word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
|
||||
strcpy(word, words.back());
|
||||
strcat(word, start);
|
||||
words.pop_back();
|
||||
concat = false;
|
||||
} else {
|
||||
word = mempool->strdup(start);
|
||||
}
|
||||
words.push_back(word);
|
||||
}
|
||||
break;
|
||||
}
|
||||
if(*line == '=' && !quoted){
|
||||
*line = ' ';continue;
|
||||
}
|
||||
|
||||
// Allowing \" in there causes problems with directory paths
|
||||
// like "C:\MaNGOS\"
|
||||
//if(*line == '\\' && (*(line+1) == '"' || *(line+1) == '\'')){
|
||||
if(*line == '\\' && (*(line+1) == '\'')) {
|
||||
*bg++ = *(line+1);
|
||||
line+=2; continue;
|
||||
}
|
||||
if(*line == '\\' && *(line+1) == 'n'){
|
||||
*bg++ = '\n';
|
||||
line+=2; continue;
|
||||
}
|
||||
if(*line == '\\' && *(line+1) == 'r'){
|
||||
*bg++ = '\r';
|
||||
line+=2; continue;
|
||||
}
|
||||
if(*line == '\\' && (*(line+1) == '\n' || *(line+1) == '\r')){
|
||||
*bg = 0;
|
||||
if(strlen(start)){
|
||||
|
||||
if(concat){
|
||||
word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
|
||||
strcpy(word, words.back());
|
||||
strcat(word, start);
|
||||
words.pop_back();
|
||||
concat = false;
|
||||
} else {
|
||||
word = mempool->strdup(start);
|
||||
}
|
||||
words.push_back(word);
|
||||
}
|
||||
multiline = true;
|
||||
break;
|
||||
}
|
||||
if(*line == '"' || *line == '\''){
|
||||
quoted = !quoted;
|
||||
++line; continue;
|
||||
}
|
||||
if(isspace(*line) && !quoted){
|
||||
*bg++ = 0;
|
||||
if(strlen(start)){
|
||||
|
||||
if(concat){
|
||||
word = (char*)mempool->alloc(strlen(words.back())+strlen(start)+1);
|
||||
strcpy(word, words.back());
|
||||
strcat(word, start);
|
||||
words.pop_back();
|
||||
concat = false;
|
||||
} else {
|
||||
word = mempool->strdup(start);
|
||||
}
|
||||
words.push_back(word);
|
||||
}
|
||||
start = bg;
|
||||
while(isspace(*++line)) {}
|
||||
|
||||
continue;
|
||||
}
|
||||
*bg++ = *line++;
|
||||
}
|
||||
|
||||
if(quoted && !multiline){
|
||||
error(curLine, fileName, "unterminated quote");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return multiline?1:0;
|
||||
}
|
||||
|
||||
int DOTCONFDocument::parseLine()
|
||||
{
|
||||
char * word = NULL;
|
||||
char * nodeName = NULL;
|
||||
char * nodeValue = NULL;
|
||||
DOTCONFDocumentNode * tagNode = NULL;
|
||||
bool newNode = false;
|
||||
|
||||
for(std::list<char*>::iterator i = words.begin(); i != words.end(); i++) {
|
||||
word = *i;
|
||||
|
||||
if(*word == '<'){
|
||||
newNode = true;
|
||||
}
|
||||
|
||||
if(newNode){
|
||||
nodeValue = NULL;
|
||||
nodeName = NULL;
|
||||
newNode = false;
|
||||
}
|
||||
|
||||
size_t wordLen = strlen(word);
|
||||
if(word[wordLen-1] == '>'){
|
||||
word[wordLen-1] = 0;
|
||||
newNode = true;
|
||||
}
|
||||
|
||||
if(nodeName == NULL){
|
||||
nodeName = word;
|
||||
bool closed = true;
|
||||
if(*nodeName == '<'){
|
||||
if(*(nodeName+1) != '/'){
|
||||
++nodeName;
|
||||
closed = false;
|
||||
} else {
|
||||
nodeName+=2;
|
||||
std::list<DOTCONFDocumentNode*>::reverse_iterator itr=nodeTree.rbegin();
|
||||
for(; itr!=nodeTree.rend(); ++itr){
|
||||
if(!cmp_func(nodeName, (*itr)->name) && !(*itr)->closed){
|
||||
(*itr)->closed = true;
|
||||
curParent = (*itr)->parentNode;
|
||||
curPrev = *itr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(itr==nodeTree.rend()){
|
||||
error(curLine, fileName, "not matched closing tag </%s>", nodeName);
|
||||
return -1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
tagNode = new DOTCONFDocumentNode;
|
||||
tagNode->name = strdup(nodeName);
|
||||
tagNode->document = this;
|
||||
tagNode->fileName = processedFiles.back();
|
||||
tagNode->lineNum = curLine;
|
||||
tagNode->closed = closed;
|
||||
if(!nodeTree.empty()){
|
||||
DOTCONFDocumentNode * prev = nodeTree.back();
|
||||
if(prev->closed){
|
||||
|
||||
curPrev->nextNode = tagNode;
|
||||
tagNode->previousNode = curPrev;
|
||||
tagNode->parentNode = curParent;
|
||||
|
||||
} else {
|
||||
prev->childNode = tagNode;
|
||||
tagNode->parentNode = prev;
|
||||
curParent = prev;
|
||||
}
|
||||
}
|
||||
nodeTree.push_back(tagNode);
|
||||
curPrev = tagNode;
|
||||
} else {
|
||||
nodeValue = word;
|
||||
tagNode->pushValue(nodeValue);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
int DOTCONFDocument::parseFile(DOTCONFDocumentNode * _parent)
|
||||
{
|
||||
char str[512];
|
||||
int ret = 0;
|
||||
curLine = 0;
|
||||
curParent = _parent;
|
||||
|
||||
quoted = false;
|
||||
size_t slen = 0;
|
||||
|
||||
while(fgets(str, 511, file)){
|
||||
++curLine;
|
||||
slen = strlen(str);
|
||||
if( slen >= 510 ){
|
||||
error(curLine, fileName, "warning: line too long");
|
||||
}
|
||||
if(str[slen-1] != '\n'){
|
||||
str[slen] = '\n';
|
||||
str[slen+1] = 0;
|
||||
}
|
||||
if((ret = cleanupLine(str)) == -1){
|
||||
break;
|
||||
}
|
||||
if(ret == 0){
|
||||
if(!words.empty()){
|
||||
ret = parseLine();
|
||||
mempool->free();
|
||||
words.clear();
|
||||
if(ret == -1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DOTCONFDocument::checkConfig(const std::list<DOTCONFDocumentNode*>::iterator & from)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
DOTCONFDocumentNode * tagNode = NULL;
|
||||
int vi = 0;
|
||||
for(std::list<DOTCONFDocumentNode*>::iterator i = from; i != nodeTree.end(); i++){
|
||||
tagNode = *i;
|
||||
if(!tagNode->closed){
|
||||
error(tagNode->lineNum, tagNode->fileName, "unclosed tag %s", tagNode->name);
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
vi = 0;
|
||||
while( vi < tagNode->valuesCount ){
|
||||
|
||||
if(strstr(tagNode->values[vi], "${") && strchr(tagNode->values[vi], '}') ){
|
||||
ret = macroSubstitute(tagNode, vi );
|
||||
mempool->free();
|
||||
if(ret == -1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
++vi;
|
||||
}
|
||||
if(ret == -1){
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DOTCONFDocument::setContent(const char * _fileName)
|
||||
{
|
||||
int ret = 0;
|
||||
char realpathBuf[PATH_MAX];
|
||||
|
||||
if(realpath(_fileName, realpathBuf) == NULL){
|
||||
error(0, NULL, "realpath(%s) failed: %s", _fileName, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileName = strdup(realpathBuf);
|
||||
|
||||
processedFiles.push_back(strdup(realpathBuf));
|
||||
|
||||
if(( file = fopen(fileName, "r")) == NULL){
|
||||
error(0, NULL, "failed to open file '%s': %s", fileName, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ret = parseFile();
|
||||
|
||||
(void) fclose(file);
|
||||
|
||||
if(!ret){
|
||||
|
||||
if( (ret = checkConfig(nodeTree.begin())) == -1){
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::list<DOTCONFDocumentNode*>::iterator from;
|
||||
DOTCONFDocumentNode * tagNode = NULL;
|
||||
int vi = 0;
|
||||
for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i!=nodeTree.end(); i++){
|
||||
tagNode = *i;
|
||||
if(!cmp_func("DOTCONFPPIncludeFile", tagNode->name)){
|
||||
vi = 0;
|
||||
while( vi < tagNode->valuesCount ){
|
||||
if(access(tagNode->values[vi], R_OK) == -1){
|
||||
error(tagNode->lineNum, tagNode->fileName, "%s: %s", tagNode->values[vi], strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if(realpath(tagNode->values[vi], realpathBuf) == NULL){
|
||||
error(tagNode->lineNum, tagNode->fileName, "realpath(%s) failed: %s", tagNode->values[vi], strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool processed = false;
|
||||
for(std::list<char*>::const_iterator itInode = processedFiles.begin(); itInode != processedFiles.end(); itInode++){
|
||||
if(!strcmp(*itInode, realpathBuf)){
|
||||
processed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(processed){
|
||||
break;
|
||||
}
|
||||
|
||||
processedFiles.push_back(strdup(realpathBuf));
|
||||
|
||||
file = fopen(tagNode->values[vi], "r");
|
||||
if(file == NULL){
|
||||
error(tagNode->lineNum, fileName, "failed to open file '%s': %s", tagNode->values[vi], strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fileName = strdup(realpathBuf);
|
||||
from = nodeTree.end(); --from;
|
||||
|
||||
ret = parseFile();
|
||||
(void) fclose(file);
|
||||
if(ret == -1)
|
||||
return -1;
|
||||
if(checkConfig(++from) == -1){
|
||||
return -1;
|
||||
}
|
||||
++vi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(!requiredOptions.empty())
|
||||
ret = checkRequiredOptions();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int DOTCONFDocument::checkRequiredOptions()
|
||||
{
|
||||
for(std::list<char*>::const_iterator ci = requiredOptions.begin(); ci != requiredOptions.end(); ci++){
|
||||
bool matched = false;
|
||||
for(std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin(); i!=nodeTree.end(); i++){
|
||||
if(!cmp_func((*i)->name, *ci)){
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!matched){
|
||||
error(0, NULL, "required option '%s' not specified", *ci);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DOTCONFDocument::error(int lineNum, const char * fileName_, const char * fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
|
||||
size_t len = (lineNum!=0?strlen(fileName_):0) + strlen(fmt) + 50;
|
||||
char * buf = (char*)mempool->alloc(len);
|
||||
|
||||
if(lineNum)
|
||||
(void) snprintf(buf, len, "DOTCONF++: file '%s', line %d: %s\n", fileName_, lineNum, fmt);
|
||||
else
|
||||
(void) snprintf(buf, len, "DOTCONF++: %s\n", fmt);
|
||||
|
||||
(void) vfprintf(stderr, buf, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
char * DOTCONFDocument::getSubstitution(char * macro, int lineNum)
|
||||
{
|
||||
char * buf = NULL;
|
||||
char * variable = macro+2;
|
||||
|
||||
char * endBr = strchr(macro, '}');
|
||||
|
||||
if(!endBr){
|
||||
error(lineNum, fileName, "unterminated '{'");
|
||||
return NULL;
|
||||
}
|
||||
*endBr = 0;
|
||||
|
||||
char * defaultValue = strchr(variable, ':');
|
||||
|
||||
if(defaultValue){
|
||||
*defaultValue++ = 0;
|
||||
if(*defaultValue != '-'){
|
||||
error(lineNum, fileName, "incorrect macro substitution syntax");
|
||||
return NULL;
|
||||
}
|
||||
++defaultValue;
|
||||
if(*defaultValue == '"' || *defaultValue == '\''){
|
||||
++defaultValue;
|
||||
defaultValue[strlen(defaultValue)-1] = 0;
|
||||
}
|
||||
} else {
|
||||
defaultValue = NULL;
|
||||
}
|
||||
|
||||
char * subs = getenv(variable);
|
||||
if( subs ){
|
||||
buf = mempool->strdup(subs);
|
||||
} else {
|
||||
std::list<DOTCONFDocumentNode*>::iterator i = nodeTree.begin();
|
||||
DOTCONFDocumentNode * tagNode = NULL;
|
||||
for(; i!=nodeTree.end(); i++){
|
||||
tagNode = *i;
|
||||
if(!cmp_func(tagNode->name, variable)){
|
||||
if(tagNode->valuesCount != 0){
|
||||
buf = mempool->strdup(tagNode->values[0]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( i == nodeTree.end() ){
|
||||
if( defaultValue ){
|
||||
buf = mempool->strdup(defaultValue);
|
||||
} else {
|
||||
error(lineNum, fileName, "substitution not found and default value not given");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
int DOTCONFDocument::macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex)
|
||||
{
|
||||
int ret = 0;
|
||||
char * macro = tagNode->values[valueIndex];
|
||||
size_t valueLen = strlen(tagNode->values[valueIndex])+1;
|
||||
char * value = (char*)mempool->alloc(valueLen);
|
||||
char * v = value;
|
||||
char * subs = NULL;
|
||||
|
||||
while(*macro){
|
||||
if(*macro == '$' && *(macro+1) == '{'){
|
||||
char * m = strchr(macro, '}');
|
||||
subs = getSubstitution(macro, tagNode->lineNum);
|
||||
if(subs == NULL){
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
macro = m + 1;
|
||||
*v = 0;
|
||||
v = (char*)mempool->alloc(strlen(value)+strlen(subs)+valueLen);
|
||||
strcpy(v, value);
|
||||
value = strcat(v, subs);
|
||||
v = value + strlen(value);
|
||||
continue;
|
||||
}
|
||||
*v++ = *macro++;
|
||||
}
|
||||
*v = 0;
|
||||
|
||||
free(tagNode->values[valueIndex]);
|
||||
tagNode->values[valueIndex] = strdup(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const DOTCONFDocumentNode * DOTCONFDocument::getFirstNode() const
|
||||
{
|
||||
if ( !nodeTree.empty() ) {
|
||||
return *nodeTree.begin();
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const DOTCONFDocumentNode * DOTCONFDocument::findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode, const DOTCONFDocumentNode * startNode) const
|
||||
{
|
||||
|
||||
|
||||
std::list<DOTCONFDocumentNode*>::const_iterator i = nodeTree.begin();
|
||||
|
||||
if(startNode == NULL)
|
||||
startNode = parentNode;
|
||||
|
||||
if(startNode != NULL){
|
||||
while( i != nodeTree.end() && (*i) != startNode ){
|
||||
++i;
|
||||
}
|
||||
if( i != nodeTree.end() ) ++i;
|
||||
}
|
||||
|
||||
for(; i!=nodeTree.end(); i++){
|
||||
|
||||
if((*i)->parentNode != parentNode){
|
||||
continue;
|
||||
}
|
||||
if(!cmp_func(nodeName, (*i)->name)){
|
||||
return *i;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void DOTCONFDocument::setRequiredOptionNames(const char ** requiredOptionNames)
|
||||
{
|
||||
while(*requiredOptionNames){
|
||||
requiredOptions.push_back(strdup( *requiredOptionNames ));
|
||||
++requiredOptionNames;
|
||||
}
|
||||
}
|
||||
110
src/shared/Config/dotconfpp/dotconfpp.h
Normal file
110
src/shared/Config/dotconfpp/dotconfpp.h
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
|
||||
|
||||
|
||||
#ifndef DOTCONFPP_H
|
||||
#define DOTCONFPP_H
|
||||
|
||||
#include <list>
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define PATH_MAX _MAX_PATH
|
||||
#define snprintf _snprintf
|
||||
#define strcasecmp stricmp
|
||||
#define realpath(path,resolved_path) _fullpath(resolved_path, path, _MAX_PATH)
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <strings.h>
|
||||
#endif
|
||||
|
||||
#include "mempool.h"
|
||||
|
||||
class DOTCONFDocument;
|
||||
|
||||
class DOTCONFDocumentNode
|
||||
{
|
||||
friend class DOTCONFDocument;
|
||||
private:
|
||||
DOTCONFDocumentNode * previousNode;
|
||||
DOTCONFDocumentNode * nextNode;
|
||||
DOTCONFDocumentNode * parentNode;
|
||||
DOTCONFDocumentNode * childNode;
|
||||
char ** values;
|
||||
int valuesCount;
|
||||
char * name;
|
||||
const DOTCONFDocument * document;
|
||||
int lineNum;
|
||||
char * fileName;
|
||||
bool closed;
|
||||
|
||||
void pushValue(char * _value);
|
||||
|
||||
public:
|
||||
DOTCONFDocumentNode();
|
||||
~DOTCONFDocumentNode();
|
||||
|
||||
const char * getConfigurationFileName()const { return fileName; }
|
||||
int getConfigurationLineNumber() const { return lineNum; }
|
||||
|
||||
const DOTCONFDocumentNode * getNextNode() const { return nextNode; }
|
||||
const DOTCONFDocumentNode * getPreviuosNode() const { return previousNode; }
|
||||
const DOTCONFDocumentNode * getParentNode() const { return parentNode; }
|
||||
const DOTCONFDocumentNode * getChildNode() const { return childNode; }
|
||||
const char* getValue(int index = 0) const;
|
||||
const char * getName() const { return name; }
|
||||
const DOTCONFDocument * getDocument() const { return document; }
|
||||
};
|
||||
|
||||
class DOTCONFDocument
|
||||
{
|
||||
public:
|
||||
enum CaseSensitive { CASESENSETIVE, CASEINSENSETIVE };
|
||||
protected:
|
||||
AsyncDNSMemPool * mempool;
|
||||
private:
|
||||
DOTCONFDocumentNode * curParent;
|
||||
DOTCONFDocumentNode * curPrev;
|
||||
int curLine;
|
||||
bool quoted;
|
||||
std::list<DOTCONFDocumentNode*> nodeTree;
|
||||
std::list<char*> requiredOptions;
|
||||
std::list<char*> processedFiles;
|
||||
FILE * file;
|
||||
char * fileName;
|
||||
std::list<char*> words;
|
||||
int (*cmp_func)(const char *, const char *);
|
||||
|
||||
int checkRequiredOptions();
|
||||
int parseLine();
|
||||
int parseFile(DOTCONFDocumentNode * _parent = NULL);
|
||||
int checkConfig(const std::list<DOTCONFDocumentNode*>::iterator & from);
|
||||
int cleanupLine(char * line);
|
||||
char * getSubstitution(char * macro, int lineNum);
|
||||
int macroSubstitute(DOTCONFDocumentNode * tagNode, int valueIndex);
|
||||
|
||||
protected:
|
||||
virtual void error(int lineNum, const char * fileName, const char * fmt, ...) ATTR_PRINTF(4,5);
|
||||
|
||||
public:
|
||||
DOTCONFDocument(CaseSensitive caseSensitivity = CASESENSETIVE);
|
||||
virtual ~DOTCONFDocument();
|
||||
|
||||
int setContent(const char * _fileName);
|
||||
|
||||
void setRequiredOptionNames(const char ** requiredOptionNames);
|
||||
const DOTCONFDocumentNode * getFirstNode() const;
|
||||
const DOTCONFDocumentNode * findNode(const char * nodeName, const DOTCONFDocumentNode * parentNode = NULL, const DOTCONFDocumentNode * startNode = NULL) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
100
src/shared/Config/dotconfpp/mempool.cpp
Normal file
100
src/shared/Config/dotconfpp/mempool.cpp
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
|
||||
|
||||
|
||||
#include "mempool.h"
|
||||
|
||||
AsyncDNSMemPool::PoolChunk::PoolChunk(size_t _size):
|
||||
pool(NULL), pos(0), size(_size)
|
||||
{
|
||||
pool = ::malloc(size);
|
||||
}
|
||||
|
||||
AsyncDNSMemPool::PoolChunk::~PoolChunk()
|
||||
{
|
||||
::free(pool);
|
||||
}
|
||||
|
||||
AsyncDNSMemPool::AsyncDNSMemPool(size_t _defaultSize):
|
||||
chunks(NULL), chunksCount(0), defaultSize(_defaultSize),
|
||||
poolUsage(0), poolUsageCounter(0)
|
||||
{
|
||||
}
|
||||
|
||||
AsyncDNSMemPool::~AsyncDNSMemPool()
|
||||
{
|
||||
for(size_t i = 0; i<chunksCount; i++){
|
||||
delete chunks[i];
|
||||
}
|
||||
::free(chunks);
|
||||
}
|
||||
|
||||
int AsyncDNSMemPool::initialize()
|
||||
{
|
||||
chunksCount = 1;
|
||||
chunks = (PoolChunk**)::malloc(sizeof(PoolChunk*));
|
||||
if(chunks == NULL)
|
||||
return -1;
|
||||
|
||||
chunks[chunksCount-1] = new PoolChunk(defaultSize);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AsyncDNSMemPool::addNewChunk(size_t size)
|
||||
{
|
||||
++chunksCount;
|
||||
chunks = (PoolChunk**)::realloc(chunks, chunksCount*sizeof(PoolChunk*));
|
||||
if(size <= defaultSize)
|
||||
chunks[chunksCount-1] = new PoolChunk(defaultSize);
|
||||
else
|
||||
chunks[chunksCount-1] = new PoolChunk(size);
|
||||
}
|
||||
|
||||
void * AsyncDNSMemPool::alloc(size_t size)
|
||||
{
|
||||
PoolChunk * chunk = NULL;
|
||||
for(size_t i = 0; i<chunksCount; i++){
|
||||
chunk = chunks[i];
|
||||
if((chunk->size - chunk->pos) >= size){
|
||||
chunk->pos += size;
|
||||
return ((char*)chunk->pool) + chunk->pos - size;
|
||||
}
|
||||
}
|
||||
addNewChunk(size);
|
||||
chunks[chunksCount-1]->pos = size;
|
||||
return chunks[chunksCount-1]->pool;
|
||||
}
|
||||
|
||||
void AsyncDNSMemPool::free()
|
||||
{
|
||||
size_t pu = 0;
|
||||
size_t psz = 0;
|
||||
++poolUsageCounter;
|
||||
|
||||
for(size_t i = 0; i<chunksCount; i++){
|
||||
pu += chunks[i]->pos;
|
||||
psz += chunks[i]->size;
|
||||
chunks[i]->pos = 0;
|
||||
}
|
||||
poolUsage=(poolUsage>pu)?poolUsage:pu;
|
||||
|
||||
if(poolUsageCounter >= 10 && chunksCount > 1){
|
||||
psz -= chunks[chunksCount-1]->size;
|
||||
if(poolUsage < psz){
|
||||
--chunksCount;
|
||||
delete chunks[chunksCount];
|
||||
}
|
||||
poolUsage = 0;
|
||||
poolUsageCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void * AsyncDNSMemPool::calloc(size_t size)
|
||||
{
|
||||
return ::memset(this->alloc(size), 0, size);
|
||||
}
|
||||
|
||||
char * AsyncDNSMemPool::strdup(const char *str)
|
||||
{
|
||||
return ::strcpy((char*)this->alloc(strlen(str)+1), str);
|
||||
}
|
||||
46
src/shared/Config/dotconfpp/mempool.h
Normal file
46
src/shared/Config/dotconfpp/mempool.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
|
||||
|
||||
#ifndef ASYNC_DNS_MEMPOOL_H
|
||||
#define ASYNC_DNS_MEMPOOL_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#undef free
|
||||
#undef calloc
|
||||
#undef strdup
|
||||
|
||||
class AsyncDNSMemPool
|
||||
{
|
||||
private:
|
||||
struct PoolChunk {
|
||||
void * pool;
|
||||
size_t pos;
|
||||
size_t size;
|
||||
|
||||
PoolChunk(size_t _size);
|
||||
~PoolChunk();
|
||||
};
|
||||
PoolChunk ** chunks;
|
||||
size_t chunksCount;
|
||||
size_t defaultSize;
|
||||
|
||||
size_t poolUsage;
|
||||
size_t poolUsageCounter;
|
||||
|
||||
void addNewChunk(size_t size);
|
||||
|
||||
public:
|
||||
AsyncDNSMemPool(size_t _defaultSize = 4096);
|
||||
virtual ~AsyncDNSMemPool();
|
||||
|
||||
int initialize();
|
||||
void free();
|
||||
void * alloc(size_t size);
|
||||
void * calloc(size_t size);
|
||||
char * strdup(const char *str);
|
||||
};
|
||||
|
||||
#endif
|
||||
104
src/shared/Database/DBCEnums.h
Normal file
104
src/shared/Database/DBCEnums.h
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DBCENUMS_H
|
||||
#define DBCENUMS_H
|
||||
|
||||
enum AreaTeams
|
||||
{
|
||||
AREATEAM_NONE = 0,
|
||||
AREATEAM_ALLY = 2,
|
||||
AREATEAM_HORDE = 4
|
||||
};
|
||||
|
||||
enum AreaFlags
|
||||
{
|
||||
AREA_FLAG_SNOW = 0x00000001, // snow (only Dun Morogh, Naxxramas, Razorfen Downs and Winterspring)
|
||||
AREA_FLAG_UNK1 = 0x00000002, // unknown, (only Naxxramas and Razorfen Downs)
|
||||
AREA_FLAG_UNK2 = 0x00000004, // Only used on development map
|
||||
AREA_FLAG_SLAVE_CAPITAL = 0x00000008, // slave capital city flag?
|
||||
AREA_FLAG_UNK3 = 0x00000010, // unknown
|
||||
AREA_FLAG_SLAVE_CAPITAL2 = 0x00000020, // slave capital city flag?
|
||||
AREA_FLAG_UNK4 = 0x00000040, // many zones have this flag
|
||||
AREA_FLAG_ARENA = 0x00000080, // arena, both instanced and world arenas
|
||||
AREA_FLAG_CAPITAL = 0x00000100, // main capital city flag
|
||||
AREA_FLAG_CITY = 0x00000200, // only for one zone named "City" (where it located?)
|
||||
AREA_FLAG_OUTLAND = 0x00000400, // outland zones? (only Eye of the Storm not have this flag, but have 0x00004000 flag)
|
||||
AREA_FLAG_SANCTUARY = 0x00000800, // sanctuary area (PvP disabled)
|
||||
AREA_FLAG_NEED_FLY = 0x00001000, // only Netherwing Ledge, Socrethar's Seat, Tempest Keep, The Arcatraz, The Botanica, The Mechanar, Sorrow Wing Point, Dragonspine Ridge, Netherwing Mines, Dragonmaw Base Camp, Dragonmaw Skyway
|
||||
AREA_FLAG_UNUSED1 = 0x00002000, // not used now (no area/zones with this flag set in 2.4.2)
|
||||
AREA_FLAG_OUTLAND2 = 0x00004000, // outland zones? (only Circle of Blood Arena not have this flag, but have 0x00000400 flag)
|
||||
AREA_FLAG_PVP = 0x00008000, // pvp objective area? (Death's Door also has this flag although it's no pvp object area)
|
||||
AREA_FLAG_ARENA_INSTANCE = 0x00010000, // used by instanced arenas only
|
||||
AREA_FLAG_UNUSED2 = 0x00020000, // not used now (no area/zones with this flag set in 2.4.2)
|
||||
AREA_FLAG_UNK5 = 0x00040000, // just used for Amani Pass, Hatchet Hills
|
||||
AREA_FLAG_LOWLEVEL = 0x00100000 // used for some starting areas with area_level <=15
|
||||
};
|
||||
|
||||
enum FactionTemplateFlags
|
||||
{
|
||||
FACTION_TEMPLATE_FLAG_CONTESTED_GUARD = 0x00001000, // faction will attack players that were involved in PvP combats
|
||||
};
|
||||
|
||||
enum FactionMasks
|
||||
{
|
||||
FACTION_MASK_PLAYER = 1, // any player
|
||||
FACTION_MASK_ALLIANCE = 2, // player or creature from alliance team
|
||||
FACTION_MASK_HORDE = 4, // player or creature from horde team
|
||||
FACTION_MASK_MONSTER = 8 // aggressive creature from monster team
|
||||
// if none flags set then non-aggressive creature
|
||||
};
|
||||
|
||||
enum MapTypes
|
||||
{
|
||||
MAP_COMMON = 0,
|
||||
MAP_INSTANCE = 1,
|
||||
MAP_RAID = 2,
|
||||
MAP_BATTLEGROUND = 3,
|
||||
MAP_ARENA = 4
|
||||
};
|
||||
|
||||
enum AbilytyLearnType
|
||||
{
|
||||
ABILITY_LEARNED_ON_GET_PROFESSION_SKILL = 1,
|
||||
ABILITY_LEARNED_ON_GET_RACE_OR_CLASS_SKILL = 2
|
||||
};
|
||||
|
||||
enum ItemEnchantmentType
|
||||
{
|
||||
ITEM_ENCHANTMENT_TYPE_NONE = 0,
|
||||
ITEM_ENCHANTMENT_TYPE_COMBAT_SPELL = 1,
|
||||
ITEM_ENCHANTMENT_TYPE_DAMAGE = 2,
|
||||
ITEM_ENCHANTMENT_TYPE_EQUIP_SPELL = 3,
|
||||
ITEM_ENCHANTMENT_TYPE_RESISTANCE = 4,
|
||||
ITEM_ENCHANTMENT_TYPE_STAT = 5,
|
||||
ITEM_ENCHANTMENT_TYPE_TOTEM = 6
|
||||
};
|
||||
|
||||
enum TotemCategoryType
|
||||
{
|
||||
TOTEM_CATEGORY_TYPE_KNIFE = 1,
|
||||
TOTEM_CATEGORY_TYPE_TOTEM = 2,
|
||||
TOTEM_CATEGORY_TYPE_ROD = 3,
|
||||
TOTEM_CATEGORY_TYPE_PICK = 21,
|
||||
TOTEM_CATEGORY_TYPE_STONE = 22,
|
||||
TOTEM_CATEGORY_TYPE_HAMMER = 23,
|
||||
TOTEM_CATEGORY_TYPE_SPANNER = 24
|
||||
};
|
||||
|
||||
#endif
|
||||
637
src/shared/Database/DBCStores.cpp
Normal file
637
src/shared/Database/DBCStores.cpp
Normal file
|
|
@ -0,0 +1,637 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DBCStores.h"
|
||||
//#include "DataStore.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Log.h"
|
||||
#include "ProgressBar.h"
|
||||
|
||||
#include "DBCfmt.cpp"
|
||||
|
||||
#include <map>
|
||||
|
||||
typedef std::map<uint16,uint32> AreaFlagByAreaID;
|
||||
typedef std::map<uint32,uint32> AreaFlagByMapID;
|
||||
|
||||
DBCStorage <AreaTableEntry> sAreaStore(AreaTableEntryfmt);
|
||||
static AreaFlagByAreaID sAreaFlagByAreaID;
|
||||
static AreaFlagByMapID sAreaFlagByMapID; // for instances without generated *.map files
|
||||
|
||||
DBCStorage <AreaTriggerEntry> sAreaTriggerStore(AreaTriggerEntryfmt);
|
||||
DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore(BankBagSlotPricesEntryfmt);
|
||||
DBCStorage <BattlemasterListEntry> sBattlemasterListStore(BattlemasterListEntryfmt);
|
||||
DBCStorage <CharTitlesEntry> sCharTitlesStore(CharTitlesEntryfmt);
|
||||
DBCStorage <ChatChannelsEntry> sChatChannelsStore(ChatChannelsEntryfmt);
|
||||
DBCStorage <ChrClassesEntry> sChrClassesStore(ChrClassesEntryfmt);
|
||||
DBCStorage <ChrRacesEntry> sChrRacesStore(ChrRacesEntryfmt);
|
||||
DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore(CreatureDisplayInfofmt);
|
||||
DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore(CreatureFamilyfmt);
|
||||
DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore(CreatureSpellDatafmt);
|
||||
|
||||
DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore(DurabilityQualityfmt);
|
||||
DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore(DurabilityCostsfmt);
|
||||
|
||||
DBCStorage <EmotesTextEntry> sEmotesTextStore(EmoteEntryfmt);
|
||||
|
||||
typedef std::map<uint32,SimpleFactionsList> FactionTeamMap;
|
||||
static FactionTeamMap sFactionTeamMap;
|
||||
DBCStorage <FactionEntry> sFactionStore(FactionEntryfmt);
|
||||
DBCStorage <FactionTemplateEntry> sFactionTemplateStore(FactionTemplateEntryfmt);
|
||||
|
||||
DBCStorage <GemPropertiesEntry> sGemPropertiesStore(GemPropertiesEntryfmt);
|
||||
|
||||
DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore(GtCombatRatingsfmt);
|
||||
DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore(GtChanceToMeleeCritBasefmt);
|
||||
DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore(GtChanceToMeleeCritfmt);
|
||||
DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore(GtChanceToSpellCritBasefmt);
|
||||
DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore(GtChanceToSpellCritfmt);
|
||||
DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore(GtOCTRegenHPfmt);
|
||||
//DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore(GtOCTRegenMPfmt); -- not used currently
|
||||
DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore(GtRegenHPPerSptfmt);
|
||||
DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore(GtRegenMPPerSptfmt);
|
||||
DBCStorage <ItemEntry> sItemStore(Itemfmt);
|
||||
//DBCStorage <ItemCondExtCostsEntry> sItemCondExtCostsStore(ItemCondExtCostsEntryfmt);
|
||||
//DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore(ItemDisplayTemplateEntryfmt); -- not used currently
|
||||
DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore(ItemExtendedCostEntryfmt);
|
||||
DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore(ItemRandomPropertiesfmt);
|
||||
DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore(ItemRandomSuffixfmt);
|
||||
DBCStorage <ItemSetEntry> sItemSetStore(ItemSetEntryfmt);
|
||||
|
||||
DBCStorage <LockEntry> sLockStore(LockEntryfmt);
|
||||
|
||||
DBCStorage <MailTemplateEntry> sMailTemplateStore(MailTemplateEntryfmt);
|
||||
DBCStorage <MapEntry> sMapStore(MapEntryfmt);
|
||||
|
||||
DBCStorage <QuestSortEntry> sQuestSortStore(QuestSortEntryfmt);
|
||||
|
||||
DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore(RandomPropertiesPointsfmt);
|
||||
|
||||
DBCStorage <SkillLineEntry> sSkillLineStore(SkillLinefmt);
|
||||
DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore(SkillLineAbilityfmt);
|
||||
|
||||
DBCStorage <SoundEntriesEntry> sSoundEntriesStore(SoundEntriesfmt);
|
||||
|
||||
DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore(SpellItemEnchantmentfmt);
|
||||
DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore(SpellItemEnchantmentConditionfmt);
|
||||
DBCStorage <SpellEntry> sSpellStore(SpellEntryfmt);
|
||||
SpellCategoryStore sSpellCategoryStore;
|
||||
PetFamilySpellsStore sPetFamilySpellsStore;
|
||||
|
||||
DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore(SpellCastTimefmt);
|
||||
DBCStorage <SpellDurationEntry> sSpellDurationStore(SpellDurationfmt);
|
||||
DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore(SpellFocusObjectfmt);
|
||||
DBCStorage <SpellRadiusEntry> sSpellRadiusStore(SpellRadiusfmt);
|
||||
DBCStorage <SpellRangeEntry> sSpellRangeStore(SpellRangefmt);
|
||||
DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore(SpellShapeshiftfmt);
|
||||
DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore(StableSlotPricesfmt);
|
||||
DBCStorage <TalentEntry> sTalentStore(TalentEntryfmt);
|
||||
TalentSpellPosMap sTalentSpellPosMap;
|
||||
DBCStorage <TalentTabEntry> sTalentTabStore(TalentTabEntryfmt);
|
||||
|
||||
// store absolute bit position for first rank for talent inspect
|
||||
typedef std::map<uint32,uint32> TalentInspectMap;
|
||||
static TalentInspectMap sTalentPosInInspect;
|
||||
static TalentInspectMap sTalentTabSizeInInspect;
|
||||
static uint32 sTalentTabPages[12/*MAX_CLASSES*/][3];
|
||||
|
||||
DBCStorage <TaxiNodesEntry> sTaxiNodesStore(TaxiNodesEntryfmt);
|
||||
TaxiMask sTaxiNodesMask;
|
||||
|
||||
// DBC used only for initialization sTaxiPathSetBySource at startup.
|
||||
TaxiPathSetBySource sTaxiPathSetBySource;
|
||||
DBCStorage <TaxiPathEntry> sTaxiPathStore(TaxiPathEntryfmt);
|
||||
|
||||
// DBC used only for initialization sTaxiPathSetBySource at startup.
|
||||
TaxiPathNodesByPath sTaxiPathNodesByPath;
|
||||
|
||||
static DBCStorage <TaxiPathNodeEntry> sTaxiPathNodeStore(TaxiPathNodeEntryfmt);
|
||||
DBCStorage <TotemCategoryEntry> sTotemCategoryStore(TotemCategoryEntryfmt);
|
||||
DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore(WorldMapAreaEntryfmt);
|
||||
DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore(WorldSafeLocsEntryfmt);
|
||||
|
||||
typedef std::list<std::string> StoreProblemList;
|
||||
|
||||
static bool LoadDBC_assert_print(uint32 fsize,uint32 rsize, std::string filename)
|
||||
{
|
||||
sLog.outError("ERROR: Size of '%s' setted by format string (%u) not equal size of C++ structure (%u).",filename.c_str(),fsize,rsize);
|
||||
|
||||
// assert must fail after function call
|
||||
return false;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
inline void LoadDBC(uint32& availableDbcLocales,barGoLink& bar, StoreProblemList& errlist, DBCStorage<T>& storage, std::string dbc_path, std::string filename)
|
||||
{
|
||||
// compatibility format and C++ structure sizes
|
||||
assert(DBCFile::GetFormatRecordSize(storage.GetFormat()) == sizeof(T) || LoadDBC_assert_print(DBCFile::GetFormatRecordSize(storage.GetFormat()),sizeof(T),filename));
|
||||
|
||||
std::string dbc_filename = dbc_path + filename;
|
||||
if(storage.Load(dbc_filename.c_str()))
|
||||
{
|
||||
bar.step();
|
||||
for(uint8 i = 0; i < MAX_LOCALE; ++i)
|
||||
{
|
||||
if(!(availableDbcLocales & (1 << i)))
|
||||
continue;
|
||||
|
||||
std::string dbc_filename_loc = dbc_path + localeNames[i] + "/" + filename;
|
||||
if(!storage.LoadStringsFrom(dbc_filename_loc.c_str()))
|
||||
availableDbcLocales &= ~(1<<i); // mark as not available for speedup next checks
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// sort problematic dbc to (1) non compatible and (2) non-existed
|
||||
FILE * f=fopen(dbc_filename.c_str(),"rb");
|
||||
if(f)
|
||||
{
|
||||
char buf[100];
|
||||
snprintf(buf,100," (exist, but have %d fields instead %d) Wrong client version DBC file?",storage.GetFieldCount(),strlen(storage.GetFormat()));
|
||||
errlist.push_back(dbc_filename + buf);
|
||||
fclose(f);
|
||||
}
|
||||
else
|
||||
errlist.push_back(dbc_filename);
|
||||
}
|
||||
}
|
||||
|
||||
void LoadDBCStores(std::string dataPath)
|
||||
{
|
||||
std::string dbcPath = dataPath+"dbc/";
|
||||
|
||||
const uint32 DBCFilesCount = 56;
|
||||
|
||||
barGoLink bar( DBCFilesCount );
|
||||
|
||||
StoreProblemList bad_dbc_files;
|
||||
uint32 availableDbcLocales = 0xFFFFFFFF;
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaStore, dbcPath,"AreaTable.dbc");
|
||||
|
||||
// must be after sAreaStore loading
|
||||
for(uint32 i = 0; i < sAreaStore.GetNumRows(); ++i) // areaflag numbered from 0
|
||||
{
|
||||
if(AreaTableEntry const* area = sAreaStore.LookupEntry(i))
|
||||
{
|
||||
// fill AreaId->DBC records
|
||||
sAreaFlagByAreaID.insert(AreaFlagByAreaID::value_type(uint16(area->ID),area->exploreFlag));
|
||||
|
||||
// fill MapId->DBC records ( skip sub zones and continents )
|
||||
if(area->zone==0 && area->mapid != 0 && area->mapid != 1 && area->mapid != 530 )
|
||||
sAreaFlagByMapID.insert(AreaFlagByMapID::value_type(area->mapid,area->exploreFlag));
|
||||
}
|
||||
}
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sAreaTriggerStore, dbcPath,"AreaTrigger.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBankBagSlotPricesStore, dbcPath,"BankBagSlotPrices.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sBattlemasterListStore, dbcPath,"BattlemasterList.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCharTitlesStore, dbcPath,"CharTitles.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChatChannelsStore, dbcPath,"ChatChannels.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrClassesStore, dbcPath,"ChrClasses.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sChrRacesStore, dbcPath,"ChrRaces.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureDisplayInfoStore, dbcPath,"CreatureDisplayInfo.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureFamilyStore, dbcPath,"CreatureFamily.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sCreatureSpellDataStore, dbcPath,"CreatureSpellData.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityCostsStore, dbcPath,"DurabilityCosts.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sDurabilityQualityStore, dbcPath,"DurabilityQuality.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sEmotesTextStore, dbcPath,"EmotesText.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionStore, dbcPath,"Faction.dbc");
|
||||
for (uint32 i=0;i<sFactionStore.GetNumRows(); ++i)
|
||||
{
|
||||
FactionEntry const * faction = sFactionStore.LookupEntry(i);
|
||||
if (faction && faction->team)
|
||||
{
|
||||
SimpleFactionsList &flist = sFactionTeamMap[faction->team];
|
||||
flist.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sFactionTemplateStore, dbcPath,"FactionTemplate.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGemPropertiesStore, dbcPath,"GemProperties.dbc");
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtCombatRatingsStore, dbcPath,"gtCombatRatings.dbc");
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritBaseStore, dbcPath,"gtChanceToMeleeCritBase.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToMeleeCritStore, dbcPath,"gtChanceToMeleeCrit.dbc");
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritBaseStore, dbcPath,"gtChanceToSpellCritBase.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtChanceToSpellCritStore, dbcPath,"gtChanceToSpellCrit.dbc");
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenHPStore, dbcPath,"gtOCTRegenHP.dbc");
|
||||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtOCTRegenMPStore, dbcPath,"gtOCTRegenMP.dbc"); -- not used currently
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenHPPerSptStore, dbcPath,"gtRegenHPPerSpt.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sGtRegenMPPerSptStore, dbcPath,"gtRegenMPPerSpt.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemStore, dbcPath,"Item.dbc");
|
||||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemDisplayInfoStore, dbcPath,"ItemDisplayInfo.dbc"); -- not used currently
|
||||
//LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemCondExtCostsStore, dbcPath,"ItemCondExtCosts.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemExtendedCostStore, dbcPath,"ItemExtendedCost.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomPropertiesStore,dbcPath,"ItemRandomProperties.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemRandomSuffixStore, dbcPath,"ItemRandomSuffix.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sItemSetStore, dbcPath,"ItemSet.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sLockStore, dbcPath,"Lock.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMailTemplateStore, dbcPath,"MailTemplate.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sMapStore, dbcPath,"Map.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sQuestSortStore, dbcPath,"QuestSort.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sRandomPropertiesPointsStore, dbcPath,"RandPropPoints.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineStore, dbcPath,"SkillLine.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSkillLineAbilityStore, dbcPath,"SkillLineAbility.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSoundEntriesStore, dbcPath,"SoundEntries.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellStore, dbcPath,"Spell.dbc");
|
||||
for(uint32 i = 1; i < sSpellStore.GetNumRows(); ++i)
|
||||
{
|
||||
SpellEntry const * spell = sSpellStore.LookupEntry(i);
|
||||
if(spell && spell->Category)
|
||||
sSpellCategoryStore[spell->Category].insert(i);
|
||||
|
||||
// DBC not support uint64 fields but SpellEntry have SpellFamilyFlags mapped at 2 uint32 fields
|
||||
// uint32 field already converted to bigendian if need, but must be swapped for correct uint64 bigendian view
|
||||
#if MANGOS_ENDIAN == MANGOS_BIGENDIAN
|
||||
std::swap(*((uint32*)(&spell->SpellFamilyFlags)),*(((uint32*)(&spell->SpellFamilyFlags))+1));
|
||||
#endif
|
||||
}
|
||||
|
||||
for (uint32 j = 0; j < sSkillLineAbilityStore.GetNumRows(); ++j)
|
||||
{
|
||||
SkillLineAbilityEntry const *skillLine = sSkillLineAbilityStore.LookupEntry(j);
|
||||
|
||||
if(!skillLine)
|
||||
continue;
|
||||
|
||||
SpellEntry const* spellInfo = sSpellStore.LookupEntry(skillLine->spellId);
|
||||
|
||||
if(spellInfo && (spellInfo->Attributes & 0x1D0) == 0x1D0)
|
||||
{
|
||||
for (unsigned int i = 1; i < sCreatureFamilyStore.GetNumRows(); ++i)
|
||||
{
|
||||
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(i);
|
||||
if(!cFamily)
|
||||
continue;
|
||||
|
||||
if(skillLine->skillId != cFamily->skillLine[0] && skillLine->skillId != cFamily->skillLine[1])
|
||||
continue;
|
||||
|
||||
sPetFamilySpellsStore[i].insert(spellInfo->Id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellCastTimesStore, dbcPath,"SpellCastTimes.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellDurationStore, dbcPath,"SpellDuration.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellFocusObjectStore, dbcPath,"SpellFocusObject.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentStore,dbcPath,"SpellItemEnchantment.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellItemEnchantmentConditionStore,dbcPath,"SpellItemEnchantmentCondition.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRadiusStore, dbcPath,"SpellRadius.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellRangeStore, dbcPath,"SpellRange.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sSpellShapeshiftStore, dbcPath,"SpellShapeshiftForm.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sStableSlotPricesStore, dbcPath,"StableSlotPrices.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentStore, dbcPath,"Talent.dbc");
|
||||
|
||||
// create talent spells set
|
||||
for (unsigned int i = 0; i < sTalentStore.GetNumRows(); ++i)
|
||||
{
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
|
||||
if (!talentInfo) continue;
|
||||
for (int j = 0; j < 5; j++)
|
||||
if(talentInfo->RankID[j])
|
||||
sTalentSpellPosMap[talentInfo->RankID[j]] = TalentSpellPos(i,j);
|
||||
}
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTalentTabStore, dbcPath,"TalentTab.dbc");
|
||||
|
||||
// preper fast data access to bit pos of talent ranks for use at inspecting
|
||||
{
|
||||
// fill table by amount of talent ranks and fill sTalentTabBitSizeInInspect
|
||||
// store in with (row,col,talent)->size key for correct sorting by (row,col)
|
||||
typedef std::map<uint32,uint32> TalentBitSize;
|
||||
TalentBitSize sTalentBitSize;
|
||||
for(uint32 i = 1; i < sTalentStore.GetNumRows(); ++i)
|
||||
{
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry(i);
|
||||
if (!talentInfo) continue;
|
||||
|
||||
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentInfo->TalentTab );
|
||||
if(!talentTabInfo)
|
||||
continue;
|
||||
|
||||
// find talent rank
|
||||
uint32 curtalent_maxrank = 0;
|
||||
for(uint32 k = 5; k > 0; --k)
|
||||
{
|
||||
if(talentInfo->RankID[k-1])
|
||||
{
|
||||
curtalent_maxrank = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sTalentBitSize[(talentInfo->Row<<24) + (talentInfo->Col<<16)+talentInfo->TalentID] = curtalent_maxrank;
|
||||
sTalentTabSizeInInspect[talentInfo->TalentTab] += curtalent_maxrank;
|
||||
}
|
||||
|
||||
// now have all max ranks (and then bit amount used for store talent ranks in inspect)
|
||||
for(uint32 talentTabId = 1; talentTabId < sTalentTabStore.GetNumRows(); ++talentTabId)
|
||||
{
|
||||
TalentTabEntry const *talentTabInfo = sTalentTabStore.LookupEntry( talentTabId );
|
||||
if(!talentTabInfo)
|
||||
continue;
|
||||
|
||||
// store class talent tab pages
|
||||
uint32 cls = 1;
|
||||
for(uint32 m=1;!(m & talentTabInfo->ClassMask) && cls < 12 /*MAX_CLASSES*/;m <<=1, ++cls) {}
|
||||
|
||||
sTalentTabPages[cls][talentTabInfo->tabpage]=talentTabId;
|
||||
|
||||
// add total amount bits for first rank starting from talent tab first talent rank pos.
|
||||
uint32 pos = 0;
|
||||
for(TalentBitSize::iterator itr = sTalentBitSize.begin(); itr != sTalentBitSize.end(); ++itr)
|
||||
{
|
||||
uint32 talentId = itr->first & 0xFFFF;
|
||||
TalentEntry const *talentInfo = sTalentStore.LookupEntry( talentId );
|
||||
if(!talentInfo)
|
||||
continue;
|
||||
|
||||
if(talentInfo->TalentTab != talentTabId)
|
||||
continue;
|
||||
|
||||
sTalentPosInInspect[talentId] = pos;
|
||||
pos+= itr->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiNodesStore, dbcPath,"TaxiNodes.dbc");
|
||||
|
||||
// Initialize global taxinodes mask
|
||||
memset(sTaxiNodesMask,0,sizeof(sTaxiNodesMask));
|
||||
for(uint32 i = 1; i < sTaxiNodesStore.GetNumRows(); ++i)
|
||||
{
|
||||
if(sTaxiNodesStore.LookupEntry(i))
|
||||
{
|
||||
uint8 field = (uint8)((i - 1) / 32);
|
||||
uint32 submask = 1<<((i-1)%32);
|
||||
sTaxiNodesMask[field] |= submask;
|
||||
}
|
||||
}
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathStore, dbcPath,"TaxiPath.dbc");
|
||||
for(uint32 i = 1; i < sTaxiPathStore.GetNumRows(); ++i)
|
||||
if(TaxiPathEntry const* entry = sTaxiPathStore.LookupEntry(i))
|
||||
sTaxiPathSetBySource[entry->from][entry->to] = TaxiPathBySourceAndDestination(entry->ID,entry->price);
|
||||
uint32 pathCount = sTaxiPathStore.GetNumRows();
|
||||
|
||||
//## TaxiPathNode.dbc ## Loaded only for initialization different structures
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTaxiPathNodeStore, dbcPath,"TaxiPathNode.dbc");
|
||||
// Calculate path nodes count
|
||||
std::vector<uint32> pathLength;
|
||||
pathLength.resize(pathCount); // 0 and some other indexes not used
|
||||
for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
|
||||
if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
|
||||
++pathLength[entry->path];
|
||||
// Set path length
|
||||
sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used
|
||||
for(uint32 i = 1; i < sTaxiPathNodesByPath.size(); ++i)
|
||||
sTaxiPathNodesByPath[i].resize(pathLength[i]);
|
||||
// fill data
|
||||
for(uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
|
||||
if(TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
|
||||
sTaxiPathNodesByPath[entry->path][entry->index] = TaxiPathNode(entry->mapid,entry->x,entry->y,entry->z,entry->actionFlag,entry->delay);
|
||||
sTaxiPathNodeStore.Clear();
|
||||
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sTotemCategoryStore, dbcPath,"TotemCategory.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldMapAreaStore, dbcPath,"WorldMapArea.dbc");
|
||||
LoadDBC(availableDbcLocales,bar,bad_dbc_files,sWorldSafeLocsStore, dbcPath,"WorldSafeLocs.dbc");
|
||||
|
||||
// error checks
|
||||
if(bad_dbc_files.size() >= DBCFilesCount )
|
||||
{
|
||||
sLog.outError("\nIncorrect DataDir value in mangosd.conf or ALL required *.dbc files (%d) not found by path: %sdbc",DBCFilesCount,dataPath.c_str());
|
||||
exit(1);
|
||||
}
|
||||
else if(!bad_dbc_files.empty() )
|
||||
{
|
||||
std::string str;
|
||||
for(std::list<std::string>::iterator i = bad_dbc_files.begin(); i != bad_dbc_files.end(); ++i)
|
||||
str += *i + "\n";
|
||||
|
||||
sLog.outError("\nSome required *.dbc files (%u from %d) not found or not compatible:\n%s",bad_dbc_files.size(),DBCFilesCount,str.c_str());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// check at up-to-date DBC files (53085 is last added spell in 2.4.3)
|
||||
// check at up-to-date DBC files (17514 is last ID in SkillLineAbilities in 2.4.3)
|
||||
// check at up-to-date DBC files (598 is last map added in 2.4.3)
|
||||
// check at up-to-date DBC files (1127 is last gem property added in 2.4.3)
|
||||
// check at up-to-date DBC files (2425 is last item extended cost added in 2.4.3)
|
||||
// check at up-to-date DBC files (71 is last char title added in 2.4.3)
|
||||
// check at up-to-date DBC files (1768 is last area added in 2.4.3)
|
||||
if( !sSpellStore.LookupEntry(53085) ||
|
||||
!sSkillLineAbilityStore.LookupEntry(17514) ||
|
||||
!sMapStore.LookupEntry(598) ||
|
||||
!sGemPropertiesStore.LookupEntry(1127) ||
|
||||
!sItemExtendedCostStore.LookupEntry(2425) ||
|
||||
!sCharTitlesStore.LookupEntry(71) ||
|
||||
!sAreaStore.LookupEntry(1768) )
|
||||
{
|
||||
sLog.outError("\nYou have _outdated_ DBC files. Please extract correct versions from current using client.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
sLog.outString();
|
||||
sLog.outString( ">> Loaded %d data stores", DBCFilesCount );
|
||||
sLog.outString();
|
||||
}
|
||||
|
||||
SimpleFactionsList const* GetFactionTeamList(uint32 faction)
|
||||
{
|
||||
FactionTeamMap::const_iterator itr = sFactionTeamMap.find(faction);
|
||||
if(itr==sFactionTeamMap.end())
|
||||
return NULL;
|
||||
return &itr->second;
|
||||
}
|
||||
|
||||
char* GetPetName(uint32 petfamily, uint32 dbclang)
|
||||
{
|
||||
if(!petfamily)
|
||||
return NULL;
|
||||
CreatureFamilyEntry const *pet_family = sCreatureFamilyStore.LookupEntry(petfamily);
|
||||
if(!pet_family)
|
||||
return NULL;
|
||||
return pet_family->Name[dbclang]?pet_family->Name[dbclang]:NULL;
|
||||
}
|
||||
|
||||
TalentSpellPos const* GetTalentSpellPos(uint32 spellId)
|
||||
{
|
||||
TalentSpellPosMap::const_iterator itr = sTalentSpellPosMap.find(spellId);
|
||||
if(itr==sTalentSpellPosMap.end())
|
||||
return NULL;
|
||||
|
||||
return &itr->second;
|
||||
}
|
||||
|
||||
uint32 GetTalentSpellCost(uint32 spellId)
|
||||
{
|
||||
if(TalentSpellPos const* pos = GetTalentSpellPos(spellId))
|
||||
return pos->rank+1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id)
|
||||
{
|
||||
AreaFlagByAreaID::iterator i = sAreaFlagByAreaID.find(area_id);
|
||||
if(i == sAreaFlagByAreaID.end())
|
||||
return NULL;
|
||||
|
||||
return sAreaStore.LookupEntry(i->second);
|
||||
}
|
||||
|
||||
AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id)
|
||||
{
|
||||
if(area_flag)
|
||||
return sAreaStore.LookupEntry(area_flag);
|
||||
|
||||
if(MapEntry const* mapEntry = sMapStore.LookupEntry(map_id))
|
||||
return GetAreaEntryByAreaID(mapEntry->linked_zone);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32 GetAreaFlagByMapId(uint32 mapid)
|
||||
{
|
||||
AreaFlagByMapID::iterator i = sAreaFlagByMapID.find(mapid);
|
||||
if(i == sAreaFlagByMapID.end())
|
||||
return 0;
|
||||
else
|
||||
return i->second;
|
||||
}
|
||||
|
||||
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId)
|
||||
{
|
||||
if(mapid != 530) // speed for most cases
|
||||
return mapid;
|
||||
|
||||
if(WorldMapAreaEntry const* wma = sWorldMapAreaStore.LookupEntry(zoneId))
|
||||
return wma->virtual_map_id >= 0 ? wma->virtual_map_id : wma->map_id;
|
||||
|
||||
return mapid;
|
||||
}
|
||||
|
||||
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId)
|
||||
{
|
||||
mapid = GetVirtualMapForMapAndZone(mapid,zoneId);
|
||||
if(mapid < 2)
|
||||
return CONTENT_1_60;
|
||||
|
||||
MapEntry const* mapEntry = sMapStore.LookupEntry(mapid);
|
||||
if(!mapEntry)
|
||||
return CONTENT_1_60;
|
||||
|
||||
switch(mapEntry->Expansion())
|
||||
{
|
||||
default: return CONTENT_1_60;
|
||||
case 1: return CONTENT_61_70;
|
||||
case 2: return CONTENT_71_80;
|
||||
}
|
||||
}
|
||||
|
||||
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id)
|
||||
{
|
||||
// not sorted, numbering index from 0
|
||||
for(uint32 i = 0; i < sChatChannelsStore.GetNumRows(); ++i)
|
||||
{
|
||||
ChatChannelsEntry const* ch = sChatChannelsStore.LookupEntry(i);
|
||||
if(ch && ch->ChannelID == channel_id)
|
||||
return ch;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId)
|
||||
{
|
||||
if(requiredTotemCategoryId==0)
|
||||
return true;
|
||||
if(itemTotemCategoryId==0)
|
||||
return false;
|
||||
|
||||
TotemCategoryEntry const* itemEntry = sTotemCategoryStore.LookupEntry(itemTotemCategoryId);
|
||||
if(!itemEntry)
|
||||
return false;
|
||||
TotemCategoryEntry const* reqEntry = sTotemCategoryStore.LookupEntry(requiredTotemCategoryId);
|
||||
if(!reqEntry)
|
||||
return false;
|
||||
|
||||
if(itemEntry->categoryType!=reqEntry->categoryType)
|
||||
return false;
|
||||
|
||||
return (itemEntry->categoryMask & reqEntry->categoryMask)==reqEntry->categoryMask;
|
||||
}
|
||||
|
||||
void Zone2MapCoordinates(float& x,float& y,uint32 zone)
|
||||
{
|
||||
WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
|
||||
|
||||
// if not listed then map coordinates (instance)
|
||||
if(!maEntry)
|
||||
return;
|
||||
|
||||
std::swap(x,y); // at client map coords swapped
|
||||
x = x*((maEntry->x2-maEntry->x1)/100)+maEntry->x1;
|
||||
y = y*((maEntry->y2-maEntry->y1)/100)+maEntry->y1; // client y coord from top to down
|
||||
}
|
||||
|
||||
void Map2ZoneCoordinates(float& x,float& y,uint32 zone)
|
||||
{
|
||||
WorldMapAreaEntry const* maEntry = sWorldMapAreaStore.LookupEntry(zone);
|
||||
|
||||
// if not listed then map coordinates (instance)
|
||||
if(!maEntry)
|
||||
return;
|
||||
|
||||
x = (x-maEntry->x1)/((maEntry->x2-maEntry->x1)/100);
|
||||
y = (y-maEntry->y1)/((maEntry->y2-maEntry->y1)/100); // client y coord from top to down
|
||||
std::swap(x,y); // client have map coords swapped
|
||||
}
|
||||
|
||||
uint32 GetTalentInspectBitPosInTab(uint32 talentId)
|
||||
{
|
||||
TalentInspectMap::const_iterator itr = sTalentPosInInspect.find(talentId);
|
||||
if(itr == sTalentPosInInspect.end())
|
||||
return 0;
|
||||
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
uint32 GetTalentTabInspectBitSize(uint32 talentTabId)
|
||||
{
|
||||
TalentInspectMap::const_iterator itr = sTalentTabSizeInInspect.find(talentTabId);
|
||||
if(itr == sTalentTabSizeInInspect.end())
|
||||
return 0;
|
||||
|
||||
return itr->second;
|
||||
}
|
||||
|
||||
uint32 const* GetTalentTabPages(uint32 cls)
|
||||
{
|
||||
return sTalentTabPages[cls];
|
||||
}
|
||||
|
||||
// script support functions
|
||||
MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore() { return &sSoundEntriesStore; }
|
||||
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore() { return &sSpellStore; }
|
||||
MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore() { return &sSpellRangeStore; }
|
||||
202
src/shared/Database/DBCStores.h
Normal file
202
src/shared/Database/DBCStores.h
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DBCSTORES_H
|
||||
#define DBCSTORES_H
|
||||
|
||||
#include "Common.h"
|
||||
//#include "DataStore.h"
|
||||
#include "dbcfile.h"
|
||||
#include "DBCStructure.h"
|
||||
|
||||
#include <list>
|
||||
|
||||
typedef std::list<uint32> SimpleFactionsList;
|
||||
|
||||
SimpleFactionsList const* GetFactionTeamList(uint32 faction);
|
||||
char* GetPetName(uint32 petfamily, uint32 dbclang);
|
||||
uint32 GetTalentSpellCost(uint32 spellId);
|
||||
TalentSpellPos const* GetTalentSpellPos(uint32 spellId);
|
||||
|
||||
AreaTableEntry const* GetAreaEntryByAreaID(uint32 area_id);
|
||||
AreaTableEntry const* GetAreaEntryByAreaFlagAndMap(uint32 area_flag,uint32 map_id);
|
||||
uint32 GetAreaFlagByMapId(uint32 mapid);
|
||||
|
||||
uint32 GetVirtualMapForMapAndZone(uint32 mapid, uint32 zoneId);
|
||||
|
||||
enum ContentLevels
|
||||
{
|
||||
CONTENT_1_60 = 0,
|
||||
CONTENT_61_70,
|
||||
CONTENT_71_80
|
||||
};
|
||||
ContentLevels GetContentLevelsForMapAndZone(uint32 mapid, uint32 zoneId);
|
||||
|
||||
ChatChannelsEntry const* GetChannelEntryFor(uint32 channel_id);
|
||||
|
||||
bool IsTotemCategoryCompatiableWith(uint32 itemTotemCategoryId, uint32 requiredTotemCategoryId);
|
||||
|
||||
void Zone2MapCoordinates(float& x,float& y,uint32 zone);
|
||||
void Map2ZoneCoordinates(float& x,float& y,uint32 zone);
|
||||
|
||||
uint32 GetTalentInspectBitPosInTab(uint32 talentId);
|
||||
uint32 GetTalentTabInspectBitSize(uint32 talentTabId);
|
||||
uint32 const* /*[3]*/ GetTalentTabPages(uint32 cls);
|
||||
|
||||
template<class T>
|
||||
class DBCStorage
|
||||
{
|
||||
typedef std::list<char*> StringPoolList;
|
||||
public:
|
||||
explicit DBCStorage(const char *f) : nCount(0), fieldCount(0), fmt(f), indexTable(NULL), m_dataTable(NULL) { }
|
||||
~DBCStorage() { Clear(); }
|
||||
|
||||
T const* LookupEntry(uint32 id) const { return (id>=nCount)?NULL:indexTable[id]; }
|
||||
uint32 GetNumRows() const { return nCount; }
|
||||
char const* GetFormat() const { return fmt; }
|
||||
uint32 GetFieldCount() const { return fieldCount; }
|
||||
|
||||
bool Load(char const* fn)
|
||||
{
|
||||
DBCFile dbc;
|
||||
// Check if load was sucessful, only then continue
|
||||
if(!dbc.Load(fn, fmt))
|
||||
return false;
|
||||
|
||||
fieldCount = dbc.GetCols();
|
||||
m_dataTable = (T*)dbc.AutoProduceData(fmt,nCount,(char**&)indexTable);
|
||||
m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
|
||||
|
||||
// error in dbc file at loading if NULL
|
||||
return indexTable!=NULL;
|
||||
}
|
||||
|
||||
bool LoadStringsFrom(char const* fn)
|
||||
{
|
||||
// DBC must be already loaded using Load
|
||||
if(!indexTable)
|
||||
return false;
|
||||
|
||||
DBCFile dbc;
|
||||
// Check if load was successful, only then continue
|
||||
if(!dbc.Load(fn, fmt))
|
||||
return false;
|
||||
|
||||
m_stringPoolList.push_back(dbc.AutoProduceStrings(fmt,(char*)m_dataTable));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
if (!indexTable)
|
||||
return;
|
||||
|
||||
delete[] ((char*)indexTable);
|
||||
indexTable = NULL;
|
||||
delete[] ((char*)m_dataTable);
|
||||
m_dataTable = NULL;
|
||||
|
||||
while(!m_stringPoolList.empty())
|
||||
{
|
||||
delete[] m_stringPoolList.front();
|
||||
m_stringPoolList.pop_front();
|
||||
}
|
||||
nCount = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
uint32 nCount;
|
||||
uint32 fieldCount;
|
||||
char const* fmt;
|
||||
T** indexTable;
|
||||
T* m_dataTable;
|
||||
StringPoolList m_stringPoolList;
|
||||
};
|
||||
|
||||
extern DBCStorage <AreaTableEntry> sAreaStore;// recommend access using functions
|
||||
extern DBCStorage <AreaTriggerEntry> sAreaTriggerStore;
|
||||
extern DBCStorage <BankBagSlotPricesEntry> sBankBagSlotPricesStore;
|
||||
extern DBCStorage <BattlemasterListEntry> sBattlemasterListStore;
|
||||
//extern DBCStorage <ChatChannelsEntry> sChatChannelsStore; -- accessed using function, no usable index
|
||||
extern DBCStorage <CharTitlesEntry> sCharTitlesStore;
|
||||
extern DBCStorage <ChrClassesEntry> sChrClassesStore;
|
||||
extern DBCStorage <ChrRacesEntry> sChrRacesStore;
|
||||
extern DBCStorage <CreatureDisplayInfoEntry> sCreatureDisplayInfoStore;
|
||||
extern DBCStorage <CreatureFamilyEntry> sCreatureFamilyStore;
|
||||
extern DBCStorage <CreatureSpellDataEntry> sCreatureSpellDataStore;
|
||||
extern DBCStorage <DurabilityCostsEntry> sDurabilityCostsStore;
|
||||
extern DBCStorage <DurabilityQualityEntry> sDurabilityQualityStore;
|
||||
extern DBCStorage <EmotesTextEntry> sEmotesTextStore;
|
||||
extern DBCStorage <FactionEntry> sFactionStore;
|
||||
extern DBCStorage <FactionTemplateEntry> sFactionTemplateStore;
|
||||
extern DBCStorage <GemPropertiesEntry> sGemPropertiesStore;
|
||||
|
||||
extern DBCStorage <GtCombatRatingsEntry> sGtCombatRatingsStore;
|
||||
extern DBCStorage <GtChanceToMeleeCritBaseEntry> sGtChanceToMeleeCritBaseStore;
|
||||
extern DBCStorage <GtChanceToMeleeCritEntry> sGtChanceToMeleeCritStore;
|
||||
extern DBCStorage <GtChanceToSpellCritBaseEntry> sGtChanceToSpellCritBaseStore;
|
||||
extern DBCStorage <GtChanceToSpellCritEntry> sGtChanceToSpellCritStore;
|
||||
extern DBCStorage <GtOCTRegenHPEntry> sGtOCTRegenHPStore;
|
||||
//extern DBCStorage <GtOCTRegenMPEntry> sGtOCTRegenMPStore; -- not used currently
|
||||
extern DBCStorage <GtRegenHPPerSptEntry> sGtRegenHPPerSptStore;
|
||||
extern DBCStorage <GtRegenMPPerSptEntry> sGtRegenMPPerSptStore;
|
||||
extern DBCStorage <ItemEntry> sItemStore;
|
||||
//extern DBCStorage <ItemDisplayInfoEntry> sItemDisplayInfoStore; -- not used currently
|
||||
extern DBCStorage <ItemExtendedCostEntry> sItemExtendedCostStore;
|
||||
extern DBCStorage <ItemRandomPropertiesEntry> sItemRandomPropertiesStore;
|
||||
extern DBCStorage <ItemRandomSuffixEntry> sItemRandomSuffixStore;
|
||||
extern DBCStorage <ItemSetEntry> sItemSetStore;
|
||||
extern DBCStorage <LockEntry> sLockStore;
|
||||
extern DBCStorage <MailTemplateEntry> sMailTemplateStore;
|
||||
extern DBCStorage <MapEntry> sMapStore;
|
||||
extern DBCStorage <QuestSortEntry> sQuestSortStore;
|
||||
extern DBCStorage <RandomPropertiesPointsEntry> sRandomPropertiesPointsStore;
|
||||
extern DBCStorage <SkillLineEntry> sSkillLineStore;
|
||||
extern DBCStorage <SkillLineAbilityEntry> sSkillLineAbilityStore;
|
||||
extern DBCStorage <SoundEntriesEntry> sSoundEntriesStore;
|
||||
extern DBCStorage <SpellCastTimesEntry> sSpellCastTimesStore;
|
||||
extern DBCStorage <SpellDurationEntry> sSpellDurationStore;
|
||||
extern DBCStorage <SpellFocusObjectEntry> sSpellFocusObjectStore;
|
||||
extern DBCStorage <SpellItemEnchantmentEntry> sSpellItemEnchantmentStore;
|
||||
extern DBCStorage <SpellItemEnchantmentConditionEntry> sSpellItemEnchantmentConditionStore;
|
||||
extern SpellCategoryStore sSpellCategoryStore;
|
||||
extern PetFamilySpellsStore sPetFamilySpellsStore;
|
||||
extern DBCStorage <SpellRadiusEntry> sSpellRadiusStore;
|
||||
extern DBCStorage <SpellRangeEntry> sSpellRangeStore;
|
||||
extern DBCStorage <SpellShapeshiftEntry> sSpellShapeshiftStore;
|
||||
extern DBCStorage <SpellEntry> sSpellStore;
|
||||
extern DBCStorage <StableSlotPricesEntry> sStableSlotPricesStore;
|
||||
extern DBCStorage <TalentEntry> sTalentStore;
|
||||
extern DBCStorage <TalentTabEntry> sTalentTabStore;
|
||||
extern DBCStorage <TaxiNodesEntry> sTaxiNodesStore;
|
||||
extern DBCStorage <TaxiPathEntry> sTaxiPathStore;
|
||||
extern TaxiMask sTaxiNodesMask;
|
||||
extern TaxiPathSetBySource sTaxiPathSetBySource;
|
||||
extern TaxiPathNodesByPath sTaxiPathNodesByPath;
|
||||
extern DBCStorage <TotemCategoryEntry> sTotemCategoryStore;
|
||||
//extern DBCStorage <WorldMapAreaEntry> sWorldMapAreaStore; -- use Zone2MapCoordinates and Map2ZoneCoordinates
|
||||
extern DBCStorage <WorldSafeLocsEntry> sWorldSafeLocsStore;
|
||||
|
||||
void LoadDBCStores(std::string dataPath);
|
||||
|
||||
// script support functions
|
||||
MANGOS_DLL_SPEC DBCStorage <SoundEntriesEntry> const* GetSoundEntriesStore();
|
||||
MANGOS_DLL_SPEC DBCStorage <SpellEntry> const* GetSpellStore();
|
||||
MANGOS_DLL_SPEC DBCStorage <SpellRangeEntry> const* GetSpellRangeStore();
|
||||
#endif
|
||||
868
src/shared/Database/DBCStructure.h
Normal file
868
src/shared/Database/DBCStructure.h
Normal file
|
|
@ -0,0 +1,868 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DBCSTRUCTURE_H
|
||||
#define DBCSTRUCTURE_H
|
||||
|
||||
#include "DBCEnums.h"
|
||||
#include "Platform/Define.h"
|
||||
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
// Structures using to access raw DBC data and required packing to portability
|
||||
|
||||
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
|
||||
#if defined( __GNUC__ )
|
||||
#pragma pack(1)
|
||||
#else
|
||||
#pragma pack(push,1)
|
||||
#endif
|
||||
|
||||
struct AreaTableEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
uint32 mapid; // 1
|
||||
uint32 zone; // 2 if 0 then it's zone, else it's zone id of this area
|
||||
uint32 exploreFlag; // 3, main index
|
||||
uint32 flags; // 4, unknown value but 312 for all cities
|
||||
// 5-9 unused
|
||||
int32 area_level; // 10
|
||||
char* area_name[16]; // 11-26
|
||||
// 27, string flags, unused
|
||||
uint32 team; // 28
|
||||
};
|
||||
|
||||
struct AreaTriggerEntry
|
||||
{
|
||||
uint32 id; // 0
|
||||
uint32 mapid; // 1
|
||||
float x; // 2
|
||||
float y; // 3
|
||||
float z; // 4
|
||||
float radius; // 5
|
||||
float box_x; // 6 extent x edge
|
||||
float box_y; // 7 extent y edge
|
||||
float box_z; // 8 extent z edge
|
||||
float box_orientation; // 9 extent rotation by about z axis
|
||||
};
|
||||
|
||||
struct BankBagSlotPricesEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 price;
|
||||
};
|
||||
|
||||
struct BattlemasterListEntry
|
||||
{
|
||||
uint32 id; // 0
|
||||
uint32 mapid[3]; // 1-3 mapid
|
||||
// 4-8 unused
|
||||
uint32 type; // 9 (3 - BG, 4 - arena)
|
||||
uint32 minlvl; // 10
|
||||
uint32 maxlvl; // 11
|
||||
uint32 maxplayersperteam; // 12
|
||||
// 13-14 unused
|
||||
char* name[16]; // 15-30
|
||||
// 31 string flag, unused
|
||||
// 32 unused
|
||||
};
|
||||
|
||||
struct CharTitlesEntry
|
||||
{
|
||||
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
|
||||
//uint32 unk1; // 1 flags?
|
||||
//char* name[16]; // 2-17, unused
|
||||
// 18 string flag, unused
|
||||
//char* name2[16]; // 19-34, unused
|
||||
// 35 string flag, unused
|
||||
uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
|
||||
};
|
||||
|
||||
struct ChatChannelsEntry
|
||||
{
|
||||
uint32 ChannelID; // 0
|
||||
uint32 flags; // 1
|
||||
char* pattern[16]; // 3-18
|
||||
// 19 string flags, unused
|
||||
//char* name[16]; // 20-35 unused
|
||||
// 36 string flag, unused
|
||||
};
|
||||
|
||||
struct ChrClassesEntry
|
||||
{
|
||||
uint32 ClassID; // 0
|
||||
// 1-2, unused
|
||||
uint32 powerType; // 3
|
||||
// 4, unused
|
||||
//char* name[16]; // 5-20 unused
|
||||
// 21 string flag, unused
|
||||
//char* string1[16]; // 21-36 unused
|
||||
// 37 string flag, unused
|
||||
//char* string2[16]; // 38-53 unused
|
||||
// 54 string flag, unused
|
||||
// 55, unused
|
||||
uint32 spellfamily; // 56
|
||||
// 57, unused
|
||||
};
|
||||
|
||||
struct ChrRacesEntry
|
||||
{
|
||||
uint32 RaceID; // 0
|
||||
// 1 unused
|
||||
uint32 FactionID; // 2 facton template id
|
||||
// 3 unused
|
||||
uint32 model_m; // 4
|
||||
uint32 model_f; // 5
|
||||
// 6-7 unused
|
||||
uint32 TeamID; // 8 (7-Alliance 1-Horde)
|
||||
// 9-12 unused
|
||||
uint32 startmovie; // 13 id from CinematicCamera.dbc
|
||||
char* name[16]; // 14-29 used for DBC language detection/selection
|
||||
// 30 string flags, unused
|
||||
//char* string1[16]; // 31-46 used for DBC language detection/selection
|
||||
// 47 string flags, unused
|
||||
//char* string2[16]; // 48-63 used for DBC language detection/selection
|
||||
// 64 string flags, unused
|
||||
// 65-67 unused
|
||||
uint32 addon; // 68 (0 - original race, 1 - tbc addon, ...)
|
||||
};
|
||||
|
||||
struct CreatureDisplayInfoEntry
|
||||
{
|
||||
uint32 Displayid; // 0
|
||||
// 1-3,unused
|
||||
float scale; // 4
|
||||
// 5-13,unused
|
||||
};
|
||||
|
||||
struct CreatureFamilyEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
float minScale; // 1
|
||||
uint32 minScaleLevel; // 2 0/1
|
||||
float maxScale; // 3
|
||||
uint32 maxScaleLevel; // 4 0/60
|
||||
uint32 skillLine[2]; // 5-6
|
||||
uint32 petFoodMask; // 7
|
||||
char* Name[16]; // 8-23
|
||||
// 24 string flags, unused
|
||||
// 25 icon, unused
|
||||
};
|
||||
|
||||
struct CreatureSpellDataEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//uint32 spellId[4]; // 1-4 hunter pet learned spell (for later use)
|
||||
};
|
||||
|
||||
struct DurabilityCostsEntry
|
||||
{
|
||||
uint32 Itemlvl; // 0
|
||||
uint32 multiplier[29]; // 1-29
|
||||
};
|
||||
|
||||
struct DurabilityQualityEntry
|
||||
{
|
||||
uint32 Id; // 0
|
||||
float quality_mod; // 1
|
||||
};
|
||||
|
||||
struct EmotesTextEntry
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 textid;
|
||||
};
|
||||
|
||||
struct FactionEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
int32 reputationListID; // 1
|
||||
uint32 BaseRepRaceMask[4]; // 2-5 Base reputation race masks (see enum Races)
|
||||
uint32 BaseRepClassMask[4]; // 6-9 Base reputation class masks (see enum Classes)
|
||||
int32 BaseRepValue[4]; // 10-13 Base reputation values
|
||||
uint32 ReputationFlags[4]; // 14-17 Default flags to apply
|
||||
uint32 team; // 18 enum Team
|
||||
char* name[16]; // 19-34
|
||||
// 35 string flags, unused
|
||||
//char* description[16]; // 36-51 unused
|
||||
// 52 string flags, unused
|
||||
};
|
||||
|
||||
struct FactionTemplateEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
uint32 faction; // 1
|
||||
uint32 factionFlags; // 2 specific flags for that faction
|
||||
uint32 ourMask; // 3 if mask set (see FactionMasks) then faction included in masked team
|
||||
uint32 friendlyMask; // 4 if mask set (see FactionMasks) then faction friendly to masked team
|
||||
uint32 hostileMask; // 5 if mask set (see FactionMasks) then faction hostile to masked team
|
||||
uint32 enemyFaction1; // 6
|
||||
uint32 enemyFaction2; // 7
|
||||
uint32 enemyFaction3; // 8
|
||||
uint32 enemyFaction4; // 9
|
||||
uint32 friendFaction1; // 10
|
||||
uint32 friendFaction2; // 11
|
||||
uint32 friendFaction3; // 12
|
||||
uint32 friendFaction4; // 13
|
||||
//------------------------------------------------------- end structure
|
||||
|
||||
// helpers
|
||||
bool IsFriendlyTo(FactionTemplateEntry const& entry) const
|
||||
{
|
||||
if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction )
|
||||
return false;
|
||||
if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction )
|
||||
return true;
|
||||
return (friendlyMask & entry.ourMask) || (ourMask & entry.friendlyMask);
|
||||
}
|
||||
bool IsHostileTo(FactionTemplateEntry const& entry) const
|
||||
{
|
||||
if(enemyFaction1 == entry.faction || enemyFaction2 == entry.faction || enemyFaction3 == entry.faction || enemyFaction4 == entry.faction )
|
||||
return true;
|
||||
if(friendFaction1 == entry.faction || friendFaction2 == entry.faction || friendFaction3 == entry.faction || friendFaction4 == entry.faction )
|
||||
return false;
|
||||
return (hostileMask & entry.ourMask) != 0;
|
||||
}
|
||||
bool IsHostileToPlayers() const { return (hostileMask & FACTION_MASK_PLAYER) !=0; }
|
||||
bool IsNeutralToAll() const { return hostileMask == 0 && friendlyMask == 0 && enemyFaction1==0 && enemyFaction2==0 && enemyFaction3==0 && enemyFaction4==0; }
|
||||
bool IsContestedGuardFaction() const { return (factionFlags & FACTION_TEMPLATE_FLAG_CONTESTED_GUARD)!=0; }
|
||||
};
|
||||
|
||||
struct GemPropertiesEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 spellitemenchantement;
|
||||
uint32 color;
|
||||
};
|
||||
|
||||
#define GT_MAX_LEVEL 100
|
||||
|
||||
struct GtCombatRatingsEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
struct GtChanceToMeleeCritBaseEntry
|
||||
{
|
||||
float base;
|
||||
};
|
||||
|
||||
struct GtChanceToMeleeCritEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
struct GtChanceToSpellCritBaseEntry
|
||||
{
|
||||
float base;
|
||||
};
|
||||
|
||||
struct GtChanceToSpellCritEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
struct GtOCTRegenHPEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
//struct GtOCTRegenMPEntry
|
||||
//{
|
||||
// float ratio;
|
||||
//};
|
||||
|
||||
struct GtRegenHPPerSptEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
struct GtRegenMPPerSptEntry
|
||||
{
|
||||
float ratio;
|
||||
};
|
||||
|
||||
struct ItemEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 DisplayId;
|
||||
uint32 InventoryType;
|
||||
uint32 Sheath;
|
||||
};
|
||||
|
||||
struct ItemDisplayInfoEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 randomPropertyChance;
|
||||
};
|
||||
|
||||
//struct ItemCondExtCostsEntry
|
||||
//{
|
||||
// uint32 ID;
|
||||
// uint32 condExtendedCost; // ItemPrototype::CondExtendedCost
|
||||
// uint32 itemextendedcostentry; // ItemPrototype::ExtendedCost
|
||||
// uint32 arenaseason; // arena season number(1-4)
|
||||
//};
|
||||
|
||||
struct ItemExtendedCostEntry
|
||||
{
|
||||
uint32 ID; // 0 extended-cost entry id
|
||||
uint32 reqhonorpoints; // 1 required honor points
|
||||
uint32 reqarenapoints; // 2 required arena points
|
||||
uint32 reqitem[5]; // 3-7 required item id
|
||||
uint32 reqitemcount[5]; // 8-12 required count of 1st item
|
||||
uint32 reqpersonalarenarating; // 13 required personal arena rating
|
||||
};
|
||||
|
||||
struct ItemRandomPropertiesEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//char* internalName // 1 unused
|
||||
uint32 enchant_id[3]; // 2-4
|
||||
// 5-6 unused, 0 only values, reserved for additional enchantments?
|
||||
//char* nameSuffix[16] // 7-22, unused
|
||||
// 23 nameSufix flags, unused
|
||||
};
|
||||
|
||||
struct ItemRandomSuffixEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//char* name[16] // 1-16 unused
|
||||
// 17, name flags, unused
|
||||
// 18 unused
|
||||
uint32 enchant_id[3]; // 19-21
|
||||
uint32 prefix[3]; // 22-24
|
||||
};
|
||||
|
||||
struct ItemSetEntry
|
||||
{
|
||||
//uint32 id // 0 item set ID
|
||||
char* name[16]; // 1-16
|
||||
// 17 string flags, unused
|
||||
// 18-28 items from set, but not have all items listed, use ItemPrototype::ItemSet instead
|
||||
// 29-34 unused
|
||||
uint32 spells[8]; // 35-42
|
||||
uint32 items_to_triggerspell[8]; // 43-50
|
||||
uint32 required_skill_id; // 51
|
||||
uint32 required_skill_value; // 52
|
||||
};
|
||||
|
||||
struct LockEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
uint32 keytype[5]; // 1-5
|
||||
// 6-8, not used
|
||||
uint32 key[5]; // 9-13
|
||||
// 14-16, not used
|
||||
uint32 requiredminingskill; // 17
|
||||
uint32 requiredlockskill; // 18
|
||||
// 19-32, not used
|
||||
};
|
||||
|
||||
struct MailTemplateEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//char* subject[16]; // 1-16
|
||||
// 17 name flags, unused
|
||||
//char* content[16]; // 18-33
|
||||
};
|
||||
|
||||
struct MapEntry
|
||||
{
|
||||
uint32 MapID; // 0
|
||||
//char* internalname; // 1 unused
|
||||
uint32 map_type; // 2
|
||||
// 3 unused
|
||||
char* name[16]; // 4-19
|
||||
// 20 name flags, unused
|
||||
// 21-23 unused (something PvPZone related - levels?)
|
||||
// 24-26
|
||||
uint32 linked_zone; // 27 common zone for instance and continent map
|
||||
//char* hordeIntro // 28-43 text for PvP Zones
|
||||
// 44 intro text flags
|
||||
//char* allianceIntro // 45-60 text for PvP Zones
|
||||
// 46 intro text flags
|
||||
// 47-61 not used
|
||||
uint32 multimap_id; // 62
|
||||
// 63-65 not used
|
||||
//chat* unknownText1 // 66-81 unknown empty text fields, possible normal Intro text.
|
||||
// 82 text flags
|
||||
//chat* heroicIntroText // 83-98 heroic mode requirement text
|
||||
// 99 text flags
|
||||
//chat* unknownText2 // 100-115 unknown empty text fields
|
||||
// 116 text flags
|
||||
int32 parent_map; // 117 map_id of parent map
|
||||
//float start_x // 118 enter x coordinate (if exist single entry)
|
||||
//float start_y // 119 enter y coordinate (if exist single entry)
|
||||
uint32 resetTimeRaid; // 120
|
||||
uint32 resetTimeHeroic; // 121
|
||||
// 122-123
|
||||
uint32 addon; // 124 (0-original maps,1-tbc addon)
|
||||
|
||||
// Helpers
|
||||
uint32 Expansion() const { return addon; }
|
||||
bool Instanceable() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
|
||||
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
|
||||
bool IsDungeon() const { return map_type == MAP_INSTANCE || map_type == MAP_RAID; }
|
||||
bool IsRaid() const { return map_type == MAP_RAID; }
|
||||
bool IsBattleGround() const { return map_type == MAP_BATTLEGROUND; }
|
||||
bool IsBattleArena() const { return map_type == MAP_ARENA; }
|
||||
bool IsBattleGroundOrArena() const { return map_type == MAP_BATTLEGROUND || map_type == MAP_ARENA; }
|
||||
bool SupportsHeroicMode() const { return resetTimeHeroic && !resetTimeRaid; }
|
||||
bool HasResetTime() const { return resetTimeHeroic || resetTimeRaid; }
|
||||
|
||||
bool IsMountAllowed() const
|
||||
{
|
||||
return !IsDungeon() ||
|
||||
MapID==568 || MapID==309 || MapID==209 || MapID==534 ||
|
||||
MapID==560 || MapID==509 || MapID==269;
|
||||
}
|
||||
};
|
||||
|
||||
struct QuestSortEntry
|
||||
{
|
||||
uint32 id; // 0, sort id
|
||||
//char* name[16]; // 1-16, unused
|
||||
// 17 name flags, unused
|
||||
};
|
||||
|
||||
struct RandomPropertiesPointsEntry
|
||||
{
|
||||
//uint32 Id; // 0 hidden key
|
||||
uint32 itemLevel; // 1
|
||||
uint32 EpicPropertiesPoints[5]; // 2-6
|
||||
uint32 RarePropertiesPoints[5]; // 7-11
|
||||
uint32 UncommonPropertiesPoints[5]; // 12-16
|
||||
};
|
||||
|
||||
//struct SkillLineCategoryEntry{
|
||||
// uint32 id; // 0 hidden key
|
||||
// char* name[16]; // 1 - 17 Category name
|
||||
// // 18 string flag
|
||||
// uint32 displayOrder; // Display order in character tab
|
||||
//};
|
||||
|
||||
//struct SkillRaceClassInfoEntry{
|
||||
// uint32 id; // 0
|
||||
// uint32 skillId; // 1 present some refrences to unknown skill
|
||||
// uint32 raceMask; // 2
|
||||
// uint32 classMask; // 3
|
||||
// uint32 flags; // 4 mask for some thing
|
||||
// uint32 reqLevel; // 5
|
||||
// uint32 skillTierId; // 6
|
||||
// uint32 skillCostID; // 7
|
||||
//};
|
||||
|
||||
//struct SkillTiersEntry{
|
||||
// uint32 id; // 0
|
||||
// uint32 skillValue[16]; // 1-17 unknown possibly add value on learn?
|
||||
// uint32 maxSkillValue[16]; // Max value for rank
|
||||
//};
|
||||
|
||||
struct SkillLineEntry
|
||||
{
|
||||
uint32 id; // 0
|
||||
uint32 categoryId; // 1 (index from SkillLineCategory.dbc)
|
||||
//uint32 skillCostID; // 2 not used
|
||||
char* name[16]; // 3-18
|
||||
// 19 string flags, not used
|
||||
//char* description[16]; // 20-35, not used
|
||||
// 36 string flags, not used
|
||||
uint32 spellIcon; // 37
|
||||
};
|
||||
|
||||
struct SkillLineAbilityEntry
|
||||
{
|
||||
uint32 id; // 0, INDEX
|
||||
uint32 skillId; // 1
|
||||
uint32 spellId; // 2
|
||||
uint32 racemask; // 3
|
||||
uint32 classmask; // 4
|
||||
//uint32 racemaskNot; // 5 always 0 in 2.4.2
|
||||
//uint32 classmaskNot; // 6 always 0 in 2.4.2
|
||||
uint32 req_skill_value; // 7 for trade skill.not for training.
|
||||
uint32 forward_spellid; // 8
|
||||
uint32 learnOnGetSkill; // 9 can be 1 or 2 for spells learned on get skill
|
||||
uint32 max_value; // 10
|
||||
uint32 min_value; // 11
|
||||
// 12-13, unknown, always 0
|
||||
uint32 reqtrainpoints; // 14
|
||||
};
|
||||
|
||||
struct SoundEntriesEntry
|
||||
{
|
||||
uint32 Id; // 0, sound id
|
||||
//uint32 Type; // 1, sound type (10 generally for creature, etc)
|
||||
//char* InternalName; // 2, internal name, for use in lookup command for example
|
||||
//char* FileName[10]; // 3-12, file names
|
||||
//uint32 Unk13[10]; // 13-22, linked with file names?
|
||||
//char* Path; // 23
|
||||
// 24-28, unknown
|
||||
};
|
||||
|
||||
struct SpellEntry
|
||||
{
|
||||
uint32 Id; // 0 normally counted from 0 field (but some tools start counting from 1, check this before tool use for data view!)
|
||||
uint32 Category; // 1
|
||||
//uint32 castUI // 2 not used
|
||||
uint32 Dispel; // 3
|
||||
uint32 Mechanic; // 4
|
||||
uint32 Attributes; // 5
|
||||
uint32 AttributesEx; // 6
|
||||
uint32 AttributesEx2; // 7
|
||||
uint32 AttributesEx3; // 8
|
||||
uint32 AttributesEx4; // 9
|
||||
uint32 AttributesEx5; // 10
|
||||
//uint32 AttributesEx6; // 11 not used
|
||||
uint32 Stances; // 12
|
||||
uint32 StancesNot; // 13
|
||||
uint32 Targets; // 14
|
||||
uint32 TargetCreatureType; // 15
|
||||
uint32 RequiresSpellFocus; // 16
|
||||
uint32 FacingCasterFlags; // 17
|
||||
uint32 CasterAuraState; // 18
|
||||
uint32 TargetAuraState; // 19
|
||||
uint32 CasterAuraStateNot; // 20
|
||||
uint32 TargetAuraStateNot; // 21
|
||||
uint32 CastingTimeIndex; // 22
|
||||
uint32 RecoveryTime; // 23
|
||||
uint32 CategoryRecoveryTime; // 24
|
||||
uint32 InterruptFlags; // 25
|
||||
uint32 AuraInterruptFlags; // 26
|
||||
uint32 ChannelInterruptFlags; // 27
|
||||
uint32 procFlags; // 28
|
||||
uint32 procChance; // 29
|
||||
uint32 procCharges; // 30
|
||||
uint32 maxLevel; // 31
|
||||
uint32 baseLevel; // 32
|
||||
uint32 spellLevel; // 33
|
||||
uint32 DurationIndex; // 34
|
||||
uint32 powerType; // 35
|
||||
uint32 manaCost; // 36
|
||||
uint32 manaCostPerlevel; // 37
|
||||
uint32 manaPerSecond; // 38
|
||||
uint32 manaPerSecondPerLevel; // 39
|
||||
uint32 rangeIndex; // 40
|
||||
float speed; // 41
|
||||
//uint32 modalNextSpell; // 42
|
||||
uint32 StackAmount; // 43
|
||||
uint32 Totem[2]; // 44-45
|
||||
int32 Reagent[8]; // 46-53
|
||||
uint32 ReagentCount[8]; // 54-61
|
||||
int32 EquippedItemClass; // 62 (value)
|
||||
int32 EquippedItemSubClassMask; // 63 (mask)
|
||||
int32 EquippedItemInventoryTypeMask; // 64 (mask)
|
||||
uint32 Effect[3]; // 65-67
|
||||
int32 EffectDieSides[3]; // 68-70
|
||||
uint32 EffectBaseDice[3]; // 71-73
|
||||
float EffectDicePerLevel[3]; // 74-76
|
||||
float EffectRealPointsPerLevel[3]; // 77-79
|
||||
int32 EffectBasePoints[3]; // 80-82 (don't must be used in spell/auras explicitly, must be used cached Spell::m_currentBasePoints)
|
||||
uint32 EffectMechanic[3]; // 83-85
|
||||
uint32 EffectImplicitTargetA[3]; // 86-88
|
||||
uint32 EffectImplicitTargetB[3]; // 89-91
|
||||
uint32 EffectRadiusIndex[3]; // 92-94 - spellradius.dbc
|
||||
uint32 EffectApplyAuraName[3]; // 95-97
|
||||
uint32 EffectAmplitude[3]; // 98-100
|
||||
float EffectMultipleValue[3]; // 101-103
|
||||
uint32 EffectChainTarget[3]; // 104-106
|
||||
uint32 EffectItemType[3]; // 107-109
|
||||
int32 EffectMiscValue[3]; // 110-112
|
||||
int32 EffectMiscValueB[3]; // 113-115
|
||||
uint32 EffectTriggerSpell[3]; // 116-118
|
||||
float EffectPointsPerComboPoint[3]; // 119-121
|
||||
uint32 SpellVisual; // 122
|
||||
// 123 not used
|
||||
uint32 SpellIconID; // 124
|
||||
uint32 activeIconID; // 125
|
||||
//uint32 spellPriority; // 126
|
||||
char* SpellName[16]; // 127-142
|
||||
//uint32 SpellNameFlag; // 143
|
||||
char* Rank[16]; // 144-159
|
||||
//uint32 RankFlags; // 160
|
||||
//char* Description[16]; // 161-176 not used
|
||||
//uint32 DescriptionFlags; // 177 not used
|
||||
//char* ToolTip[16]; // 178-193 not used
|
||||
//uint32 ToolTipFlags; // 194 not used
|
||||
uint32 ManaCostPercentage; // 195
|
||||
uint32 StartRecoveryCategory; // 196
|
||||
uint32 StartRecoveryTime; // 197
|
||||
uint32 MaxTargetLevel; // 198
|
||||
uint32 SpellFamilyName; // 199
|
||||
uint64 SpellFamilyFlags; // 200+201
|
||||
uint32 MaxAffectedTargets; // 202
|
||||
uint32 DmgClass; // 203 defenseType
|
||||
uint32 PreventionType; // 204
|
||||
//uint32 StanceBarOrder; // 205 not used
|
||||
float DmgMultiplier[3]; // 206-208
|
||||
//uint32 MinFactionId; // 209 not used, and 0 in 2.4.2
|
||||
//uint32 MinReputation; // 210 not used, and 0 in 2.4.2
|
||||
//uint32 RequiredAuraVision; // 211 not used
|
||||
uint32 TotemCategory[2]; // 212-213
|
||||
uint32 AreaId; // 214
|
||||
uint32 SchoolMask; // 215 school mask
|
||||
|
||||
private:
|
||||
// prevent creating custom entries (copy data from original in fact)
|
||||
SpellEntry(SpellEntry const&); // DON'T must have implementation
|
||||
};
|
||||
|
||||
typedef std::set<uint32> SpellCategorySet;
|
||||
typedef std::map<uint32,SpellCategorySet > SpellCategoryStore;
|
||||
typedef std::set<uint32> PetFamilySpellsSet;
|
||||
typedef std::map<uint32,PetFamilySpellsSet > PetFamilySpellsStore;
|
||||
|
||||
struct SpellCastTimesEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
int32 CastTime; // 1
|
||||
//float CastTimePerLevel; // 2 unsure / per skill?
|
||||
//int32 MinCastTime; // 3 unsure
|
||||
};
|
||||
|
||||
struct SpellFocusObjectEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//char* Name[16]; // 1-15 unused
|
||||
// 16 string flags, unused
|
||||
};
|
||||
|
||||
// stored in SQL table
|
||||
struct SpellThreatEntry
|
||||
{
|
||||
uint32 spellId;
|
||||
int32 threat;
|
||||
};
|
||||
|
||||
struct SpellRadiusEntry
|
||||
{
|
||||
uint32 ID;
|
||||
float Radius;
|
||||
float Radius2;
|
||||
};
|
||||
|
||||
struct SpellRangeEntry
|
||||
{
|
||||
uint32 ID;
|
||||
float minRange;
|
||||
float maxRange;
|
||||
};
|
||||
|
||||
struct SpellShapeshiftEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//uint32 buttonPosition; // 1 unused
|
||||
//char* Name[16]; // 2-17 unused
|
||||
//uint32 NameFlags; // 18 unused
|
||||
uint32 flags1; // 19
|
||||
int32 creatureType; // 20 <=0 humanoid, other normal creature types
|
||||
//uint32 unk1; // 21 unused
|
||||
uint32 attackSpeed; // 22
|
||||
//uint32 modelID; // 23 unused, alliance modelid (where horde case?)
|
||||
//uint32 unk2; // 24 unused
|
||||
//uint32 unk3; // 25 unused
|
||||
//uint32 unk4; // 26 unused
|
||||
//uint32 unk5; // 27 unused
|
||||
//uint32 unk6; // 28 unused
|
||||
//uint32 unk7; // 29 unused
|
||||
//uint32 unk8; // 30 unused
|
||||
//uint32 unk9; // 31 unused
|
||||
//uint32 unk10; // 32 unused
|
||||
//uint32 unk11; // 33 unused
|
||||
//uint32 unk12; // 34 unused
|
||||
};
|
||||
|
||||
struct SpellDurationEntry
|
||||
{
|
||||
uint32 ID;
|
||||
int32 Duration[3];
|
||||
};
|
||||
|
||||
struct SpellItemEnchantmentEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
uint32 type[3]; // 1-3
|
||||
uint32 amount[3]; // 4-6
|
||||
//uint32 amount2[3] // 7-9 always same as similar `amount` value
|
||||
uint32 spellid[3]; // 10-12
|
||||
char* description[16]; // 13-29
|
||||
// 30 description flags
|
||||
uint32 aura_id; // 31
|
||||
uint32 slot; // 32
|
||||
uint32 GemID; // 33
|
||||
uint32 EnchantmentCondition; // 34
|
||||
};
|
||||
|
||||
struct SpellItemEnchantmentConditionEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint8 Color[5];
|
||||
uint8 Comparator[5];
|
||||
uint8 CompareColor[5];
|
||||
uint32 Value[5];
|
||||
};
|
||||
|
||||
struct StableSlotPricesEntry
|
||||
{
|
||||
uint32 Slot;
|
||||
uint32 Price;
|
||||
};
|
||||
|
||||
struct TalentEntry
|
||||
{
|
||||
uint32 TalentID; // 0
|
||||
uint32 TalentTab; // 1 index in TalentTab.dbc (TalentTabEntry)
|
||||
uint32 Row; // 2
|
||||
uint32 Col; // 3
|
||||
uint32 RankID[5]; // 4-8
|
||||
// 9-12 not used, always 0, maybe not used high ranks
|
||||
uint32 DependsOn; // 13 index in Talent.dbc (TalentEntry)
|
||||
// 14-15 not used
|
||||
uint32 DependsOnRank; // 16
|
||||
// 17-19 not used
|
||||
uint32 DependsOnSpell; // 20 req.spell
|
||||
};
|
||||
|
||||
struct TalentTabEntry
|
||||
{
|
||||
uint32 TalentTabID; // 0
|
||||
//char* name[16]; // 1-16, unused
|
||||
//uint32 nameFlags; // 17, unused
|
||||
//unit32 spellicon; // 18
|
||||
// 19 not used
|
||||
uint32 ClassMask; // 20
|
||||
uint32 tabpage; // 21
|
||||
//char* internalname; // 22
|
||||
};
|
||||
|
||||
struct TaxiNodesEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
uint32 map_id; // 1
|
||||
float x; // 2
|
||||
float y; // 3
|
||||
float z; // 4
|
||||
//char* name[16]; // 5-21
|
||||
// 22 string flags, unused
|
||||
uint32 horde_mount_type; // 23
|
||||
uint32 alliance_mount_type; // 24
|
||||
};
|
||||
|
||||
struct TaxiPathEntry
|
||||
{
|
||||
uint32 ID;
|
||||
uint32 from;
|
||||
uint32 to;
|
||||
uint32 price;
|
||||
};
|
||||
|
||||
struct TaxiPathNodeEntry
|
||||
{
|
||||
uint32 path;
|
||||
uint32 index;
|
||||
uint32 mapid;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32 actionFlag;
|
||||
uint32 delay;
|
||||
};
|
||||
|
||||
struct TotemCategoryEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
//char* name[16]; // 1-16
|
||||
// 17 string flags, unused
|
||||
uint32 categoryType; // 18 (one for specialization)
|
||||
uint32 categoryMask; // 19 (compatibility mask for same type: different for totems, compatible from high to low for rods)
|
||||
};
|
||||
|
||||
struct WorldMapAreaEntry
|
||||
{
|
||||
//uint32 ID; // 0
|
||||
uint32 map_id; // 1
|
||||
uint32 area_id; // 2 index (continent 0 areas ignored)
|
||||
//char* internal_name // 3
|
||||
float y1; // 4
|
||||
float y2; // 5
|
||||
float x1; // 6
|
||||
float x2; // 7
|
||||
int32 virtual_map_id; // 8 -1 (map_id have correct map) other: virtual map where zone show (map_id - where zone in fact internally)
|
||||
};
|
||||
|
||||
struct WorldSafeLocsEntry
|
||||
{
|
||||
uint32 ID; // 0
|
||||
uint32 map_id; // 1
|
||||
float x; // 2
|
||||
float y; // 3
|
||||
float z; // 4
|
||||
//char* name[16] // 5-20 name, unused
|
||||
// 21 name flags, unused
|
||||
};
|
||||
|
||||
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
|
||||
#if defined( __GNUC__ )
|
||||
#pragma pack()
|
||||
#else
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
// Structures not used for casting to loaded DBC data and not required then packing
|
||||
struct TalentSpellPos
|
||||
{
|
||||
TalentSpellPos() : talent_id(0), rank(0) {}
|
||||
TalentSpellPos(uint16 _talent_id, uint8 _rank) : talent_id(_talent_id), rank(_rank) {}
|
||||
|
||||
uint16 talent_id;
|
||||
uint8 rank;
|
||||
};
|
||||
|
||||
typedef std::map<uint32,TalentSpellPos> TalentSpellPosMap;
|
||||
|
||||
struct TaxiPathBySourceAndDestination
|
||||
{
|
||||
TaxiPathBySourceAndDestination() : ID(0),price(0) {}
|
||||
TaxiPathBySourceAndDestination(uint32 _id,uint32 _price) : ID(_id),price(_price) {}
|
||||
|
||||
uint32 ID;
|
||||
uint32 price;
|
||||
};
|
||||
typedef std::map<uint32,TaxiPathBySourceAndDestination> TaxiPathSetForSource;
|
||||
typedef std::map<uint32,TaxiPathSetForSource> TaxiPathSetBySource;
|
||||
|
||||
struct TaxiPathNode
|
||||
{
|
||||
TaxiPathNode() : mapid(0), x(0),y(0),z(0),actionFlag(0),delay(0) {}
|
||||
TaxiPathNode(uint32 _mapid, float _x, float _y, float _z, uint32 _actionFlag, uint32 _delay) : mapid(_mapid), x(_x),y(_y),z(_z),actionFlag(_actionFlag),delay(_delay) {}
|
||||
|
||||
uint32 mapid;
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
uint32 actionFlag;
|
||||
uint32 delay;
|
||||
};
|
||||
typedef std::vector<TaxiPathNode> TaxiPathNodeList;
|
||||
typedef std::vector<TaxiPathNodeList> TaxiPathNodesByPath;
|
||||
|
||||
#define TaxiMaskSize 16
|
||||
typedef uint32 TaxiMask[TaxiMaskSize];
|
||||
#endif
|
||||
78
src/shared/Database/DBCfmt.cpp
Normal file
78
src/shared/Database/DBCfmt.cpp
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
const char AreaTableEntryfmt[]="iiinixxxxxissssssssssssssssxixxxxxx";
|
||||
const char AreaTriggerEntryfmt[]="niffffffff";
|
||||
const char BankBagSlotPricesEntryfmt[]="ni";
|
||||
const char BattlemasterListEntryfmt[]="niiixxxxxiiiixxssssssssssssssssxx";
|
||||
const char CharTitlesEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
|
||||
const char ChatChannelsEntryfmt[]="iixssssssssssssssssxxxxxxxxxxxxxxxxxx";
|
||||
// ChatChannelsEntryfmt, index not used (more compact store)
|
||||
const char ChrClassesEntryfmt[]="nxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxix";
|
||||
const char ChrRacesEntryfmt[]="nxixiixxixxxxissssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";
|
||||
const char CreatureDisplayInfofmt[]="nxxxfxxxxxxxxx";
|
||||
const char CreatureFamilyfmt[]="nfifiiiissssssssssssssssxx";
|
||||
const char CreatureSpellDatafmt[]="nxxxxxxxx";
|
||||
const char DurabilityCostsfmt[]="niiiiiiiiiiiiiiiiiiiiiiiiiiiii";
|
||||
const char DurabilityQualityfmt[]="nf";
|
||||
const char EmoteEntryfmt[]="nxixxxxxxxxxxxxxxxx";
|
||||
const char FactionEntryfmt[]="niiiiiiiiiiiiiiiiiissssssssssssssssxxxxxxxxxxxxxxxxxx";
|
||||
const char FactionTemplateEntryfmt[]="niiiiiiiiiiiii";
|
||||
const char GemPropertiesEntryfmt[]="nixxi";
|
||||
const char GtCombatRatingsfmt[]="f";
|
||||
const char GtChanceToMeleeCritBasefmt[]="f";
|
||||
const char GtChanceToMeleeCritfmt[]="f";
|
||||
const char GtChanceToSpellCritBasefmt[]="f";
|
||||
const char GtChanceToSpellCritfmt[]="f";
|
||||
const char GtOCTRegenHPfmt[]="f";
|
||||
//const char GtOCTRegenMPfmt[]="f";
|
||||
const char GtRegenHPPerSptfmt[]="f";
|
||||
const char GtRegenMPPerSptfmt[]="f";
|
||||
const char Itemfmt[]="niii";
|
||||
//const char ItemDisplayTemplateEntryfmt[]="nxxxxxxxxxxixxxxxxxxxxx";
|
||||
//const char ItemCondExtCostsEntryfmt[]="xiii";
|
||||
const char ItemExtendedCostEntryfmt[]="niiiiiiiiiiiii";
|
||||
const char ItemRandomPropertiesfmt[]="nxiiixxxxxxxxxxxxxxxxxxx";
|
||||
const char ItemRandomSuffixfmt[]="nxxxxxxxxxxxxxxxxxxiiiiii";
|
||||
const char ItemSetEntryfmt[]="dssssssssssssssssxxxxxxxxxxxxxxxxxxiiiiiiiiiiiiiiiiii";
|
||||
const char LockEntryfmt[]="niiiiixxxiiiiixxxiixxxxxxxxxxxxxx";
|
||||
const char MailTemplateEntryfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
const char MapEntryfmt[]="nxixssssssssssssssssxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxiixxi";
|
||||
const char QuestSortEntryfmt[]="nxxxxxxxxxxxxxxxxx";
|
||||
const char RandomPropertiesPointsfmt[]="niiiiiiiiiiiiiii";
|
||||
const char SkillLinefmt[]="nixssssssssssssssssxxxxxxxxxxxxxxxxxxi";
|
||||
const char SkillLineAbilityfmt[]="niiiixxiiiiixxi";
|
||||
const char SoundEntriesfmt[]="nxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
const char SpellCastTimefmt[]="nixx";
|
||||
const char SpellDurationfmt[]="niii";
|
||||
const char SpellEntryfmt[]="nixiiiiiiiixiiiiiiiiiiiiiiiiiiiiiiiiiiiiifxiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffffffiiiiiiiiiiiiiiiiiiiiifffiiiiiiiiiiiiiiifffixiixssssssssssssssssxssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiiiiiiiiiixfffxxxiiii";
|
||||
const char SpellFocusObjectfmt[]="nxxxxxxxxxxxxxxxxx";
|
||||
const char SpellItemEnchantmentfmt[]="niiiiiixxxiiissssssssssssssssxiiii";
|
||||
const char SpellItemEnchantmentConditionfmt[]="nbbbbbxxxxxbbbbbbbbbbiiiiiXXXXX";
|
||||
const char SpellRadiusfmt[]="nfxf";
|
||||
const char SpellRangefmt[]="nffxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
|
||||
const char SpellShapeshiftfmt[]="nxxxxxxxxxxxxxxxxxxiixixxxxxxxxxxxx";
|
||||
const char StableSlotPricesfmt[] = "ni";
|
||||
const char TalentEntryfmt[]="niiiiiiiixxxxixxixxxi";
|
||||
const char TalentTabEntryfmt[]="nxxxxxxxxxxxxxxxxxxxiix";
|
||||
const char TaxiNodesEntryfmt[]="nifffxxxxxxxxxxxxxxxxxii";
|
||||
const char TaxiPathEntryfmt[]="niii";
|
||||
const char TaxiPathNodeEntryfmt[]="diiifffiixx";
|
||||
const char TotemCategoryEntryfmt[]="nxxxxxxxxxxxxxxxxxii";
|
||||
const char WorldMapAreaEntryfmt[]="xinxffffi";
|
||||
const char WorldSafeLocsEntryfmt[]="nifffxxxxxxxxxxxxxxxxx";
|
||||
171
src/shared/Database/Database.cpp
Normal file
171
src/shared/Database/Database.cpp
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
Database::~Database()
|
||||
{
|
||||
/*Delete objects*/
|
||||
}
|
||||
|
||||
bool Database::Initialize(const char *)
|
||||
{
|
||||
// Enable logging of SQL commands (usally only GM commands)
|
||||
// (See method: PExecuteLog)
|
||||
m_logSQL = sConfig.GetBoolDefault("LogSQL", false);
|
||||
m_logsDir = sConfig.GetStringDefault("LogsDir","");
|
||||
if(!m_logsDir.empty())
|
||||
{
|
||||
if((m_logsDir.at(m_logsDir.length()-1)!='/') && (m_logsDir.at(m_logsDir.length()-1)!='\\'))
|
||||
m_logsDir.append("/");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Database::ThreadStart()
|
||||
{
|
||||
}
|
||||
|
||||
void Database::ThreadEnd()
|
||||
{
|
||||
}
|
||||
|
||||
void Database::escape_string(std::string& str)
|
||||
{
|
||||
if(str.empty())
|
||||
return;
|
||||
|
||||
char* buf = new char[str.size()*2+1];
|
||||
escape_string(buf,str.c_str(),str.size());
|
||||
str = buf;
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
bool Database::PExecuteLog(const char * format,...)
|
||||
{
|
||||
if (!format)
|
||||
return false;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
if( m_logSQL )
|
||||
{
|
||||
time_t curr;
|
||||
tm local;
|
||||
time(&curr); // get current time_t value
|
||||
local=*(localtime(&curr)); // dereference and assign
|
||||
char fName[128];
|
||||
sprintf( fName, "%04d-%02d-%02d_logSQL.sql", local.tm_year+1900, local.tm_mon+1, local.tm_mday );
|
||||
|
||||
FILE* log_file;
|
||||
std::string logsDir_fname = m_logsDir+fName;
|
||||
log_file = fopen(logsDir_fname.c_str(), "a");
|
||||
if (log_file)
|
||||
{
|
||||
fprintf(log_file, "%s;\n", szQuery);
|
||||
fclose(log_file);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The file could not be opened
|
||||
sLog.outError("SQL-Logging is disabled - Log file for the SQL commands could not be openend: %s",fName);
|
||||
}
|
||||
}
|
||||
|
||||
return Execute(szQuery);
|
||||
}
|
||||
|
||||
void Database::SetResultQueue(SqlResultQueue * queue)
|
||||
{
|
||||
m_queryQueues[ZThread::ThreadImpl::current()] = queue;
|
||||
}
|
||||
|
||||
QueryResult* Database::PQuery(const char *format,...)
|
||||
{
|
||||
if(!format) return NULL;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return Query(szQuery);
|
||||
}
|
||||
|
||||
bool Database::PExecute(const char * format,...)
|
||||
{
|
||||
if (!format)
|
||||
return false;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return Execute(szQuery);
|
||||
}
|
||||
|
||||
bool Database::DirectPExecute(const char * format,...)
|
||||
{
|
||||
if (!format)
|
||||
return false;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return DirectExecute(szQuery);
|
||||
}
|
||||
113
src/shared/Database/Database.h
Normal file
113
src/shared/Database/Database.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DATABASE_H
|
||||
#define DATABASE_H
|
||||
|
||||
#include "zthread/Thread.h"
|
||||
#include "../src/zthread/ThreadImpl.h"
|
||||
#include "Utilities/HashMap.h"
|
||||
#include "Database/SqlDelayThread.h"
|
||||
|
||||
class SqlTransaction;
|
||||
class SqlResultQueue;
|
||||
class SqlQueryHolder;
|
||||
|
||||
typedef HM_NAMESPACE::hash_map<ZThread::ThreadImpl*, SqlTransaction*> TransactionQueues;
|
||||
typedef HM_NAMESPACE::hash_map<ZThread::ThreadImpl*, SqlResultQueue*> QueryQueues;
|
||||
|
||||
#define MAX_QUERY_LEN 1024
|
||||
|
||||
class MANGOS_DLL_SPEC Database
|
||||
{
|
||||
protected:
|
||||
Database() : m_threadBody(NULL), m_delayThread(NULL) {};
|
||||
|
||||
TransactionQueues m_tranQueues; ///< Transaction queues from diff. threads
|
||||
QueryQueues m_queryQueues; ///< Query queues from diff threads
|
||||
SqlDelayThread* m_threadBody; ///< Pointer to delay sql executer
|
||||
ZThread::Thread* m_delayThread; ///< Pointer to executer thread
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Database();
|
||||
|
||||
virtual bool Initialize(const char *infoString);
|
||||
virtual void InitDelayThread() = 0;
|
||||
virtual void HaltDelayThread() = 0;
|
||||
|
||||
virtual QueryResult* Query(const char *sql) = 0;
|
||||
QueryResult* PQuery(const char *format,...) ATTR_PRINTF(2,3);
|
||||
|
||||
/// Async queries and query holders, implemented in DatabaseImpl.h
|
||||
template<class Class>
|
||||
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql);
|
||||
template<class Class, typename ParamType1>
|
||||
bool AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql);
|
||||
template<typename ParamType1>
|
||||
bool AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql);
|
||||
template<class Class>
|
||||
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...) ATTR_PRINTF(4,5);
|
||||
template<class Class, typename ParamType1>
|
||||
bool AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
|
||||
template<typename ParamType1>
|
||||
bool AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...) ATTR_PRINTF(5,6);
|
||||
template<class Class>
|
||||
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder);
|
||||
template<class Class, typename ParamType1>
|
||||
bool DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1);
|
||||
|
||||
virtual bool Execute(const char *sql) = 0;
|
||||
bool PExecute(const char *format,...) ATTR_PRINTF(2,3);
|
||||
virtual bool DirectExecute(const char* sql) = 0;
|
||||
bool DirectPExecute(const char *format,...) ATTR_PRINTF(2,3);
|
||||
|
||||
// Writes SQL commands to a LOG file (see mangosd.conf "LogSQL")
|
||||
bool PExecuteLog(const char *format,...) ATTR_PRINTF(2,3);
|
||||
|
||||
virtual bool BeginTransaction() // nothing do if DB not support transactions
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool CommitTransaction() // nothing do if DB not support transactions
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual bool RollbackTransaction() // can't rollback without transaction support
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual operator bool () const = 0;
|
||||
|
||||
virtual unsigned long escape_string(char *to, const char *from, unsigned long length) { strncpy(to,from,length); return length; }
|
||||
void escape_string(std::string& str);
|
||||
|
||||
// must be called before first query in thread (one time for thread using one from existed Database objects)
|
||||
virtual void ThreadStart();
|
||||
// must be called before finish thread run (one time for thread using one from existed Database objects)
|
||||
virtual void ThreadEnd();
|
||||
|
||||
// sets the result queue of the current thread, be careful what thread you call this from
|
||||
void SetResultQueue(SqlResultQueue * queue);
|
||||
|
||||
private:
|
||||
bool m_logSQL;
|
||||
std::string m_logsDir;
|
||||
};
|
||||
#endif
|
||||
54
src/shared/Database/DatabaseEnv.h
Normal file
54
src/shared/Database/DatabaseEnv.h
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if !defined(DATABASEENV_H)
|
||||
#define DATABASEENV_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
#include "Errors.h"
|
||||
|
||||
#include "Database/DBCStores.h"
|
||||
#include "Database/Field.h"
|
||||
#include "Database/QueryResult.h"
|
||||
|
||||
#ifdef DO_POSTGRESQL
|
||||
#include "Database/QueryResultPostgre.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/DatabasePostgre.h"
|
||||
typedef DatabasePostgre DatabaseType;
|
||||
#define _LIKE_ "ILIKE"
|
||||
#define _TABLE_SIM_ "\""
|
||||
#define _CONCAT3_(A,B,C) "( " A " || " B " || " C " )"
|
||||
#else
|
||||
#include "Database/QueryResultMysql.h"
|
||||
#include "Database/QueryResultSqlite.h"
|
||||
#include "Database/Database.h"
|
||||
#include "Database/DatabaseMysql.h"
|
||||
#include "Database/DatabaseSqlite.h"
|
||||
typedef DatabaseMysql DatabaseType;
|
||||
#define _LIKE_ "LIKE"
|
||||
#define _TABLE_SIM_ "`"
|
||||
#define _CONCAT3_(A,B,C) "CONCAT( " A " , " B " , " C " )"
|
||||
#endif
|
||||
|
||||
extern DatabaseType WorldDatabase;
|
||||
extern DatabaseType CharacterDatabase;
|
||||
extern DatabaseType loginDatabase;
|
||||
|
||||
#endif
|
||||
145
src/shared/Database/DatabaseImpl.h
Normal file
145
src/shared/Database/DatabaseImpl.h
Normal file
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Database/Database.h"
|
||||
#include "Database/SqlOperations.h"
|
||||
|
||||
/// Function body definitions for the template function members of the Database class
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*), const char *sql)
|
||||
{
|
||||
if (!sql) return false;
|
||||
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
|
||||
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
|
||||
if (itr == m_queryQueues.end()) return false;
|
||||
m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback<Class>(object, method), itr->second));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
Database::AsyncQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql)
|
||||
{
|
||||
if (!sql) return false;
|
||||
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
|
||||
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
|
||||
if (itr == m_queryQueues.end()) return false;
|
||||
m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::QueryCallback<Class, ParamType1>(object, method, (QueryResult*)NULL, param1), itr->second));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename ParamType1>
|
||||
bool
|
||||
Database::AsyncQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *sql)
|
||||
{
|
||||
if (!sql) return false;
|
||||
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
|
||||
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
|
||||
if (itr == m_queryQueues.end()) return false;
|
||||
m_threadBody->Delay(new SqlQuery(sql, new MaNGOS::SQueryCallback<ParamType1>(method, (QueryResult*)NULL, param1), itr->second));
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*), const char *format,...)
|
||||
{
|
||||
if(!format) return false;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return AsyncQuery(object, method, szQuery);
|
||||
}
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
Database::AsyncPQuery(Class *object, void (Class::*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...)
|
||||
{
|
||||
if(!format) return false;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return AsyncQuery(object, method, param1, szQuery);
|
||||
}
|
||||
|
||||
template<typename ParamType1>
|
||||
bool
|
||||
Database::AsyncPQuery(void (*method)(QueryResult*, ParamType1), ParamType1 param1, const char *format,...)
|
||||
{
|
||||
if(!format) return false;
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return AsyncQuery(method, param1, szQuery);
|
||||
}
|
||||
|
||||
template<class Class>
|
||||
bool
|
||||
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*), SqlQueryHolder *holder)
|
||||
{
|
||||
if (!holder) return false;
|
||||
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
|
||||
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
|
||||
if (itr == m_queryQueues.end()) return false;
|
||||
holder->Execute(new MaNGOS::QueryCallback<Class, SqlQueryHolder*>(object, method, (QueryResult*)NULL, holder), m_threadBody, itr->second);
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Class, typename ParamType1>
|
||||
bool
|
||||
Database::DelayQueryHolder(Class *object, void (Class::*method)(QueryResult*, SqlQueryHolder*, ParamType1), SqlQueryHolder *holder, ParamType1 param1)
|
||||
{
|
||||
if (!holder) return false;
|
||||
ZThread::ThreadImpl * queryThread = ZThread::ThreadImpl::current();
|
||||
QueryQueues::iterator itr = m_queryQueues.find(queryThread);
|
||||
if (itr == m_queryQueues.end()) return false;
|
||||
holder->Execute(new MaNGOS::QueryCallback<Class, SqlQueryHolder*, ParamType1>(object, method, (QueryResult*)NULL, holder, param1), m_threadBody, itr->second);
|
||||
return true;
|
||||
}
|
||||
408
src/shared/Database/DatabaseMysql.cpp
Normal file
408
src/shared/Database/DatabaseMysql.cpp
Normal file
|
|
@ -0,0 +1,408 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#include "Util.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Platform/Define.h"
|
||||
#include "../src/zthread/ThreadImpl.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Database/MySQLDelayThread.h"
|
||||
#include "Database/SqlOperations.h"
|
||||
#include "Timer.h"
|
||||
|
||||
void DatabaseMysql::ThreadStart()
|
||||
{
|
||||
mysql_thread_init();
|
||||
}
|
||||
|
||||
void DatabaseMysql::ThreadEnd()
|
||||
{
|
||||
mysql_thread_end();
|
||||
}
|
||||
|
||||
size_t DatabaseMysql::db_count = 0;
|
||||
|
||||
DatabaseMysql::DatabaseMysql() : Database(), mMysql(0)
|
||||
{
|
||||
// before first connection
|
||||
if( db_count++ == 0 )
|
||||
{
|
||||
// Mysql Library Init
|
||||
mysql_library_init(-1, NULL, NULL);
|
||||
|
||||
if (!mysql_thread_safe())
|
||||
{
|
||||
sLog.outError("FATAL ERROR: Used MySQL library isn't thread-safe.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DatabaseMysql::~DatabaseMysql()
|
||||
{
|
||||
if (m_delayThread)
|
||||
HaltDelayThread();
|
||||
|
||||
if (mMysql)
|
||||
mysql_close(mMysql);
|
||||
|
||||
//Free Mysql library pointers for last ~DB
|
||||
if(--db_count == 0)
|
||||
mysql_library_end();
|
||||
}
|
||||
|
||||
bool DatabaseMysql::Initialize(const char *infoString)
|
||||
{
|
||||
|
||||
if(!Database::Initialize(infoString))
|
||||
return false;
|
||||
|
||||
tranThread = NULL;
|
||||
MYSQL *mysqlInit;
|
||||
mysqlInit = mysql_init(NULL);
|
||||
if (!mysqlInit)
|
||||
{
|
||||
sLog.outError( "Could not initialize Mysql connection" );
|
||||
return false;
|
||||
}
|
||||
|
||||
InitDelayThread();
|
||||
|
||||
Tokens tokens = StrSplit(infoString, ";");
|
||||
|
||||
Tokens::iterator iter;
|
||||
|
||||
std::string host, port_or_socket, user, password, database;
|
||||
int port;
|
||||
char const* unix_socket;
|
||||
|
||||
iter = tokens.begin();
|
||||
|
||||
if(iter != tokens.end())
|
||||
host = *iter++;
|
||||
if(iter != tokens.end())
|
||||
port_or_socket = *iter++;
|
||||
if(iter != tokens.end())
|
||||
user = *iter++;
|
||||
if(iter != tokens.end())
|
||||
password = *iter++;
|
||||
if(iter != tokens.end())
|
||||
database = *iter++;
|
||||
|
||||
mysql_options(mysqlInit,MYSQL_SET_CHARSET_NAME,"utf8");
|
||||
#ifdef WIN32
|
||||
if(host==".") // named pipe use option (Windows)
|
||||
{
|
||||
unsigned int opt = MYSQL_PROTOCOL_PIPE;
|
||||
mysql_options(mysqlInit,MYSQL_OPT_PROTOCOL,(char const*)&opt);
|
||||
port = 0;
|
||||
unix_socket = 0;
|
||||
}
|
||||
else // generic case
|
||||
{
|
||||
port = atoi(port_or_socket.c_str());
|
||||
unix_socket = 0;
|
||||
}
|
||||
#else
|
||||
if(host==".") // socket use option (Unix/Linux)
|
||||
{
|
||||
unsigned int opt = MYSQL_PROTOCOL_SOCKET;
|
||||
mysql_options(mysqlInit,MYSQL_OPT_PROTOCOL,(char const*)&opt);
|
||||
host = "localhost";
|
||||
port = 0;
|
||||
unix_socket = port_or_socket.c_str();
|
||||
}
|
||||
else // generic case
|
||||
{
|
||||
port = atoi(port_or_socket.c_str());
|
||||
unix_socket = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
mMysql = mysql_real_connect(mysqlInit, host.c_str(), user.c_str(),
|
||||
password.c_str(), database.c_str(), port, unix_socket, 0);
|
||||
|
||||
if (mMysql)
|
||||
{
|
||||
sLog.outDetail( "Connected to MySQL database at %s",
|
||||
host.c_str());
|
||||
sLog.outString( "MySQL client library: %s", mysql_get_client_info());
|
||||
sLog.outString( "MySQL server ver: %s ", mysql_get_server_info( mMysql));
|
||||
|
||||
/*----------SET AUTOCOMMIT ON---------*/
|
||||
// It seems mysql 5.0.x have enabled this feature
|
||||
// by default. In crash case you can lose data!!!
|
||||
// So better to turn this off
|
||||
// ---
|
||||
// This is wrong since mangos use transactions,
|
||||
// autocommit is turned of during it.
|
||||
// Setting it to on makes atomic updates work
|
||||
if (!mysql_autocommit(mMysql, 1))
|
||||
sLog.outDetail("AUTOCOMMIT SUCCESSFULLY SET TO 1");
|
||||
else
|
||||
sLog.outDetail("AUTOCOMMIT NOT SET TO 1");
|
||||
/*-------------------------------------*/
|
||||
|
||||
// set connection properties to UTF8 to properly handle locales for different
|
||||
// server configs - core sends data in UTF8, so MySQL must expect UTF8 too
|
||||
PExecute("SET NAMES `utf8`");
|
||||
PExecute("SET CHARACTER SET `utf8`");
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outError( "Could not connect to MySQL database at %s: %s\n",
|
||||
host.c_str(),mysql_error(mysqlInit));
|
||||
mysql_close(mysqlInit);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
QueryResult* DatabaseMysql::Query(const char *sql)
|
||||
{
|
||||
if (!mMysql)
|
||||
return 0;
|
||||
|
||||
MYSQL_RES *result = 0;
|
||||
uint64 rowCount = 0;
|
||||
uint32 fieldCount = 0;
|
||||
|
||||
{
|
||||
// guarded block for thread-safe mySQL request
|
||||
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
|
||||
#ifdef MANGOS_DEBUG
|
||||
uint32 _s = getMSTime();
|
||||
#endif
|
||||
if(mysql_query(mMysql, sql))
|
||||
{
|
||||
sLog.outErrorDb( "SQL: %s", sql );
|
||||
sLog.outErrorDb("query ERROR: %s", mysql_error(mMysql));
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MANGOS_DEBUG
|
||||
sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql );
|
||||
#endif
|
||||
}
|
||||
|
||||
result = mysql_store_result(mMysql);
|
||||
|
||||
rowCount = mysql_affected_rows(mMysql);
|
||||
fieldCount = mysql_field_count(mMysql);
|
||||
// end guarded block
|
||||
}
|
||||
|
||||
if (!result )
|
||||
return NULL;
|
||||
|
||||
if (!rowCount)
|
||||
{
|
||||
mysql_free_result(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QueryResultMysql *queryResult = new QueryResultMysql(result, rowCount, fieldCount);
|
||||
|
||||
queryResult->NextRow();
|
||||
|
||||
return queryResult;
|
||||
}
|
||||
|
||||
bool DatabaseMysql::Execute(const char *sql)
|
||||
{
|
||||
if (!mMysql)
|
||||
return false;
|
||||
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody) return DirectExecute(sql);
|
||||
|
||||
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
{ // Statement for transaction
|
||||
i->second->DelayExecute(sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple sql statement
|
||||
m_threadBody->Delay(new SqlStatement(sql));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabaseMysql::DirectExecute(const char* sql)
|
||||
{
|
||||
if (!mMysql)
|
||||
return false;
|
||||
|
||||
{
|
||||
// guarded block for thread-safe mySQL request
|
||||
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
|
||||
#ifdef MANGOS_DEBUG
|
||||
uint32 _s = getMSTime();
|
||||
#endif
|
||||
if(mysql_query(mMysql, sql))
|
||||
{
|
||||
sLog.outErrorDb("SQL: %s", sql);
|
||||
sLog.outErrorDb("SQL ERROR: %s", mysql_error(mMysql));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MANGOS_DEBUG
|
||||
sLog.outDebug("[%u ms] SQL: %s", getMSTimeDiff(_s,getMSTime()), sql );
|
||||
#endif
|
||||
}
|
||||
// end guarded block
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabaseMysql::_TransactionCmd(const char *sql)
|
||||
{
|
||||
if (mysql_query(mMysql, sql))
|
||||
{
|
||||
sLog.outError("SQL: %s", sql);
|
||||
sLog.outError("SQL ERROR: %s", mysql_error(mMysql));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("SQL: %s", sql);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabaseMysql::BeginTransaction()
|
||||
{
|
||||
if (!mMysql)
|
||||
return false;
|
||||
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody)
|
||||
{
|
||||
if (tranThread==ZThread::ThreadImpl::current())
|
||||
return false; // huh? this thread already started transaction
|
||||
mMutex.acquire();
|
||||
if (!_TransactionCmd("START TRANSACTION"))
|
||||
{
|
||||
mMutex.release(); // can't start transaction
|
||||
return false;
|
||||
}
|
||||
return true; // transaction started
|
||||
}
|
||||
|
||||
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
// If for thread exists queue and also contains transaction
|
||||
// delete that transaction (not allow trans in trans)
|
||||
delete i->second;
|
||||
|
||||
m_tranQueues[tranThread] = new SqlTransaction();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabaseMysql::CommitTransaction()
|
||||
{
|
||||
if (!mMysql)
|
||||
return false;
|
||||
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody)
|
||||
{
|
||||
if (tranThread!=ZThread::ThreadImpl::current())
|
||||
return false;
|
||||
bool _res = _TransactionCmd("COMMIT");
|
||||
tranThread = NULL;
|
||||
mMutex.release();
|
||||
return _res;
|
||||
}
|
||||
|
||||
tranThread = ZThread::ThreadImpl::current();
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
{
|
||||
m_threadBody->Delay(i->second);
|
||||
i->second = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DatabaseMysql::RollbackTransaction()
|
||||
{
|
||||
if (!mMysql)
|
||||
return false;
|
||||
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody)
|
||||
{
|
||||
if (tranThread!=ZThread::ThreadImpl::current())
|
||||
return false;
|
||||
bool _res = _TransactionCmd("ROLLBACK");
|
||||
tranThread = NULL;
|
||||
mMutex.release();
|
||||
return _res;
|
||||
}
|
||||
|
||||
tranThread = ZThread::ThreadImpl::current();
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
{
|
||||
delete i->second;
|
||||
i->second = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long DatabaseMysql::escape_string(char *to, const char *from, unsigned long length)
|
||||
{
|
||||
if (!mMysql || !to || !from || !length)
|
||||
return 0;
|
||||
|
||||
return(mysql_real_escape_string(mMysql, to, from, length));
|
||||
}
|
||||
|
||||
void DatabaseMysql::InitDelayThread()
|
||||
{
|
||||
assert(!m_delayThread);
|
||||
|
||||
//New delay thread for delay execute
|
||||
m_delayThread = new ZThread::Thread(m_threadBody = new MySQLDelayThread(this));
|
||||
}
|
||||
|
||||
void DatabaseMysql::HaltDelayThread()
|
||||
{
|
||||
if (!m_threadBody || !m_delayThread) return;
|
||||
|
||||
m_threadBody->Stop(); //Stop event
|
||||
m_delayThread->wait(); //Wait for flush to DB
|
||||
delete m_delayThread; //This also deletes m_threadBody
|
||||
m_delayThread = NULL;
|
||||
m_threadBody = NULL;
|
||||
}
|
||||
#endif
|
||||
77
src/shared/Database/DatabaseMysql.h
Normal file
77
src/shared/Database/DatabaseMysql.h
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#ifndef _DATABASEMYSQL_H
|
||||
#define _DATABASEMYSQL_H
|
||||
|
||||
#include "Database.h"
|
||||
#include "Policies/Singleton.h"
|
||||
#include "zthread/FastMutex.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define FD_SETSIZE 1024
|
||||
#include <winsock2.h>
|
||||
#include <mysql/mysql.h>
|
||||
#else
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
class MANGOS_DLL_SPEC DatabaseMysql : public Database
|
||||
{
|
||||
friend class MaNGOS::OperatorNew<DatabaseMysql>;
|
||||
|
||||
public:
|
||||
DatabaseMysql();
|
||||
~DatabaseMysql();
|
||||
|
||||
//! Initializes Mysql and connects to a server.
|
||||
/*! infoString should be formated like hostname;username;password;database. */
|
||||
bool Initialize(const char *infoString);
|
||||
void InitDelayThread();
|
||||
void HaltDelayThread();
|
||||
QueryResult* Query(const char *sql);
|
||||
bool Execute(const char *sql);
|
||||
bool DirectExecute(const char* sql);
|
||||
bool BeginTransaction();
|
||||
bool CommitTransaction();
|
||||
bool RollbackTransaction();
|
||||
|
||||
operator bool () const { return mMysql != NULL; }
|
||||
|
||||
unsigned long escape_string(char *to, const char *from, unsigned long length);
|
||||
using Database::escape_string;
|
||||
|
||||
// must be call before first query in thread
|
||||
void ThreadStart();
|
||||
// must be call before finish thread run
|
||||
void ThreadEnd();
|
||||
private:
|
||||
ZThread::FastMutex mMutex;
|
||||
|
||||
ZThread::ThreadImpl* tranThread;
|
||||
|
||||
MYSQL *mMysql;
|
||||
|
||||
static size_t db_count;
|
||||
|
||||
bool _TransactionCmd(const char *sql);
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
345
src/shared/Database/DatabasePostgre.cpp
Normal file
345
src/shared/Database/DatabasePostgre.cpp
Normal file
|
|
@ -0,0 +1,345 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef DO_POSTGRESQL
|
||||
|
||||
#include "Util.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Platform/Define.h"
|
||||
#include "../src/zthread/ThreadImpl.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "Database/PGSQLDelayThread.h"
|
||||
#include "Database/SqlOperations.h"
|
||||
#include "Timer.h"
|
||||
|
||||
void DatabasePostgre::ThreadStart()
|
||||
{
|
||||
}
|
||||
|
||||
void DatabasePostgre::ThreadEnd()
|
||||
{
|
||||
}
|
||||
|
||||
size_t DatabasePostgre::db_count = 0;
|
||||
|
||||
DatabasePostgre::DatabasePostgre() : Database(), mPGconn(NULL)
|
||||
{
|
||||
// before first connection
|
||||
if( db_count++ == 0 )
|
||||
{
|
||||
|
||||
if (!PQisthreadsafe())
|
||||
{
|
||||
sLog.outError("FATAL ERROR: PostgreSQL libpq isn't thread-safe.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DatabasePostgre::~DatabasePostgre()
|
||||
{
|
||||
|
||||
if (m_delayThread)
|
||||
HaltDelayThread();
|
||||
|
||||
if( mPGconn )
|
||||
{
|
||||
PQfinish(mPGconn);
|
||||
mPGconn = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bool DatabasePostgre::Initialize(const char *infoString)
|
||||
{
|
||||
if(!Database::Initialize(infoString))
|
||||
return false;
|
||||
|
||||
tranThread = NULL;
|
||||
|
||||
InitDelayThread();
|
||||
|
||||
Tokens tokens = StrSplit(infoString, ";");
|
||||
|
||||
Tokens::iterator iter;
|
||||
|
||||
std::string host, port_or_socket, user, password, database;
|
||||
|
||||
iter = tokens.begin();
|
||||
|
||||
if(iter != tokens.end())
|
||||
host = *iter++;
|
||||
if(iter != tokens.end())
|
||||
port_or_socket = *iter++;
|
||||
if(iter != tokens.end())
|
||||
user = *iter++;
|
||||
if(iter != tokens.end())
|
||||
password = *iter++;
|
||||
if(iter != tokens.end())
|
||||
database = *iter++;
|
||||
|
||||
mPGconn = PQsetdbLogin(host.c_str(), port_or_socket.c_str(), NULL, NULL, database.c_str(), user.c_str(), password.c_str());
|
||||
|
||||
/* check to see that the backend connection was successfully made */
|
||||
if (PQstatus(mPGconn) != CONNECTION_OK)
|
||||
{
|
||||
sLog.outError( "Could not connect to Postgre database at %s: %s",
|
||||
host.c_str(), PQerrorMessage(mPGconn));
|
||||
PQfinish(mPGconn);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
sLog.outDetail( "Connected to Postgre database at %s",
|
||||
host.c_str());
|
||||
sLog.outString( "PostgreSQL server ver: %d",PQserverVersion(mPGconn));
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
QueryResult* DatabasePostgre::Query(const char *sql)
|
||||
{
|
||||
if (!mPGconn)
|
||||
return 0;
|
||||
|
||||
uint64 rowCount = 0;
|
||||
uint32 fieldCount = 0;
|
||||
|
||||
// guarded block for thread-safe request
|
||||
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
|
||||
#ifdef MANGOS_DEBUG
|
||||
uint32 _s = getMSTime();
|
||||
#endif
|
||||
// Send the query
|
||||
PGresult * result = PQexec(mPGconn, sql);
|
||||
if (!result )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (PQresultStatus(result) != PGRES_TUPLES_OK)
|
||||
{
|
||||
sLog.outErrorDb( "SQL : %s", sql );
|
||||
sLog.outErrorDb( "SQL %s", PQerrorMessage(mPGconn));
|
||||
PQclear(result);
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MANGOS_DEBUG
|
||||
sLog.outDebug("[%u ms] SQL: %s", getMSTime() - _s, sql );
|
||||
#endif
|
||||
}
|
||||
|
||||
rowCount = PQntuples(result);
|
||||
fieldCount = PQnfields(result);
|
||||
// end guarded block
|
||||
|
||||
if (!rowCount)
|
||||
{
|
||||
PQclear(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
QueryResultPostgre * queryResult = new QueryResultPostgre(result, rowCount, fieldCount);
|
||||
queryResult->NextRow();
|
||||
|
||||
return queryResult;
|
||||
}
|
||||
|
||||
bool DatabasePostgre::Execute(const char *sql)
|
||||
{
|
||||
|
||||
if (!mPGconn)
|
||||
return false;
|
||||
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody) return DirectExecute(sql);
|
||||
|
||||
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
{ // Statement for transaction
|
||||
i->second->DelayExecute(sql);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Simple sql statement
|
||||
m_threadBody->Delay(new SqlStatement(sql));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabasePostgre::DirectExecute(const char* sql)
|
||||
{
|
||||
if (!mPGconn)
|
||||
return false;
|
||||
{
|
||||
// guarded block for thread-safe request
|
||||
ZThread::Guard<ZThread::FastMutex> query_connection_guard(mMutex);
|
||||
#ifdef MANGOS_DEBUG
|
||||
uint32 _s = getMSTime();
|
||||
#endif
|
||||
PGresult *res = PQexec(mPGconn, sql);
|
||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
sLog.outErrorDb( "SQL: %s", sql );
|
||||
sLog.outErrorDb( "SQL %s", PQerrorMessage(mPGconn) );
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef MANGOS_DEBUG
|
||||
sLog.outDebug("[%u ms] SQL: %s", getMSTime() - _s, sql );
|
||||
#endif
|
||||
}
|
||||
PQclear(res);
|
||||
|
||||
// end guarded block
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabasePostgre::_TransactionCmd(const char *sql)
|
||||
{
|
||||
if (!mPGconn)
|
||||
return false;
|
||||
|
||||
PGresult *res = PQexec(mPGconn, sql);
|
||||
if (PQresultStatus(res) != PGRES_COMMAND_OK)
|
||||
{
|
||||
sLog.outError("SQL: %s", sql);
|
||||
sLog.outError("SQL ERROR: %s", PQerrorMessage(mPGconn));
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG_LOG("SQL: %s", sql);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabasePostgre::BeginTransaction()
|
||||
{
|
||||
if (!mPGconn)
|
||||
return false;
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody)
|
||||
{
|
||||
if (tranThread==ZThread::ThreadImpl::current())
|
||||
return false; // huh? this thread already started transaction
|
||||
mMutex.acquire();
|
||||
if (!_TransactionCmd("START TRANSACTION"))
|
||||
{
|
||||
mMutex.release(); // can't start transaction
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
// transaction started
|
||||
tranThread = ZThread::ThreadImpl::current(); // owner of this transaction
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
// If for thread exists queue and also contains transaction
|
||||
// delete that transaction (not allow trans in trans)
|
||||
delete i->second;
|
||||
|
||||
m_tranQueues[tranThread] = new SqlTransaction();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DatabasePostgre::CommitTransaction()
|
||||
{
|
||||
if (!mPGconn)
|
||||
return false;
|
||||
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody)
|
||||
{
|
||||
if (tranThread!=ZThread::ThreadImpl::current())
|
||||
return false;
|
||||
bool _res = _TransactionCmd("COMMIT");
|
||||
tranThread = NULL;
|
||||
mMutex.release();
|
||||
return _res;
|
||||
}
|
||||
tranThread = ZThread::ThreadImpl::current();
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
{
|
||||
m_threadBody->Delay(i->second);
|
||||
i->second = NULL;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DatabasePostgre::RollbackTransaction()
|
||||
{
|
||||
if (!mPGconn)
|
||||
return false;
|
||||
// don't use queued execution if it has not been initialized
|
||||
if (!m_threadBody)
|
||||
{
|
||||
if (tranThread!=ZThread::ThreadImpl::current())
|
||||
return false;
|
||||
bool _res = _TransactionCmd("ROLLBACK");
|
||||
tranThread = NULL;
|
||||
mMutex.release();
|
||||
return _res;
|
||||
}
|
||||
tranThread = ZThread::ThreadImpl::current();
|
||||
TransactionQueues::iterator i = m_tranQueues.find(tranThread);
|
||||
if (i != m_tranQueues.end() && i->second != NULL)
|
||||
{
|
||||
delete i->second;
|
||||
i->second = NULL;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned long DatabasePostgre::escape_string(char *to, const char *from, unsigned long length)
|
||||
{
|
||||
if (!mPGconn || !to || !from || !length)
|
||||
return 0;
|
||||
|
||||
return PQescapeString(to, from, length);
|
||||
}
|
||||
|
||||
void DatabasePostgre::InitDelayThread()
|
||||
{
|
||||
assert(!m_delayThread);
|
||||
|
||||
//New delay thread for delay execute
|
||||
m_delayThread = new ZThread::Thread(m_threadBody = new PGSQLDelayThread(this));
|
||||
}
|
||||
|
||||
void DatabasePostgre::HaltDelayThread()
|
||||
{
|
||||
if (!m_threadBody || !m_delayThread) return;
|
||||
|
||||
m_threadBody->Stop(); //Stop event
|
||||
m_delayThread->wait(); //Wait for flush to DB
|
||||
delete m_delayThread; //This also deletes m_threadBody
|
||||
m_delayThread = NULL;
|
||||
m_threadBody = NULL;
|
||||
}
|
||||
#endif
|
||||
75
src/shared/Database/DatabasePostgre.h
Normal file
75
src/shared/Database/DatabasePostgre.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _DatabasePostgre_H
|
||||
#define _DatabasePostgre_H
|
||||
|
||||
#include "Policies/Singleton.h"
|
||||
#include "zthread/FastMutex.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#define FD_SETSIZE 1024
|
||||
#include <winsock2.h>
|
||||
#include <postgre/libpq-fe.h>
|
||||
#else
|
||||
#include <libpq-fe.h>
|
||||
#endif
|
||||
|
||||
class DatabasePostgre : public Database
|
||||
{
|
||||
friend class MaNGOS::OperatorNew<DatabasePostgre>;
|
||||
|
||||
public:
|
||||
DatabasePostgre();
|
||||
~DatabasePostgre();
|
||||
|
||||
//! Initializes Postgres and connects to a server.
|
||||
/*! infoString should be formated like hostname;username;password;database. */
|
||||
bool Initialize(const char *infoString);
|
||||
void InitDelayThread();
|
||||
void HaltDelayThread();
|
||||
QueryResult* Query(const char *sql);
|
||||
bool Execute(const char *sql);
|
||||
bool DirectExecute(const char* sql);
|
||||
bool BeginTransaction();
|
||||
bool CommitTransaction();
|
||||
bool RollbackTransaction();
|
||||
|
||||
operator bool () const { return mPGconn != NULL; }
|
||||
|
||||
unsigned long escape_string(char *to, const char *from, unsigned long length);
|
||||
using Database::escape_string;
|
||||
|
||||
// must be call before first query in thread
|
||||
void ThreadStart();
|
||||
// must be call before finish thread run
|
||||
void ThreadEnd();
|
||||
private:
|
||||
ZThread::FastMutex mMutex;
|
||||
ZThread::FastMutex tranMutex;
|
||||
|
||||
ZThread::ThreadImpl* tranThread;
|
||||
|
||||
PGconn *mPGconn;
|
||||
|
||||
static size_t db_count;
|
||||
|
||||
bool _TransactionCmd(const char *sql);
|
||||
};
|
||||
#endif
|
||||
101
src/shared/Database/DatabaseSqlite.cpp
Normal file
101
src/shared/Database/DatabaseSqlite.cpp
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
DatabaseSqlite::DatabaseSqlite() : Database(), mSqlite(0)
|
||||
{
|
||||
}
|
||||
|
||||
DatabaseSqlite::~DatabaseSqlite()
|
||||
{
|
||||
if (mSqlite)
|
||||
sqlite_close(mSqlite);
|
||||
}
|
||||
|
||||
bool DatabaseSqlite::Initialize(const char *infoString)
|
||||
{
|
||||
if(!Database::Initialize(infoString))
|
||||
return false;
|
||||
|
||||
char *errmsg;
|
||||
|
||||
mSqlite = sqlite_open(infoString, 0, &errmsg);
|
||||
|
||||
if (!mSqlite)
|
||||
{
|
||||
|
||||
if (errmsg)
|
||||
sqlite_freemem(errmsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QueryResult* DatabaseSqlite::Query(const char *sql)
|
||||
{
|
||||
char *errmsg;
|
||||
|
||||
if (!mSqlite)
|
||||
return 0;
|
||||
|
||||
char **tableData;
|
||||
int rowCount;
|
||||
int fieldCount;
|
||||
|
||||
sqlite_get_table(mSqlite, sql, &tableData, &rowCount, &fieldCount, &errmsg);
|
||||
|
||||
if (!rowCount)
|
||||
return 0;
|
||||
|
||||
if (!tableData)
|
||||
{
|
||||
|
||||
if (errmsg)
|
||||
sqlite_freemem(errmsg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
QueryResultSqlite *queryResult = new QueryResultSqlite(tableData, rowCount, fieldCount);
|
||||
if(!queryResult)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
queryResult->NextRow();
|
||||
|
||||
return queryResult;
|
||||
}
|
||||
|
||||
bool DatabaseSqlite::Execute(const char *sql)
|
||||
{
|
||||
char *errmsg;
|
||||
|
||||
if (!mSqlite)
|
||||
return false;
|
||||
|
||||
if(sqlite_exec(mSqlite, sql, NULL, NULL, &errmsg) != SQLITE_OK)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
43
src/shared/Database/DatabaseSqlite.h
Normal file
43
src/shared/Database/DatabaseSqlite.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#ifndef _DATABASESQLITE_H
|
||||
#define _DATABASESQLITE_H
|
||||
|
||||
#include <sqlite/sqlite.h>
|
||||
|
||||
class DatabaseSqlite : public Database
|
||||
{
|
||||
public:
|
||||
DatabaseSqlite();
|
||||
~DatabaseSqlite();
|
||||
|
||||
bool Initialize(const char *infoString);
|
||||
|
||||
QueryResult* Query(const char *sql);
|
||||
bool Execute(const char *sql);
|
||||
|
||||
operator bool () const { return mSqlite != NULL; }
|
||||
|
||||
private:
|
||||
sqlite *mSqlite;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
65
src/shared/Database/Field.cpp
Normal file
65
src/shared/Database/Field.cpp
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
Field::Field() :
|
||||
mValue(NULL), mType(DB_TYPE_UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
Field::Field(Field &f)
|
||||
{
|
||||
const char *value;
|
||||
|
||||
value = f.GetString();
|
||||
|
||||
if (value && (mValue = new char[strlen(value) + 1]))
|
||||
strcpy(mValue, value);
|
||||
else
|
||||
mValue = NULL;
|
||||
|
||||
mType = f.GetType();
|
||||
}
|
||||
|
||||
Field::Field(const char *value, enum Field::DataTypes type) :
|
||||
mType(type)
|
||||
{
|
||||
if (value && (mValue = new char[strlen(value) + 1]))
|
||||
strcpy(mValue, value);
|
||||
else
|
||||
mValue = NULL;
|
||||
}
|
||||
|
||||
Field::~Field()
|
||||
{
|
||||
if(mValue) delete [] mValue;
|
||||
}
|
||||
|
||||
void Field::SetValue(const char *value)
|
||||
{
|
||||
if(mValue) delete [] mValue;
|
||||
|
||||
if (value)
|
||||
{
|
||||
mValue = new char[strlen(value) + 1];
|
||||
strcpy(mValue, value);
|
||||
}
|
||||
else
|
||||
mValue = NULL;
|
||||
}
|
||||
75
src/shared/Database/Field.h
Normal file
75
src/shared/Database/Field.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if !defined(FIELD_H)
|
||||
#define FIELD_H
|
||||
|
||||
class Field
|
||||
{
|
||||
public:
|
||||
|
||||
enum DataTypes
|
||||
{
|
||||
DB_TYPE_UNKNOWN = 0x00,
|
||||
DB_TYPE_STRING = 0x01,
|
||||
DB_TYPE_INTEGER = 0x02,
|
||||
DB_TYPE_FLOAT = 0x03,
|
||||
DB_TYPE_BOOL = 0x04
|
||||
};
|
||||
|
||||
Field();
|
||||
Field(Field &f);
|
||||
Field(const char *value, enum DataTypes type);
|
||||
|
||||
~Field();
|
||||
|
||||
enum DataTypes GetType() const { return mType; }
|
||||
|
||||
const char *GetString() const { return mValue; }
|
||||
std::string GetCppString() const
|
||||
{
|
||||
return mValue ? mValue : ""; // std::string s = 0 have undefine result in C++
|
||||
}
|
||||
float GetFloat() const { return mValue ? static_cast<float>(atof(mValue)) : 0.0f; }
|
||||
bool GetBool() const { return mValue ? atoi(mValue) > 0 : false; }
|
||||
int32 GetInt32() const { return mValue ? static_cast<int32>(atol(mValue)) : int32(0); }
|
||||
uint8 GetUInt8() const { return mValue ? static_cast<uint8>(atol(mValue)) : uint8(0); }
|
||||
uint16 GetUInt16() const { return mValue ? static_cast<uint16>(atol(mValue)) : uint16(0); }
|
||||
int16 GetInt16() const { return mValue ? static_cast<int16>(atol(mValue)) : int16(0); }
|
||||
uint32 GetUInt32() const { return mValue ? static_cast<uint32>(atol(mValue)) : uint32(0); }
|
||||
uint64 GetUInt64() const
|
||||
{
|
||||
if(mValue)
|
||||
{
|
||||
uint64 value;
|
||||
sscanf(mValue,I64FMTD,&value);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SetType(enum DataTypes type) { mType = type; }
|
||||
|
||||
void SetValue(const char *value);
|
||||
|
||||
private:
|
||||
char *mValue;
|
||||
enum DataTypes mType;
|
||||
};
|
||||
#endif
|
||||
63
src/shared/Database/Makefile.am
Normal file
63
src/shared/Database/Makefile.am
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
## Sub-directories to parse
|
||||
|
||||
## CPP flags for includes, defines, etc.
|
||||
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite
|
||||
|
||||
## Build MaNGOS shared library and its parts as convenience library.
|
||||
# All libraries will be convenience libraries. Might be changed to shared
|
||||
# later.
|
||||
noinst_LIBRARIES = libmangosdatabase.a
|
||||
|
||||
libmangosdatabase_a_SOURCES = \
|
||||
DBCStores.cpp \
|
||||
DBCStores.h \
|
||||
DBCStructure.h \
|
||||
DBCfmt.cpp \
|
||||
Database.cpp \
|
||||
Database.h \
|
||||
DatabaseEnv.h \
|
||||
DatabaseImpl.h \
|
||||
DatabaseMysql.cpp \
|
||||
DatabasePostgre.cpp \
|
||||
DatabaseMysql.h \
|
||||
DatabasePostgre.h \
|
||||
DatabaseSqlite.cpp \
|
||||
DatabaseSqlite.h \
|
||||
DBCEnums.h \
|
||||
Field.cpp \
|
||||
Field.h \
|
||||
MySQLDelayThread.h \
|
||||
PGSQLDelayThread.h \
|
||||
QueryResult.h \
|
||||
QueryResultMysql.cpp \
|
||||
QueryResultMysql.h \
|
||||
QueryResultPostgre.cpp \
|
||||
QueryResultPostgre.h \
|
||||
QueryResultSqlite.cpp \
|
||||
QueryResultSqlite.h \
|
||||
SQLStorage.cpp \
|
||||
SQLStorage.h \
|
||||
SqlDelayThread.cpp \
|
||||
SqlDelayThread.h \
|
||||
SqlOperations.cpp \
|
||||
SqlOperations.h \
|
||||
dbcfile.cpp \
|
||||
dbcfile.h
|
||||
30
src/shared/Database/MySQLDelayThread.h
Normal file
30
src/shared/Database/MySQLDelayThread.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __MYSQLDELAYTHREAD_H
|
||||
#define __MYSQLDELAYTHREAD_H
|
||||
|
||||
#include "Database/SqlDelayThread.h"
|
||||
|
||||
class MySQLDelayThread : public SqlDelayThread
|
||||
{
|
||||
public:
|
||||
MySQLDelayThread(Database* db) : SqlDelayThread(db) {}
|
||||
void Stop() { SqlDelayThread::Stop(); }
|
||||
};
|
||||
#endif //__MYSQLDELAYTHREAD_H
|
||||
30
src/shared/Database/PGSQLDelayThread.h
Normal file
30
src/shared/Database/PGSQLDelayThread.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __PGSQLDELAYTHREAD_H
|
||||
#define __PGSQLDELAYTHREAD_H
|
||||
|
||||
#include "Database/SqlDelayThread.h"
|
||||
|
||||
class PGSQLDelayThread : public SqlDelayThread
|
||||
{
|
||||
public:
|
||||
PGSQLDelayThread(Database* db) : SqlDelayThread(db) {}
|
||||
void Stop() { SqlDelayThread::Stop(); }
|
||||
};
|
||||
#endif //__PGSQLDELAYTHREAD_H
|
||||
64
src/shared/Database/QueryResult.h
Normal file
64
src/shared/Database/QueryResult.h
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if !defined(QUERYRESULT_H)
|
||||
#define QUERYRESULT_H
|
||||
|
||||
class MANGOS_DLL_SPEC QueryResult
|
||||
{
|
||||
public:
|
||||
QueryResult(uint64 rowCount, uint32 fieldCount)
|
||||
: mFieldCount(fieldCount), mRowCount(rowCount) {}
|
||||
|
||||
virtual ~QueryResult() {}
|
||||
|
||||
virtual bool NextRow() = 0;
|
||||
|
||||
typedef std::map<uint32, std::string> FieldNames;
|
||||
|
||||
uint32 GetField_idx(const std::string &name) const
|
||||
{
|
||||
for(FieldNames::const_iterator iter = GetFiedNames().begin(); iter != GetFiedNames().end(); ++iter)
|
||||
{
|
||||
if(iter->second == name)
|
||||
return iter->first;
|
||||
}
|
||||
assert(false && "unknown field name");
|
||||
return uint32(-1);
|
||||
}
|
||||
|
||||
Field *Fetch() const { return mCurrentRow; }
|
||||
|
||||
const Field & operator [] (int index) const { return mCurrentRow[index]; }
|
||||
|
||||
const Field & operator [] (const std::string &name) const
|
||||
{
|
||||
return mCurrentRow[GetField_idx(name)];
|
||||
}
|
||||
|
||||
uint32 GetFieldCount() const { return mFieldCount; }
|
||||
uint64 GetRowCount() const { return mRowCount; }
|
||||
FieldNames const& GetFiedNames() const {return mFieldNames; }
|
||||
|
||||
protected:
|
||||
Field *mCurrentRow;
|
||||
uint32 mFieldCount;
|
||||
uint64 mRowCount;
|
||||
FieldNames mFieldNames;
|
||||
};
|
||||
#endif
|
||||
110
src/shared/Database/QueryResultMysql.cpp
Normal file
110
src/shared/Database/QueryResultMysql.cpp
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
QueryResultMysql::QueryResultMysql(MYSQL_RES *result, uint64 rowCount, uint32 fieldCount) :
|
||||
QueryResult(rowCount, fieldCount), mResult(result)
|
||||
{
|
||||
|
||||
mCurrentRow = new Field[mFieldCount];
|
||||
ASSERT(mCurrentRow);
|
||||
|
||||
MYSQL_FIELD *fields = mysql_fetch_fields(mResult);
|
||||
|
||||
for (uint32 i = 0; i < mFieldCount; i++)
|
||||
{
|
||||
mFieldNames[i] = fields[i].name;
|
||||
mCurrentRow[i].SetType(ConvertNativeType(fields[i].type));
|
||||
}
|
||||
}
|
||||
|
||||
QueryResultMysql::~QueryResultMysql()
|
||||
{
|
||||
EndQuery();
|
||||
}
|
||||
|
||||
bool QueryResultMysql::NextRow()
|
||||
{
|
||||
MYSQL_ROW row;
|
||||
|
||||
if (!mResult)
|
||||
return false;
|
||||
|
||||
row = mysql_fetch_row(mResult);
|
||||
if (!row)
|
||||
{
|
||||
EndQuery();
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32 i = 0; i < mFieldCount; i++)
|
||||
mCurrentRow[i].SetValue(row[i]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryResultMysql::EndQuery()
|
||||
{
|
||||
if (mCurrentRow)
|
||||
{
|
||||
delete [] mCurrentRow;
|
||||
mCurrentRow = 0;
|
||||
}
|
||||
|
||||
if (mResult)
|
||||
{
|
||||
mysql_free_result(mResult);
|
||||
mResult = 0;
|
||||
}
|
||||
}
|
||||
|
||||
enum Field::DataTypes QueryResultMysql::ConvertNativeType(enum_field_types mysqlType) const
|
||||
{
|
||||
switch (mysqlType)
|
||||
{
|
||||
case FIELD_TYPE_TIMESTAMP:
|
||||
case FIELD_TYPE_DATE:
|
||||
case FIELD_TYPE_TIME:
|
||||
case FIELD_TYPE_DATETIME:
|
||||
case FIELD_TYPE_YEAR:
|
||||
case FIELD_TYPE_STRING:
|
||||
case FIELD_TYPE_VAR_STRING:
|
||||
case FIELD_TYPE_BLOB:
|
||||
case FIELD_TYPE_SET:
|
||||
case FIELD_TYPE_NULL:
|
||||
return Field::DB_TYPE_STRING;
|
||||
case FIELD_TYPE_TINY:
|
||||
|
||||
case FIELD_TYPE_SHORT:
|
||||
case FIELD_TYPE_LONG:
|
||||
case FIELD_TYPE_INT24:
|
||||
case FIELD_TYPE_LONGLONG:
|
||||
case FIELD_TYPE_ENUM:
|
||||
return Field::DB_TYPE_INTEGER;
|
||||
case FIELD_TYPE_DECIMAL:
|
||||
case FIELD_TYPE_FLOAT:
|
||||
case FIELD_TYPE_DOUBLE:
|
||||
return Field::DB_TYPE_FLOAT;
|
||||
default:
|
||||
return Field::DB_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
48
src/shared/Database/QueryResultMysql.h
Normal file
48
src/shared/Database/QueryResultMysql.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#if !defined(QUERYRESULTMYSQL_H)
|
||||
#define QUERYRESULTMYSQL_H
|
||||
|
||||
#ifdef WIN32
|
||||
#define FD_SETSIZE 1024
|
||||
#include <winsock2.h>
|
||||
#include <mysql/mysql.h>
|
||||
#else
|
||||
#include <mysql.h>
|
||||
#endif
|
||||
|
||||
class QueryResultMysql : public QueryResult
|
||||
{
|
||||
public:
|
||||
QueryResultMysql(MYSQL_RES *result, uint64 rowCount, uint32 fieldCount);
|
||||
|
||||
~QueryResultMysql();
|
||||
|
||||
bool NextRow();
|
||||
|
||||
private:
|
||||
enum Field::DataTypes ConvertNativeType(enum_field_types mysqlType) const;
|
||||
void EndQuery();
|
||||
|
||||
MYSQL_RES *mResult;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
139
src/shared/Database/QueryResultPostgre.cpp
Normal file
139
src/shared/Database/QueryResultPostgre.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifdef DO_POSTGRESQL
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
QueryResultPostgre::QueryResultPostgre(PGresult *result, uint64 rowCount, uint32 fieldCount) :
|
||||
QueryResult(rowCount, fieldCount), mResult(result), mTableIndex(0)
|
||||
{
|
||||
|
||||
mCurrentRow = new Field[mFieldCount];
|
||||
ASSERT(mCurrentRow);
|
||||
|
||||
for (uint32 i = 0; i < mFieldCount; i++)
|
||||
{
|
||||
mFieldNames[i] = PQfname(result, i);
|
||||
mCurrentRow[i].SetType(ConvertNativeType(PQftype( result, i )));
|
||||
}
|
||||
}
|
||||
|
||||
QueryResultPostgre::~QueryResultPostgre()
|
||||
{
|
||||
EndQuery();
|
||||
}
|
||||
|
||||
bool QueryResultPostgre::NextRow()
|
||||
{
|
||||
if (!mResult)
|
||||
return false;
|
||||
|
||||
if (mTableIndex >= mRowCount)
|
||||
{
|
||||
EndQuery();
|
||||
return false;
|
||||
}
|
||||
|
||||
char* pPQgetvalue;
|
||||
for (int j = 0; j < mFieldCount; j++)
|
||||
{
|
||||
pPQgetvalue = PQgetvalue(mResult, mTableIndex, j);
|
||||
if(pPQgetvalue && !(*pPQgetvalue))
|
||||
pPQgetvalue = NULL;
|
||||
|
||||
mCurrentRow[j].SetValue(pPQgetvalue);
|
||||
}
|
||||
++mTableIndex;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryResultPostgre::EndQuery()
|
||||
{
|
||||
if (mCurrentRow)
|
||||
{
|
||||
delete [] mCurrentRow;
|
||||
mCurrentRow = 0;
|
||||
}
|
||||
|
||||
if (mResult)
|
||||
{
|
||||
PQclear(mResult);
|
||||
mResult = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// see types in #include <postgre/pg_type.h>
|
||||
enum Field::DataTypes QueryResultPostgre::ConvertNativeType(Oid pOid ) const
|
||||
{
|
||||
switch (pOid)
|
||||
{
|
||||
case BPCHAROID:
|
||||
case CIDOID:
|
||||
case CIDROID:
|
||||
case CIRCLEOID:
|
||||
case INETOID:
|
||||
case NAMEOID:
|
||||
case TEXTOID:
|
||||
case VARCHAROID:
|
||||
return Field::DB_TYPE_STRING;
|
||||
case CASHOID:
|
||||
case FLOAT4OID:
|
||||
case FLOAT8OID:
|
||||
case NUMERICOID:
|
||||
return Field::DB_TYPE_FLOAT;
|
||||
case DATEOID: // Date
|
||||
case RELTIMEOID: // Date
|
||||
case TIMEOID: // Time
|
||||
case TIMETZOID: // Time
|
||||
case ABSTIMEOID: // DateTime
|
||||
case INTERVALOID: // DateTime
|
||||
case TIMESTAMPOID: // DateTime
|
||||
case TIMESTAMPTZOID: // DateTime
|
||||
case INT2OID: // Int
|
||||
case INT2VECTOROID: // Int
|
||||
case INT4OID: // Int
|
||||
case OIDOID: // Int
|
||||
case CHAROID: // UInt
|
||||
case INT8OID: // LongLong
|
||||
return Field::DB_TYPE_INTEGER;
|
||||
case BOOLOID:
|
||||
return Field::DB_TYPE_BOOL; // Bool
|
||||
/*
|
||||
case BOXOID: Rect;
|
||||
case LINEOID: Rect;
|
||||
case VARBITOID: BitArray;
|
||||
case BYTEAOID: ByteArray;
|
||||
*/
|
||||
case LSEGOID:
|
||||
case OIDVECTOROID:
|
||||
case PATHOID:
|
||||
case POINTOID:
|
||||
case POLYGONOID:
|
||||
case REGPROCOID:
|
||||
case TIDOID:
|
||||
case TINTERVALOID:
|
||||
case UNKNOWNOID:
|
||||
case XIDOID:
|
||||
default:
|
||||
return Field::DB_TYPE_UNKNOWN;
|
||||
}
|
||||
return Field::DB_TYPE_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
48
src/shared/Database/QueryResultPostgre.h
Normal file
48
src/shared/Database/QueryResultPostgre.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#if !defined(QUERYRESULTPOSTGRE_H)
|
||||
#define QUERYRESULTPOSTGRE_H
|
||||
|
||||
#ifdef WIN32
|
||||
#define FD_SETSIZE 1024
|
||||
#include <winsock2.h>
|
||||
#include <postgre/libpq-fe.h>
|
||||
#include <postgre/pg_type.h>
|
||||
#else
|
||||
#include <libpq-fe.h>
|
||||
//#include <pg_type.h>
|
||||
#endif
|
||||
|
||||
class QueryResultPostgre : public QueryResult
|
||||
{
|
||||
public:
|
||||
QueryResultPostgre(PGresult *result, uint64 rowCount, uint32 fieldCount);
|
||||
|
||||
~QueryResultPostgre();
|
||||
|
||||
bool NextRow();
|
||||
|
||||
private:
|
||||
enum Field::DataTypes ConvertNativeType(Oid pOid) const;
|
||||
void EndQuery();
|
||||
|
||||
PGresult *mResult;
|
||||
uint32 mTableIndex;
|
||||
};
|
||||
#endif
|
||||
96
src/shared/Database/QueryResultSqlite.cpp
Normal file
96
src/shared/Database/QueryResultSqlite.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
QueryResultSqlite::QueryResultSqlite(char **tableData, uint32 rowCount, uint32 fieldCount) :
|
||||
QueryResult(rowCount, fieldCount), mTableData(tableData), mTableIndex(0)
|
||||
{
|
||||
mCurrentRow = new Field[mFieldCount];
|
||||
|
||||
for (uint32 i = 0; i < mFieldCount; i++)
|
||||
{
|
||||
mFieldNames[i] = mTableData[i];
|
||||
mCurrentRow[i].SetType(Field::DB_TYPE_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
QueryResultSqlite::~QueryResultSqlite()
|
||||
{
|
||||
EndQuery();
|
||||
}
|
||||
|
||||
bool QueryResultSqlite::NextRow()
|
||||
{
|
||||
int startIndex;
|
||||
uint32 i;
|
||||
|
||||
if (!mTableData)
|
||||
return false;
|
||||
|
||||
if (mTableIndex >= mRowCount)
|
||||
{
|
||||
EndQuery();
|
||||
return false;
|
||||
}
|
||||
|
||||
startIndex = (mTableIndex + 1) * mFieldCount;
|
||||
for (i = 0; i < mFieldCount; i++)
|
||||
{
|
||||
mCurrentRow[i].SetValue(mTableData[startIndex + i]);
|
||||
}
|
||||
|
||||
++mTableIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
void QueryResultSqlite::EndQuery()
|
||||
{
|
||||
if (mCurrentRow)
|
||||
{
|
||||
delete [] mCurrentRow;
|
||||
mCurrentRow = NULL;
|
||||
}
|
||||
if (mTableData)
|
||||
{
|
||||
sqlite_free_table(mTableData);
|
||||
mTableData = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
enum Field::DataTypes QueryResultSqlite::ConvertNativeType(const char* sqliteType) const
|
||||
{
|
||||
if (sqliteType)
|
||||
{
|
||||
switch (*sqliteType)
|
||||
{
|
||||
case 'S':
|
||||
return Field::DB_TYPE_STRING;
|
||||
case 'I':
|
||||
return Field::DB_TYPE_INTEGER;
|
||||
case 'F':
|
||||
return Field::DB_TYPE_FLOAT;
|
||||
default:
|
||||
return Field::DB_TYPE_UNKNOWN;
|
||||
};
|
||||
}
|
||||
return Field::DB_TYPE_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
43
src/shared/Database/QueryResultSqlite.h
Normal file
43
src/shared/Database/QueryResultSqlite.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
|
||||
#if !defined(QUERYRESULTSQLITE_H)
|
||||
#define QUERYRESULTSQLITE_H
|
||||
|
||||
#include <sqlite/sqlite.h>
|
||||
|
||||
class QueryResultSqlite : public QueryResult
|
||||
{
|
||||
public:
|
||||
QueryResultSqlite(char **tableData, uint32 rowCount, uint32 fieldCount);
|
||||
|
||||
~QueryResultSqlite();
|
||||
|
||||
bool NextRow();
|
||||
|
||||
private:
|
||||
enum Field::DataTypes ConvertNativeType(const char* sqliteType) const;
|
||||
void EndQuery();
|
||||
|
||||
char **mTableData;
|
||||
uint32 mTableIndex;
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
191
src/shared/Database/SQLStorage.cpp
Normal file
191
src/shared/Database/SQLStorage.cpp
Normal file
|
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "SQLStorage.h"
|
||||
#include "ProgressBar.h"
|
||||
#include "Log.h"
|
||||
#include "dbcfile.h"
|
||||
|
||||
#ifdef DO_POSTGRESQL
|
||||
extern DatabasePostgre WorldDatabase;
|
||||
#else
|
||||
extern DatabaseMysql WorldDatabase;
|
||||
#endif
|
||||
|
||||
const char CreatureInfofmt[]="iiiiiisssiiiiiiiiiiffiffiiiiiiiiiiiffiiiiiiiiiiiiiiiiiiisiilliiis";
|
||||
const char CreatureDataAddonInfofmt[]="iiiiiiis";
|
||||
const char CreatureModelfmt[]="iffbi";
|
||||
const char CreatureInfoAddonInfofmt[]="iiiiiiis";
|
||||
const char EquipmentInfofmt[]="iiiiiiiiii";
|
||||
const char GameObjectInfofmt[]="iiissiifiiiiiiiiiiiiiiiiiiiiiiiis";
|
||||
const char ItemPrototypefmt[]="iiiisiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiffiffiffiffiffiiiiiiiiiifiiifiiiiiifiiiiiifiiiiiifiiiiiifiiiisiiiiiiiiiiiiiiiiiiiiiiiiifsiiiii";
|
||||
const char PageTextfmt[]="isi";
|
||||
const char SpellThreatfmt[]="ii";
|
||||
const char InstanceTemplatefmt[]="iiiiiiffffs";
|
||||
|
||||
SQLStorage sCreatureStorage(CreatureInfofmt,"entry","creature_template");
|
||||
SQLStorage sCreatureDataAddonStorage(CreatureDataAddonInfofmt,"guid","creature_addon");
|
||||
SQLStorage sCreatureModelStorage(CreatureModelfmt,"modelid","creature_model_info");
|
||||
SQLStorage sCreatureInfoAddonStorage(CreatureInfoAddonInfofmt,"entry","creature_template_addon");
|
||||
SQLStorage sEquipmentStorage(EquipmentInfofmt,"entry","creature_equip_template");
|
||||
SQLStorage sGOStorage(GameObjectInfofmt,"entry","gameobject_template");
|
||||
SQLStorage sItemStorage(ItemPrototypefmt,"entry","item_template");
|
||||
SQLStorage sPageTextStore(PageTextfmt,"entry","page_text");
|
||||
SQLStorage sSpellThreatStore(SpellThreatfmt,"entry","spell_threat");
|
||||
SQLStorage sInstanceTemplate(InstanceTemplatefmt,"map","instance_template");
|
||||
|
||||
void SQLStorage::Free ()
|
||||
{
|
||||
uint32 offset=0;
|
||||
for(uint32 x=0;x<iNumFields;x++)
|
||||
if (format[x]==FT_STRING)
|
||||
{
|
||||
for(uint32 y=0;y<MaxEntry;y++)
|
||||
if(pIndex[y])
|
||||
delete [] *(char**)((char*)(pIndex[y])+offset);
|
||||
|
||||
offset+=sizeof(char*);
|
||||
}
|
||||
else if (format[x]==FT_LOGIC)
|
||||
offset+=sizeof(bool);
|
||||
else if (format[x]==FT_BYTE)
|
||||
offset+=sizeof(char);
|
||||
else
|
||||
offset+=4;
|
||||
|
||||
delete [] pIndex;
|
||||
delete [] data;
|
||||
}
|
||||
|
||||
void SQLStorage::Load ()
|
||||
{
|
||||
uint32 maxi;
|
||||
Field *fields;
|
||||
QueryResult *result = WorldDatabase.PQuery("SELECT MAX(%s) FROM %s",entry_field,table);
|
||||
if(!result)
|
||||
{
|
||||
sLog.outError("Error loading %s table (not exist?)\n",table);
|
||||
exit(1); // Stop server at loading non exited table or not accessable table
|
||||
}
|
||||
|
||||
maxi= (*result)[0].GetUInt32()+1;
|
||||
delete result;
|
||||
|
||||
result = WorldDatabase.PQuery("SELECT COUNT(*) FROM %s",table);
|
||||
if(result)
|
||||
{
|
||||
fields = result->Fetch();
|
||||
RecordCount=fields[0].GetUInt32();
|
||||
delete result;
|
||||
}
|
||||
else
|
||||
RecordCount = 0;
|
||||
|
||||
result = WorldDatabase.PQuery("SELECT * FROM %s",table);
|
||||
|
||||
if(!result)
|
||||
{
|
||||
sLog.outError("%s table is empty!\n",table);
|
||||
RecordCount = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
uint32 recordsize=0;
|
||||
uint32 offset=0;
|
||||
|
||||
if(iNumFields!=result->GetFieldCount())
|
||||
{
|
||||
RecordCount = 0;
|
||||
sLog.outError("Error in %s table, probably sql file format was updated (there should be %d fields in sql).\n",table,iNumFields);
|
||||
delete result;
|
||||
exit(1); // Stop server at loading broken or non-compatible table.
|
||||
}
|
||||
|
||||
//get struct size
|
||||
uint32 sc=0;
|
||||
uint32 bo=0;
|
||||
uint32 bb=0;
|
||||
for(uint32 x=0;x<iNumFields;x++)
|
||||
if(format[x]==FT_STRING)
|
||||
++sc;
|
||||
else if (format[x]==FT_LOGIC)
|
||||
++bo;
|
||||
else if (format[x]==FT_BYTE)
|
||||
++bb;
|
||||
recordsize=(iNumFields-sc-bo-bb)*4+sc*sizeof(char*)+bo*sizeof(bool)+bb*sizeof(char);
|
||||
|
||||
char** newIndex=new char*[maxi];
|
||||
memset(newIndex,0,maxi*sizeof(char*));
|
||||
|
||||
char * _data= new char[RecordCount *recordsize];
|
||||
uint32 count=0;
|
||||
barGoLink bar( RecordCount );
|
||||
do
|
||||
{
|
||||
fields = result->Fetch();
|
||||
bar.step();
|
||||
char *p=(char*)&_data[recordsize*count];
|
||||
newIndex[fields[0].GetUInt32()]=p;
|
||||
|
||||
offset=0;
|
||||
for(uint32 x=0;x<iNumFields;x++)
|
||||
switch(format[x])
|
||||
{
|
||||
case FT_LOGIC:
|
||||
*((bool*)(&p[offset]))=(fields[x].GetUInt32()>0);
|
||||
offset+=sizeof(bool);
|
||||
break;
|
||||
case FT_BYTE:
|
||||
*((char*)(&p[offset]))=(fields[x].GetUInt8());
|
||||
offset+=sizeof(char);
|
||||
break;
|
||||
case FT_INT:
|
||||
*((uint32*)(&p[offset]))=fields[x].GetUInt32();
|
||||
offset+=sizeof(uint32);
|
||||
break;
|
||||
case FT_FLOAT:
|
||||
*((float*)(&p[offset]))=fields[x].GetFloat();
|
||||
offset+=sizeof(float);
|
||||
break;
|
||||
case FT_STRING:
|
||||
char const* tmp = fields[x].GetString();
|
||||
char* st;
|
||||
if(!tmp)
|
||||
{
|
||||
st=new char[1];
|
||||
*st=0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32 l=strlen(tmp)+1;
|
||||
st=new char[l];
|
||||
memcpy(st,tmp,l);
|
||||
}
|
||||
*((char**)(&p[offset]))=st;
|
||||
offset+=sizeof(char*);
|
||||
break;
|
||||
}
|
||||
++count;
|
||||
}while( result->NextRow() );
|
||||
|
||||
delete result;
|
||||
|
||||
pIndex =newIndex;
|
||||
MaxEntry=maxi;
|
||||
data=_data;
|
||||
}
|
||||
68
src/shared/Database/SQLStorage.h
Normal file
68
src/shared/Database/SQLStorage.h
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef SQLSTORAGE_H
|
||||
#define SQLSTORAGE_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Database/DatabaseEnv.h"
|
||||
|
||||
class SQLStorage
|
||||
{
|
||||
public:
|
||||
|
||||
SQLStorage(const char*fmt,const char * _entry_field,const char * sqlname)
|
||||
{
|
||||
format=fmt;
|
||||
entry_field = _entry_field;
|
||||
table=sqlname;
|
||||
data=NULL;
|
||||
pIndex=NULL;
|
||||
iNumFields =strlen(fmt);
|
||||
MaxEntry = 0;
|
||||
}
|
||||
~SQLStorage()
|
||||
{
|
||||
Free();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T const* LookupEntry(uint32 id) const
|
||||
{
|
||||
if( id == 0 )
|
||||
return NULL;
|
||||
if(id >= MaxEntry)
|
||||
return NULL;
|
||||
return reinterpret_cast<T const*>(pIndex[id]);
|
||||
}
|
||||
|
||||
uint32 RecordCount;
|
||||
uint32 MaxEntry;
|
||||
uint32 iNumFields;
|
||||
void Load();
|
||||
void Free();
|
||||
private:
|
||||
char** pIndex;
|
||||
|
||||
char *data;
|
||||
const char *format;
|
||||
const char *table;
|
||||
const char *entry_field;
|
||||
//bool HasString;
|
||||
};
|
||||
#endif
|
||||
55
src/shared/Database/SqlDelayThread.cpp
Normal file
55
src/shared/Database/SqlDelayThread.cpp
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Database/SqlDelayThread.h"
|
||||
#include "Database/SqlOperations.h"
|
||||
#include "DatabaseEnv.h"
|
||||
|
||||
SqlDelayThread::SqlDelayThread(Database* db) : m_dbEngine(db), m_running(true)
|
||||
{
|
||||
}
|
||||
|
||||
void SqlDelayThread::run()
|
||||
{
|
||||
SqlOperation* s;
|
||||
#ifndef DO_POSTGRESQL
|
||||
mysql_thread_init();
|
||||
#endif
|
||||
|
||||
while (m_running)
|
||||
{
|
||||
// if the running state gets turned off while sleeping
|
||||
// empty the queue before exiting
|
||||
ZThread::Thread::sleep(10);
|
||||
while (!m_sqlQueue.empty())
|
||||
{
|
||||
s = m_sqlQueue.next();
|
||||
s->Execute(m_dbEngine);
|
||||
delete s;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef DO_POSTGRESQL
|
||||
mysql_thread_end();
|
||||
#endif
|
||||
}
|
||||
|
||||
void SqlDelayThread::Stop()
|
||||
{
|
||||
m_running = false;
|
||||
}
|
||||
48
src/shared/Database/SqlDelayThread.h
Normal file
48
src/shared/Database/SqlDelayThread.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __SQLDELAYTHREAD_H
|
||||
#define __SQLDELAYTHREAD_H
|
||||
|
||||
#include "zthread/Thread.h"
|
||||
#include "zthread/Runnable.h"
|
||||
#include "zthread/FastMutex.h"
|
||||
#include "zthread/LockedQueue.h"
|
||||
|
||||
class Database;
|
||||
class SqlOperation;
|
||||
|
||||
class SqlDelayThread : public ZThread::Runnable
|
||||
{
|
||||
typedef ZThread::LockedQueue<SqlOperation*, ZThread::FastMutex> SqlQueue;
|
||||
private:
|
||||
SqlQueue m_sqlQueue; ///< Queue of SQL statements
|
||||
Database* m_dbEngine; ///< Pointer to used Database engine
|
||||
bool m_running;
|
||||
|
||||
SqlDelayThread();
|
||||
public:
|
||||
SqlDelayThread(Database* db);
|
||||
|
||||
///< Put sql statement to delay queue
|
||||
inline void Delay(SqlOperation* sql) { m_sqlQueue.add(sql); }
|
||||
|
||||
virtual void Stop(); ///< Stop event
|
||||
virtual void run(); ///< Main Thread loop
|
||||
};
|
||||
#endif //__SQLDELAYTHREAD_H
|
||||
197
src/shared/Database/SqlOperations.cpp
Normal file
197
src/shared/Database/SqlOperations.cpp
Normal file
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "SqlOperations.h"
|
||||
#include "SqlDelayThread.h"
|
||||
#include "DatabaseEnv.h"
|
||||
#include "DatabaseImpl.h"
|
||||
|
||||
/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
|
||||
|
||||
void SqlStatement::Execute(Database *db)
|
||||
{
|
||||
/// just do it
|
||||
db->DirectExecute(m_sql);
|
||||
}
|
||||
|
||||
void SqlTransaction::Execute(Database *db)
|
||||
{
|
||||
if(m_queue.empty())
|
||||
return;
|
||||
db->DirectExecute("START TRANSACTION");
|
||||
while(!m_queue.empty())
|
||||
{
|
||||
char const *sql = m_queue.front();
|
||||
m_queue.pop();
|
||||
|
||||
if(!db->DirectExecute(sql))
|
||||
{
|
||||
free((void*)const_cast<char*>(sql));
|
||||
db->DirectExecute("ROLLBACK");
|
||||
while(!m_queue.empty())
|
||||
{
|
||||
free((void*)const_cast<char*>(m_queue.front()));
|
||||
m_queue.pop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
free((void*)const_cast<char*>(sql));
|
||||
}
|
||||
db->DirectExecute("COMMIT");
|
||||
}
|
||||
|
||||
/// ---- ASYNC QUERIES ----
|
||||
|
||||
void SqlQuery::Execute(Database *db)
|
||||
{
|
||||
if(!m_callback || !m_queue)
|
||||
return;
|
||||
/// execute the query and store the result in the callback
|
||||
m_callback->SetResult(db->Query(m_sql));
|
||||
/// add the callback to the sql result queue of the thread it originated from
|
||||
m_queue->add(m_callback);
|
||||
}
|
||||
|
||||
void SqlResultQueue::Update()
|
||||
{
|
||||
/// execute the callbacks waiting in the synchronization queue
|
||||
while(!empty())
|
||||
{
|
||||
MaNGOS::IQueryCallback * callback = next();
|
||||
callback->Execute();
|
||||
delete callback;
|
||||
}
|
||||
}
|
||||
|
||||
void SqlQueryHolder::Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue)
|
||||
{
|
||||
if(!callback || !thread || !queue)
|
||||
return;
|
||||
|
||||
/// delay the execution of the queries, sync them with the delay thread
|
||||
/// which will in turn resync on execution (via the queue) and call back
|
||||
SqlQueryHolderEx *holderEx = new SqlQueryHolderEx(this, callback, queue);
|
||||
thread->Delay(holderEx);
|
||||
}
|
||||
|
||||
bool SqlQueryHolder::SetQuery(size_t index, const char *sql)
|
||||
{
|
||||
if(m_queries.size() <= index)
|
||||
{
|
||||
sLog.outError("Query index (%u) out of range (size: %u) for query: %s",index,m_queries.size(),sql);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(m_queries[index].first != NULL)
|
||||
{
|
||||
sLog.outError("Attempt assign query to holder index (%u) where other query stored (Old: [%s] New: [%s])",index,m_queries.size(),m_queries[index].first,sql);
|
||||
return false;
|
||||
}
|
||||
|
||||
/// not executed yet, just stored (it's not called a holder for nothing)
|
||||
m_queries[index] = SqlResultPair(strdup(sql), NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SqlQueryHolder::SetPQuery(size_t index, const char *format, ...)
|
||||
{
|
||||
if(!format)
|
||||
{
|
||||
sLog.outError("Query (index: %u) is empty.",index);
|
||||
return false;
|
||||
}
|
||||
|
||||
va_list ap;
|
||||
char szQuery [MAX_QUERY_LEN];
|
||||
va_start(ap, format);
|
||||
int res = vsnprintf( szQuery, MAX_QUERY_LEN, format, ap );
|
||||
va_end(ap);
|
||||
|
||||
if(res==-1)
|
||||
{
|
||||
sLog.outError("SQL Query truncated (and not execute) for format: %s",format);
|
||||
return false;
|
||||
}
|
||||
|
||||
return SetQuery(index,szQuery);
|
||||
}
|
||||
|
||||
QueryResult* SqlQueryHolder::GetResult(size_t index)
|
||||
{
|
||||
if(index < m_queries.size())
|
||||
{
|
||||
/// the query strings are freed on the first GetResult or in the destructor
|
||||
if(m_queries[index].first != NULL)
|
||||
{
|
||||
free((void*)(const_cast<char*>(m_queries[index].first)));
|
||||
m_queries[index].first = NULL;
|
||||
}
|
||||
/// when you get a result aways remember to delete it!
|
||||
return m_queries[index].second;
|
||||
}
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void SqlQueryHolder::SetResult(size_t index, QueryResult *result)
|
||||
{
|
||||
/// store the result in the holder
|
||||
if(index < m_queries.size())
|
||||
m_queries[index].second = result;
|
||||
}
|
||||
|
||||
SqlQueryHolder::~SqlQueryHolder()
|
||||
{
|
||||
for(size_t i = 0; i < m_queries.size(); i++)
|
||||
{
|
||||
/// if the result was never used, free the resources
|
||||
/// results used already (getresult called) are expected to be deleted
|
||||
if(m_queries[i].first != NULL)
|
||||
{
|
||||
free((void*)(const_cast<char*>(m_queries[i].first)));
|
||||
if(m_queries[i].second)
|
||||
delete m_queries[i].second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SqlQueryHolder::SetSize(size_t size)
|
||||
{
|
||||
/// to optimize push_back, reserve the number of queries about to be executed
|
||||
m_queries.resize(size);
|
||||
}
|
||||
|
||||
void SqlQueryHolderEx::Execute(Database *db)
|
||||
{
|
||||
if(!m_holder || !m_callback || !m_queue)
|
||||
return;
|
||||
|
||||
/// we can do this, we are friends
|
||||
std::vector<SqlQueryHolder::SqlResultPair> &queries = m_holder->m_queries;
|
||||
|
||||
for(size_t i = 0; i < queries.size(); i++)
|
||||
{
|
||||
/// execute all queries in the holder and pass the results
|
||||
char const *sql = queries[i].first;
|
||||
if(sql) m_holder->SetResult(i, db->Query(sql));
|
||||
}
|
||||
|
||||
/// sync with the caller thread
|
||||
m_queue->add(m_callback);
|
||||
}
|
||||
121
src/shared/Database/SqlOperations.h
Normal file
121
src/shared/Database/SqlOperations.h
Normal file
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __SQLOPERATIONS_H
|
||||
#define __SQLOPERATIONS_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include "zthread/LockedQueue.h"
|
||||
#include "zthread/FastMutex.h"
|
||||
#include "zthread/Thread.h"
|
||||
#include <queue>
|
||||
#include "Utilities/Callback.h"
|
||||
|
||||
/// ---- BASE ---
|
||||
|
||||
class Database;
|
||||
class SqlDelayThread;
|
||||
|
||||
class SqlOperation
|
||||
{
|
||||
public:
|
||||
virtual void OnRemove() { delete this; }
|
||||
virtual void Execute(Database *db) = 0;
|
||||
virtual ~SqlOperation() {}
|
||||
};
|
||||
|
||||
/// ---- ASYNC STATEMENTS / TRANSACTIONS ----
|
||||
|
||||
class SqlStatement : public SqlOperation
|
||||
{
|
||||
private:
|
||||
const char *m_sql;
|
||||
public:
|
||||
SqlStatement(const char *sql) : m_sql(strdup(sql)){}
|
||||
~SqlStatement() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
class SqlTransaction : public SqlOperation
|
||||
{
|
||||
private:
|
||||
std::queue<const char *> m_queue;
|
||||
public:
|
||||
SqlTransaction() {}
|
||||
void DelayExecute(const char *sql) { m_queue.push(strdup(sql)); }
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
/// ---- ASYNC QUERIES ----
|
||||
|
||||
class SqlQuery; /// contains a single async query
|
||||
class QueryResult; /// the result of one
|
||||
class SqlResultQueue; /// queue for thread sync
|
||||
class SqlQueryHolder; /// groups several async quries
|
||||
class SqlQueryHolderEx; /// points to a holder, added to the delay thread
|
||||
|
||||
class SqlResultQueue : public ZThread::LockedQueue<MaNGOS::IQueryCallback*, ZThread::FastMutex>
|
||||
{
|
||||
public:
|
||||
SqlResultQueue() {}
|
||||
void Update();
|
||||
};
|
||||
|
||||
class SqlQuery : public SqlOperation
|
||||
{
|
||||
private:
|
||||
const char *m_sql;
|
||||
MaNGOS::IQueryCallback * m_callback;
|
||||
SqlResultQueue * m_queue;
|
||||
public:
|
||||
SqlQuery(const char *sql, MaNGOS::IQueryCallback * callback, SqlResultQueue * queue)
|
||||
: m_sql(strdup(sql)), m_callback(callback), m_queue(queue) {}
|
||||
~SqlQuery() { void* tofree = const_cast<char*>(m_sql); free(tofree); }
|
||||
void Execute(Database *db);
|
||||
};
|
||||
|
||||
class SqlQueryHolder
|
||||
{
|
||||
friend class SqlQueryHolderEx;
|
||||
private:
|
||||
typedef std::pair<const char*, QueryResult*> SqlResultPair;
|
||||
std::vector<SqlResultPair> m_queries;
|
||||
public:
|
||||
SqlQueryHolder() {}
|
||||
~SqlQueryHolder();
|
||||
bool SetQuery(size_t index, const char *sql);
|
||||
bool SetPQuery(size_t index, const char *format, ...) ATTR_PRINTF(3,4);
|
||||
void SetSize(size_t size);
|
||||
QueryResult* GetResult(size_t index);
|
||||
void SetResult(size_t index, QueryResult *result);
|
||||
void Execute(MaNGOS::IQueryCallback * callback, SqlDelayThread *thread, SqlResultQueue *queue);
|
||||
};
|
||||
|
||||
class SqlQueryHolderEx : public SqlOperation
|
||||
{
|
||||
private:
|
||||
SqlQueryHolder * m_holder;
|
||||
MaNGOS::IQueryCallback * m_callback;
|
||||
SqlResultQueue * m_queue;
|
||||
public:
|
||||
SqlQueryHolderEx(SqlQueryHolder *holder, MaNGOS::IQueryCallback * callback, SqlResultQueue * queue)
|
||||
: m_holder(holder), m_callback(callback), m_queue(queue) {}
|
||||
void Execute(Database *db);
|
||||
};
|
||||
#endif //__SQLOPERATIONS_H
|
||||
243
src/shared/Database/dbcfile.cpp
Normal file
243
src/shared/Database/dbcfile.cpp
Normal file
|
|
@ -0,0 +1,243 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "dbcfile.h"
|
||||
|
||||
DBCFile::DBCFile()
|
||||
{
|
||||
data = NULL;
|
||||
fieldsOffset = NULL;
|
||||
}
|
||||
|
||||
bool DBCFile::Load(const char *filename, const char *fmt)
|
||||
{
|
||||
|
||||
uint32 header;
|
||||
if(data)
|
||||
{
|
||||
delete [] data;
|
||||
data=NULL;
|
||||
}
|
||||
FILE * f=fopen(filename,"rb");
|
||||
if(!f)return false;
|
||||
|
||||
fread(&header,4,1,f); // Number of records
|
||||
EndianConvert(header);
|
||||
if(header!=0x43424457)
|
||||
{
|
||||
//printf("not dbc file");
|
||||
return false; //'WDBC'
|
||||
}
|
||||
fread(&recordCount,4,1,f); // Number of records
|
||||
EndianConvert(recordCount);
|
||||
fread(&fieldCount,4,1,f); // Number of fields
|
||||
EndianConvert(fieldCount);
|
||||
fread(&recordSize,4,1,f); // Size of a record
|
||||
EndianConvert(recordSize);
|
||||
fread(&stringSize,4,1,f); // String size
|
||||
EndianConvert(stringSize);
|
||||
|
||||
fieldsOffset = new uint32[fieldCount];
|
||||
fieldsOffset[0] = 0;
|
||||
for(uint32 i = 1; i < fieldCount; i++)
|
||||
{
|
||||
fieldsOffset[i] = fieldsOffset[i - 1];
|
||||
if (fmt[i - 1] == 'b' || fmt[i - 1] == 'X') // byte fields
|
||||
fieldsOffset[i] += 1;
|
||||
else // 4 byte fields (int32/float/strings)
|
||||
fieldsOffset[i] += 4;
|
||||
}
|
||||
|
||||
data = new unsigned char[recordSize*recordCount+stringSize];
|
||||
stringTable = data + recordSize*recordCount;
|
||||
fread(data,recordSize*recordCount+stringSize,1,f);
|
||||
fclose(f);
|
||||
return true;
|
||||
}
|
||||
|
||||
DBCFile::~DBCFile()
|
||||
{
|
||||
if(data)
|
||||
delete [] data;
|
||||
if(fieldsOffset)
|
||||
delete [] fieldsOffset;
|
||||
}
|
||||
|
||||
DBCFile::Record DBCFile::getRecord(size_t id)
|
||||
{
|
||||
assert(data);
|
||||
return Record(*this, data + id*recordSize);
|
||||
}
|
||||
|
||||
uint32 DBCFile::GetFormatRecordSize(const char * format,int32* index_pos)
|
||||
{
|
||||
uint32 recordsize = 0;
|
||||
int32 i = -1;
|
||||
for(uint32 x=0; format[x];++x)
|
||||
switch(format[x])
|
||||
{
|
||||
case FT_FLOAT:
|
||||
case FT_INT:
|
||||
recordsize+=4;
|
||||
break;
|
||||
case FT_STRING:
|
||||
recordsize+=sizeof(char*);
|
||||
break;
|
||||
case FT_SORT:
|
||||
i=x;
|
||||
break;
|
||||
case FT_IND:
|
||||
i=x;
|
||||
recordsize+=4;
|
||||
break;
|
||||
case FT_BYTE:
|
||||
recordsize += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if(index_pos)
|
||||
*index_pos = i;
|
||||
|
||||
return recordsize;
|
||||
}
|
||||
|
||||
char* DBCFile::AutoProduceData(const char* format, uint32& records, char**& indexTable)
|
||||
{
|
||||
/*
|
||||
format STRING, NA, FLOAT,NA,INT <=>
|
||||
struct{
|
||||
char* field0,
|
||||
float field1,
|
||||
int field2
|
||||
}entry;
|
||||
|
||||
this func will generate entry[rows] data;
|
||||
*/
|
||||
|
||||
typedef char * ptr;
|
||||
if(strlen(format)!=fieldCount)
|
||||
return NULL;
|
||||
|
||||
//get struct size and index pos
|
||||
int32 i;
|
||||
uint32 recordsize=GetFormatRecordSize(format,&i);
|
||||
|
||||
if(i>=0)
|
||||
{
|
||||
uint32 maxi=0;
|
||||
//find max index
|
||||
for(uint32 y=0;y<recordCount;y++)
|
||||
{
|
||||
uint32 ind=getRecord(y).getUInt (i);
|
||||
if(ind>maxi)maxi=ind;
|
||||
}
|
||||
|
||||
++maxi;
|
||||
records=maxi;
|
||||
indexTable=new ptr[maxi];
|
||||
memset(indexTable,0,maxi*sizeof(ptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
records = recordCount;
|
||||
indexTable = new ptr[recordCount];
|
||||
}
|
||||
|
||||
char* dataTable= new char[recordCount*recordsize];
|
||||
|
||||
uint32 offset=0;
|
||||
|
||||
for(uint32 y =0;y<recordCount;y++)
|
||||
{
|
||||
if(i>=0)
|
||||
{
|
||||
indexTable[getRecord(y).getUInt(i)]=&dataTable[offset];
|
||||
}
|
||||
else
|
||||
indexTable[y]=&dataTable[offset];
|
||||
|
||||
for(uint32 x=0;x<fieldCount;x++)
|
||||
{
|
||||
switch(format[x])
|
||||
{
|
||||
case FT_FLOAT:
|
||||
*((float*)(&dataTable[offset]))=getRecord(y).getFloat(x);
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_IND:
|
||||
case FT_INT:
|
||||
*((uint32*)(&dataTable[offset]))=getRecord(y).getUInt(x);
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_BYTE:
|
||||
*((uint8*)(&dataTable[offset]))=getRecord(y).getUInt8(x);
|
||||
offset+=1;
|
||||
break;
|
||||
case FT_STRING:
|
||||
*((char**)(&dataTable[offset]))=NULL; // will be replaces non-empty or "" strings in AutoProduceStrings
|
||||
offset+=sizeof(char*);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return dataTable;
|
||||
}
|
||||
|
||||
char* DBCFile::AutoProduceStrings(const char* format, char* dataTable)
|
||||
{
|
||||
if(strlen(format)!=fieldCount)
|
||||
return NULL;
|
||||
|
||||
char* stringPool= new char[stringSize];
|
||||
memcpy(stringPool,stringTable,stringSize);
|
||||
|
||||
uint32 offset=0;
|
||||
|
||||
for(uint32 y =0;y<recordCount;y++)
|
||||
{
|
||||
for(uint32 x=0;x<fieldCount;x++)
|
||||
switch(format[x])
|
||||
{
|
||||
case FT_FLOAT:
|
||||
case FT_IND:
|
||||
case FT_INT:
|
||||
offset+=4;
|
||||
break;
|
||||
case FT_BYTE:
|
||||
offset+=1;
|
||||
break;
|
||||
case FT_STRING:
|
||||
// fill only not filled entries
|
||||
char** slot = (char**)(&dataTable[offset]);
|
||||
if(!*slot || !**slot)
|
||||
{
|
||||
const char * st = getRecord(y).getString(x);
|
||||
*slot=stringPool+(st-(const char*)stringTable);
|
||||
}
|
||||
offset+=sizeof(char*);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return stringPool;
|
||||
}
|
||||
107
src/shared/Database/dbcfile.h
Normal file
107
src/shared/Database/dbcfile.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef DBCFILE_H
|
||||
#define DBCFILE_H
|
||||
#include "Platform/Define.h"
|
||||
#include "Utilities/ByteConverter.h"
|
||||
#include <cassert>
|
||||
|
||||
enum
|
||||
{
|
||||
FT_NA='x', //not used or unknown, 4 byte size
|
||||
FT_NA_BYTE='X', //not used or unknown, byte
|
||||
FT_STRING='s', //char*
|
||||
FT_FLOAT='f', //float
|
||||
FT_INT='i', //uint32
|
||||
FT_BYTE='b', //uint8
|
||||
FT_SORT='d', //sorted by this field, field is not included
|
||||
FT_IND='n', //the same,but parsed to data
|
||||
FT_LOGIC='l' //Logical (boolean)
|
||||
};
|
||||
|
||||
class DBCFile
|
||||
{
|
||||
public:
|
||||
DBCFile();
|
||||
~DBCFile();
|
||||
|
||||
bool Load(const char *filename, const char *fmt);
|
||||
|
||||
class Record
|
||||
{
|
||||
public:
|
||||
float getFloat(size_t field) const
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
float val = *reinterpret_cast<float*>(offset+file.GetOffset(field));
|
||||
EndianConvert(val);
|
||||
return val;
|
||||
}
|
||||
uint32 getUInt(size_t field) const
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
uint32 val = *reinterpret_cast<uint32*>(offset+file.GetOffset(field));
|
||||
EndianConvert(val);
|
||||
return val;
|
||||
}
|
||||
uint8 getUInt8(size_t field) const
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
return *reinterpret_cast<uint8*>(offset+file.GetOffset(field));
|
||||
}
|
||||
|
||||
const char *getString(size_t field) const
|
||||
{
|
||||
assert(field < file.fieldCount);
|
||||
size_t stringOffset = getUInt(field);
|
||||
assert(stringOffset < file.stringSize);
|
||||
return reinterpret_cast<char*>(file.stringTable + stringOffset);
|
||||
}
|
||||
|
||||
private:
|
||||
Record(DBCFile &file_, unsigned char *offset_): offset(offset_), file(file_) {}
|
||||
unsigned char *offset;
|
||||
DBCFile &file;
|
||||
|
||||
friend class DBCFile;
|
||||
|
||||
};
|
||||
|
||||
// Get record by id
|
||||
Record getRecord(size_t id);
|
||||
/// Get begin iterator over records
|
||||
|
||||
uint32 GetNumRows() const { return recordCount;}
|
||||
uint32 GetCols() const { return fieldCount; }
|
||||
uint32 GetOffset(size_t id) const { return (fieldsOffset != NULL && id < fieldCount) ? fieldsOffset[id] : 0; }
|
||||
bool IsLoaded() {return (data!=NULL);}
|
||||
char* AutoProduceData(const char* fmt, uint32& count, char**& indexTable);
|
||||
char* AutoProduceStrings(const char* fmt, char* dataTable);
|
||||
static uint32 GetFormatRecordSize(const char * format, int32 * index_pos = NULL);
|
||||
private:
|
||||
|
||||
uint32 recordSize;
|
||||
uint32 recordCount;
|
||||
uint32 fieldCount;
|
||||
uint32 stringSize;
|
||||
uint32 *fieldsOffset;
|
||||
unsigned char *data;
|
||||
unsigned char *stringTable;
|
||||
};
|
||||
#endif
|
||||
29
src/shared/Errors.h
Normal file
29
src/shared/Errors.h
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOSSERVER_ERRORS_H
|
||||
#define MANGOSSERVER_ERRORS_H
|
||||
|
||||
#define WPAssert( assertion ) { if( !(assertion) ) { fprintf( stderr, "\n%s:%i ASSERTION FAILED:\n %s\n", __FILE__, __LINE__, #assertion ); assert( #assertion &&0 ); } }
|
||||
#define WPError( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%s:%i ERROR:\n %s\n", __FILE__, __LINE__, (char *)errmsg ); assert( false ); }
|
||||
#define WPWarning( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%s:%i WARNING:\n %s\n", __FILE__, __LINE__, (char *)errmsg ); }
|
||||
|
||||
#define WPFatal( assertion, errmsg ) if( ! (assertion) ) { sLog.outError( "%s:%i FATAL ERROR:\n %s\n", __FILE__, __LINE__, (char *)errmsg ); assert( #assertion &&0 ); abort(); }
|
||||
|
||||
#define ASSERT WPAssert
|
||||
#endif
|
||||
762
src/shared/Log.cpp
Normal file
762
src/shared/Log.cpp
Normal file
|
|
@ -0,0 +1,762 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Util.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
INSTANTIATE_SINGLETON_1( Log );
|
||||
|
||||
enum LogType
|
||||
{
|
||||
LogNormal = 0,
|
||||
LogDetails,
|
||||
LogDebug,
|
||||
LogError
|
||||
};
|
||||
|
||||
const int LogType_count = int(LogError) +1;
|
||||
|
||||
void Log::InitColors(std::string str)
|
||||
{
|
||||
if(str.empty())
|
||||
{
|
||||
m_colored = false;
|
||||
return;
|
||||
}
|
||||
|
||||
int color[4];
|
||||
|
||||
std::istringstream ss(str);
|
||||
|
||||
for(int i = 0; i < LogType_count; ++i)
|
||||
{
|
||||
ss >> color[i];
|
||||
|
||||
if(!ss)
|
||||
return;
|
||||
|
||||
if(color[i] < 0 || color[i] >= Color_count)
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < LogType_count; ++i)
|
||||
m_colors[i] = Color(color[i]);
|
||||
|
||||
m_colored = true;
|
||||
}
|
||||
|
||||
void Log::SetColor(bool stdout_stream, Color color)
|
||||
{
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
|
||||
static WORD WinColorFG[Color_count] =
|
||||
{
|
||||
0, // BLACK
|
||||
FOREGROUND_RED, // RED
|
||||
FOREGROUND_GREEN, // GREEN
|
||||
FOREGROUND_RED | FOREGROUND_GREEN, // BROWN
|
||||
FOREGROUND_BLUE, // BLUE
|
||||
FOREGROUND_RED | FOREGROUND_BLUE,// MAGENTA
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE, // CYAN
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,// WHITE
|
||||
// YELLOW
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
// RED_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_INTENSITY,
|
||||
// GREEN_BOLD
|
||||
FOREGROUND_GREEN | FOREGROUND_INTENSITY,
|
||||
FOREGROUND_BLUE | FOREGROUND_INTENSITY, // BLUE_BOLD
|
||||
// MAGENTA_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
// CYAN_BOLD
|
||||
FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY,
|
||||
// WHITE_BOLD
|
||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY
|
||||
};
|
||||
|
||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
|
||||
SetConsoleTextAttribute(hConsole, WinColorFG[color]);
|
||||
#else
|
||||
|
||||
enum ANSITextAttr
|
||||
{
|
||||
TA_NORMAL=0,
|
||||
TA_BOLD=1,
|
||||
TA_BLINK=5,
|
||||
TA_REVERSE=7
|
||||
};
|
||||
|
||||
enum ANSIFgTextAttr
|
||||
{
|
||||
FG_BLACK=30, FG_RED, FG_GREEN, FG_BROWN, FG_BLUE,
|
||||
FG_MAGENTA, FG_CYAN, FG_WHITE, FG_YELLOW
|
||||
};
|
||||
|
||||
enum ANSIBgTextAttr
|
||||
{
|
||||
BG_BLACK=40, BG_RED, BG_GREEN, BG_BROWN, BG_BLUE,
|
||||
BG_MAGENTA, BG_CYAN, BG_WHITE
|
||||
};
|
||||
|
||||
static uint8 UnixColorFG[Color_count] =
|
||||
{
|
||||
FG_BLACK, // BLACK
|
||||
FG_RED, // RED
|
||||
FG_GREEN, // GREEN
|
||||
FG_BROWN, // BROWN
|
||||
FG_BLUE, // BLUE
|
||||
FG_MAGENTA, // MAGENTA
|
||||
FG_CYAN, // CYAN
|
||||
FG_WHITE, // WHITE
|
||||
FG_YELLOW, // YELLOW
|
||||
FG_RED, // LRED
|
||||
FG_GREEN, // LGREEN
|
||||
FG_BLUE, // LBLUE
|
||||
FG_MAGENTA, // LMAGENTA
|
||||
FG_CYAN, // LCYAN
|
||||
FG_WHITE // LWHITE
|
||||
};
|
||||
|
||||
fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm",UnixColorFG[color],(color>=YELLOW&&color<Color_count ?";1":""));
|
||||
#endif
|
||||
}
|
||||
|
||||
void Log::ResetColor(bool stdout_stream)
|
||||
{
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
HANDLE hConsole = GetStdHandle(stdout_stream ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE );
|
||||
SetConsoleTextAttribute(hConsole, FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED );
|
||||
#else
|
||||
fprintf(( stdout_stream ? stdout : stderr ), "\x1b[0m");
|
||||
#endif
|
||||
}
|
||||
|
||||
void Log::SetLogLevel(char *Level)
|
||||
{
|
||||
int32 NewLevel =atoi((char*)Level);
|
||||
if ( NewLevel <0 )
|
||||
NewLevel = 0;
|
||||
m_logLevel = NewLevel;
|
||||
|
||||
printf( "LogLevel is %u\n",m_logLevel );
|
||||
}
|
||||
|
||||
void Log::SetLogFileLevel(char *Level)
|
||||
{
|
||||
int32 NewLevel =atoi((char*)Level);
|
||||
if ( NewLevel <0 )
|
||||
NewLevel = 0;
|
||||
m_logFileLevel = NewLevel;
|
||||
|
||||
printf( "LogFileLevel is %u\n",m_logFileLevel );
|
||||
}
|
||||
|
||||
void Log::Initialize()
|
||||
{
|
||||
std::string logsDir = sConfig.GetStringDefault("LogsDir","");
|
||||
|
||||
if(!logsDir.empty())
|
||||
{
|
||||
if((logsDir.at(logsDir.length()-1)!='/') && (logsDir.at(logsDir.length()-1)!='\\'))
|
||||
logsDir.append("/");
|
||||
}
|
||||
|
||||
std::string logfn=sConfig.GetStringDefault("LogFile", "");
|
||||
if(!logfn.empty())
|
||||
{
|
||||
if(sConfig.GetBoolDefault("LogTimestamp",false))
|
||||
{
|
||||
std::string logTimestamp = GetTimestampStr();
|
||||
logTimestamp.insert(0,"_");
|
||||
size_t dot_pos = logfn.find_last_of(".");
|
||||
if(dot_pos!=logfn.npos)
|
||||
logfn.insert(dot_pos,logTimestamp);
|
||||
else
|
||||
logfn += logTimestamp;
|
||||
}
|
||||
|
||||
logfile = fopen((logsDir+logfn).c_str(), "w");
|
||||
}
|
||||
|
||||
std::string gmlogname = sConfig.GetStringDefault("GMLogFile", "");
|
||||
if(!gmlogname.empty())
|
||||
{
|
||||
if(sConfig.GetBoolDefault("GmLogTimestamp",false))
|
||||
{
|
||||
std::string gmLogTimestamp = GetTimestampStr();
|
||||
gmLogTimestamp.insert(0,"_");
|
||||
size_t dot_pos = gmlogname.find_last_of(".");
|
||||
if(dot_pos!=gmlogname.npos)
|
||||
gmlogname.insert(dot_pos,gmLogTimestamp);
|
||||
else
|
||||
gmlogname += gmLogTimestamp;
|
||||
}
|
||||
gmLogfile = fopen((logsDir+gmlogname).c_str(), "a");
|
||||
}
|
||||
|
||||
std::string charlogname = sConfig.GetStringDefault("CharLogFile", "");
|
||||
if(!charlogname.empty())
|
||||
{
|
||||
if(sConfig.GetBoolDefault("CharLogTimestamp",false))
|
||||
{
|
||||
std::string charLogTimestamp = GetTimestampStr();
|
||||
charLogTimestamp.insert(0,"_");
|
||||
size_t dot_pos = charlogname.find_last_of(".");
|
||||
if(dot_pos!=charlogname.npos)
|
||||
charlogname.insert(dot_pos,charLogTimestamp);
|
||||
else
|
||||
charlogname += charLogTimestamp;
|
||||
}
|
||||
charLogfile = fopen((logsDir+charlogname).c_str(), "a");
|
||||
}
|
||||
|
||||
std::string dberlogname = sConfig.GetStringDefault("DBErrorLogFile", "");
|
||||
if(!dberlogname.empty())
|
||||
{
|
||||
dberLogfile = fopen((logsDir+dberlogname).c_str(), "a");
|
||||
}
|
||||
std::string ralogname = sConfig.GetStringDefault("RaLogFile", "");
|
||||
if(!ralogname.empty())
|
||||
{
|
||||
raLogfile = fopen((logsDir+ralogname).c_str(), "a");
|
||||
}
|
||||
m_includeTime = sConfig.GetBoolDefault("LogTime", false);
|
||||
m_logLevel = sConfig.GetIntDefault("LogLevel", 0);
|
||||
m_logFileLevel = sConfig.GetIntDefault("LogFileLevel", 0);
|
||||
InitColors(sConfig.GetStringDefault("LogColors", ""));
|
||||
|
||||
m_logFilter = 0;
|
||||
|
||||
if(sConfig.GetBoolDefault("LogFilter_TransportMoves", true))
|
||||
m_logFilter |= LOG_FILTER_TRANSPORT_MOVES;
|
||||
if(sConfig.GetBoolDefault("LogFilter_CreatureMoves", true))
|
||||
m_logFilter |= LOG_FILTER_CREATURE_MOVES;
|
||||
if(sConfig.GetBoolDefault("LogFilter_VisibilityChanges", true))
|
||||
m_logFilter |= LOG_FILTER_VISIBILITY_CHANGES;
|
||||
|
||||
m_charLog_Dump = sConfig.GetBoolDefault("CharLogDump", false);
|
||||
}
|
||||
|
||||
void Log::outTimestamp(FILE* file)
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
tm* aTm = localtime(&t);
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
// HH hour (2 digits 00-23)
|
||||
// MM minutes (2 digits 00-59)
|
||||
// SS seconds (2 digits 00-59)
|
||||
fprintf(file,"%-4d-%02d-%02d %02d:%02d:%02d ",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
|
||||
}
|
||||
|
||||
void Log::outTime()
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
tm* aTm = localtime(&t);
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
// HH hour (2 digits 00-23)
|
||||
// MM minutes (2 digits 00-59)
|
||||
// SS seconds (2 digits 00-59)
|
||||
printf("%02d:%02d:%02d ",aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
|
||||
}
|
||||
|
||||
std::string Log::GetTimestampStr()
|
||||
{
|
||||
time_t t = time(NULL);
|
||||
tm* aTm = localtime(&t);
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
// HH hour (2 digits 00-23)
|
||||
// MM minutes (2 digits 00-59)
|
||||
// SS seconds (2 digits 00-59)
|
||||
char buf[20];
|
||||
snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
void Log::outTitle( const char * str)
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
if(m_colored)
|
||||
SetColor(true,WHITE);
|
||||
|
||||
// not expected utf8 and then send as-is
|
||||
printf( str );
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
|
||||
printf( "\n" );
|
||||
if(logfile)
|
||||
{
|
||||
fprintf(logfile, str);
|
||||
fprintf(logfile, "\n" );
|
||||
fflush(logfile);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outString()
|
||||
{
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
printf( "\n" );
|
||||
if(logfile)
|
||||
{
|
||||
outTimestamp(logfile);
|
||||
fprintf(logfile, "\n" );
|
||||
fflush(logfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outString( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
if(m_colored)
|
||||
SetColor(true,m_colors[LogNormal]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
|
||||
printf( "\n" );
|
||||
if(logfile)
|
||||
{
|
||||
outTimestamp(logfile);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
fprintf(logfile, "\n" );
|
||||
va_end(ap);
|
||||
|
||||
fflush(logfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outError( const char * err, ... )
|
||||
{
|
||||
if( !err )
|
||||
return;
|
||||
|
||||
if(m_colored)
|
||||
SetColor(false,m_colors[LogError]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stderr,err,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(false);
|
||||
|
||||
fprintf( stderr, "\n" );
|
||||
if(logfile)
|
||||
{
|
||||
outTimestamp(logfile);
|
||||
fprintf(logfile, "ERROR:" );
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, err);
|
||||
vfprintf(logfile, err, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(logfile, "\n" );
|
||||
fflush(logfile);
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
void Log::outErrorDb( const char * err, ... )
|
||||
{
|
||||
if( !err )
|
||||
return;
|
||||
|
||||
if(m_colored)
|
||||
SetColor(false,m_colors[LogError]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stderr,err,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(false);
|
||||
|
||||
fprintf( stderr, "\n" );
|
||||
|
||||
if(logfile)
|
||||
{
|
||||
outTimestamp(logfile);
|
||||
fprintf(logfile, "ERROR:" );
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, err);
|
||||
vfprintf(logfile, err, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(logfile, "\n" );
|
||||
fflush(logfile);
|
||||
}
|
||||
|
||||
if(dberLogfile)
|
||||
{
|
||||
outTimestamp(dberLogfile);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, err);
|
||||
vfprintf(dberLogfile, err, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(dberLogfile, "\n" );
|
||||
fflush(dberLogfile);
|
||||
}
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
void Log::outBasic( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
if( m_logLevel > 0 )
|
||||
{
|
||||
if(m_colored)
|
||||
SetColor(true,m_colors[LogDetails]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
|
||||
if(logfile && m_logFileLevel > 0)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(logfile);
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
fprintf(logfile, "\n" );
|
||||
va_end(ap);
|
||||
fflush(logfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outDetail( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
if( m_logLevel > 1 )
|
||||
{
|
||||
|
||||
if(m_colored)
|
||||
SetColor(true,m_colors[LogDetails]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
if(logfile && m_logFileLevel > 1)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(logfile);
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
fprintf(logfile, "\n" );
|
||||
va_end(ap);
|
||||
fflush(logfile);
|
||||
}
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outDebugInLine( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
if( m_logLevel > 2 )
|
||||
{
|
||||
if(m_colored)
|
||||
SetColor(true,m_colors[LogDebug]);
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
}
|
||||
if(logfile && m_logFileLevel > 2)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
va_end(ap);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outDebug( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
if( m_logLevel > 2 )
|
||||
{
|
||||
if(m_colored)
|
||||
SetColor(true,m_colors[LogDebug]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
if(logfile && m_logFileLevel > 2)
|
||||
{
|
||||
outTimestamp(logfile);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(logfile, "\n" );
|
||||
fflush(logfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outCommand( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
if( m_logLevel > 1 )
|
||||
{
|
||||
if(m_colored)
|
||||
SetColor(true,m_colors[LogDetails]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
if(m_colored)
|
||||
ResetColor(true);
|
||||
|
||||
printf( "\n" );
|
||||
}
|
||||
if(logfile && m_logFileLevel > 1)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(logfile);
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
fprintf(logfile, "\n" );
|
||||
va_end(ap);
|
||||
fflush(logfile);
|
||||
}
|
||||
if(gmLogfile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(gmLogfile);
|
||||
va_start(ap, str);
|
||||
vfprintf(gmLogfile, str, ap);
|
||||
fprintf(gmLogfile, "\n" );
|
||||
va_end(ap);
|
||||
fflush(gmLogfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outChar(const char * str, ... )
|
||||
{
|
||||
|
||||
if (!str)
|
||||
return;
|
||||
|
||||
if(charLogfile)
|
||||
{
|
||||
va_list ap;
|
||||
outTimestamp(charLogfile);
|
||||
va_start(ap, str);
|
||||
vfprintf(charLogfile, str, ap);
|
||||
fprintf(charLogfile, "\n" );
|
||||
va_end(ap);
|
||||
fflush(charLogfile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name )
|
||||
{
|
||||
if(charLogfile)
|
||||
{
|
||||
fprintf(charLogfile, "== START DUMP == (account: %u guid: %u name: %s )\n%s\n== END DUMP ==\n",account_id,guid,name,str );
|
||||
fflush(charLogfile);
|
||||
}
|
||||
}
|
||||
|
||||
void Log::outMenu( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
SetColor(true,m_colors[LogNormal]);
|
||||
|
||||
if(m_includeTime)
|
||||
outTime();
|
||||
|
||||
UTF8PRINTF(stdout,str,);
|
||||
|
||||
ResetColor(true);
|
||||
|
||||
if(logfile)
|
||||
{
|
||||
outTimestamp(logfile);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vfprintf(logfile, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
fprintf(logfile, "\n" );
|
||||
fflush(logfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void Log::outRALog( const char * str, ... )
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
va_list ap;
|
||||
if (raLogfile)
|
||||
{
|
||||
outTimestamp(raLogfile);
|
||||
va_start(ap, str);
|
||||
vfprintf(raLogfile, str, ap);
|
||||
fprintf(raLogfile, "\n" );
|
||||
va_end(ap);
|
||||
fflush(raLogfile);
|
||||
}
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void outstring_log(const char * str, ...)
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsnprintf(buf,256, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
MaNGOS::Singleton<Log>::Instance().outString(buf);
|
||||
}
|
||||
|
||||
void detail_log(const char * str, ...)
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsnprintf(buf,256, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
MaNGOS::Singleton<Log>::Instance().outDetail(buf);
|
||||
}
|
||||
|
||||
void debug_log(const char * str, ...)
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsnprintf(buf,256, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
MaNGOS::Singleton<Log>::Instance().outDebug(buf);
|
||||
}
|
||||
|
||||
void error_log(const char * str, ...)
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsnprintf(buf,256, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
MaNGOS::Singleton<Log>::Instance().outError(buf);
|
||||
}
|
||||
|
||||
void error_db_log(const char * str, ...)
|
||||
{
|
||||
if( !str )
|
||||
return;
|
||||
|
||||
char buf[256];
|
||||
va_list ap;
|
||||
va_start(ap, str);
|
||||
vsnprintf(buf,256, str, ap);
|
||||
va_end(ap);
|
||||
|
||||
MaNGOS::Singleton<Log>::Instance().outErrorDb(buf);
|
||||
}
|
||||
154
src/shared/Log.h
Normal file
154
src/shared/Log.h
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOSSERVER_LOG_H
|
||||
#define MANGOSSERVER_LOG_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Policies/Singleton.h"
|
||||
|
||||
class Config;
|
||||
|
||||
// bitmask
|
||||
enum LogFilters
|
||||
{
|
||||
LOG_FILTER_TRANSPORT_MOVES = 1,
|
||||
LOG_FILTER_CREATURE_MOVES = 2,
|
||||
LOG_FILTER_VISIBILITY_CHANGES = 4
|
||||
};
|
||||
|
||||
enum Color
|
||||
{
|
||||
BLACK,
|
||||
RED,
|
||||
GREEN,
|
||||
BROWN,
|
||||
BLUE,
|
||||
MAGENTA,
|
||||
CYAN,
|
||||
GREY,
|
||||
YELLOW,
|
||||
LRED,
|
||||
LGREEN,
|
||||
LBLUE,
|
||||
LMAGENTA,
|
||||
LCYAN,
|
||||
WHITE
|
||||
};
|
||||
|
||||
const int Color_count = int(WHITE)+1;
|
||||
|
||||
class Log : public MaNGOS::Singleton<Log, MaNGOS::ClassLevelLockable<Log, ZThread::FastMutex> >
|
||||
{
|
||||
friend class MaNGOS::OperatorNew<Log>;
|
||||
Log() : raLogfile(NULL), logfile(NULL), gmLogfile(NULL), charLogfile(NULL), dberLogfile(NULL), m_colored(false) { Initialize(); }
|
||||
~Log()
|
||||
{
|
||||
if( logfile != NULL )
|
||||
fclose(logfile);
|
||||
logfile = NULL;
|
||||
|
||||
if( gmLogfile != NULL )
|
||||
fclose(gmLogfile);
|
||||
gmLogfile = NULL;
|
||||
|
||||
if (charLogfile != NULL)
|
||||
fclose(charLogfile);
|
||||
charLogfile = NULL;
|
||||
|
||||
if( dberLogfile != NULL )
|
||||
fclose(dberLogfile);
|
||||
dberLogfile = NULL;
|
||||
|
||||
if (raLogfile != NULL)
|
||||
fclose(raLogfile);
|
||||
raLogfile = NULL;
|
||||
}
|
||||
public:
|
||||
void Initialize();
|
||||
void InitColors(std::string init_str);
|
||||
void outTitle( const char * str);
|
||||
void outCommand( const char * str, ...) ATTR_PRINTF(2,3);
|
||||
void outString(); // any log level
|
||||
// any log level
|
||||
void outString( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// any log level
|
||||
void outError( const char * err, ... ) ATTR_PRINTF(2,3);
|
||||
// log level >= 1
|
||||
void outBasic( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// log level >= 2
|
||||
void outDetail( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// log level >= 3
|
||||
void outDebugInLine( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// log level >= 3
|
||||
void outDebug( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// any log level
|
||||
void outMenu( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// any log level
|
||||
void outErrorDb( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// any log level
|
||||
void outChar( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
// any log level
|
||||
void outCharDump( const char * str, uint32 account_id, uint32 guid, const char * name );
|
||||
void outRALog( const char * str, ... ) ATTR_PRINTF(2,3);
|
||||
void SetLogLevel(char * Level);
|
||||
void SetLogFileLevel(char * Level);
|
||||
void SetColor(bool stdout_stream, Color color);
|
||||
void ResetColor(bool stdout_stream);
|
||||
void outTime();
|
||||
static void outTimestamp(FILE* file);
|
||||
static std::string GetTimestampStr();
|
||||
uint32 getLogFilter() const { return m_logFilter; }
|
||||
bool IsOutDebug() const { return m_logLevel > 2 || (m_logFileLevel > 2 && logfile); }
|
||||
bool IsOutCharDump() const { return m_charLog_Dump; }
|
||||
bool IsIncludeTime() const { return m_includeTime; }
|
||||
private:
|
||||
FILE* raLogfile;
|
||||
FILE* logfile;
|
||||
FILE* gmLogfile;
|
||||
FILE* charLogfile;
|
||||
FILE* dberLogfile;
|
||||
|
||||
// log/console control
|
||||
uint32 m_logLevel;
|
||||
uint32 m_logFileLevel;
|
||||
bool m_colored;
|
||||
bool m_includeTime;
|
||||
Color m_colors[4];
|
||||
uint32 m_logFilter;
|
||||
|
||||
// char log control
|
||||
bool m_charLog_Dump;
|
||||
|
||||
};
|
||||
|
||||
#define sLog MaNGOS::Singleton<Log>::Instance()
|
||||
|
||||
#ifdef MANGOS_DEBUG
|
||||
#define DEBUG_LOG MaNGOS::Singleton<Log>::Instance().outDebug
|
||||
#else
|
||||
#define DEBUG_LOG
|
||||
#endif
|
||||
|
||||
// primary for script library
|
||||
void MANGOS_DLL_SPEC outstring_log(const char * str, ...) ATTR_PRINTF(1,2);
|
||||
void MANGOS_DLL_SPEC detail_log(const char * str, ...) ATTR_PRINTF(1,2);
|
||||
void MANGOS_DLL_SPEC debug_log(const char * str, ...) ATTR_PRINTF(1,2);
|
||||
void MANGOS_DLL_SPEC error_log(const char * str, ...) ATTR_PRINTF(1,2);
|
||||
void MANGOS_DLL_SPEC error_db_log(const char * str, ...) ATTR_PRINTF(1,2);
|
||||
#endif
|
||||
79
src/shared/Makefile.am
Normal file
79
src/shared/Makefile.am
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
# Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
## Sub-directories to parse
|
||||
SUBDIRS = Auth Config Database vmap
|
||||
|
||||
## CPP flags for includes, defines, etc.
|
||||
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../dep/include -I$(srcdir)/../framework -I$(srcdir)/../shared -I$(srcdir)/../../dep/include/g3dlite
|
||||
## AM_CPPFLAGS += -I$(srcdir)/../game -I$(srcdir)/../realmd
|
||||
|
||||
## Build MaNGOS shared library and its parts as convenience library.
|
||||
# All libraries will be convenience libraries. Might be changed to shared
|
||||
# later.
|
||||
noinst_LIBRARIES = libmangosshared.a
|
||||
|
||||
# libmangosshared library will later be reused by ...
|
||||
libmangosshared_a_SOURCES = \
|
||||
Base.cpp \
|
||||
Base.h \
|
||||
ByteBuffer.h \
|
||||
Common.cpp \
|
||||
Common.h \
|
||||
Errors.h \
|
||||
Log.cpp \
|
||||
Log.h \
|
||||
MemoryLeaks.cpp \
|
||||
MemoryLeaks.h \
|
||||
Mthread.cpp \
|
||||
Mthread.h \
|
||||
ProgressBar.cpp \
|
||||
ProgressBar.h \
|
||||
Timer.h \
|
||||
Util.cpp \
|
||||
Util.h \
|
||||
WorldPacket.h \
|
||||
svn_revision.h
|
||||
|
||||
# Get svn revision
|
||||
SVN_REVISION_FILE = svn_revision.h
|
||||
|
||||
BUILT_SOURCES = $(SVN_REVISION_FILE)
|
||||
CLEANFILES = $(SVN_REVISION_FILE)
|
||||
|
||||
FORCE:
|
||||
|
||||
$(SVN_REVISION_FILE) : $(top_builddir)/src/tools/gensvnrevision/gensvnrevision FORCE
|
||||
$(top_builddir)/src/tools/gensvnrevision/gensvnrevision $(top_srcdir)
|
||||
|
||||
## Additional files to include when running 'make dist'
|
||||
# Disabled packet logger
|
||||
EXTRA_DIST = \
|
||||
PacketLog.cpp \
|
||||
PacketLog.h
|
||||
|
||||
# System configuration
|
||||
EXTRA_DIST += \
|
||||
SystemConfig.h
|
||||
|
||||
# System Win32 files
|
||||
EXTRA_DIST += \
|
||||
ServiceWin32.cpp \
|
||||
ServiceWin32.h \
|
||||
WheatyExceptionReport.cpp \
|
||||
WheatyExceptionReport.h
|
||||
32
src/shared/MemoryLeaks.cpp
Normal file
32
src/shared/MemoryLeaks.cpp
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "MemoryLeaks.h"
|
||||
#include "Policies/SingletonImp.h"
|
||||
|
||||
INSTANTIATE_SINGLETON_1( MemoryManager ) ;
|
||||
|
||||
MemoryManager::MemoryManager( )
|
||||
{
|
||||
#if COMPILER == MICROSOFT
|
||||
// standard leak check initialization
|
||||
//_CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
|
||||
// uncomment to disable Visual Leak Detector from code
|
||||
//VLDDisable();
|
||||
#endif
|
||||
}
|
||||
48
src/shared/MemoryLeaks.h
Normal file
48
src/shared/MemoryLeaks.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOSSERVER_MEMORY_H
|
||||
#define MANGOSSERVER_MEMORY_H
|
||||
|
||||
#include "Platform/CompilerDefs.h"
|
||||
|
||||
#if COMPILER == COMPILER_MICROSOFT
|
||||
|
||||
#ifndef _WIN64
|
||||
// Visual Leak Detector support enabled
|
||||
#include <vld/vld.h>
|
||||
// standard Visual Studio leak check disabled,
|
||||
//# define _CRTDBG_MAP_ALLOC
|
||||
//# include <stdlib.h>
|
||||
//# include <crtdbg.h>
|
||||
#else
|
||||
# define _CRTDBG_MAP_ALLOC
|
||||
# include <stdlib.h>
|
||||
# include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#include "Policies/Singleton.h"
|
||||
|
||||
struct MemoryManager : public MaNGOS::Singleton < MemoryManager >
|
||||
{
|
||||
MemoryManager();
|
||||
};
|
||||
#endif
|
||||
205
src/shared/Mthread.cpp
Normal file
205
src/shared/Mthread.cpp
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/*
|
||||
Cross-platform thread handling
|
||||
Copyright (C) 2005 Andrew Zabolotny
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Mthread.h"
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE_CC__)
|
||||
# define MANGOS_PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE
|
||||
#else
|
||||
# define MANGOS_PTHREAD_MUTEX_RECURSIVE PTHREAD_MUTEX_RECURSIVE_NP
|
||||
#endif
|
||||
|
||||
#if PLATFORM != PLATFORM_WINDOWS
|
||||
|
||||
MThread::MThread ()
|
||||
{
|
||||
tid = 0;
|
||||
}
|
||||
|
||||
MThread::~MThread ()
|
||||
{
|
||||
/* Kill thread if this is not the current thread */
|
||||
if (tid && (pthread_self () != tid))
|
||||
{
|
||||
pthread_cancel (tid);
|
||||
pthread_join (tid, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void *thread_start_routine (void *arg)
|
||||
{
|
||||
MThread *newthr = (MThread *)arg;
|
||||
pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
|
||||
newthr->routine (newthr->arg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
MThread *MThread::Start (void (*routine) (void *arg), void *arg)
|
||||
{
|
||||
MThread *newthr = new MThread ();
|
||||
newthr->routine = routine;
|
||||
newthr->arg = arg;
|
||||
int rc = pthread_create (&newthr->tid, NULL, thread_start_routine, newthr);
|
||||
if (rc)
|
||||
{
|
||||
newthr->DecRef ();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return newthr;
|
||||
}
|
||||
|
||||
pthread_mutexattr_t MMutex::attr;
|
||||
int MMutex::attr_refcount = 0;
|
||||
|
||||
MMutex::MMutex ()
|
||||
{
|
||||
if (!attr_refcount++)
|
||||
{
|
||||
pthread_mutexattr_init (&attr);
|
||||
pthread_mutexattr_settype (&attr, MANGOS_PTHREAD_MUTEX_RECURSIVE);
|
||||
}
|
||||
|
||||
pthread_mutex_init (&mutex, &attr);
|
||||
}
|
||||
|
||||
MMutex::~MMutex ()
|
||||
{
|
||||
pthread_mutex_destroy (&mutex);
|
||||
if (!--attr_refcount)
|
||||
pthread_mutexattr_destroy (&attr);
|
||||
}
|
||||
|
||||
bool MMutex::Lock ()
|
||||
{
|
||||
return (pthread_mutex_lock (&mutex) == 0);
|
||||
}
|
||||
|
||||
bool MMutex::TryLock ()
|
||||
{
|
||||
return (pthread_mutex_trylock (&mutex) == 0);
|
||||
}
|
||||
|
||||
void MMutex::Unlock ()
|
||||
{
|
||||
pthread_mutex_unlock (&mutex);
|
||||
}
|
||||
|
||||
MMutex *MMutex::Create ()
|
||||
{
|
||||
return new MMutex ();
|
||||
}
|
||||
|
||||
#else //windows
|
||||
|
||||
MThread::MThread()
|
||||
{
|
||||
th = NULL;
|
||||
}
|
||||
|
||||
MThread::~MThread ()
|
||||
{
|
||||
/* Kill thread if this is not current thread */
|
||||
if (th && (GetCurrentThreadId () != id))
|
||||
{
|
||||
TerminateThread (th, 0);
|
||||
WaitForSingleObject (th, INFINITE);
|
||||
CloseHandle (th);
|
||||
}
|
||||
}
|
||||
|
||||
bool MThread::SetPriority (ThreadPriority prio)
|
||||
{
|
||||
int p;
|
||||
switch (prio)
|
||||
{
|
||||
case IDLE: p = THREAD_PRIORITY_IDLE; break;
|
||||
case LOWER: p = THREAD_PRIORITY_LOWEST; break;
|
||||
case LOW: p = THREAD_PRIORITY_BELOW_NORMAL; break;
|
||||
case NORMAL: p = THREAD_PRIORITY_NORMAL; break;
|
||||
case HIGH: p = THREAD_PRIORITY_ABOVE_NORMAL; break;
|
||||
case HIGHER: p = THREAD_PRIORITY_HIGHEST; break;
|
||||
case REALTIME: p = THREAD_PRIORITY_TIME_CRITICAL; break;
|
||||
default: p = THREAD_PRIORITY_NORMAL; break;
|
||||
}
|
||||
return SetThreadPriority (th, p);
|
||||
}
|
||||
|
||||
static DWORD WINAPI thread_start_routine (void *arg)
|
||||
//static void thread_start_routine (void *arg)
|
||||
{
|
||||
MThread *newthr = (MThread *)arg;
|
||||
newthr->id = GetCurrentThreadId ();
|
||||
newthr->routine (newthr->arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MThread *MThread::Start (void (*routine) (void *arg), void *arg)
|
||||
{
|
||||
DWORD dwtid;
|
||||
MThread *newthr = new MThread ();
|
||||
newthr->routine = routine;
|
||||
newthr->arg = arg;
|
||||
newthr->th = CreateThread (NULL, WIN32_THREAD_STACK_SIZE, thread_start_routine, newthr, 0, &dwtid);
|
||||
//newthr->th = (HANDLE)_beginthread(thread_start_routine, 0, newthr);
|
||||
if (!newthr->th)
|
||||
{
|
||||
newthr->DecRef ();
|
||||
return NULL;
|
||||
}
|
||||
return newthr;
|
||||
}
|
||||
|
||||
MMutex::MMutex ()
|
||||
{
|
||||
sem = CreateMutex (NULL, FALSE, NULL);
|
||||
}
|
||||
|
||||
MMutex::~MMutex ()
|
||||
{
|
||||
CloseHandle (sem);
|
||||
}
|
||||
|
||||
bool MMutex::Lock ()
|
||||
{
|
||||
return (WaitForSingleObject (sem, INFINITE) != WAIT_FAILED);
|
||||
}
|
||||
|
||||
bool MMutex::TryLock ()
|
||||
{
|
||||
DWORD state = WaitForSingleObject (sem, 0);
|
||||
return (state == WAIT_OBJECT_0) && (state != WAIT_ABANDONED);
|
||||
}
|
||||
|
||||
void MMutex::Unlock ()
|
||||
{
|
||||
ReleaseMutex (sem);
|
||||
}
|
||||
|
||||
MMutex *MMutex::Create ()
|
||||
{
|
||||
MMutex *mutex = new MMutex ();
|
||||
if (!mutex->sem)
|
||||
{
|
||||
mutex->DecRef ();
|
||||
return NULL;
|
||||
}
|
||||
return mutex;
|
||||
}
|
||||
#endif
|
||||
62
src/shared/Mthread.h
Normal file
62
src/shared/Mthread.h
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
#ifndef MTHREAD_H
|
||||
#define MTHREAD_H
|
||||
|
||||
#include "Base.h"
|
||||
#ifndef WIN32
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#include <windows.h>
|
||||
//#include "Process.h"
|
||||
#define WIN32_THREAD_STACK_SIZE 0x10000
|
||||
#endif
|
||||
|
||||
enum ThreadPriority
|
||||
{
|
||||
IDLE,
|
||||
LOWER,
|
||||
LOW,
|
||||
NORMAL,
|
||||
HIGH,
|
||||
HIGHER,
|
||||
REALTIME
|
||||
};
|
||||
|
||||
class MThread: public Base
|
||||
{
|
||||
public:
|
||||
static MThread *Start (void (*routine) (void *arg), void *arg);
|
||||
MThread ();
|
||||
~MThread ();
|
||||
bool SetPriority (ThreadPriority prio);
|
||||
|
||||
void (*routine) (void *arg);
|
||||
void *arg;
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE th;
|
||||
ULONG id;
|
||||
#else
|
||||
pthread_t tid;
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
class MMutex : public Base
|
||||
{
|
||||
public:
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE sem;
|
||||
#else
|
||||
pthread_mutex_t mutex;
|
||||
static pthread_mutexattr_t attr;
|
||||
static int attr_refcount;
|
||||
#endif
|
||||
static MMutex *Create ();
|
||||
MMutex ();
|
||||
virtual ~MMutex ();
|
||||
virtual bool Lock ();
|
||||
virtual bool TryLock ();
|
||||
virtual void Unlock ();
|
||||
};
|
||||
#endif // MTHREAD_H
|
||||
157
src/shared/PacketLog.cpp
Normal file
157
src/shared/PacketLog.cpp
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Common.h"
|
||||
#include "PacketLog.h"
|
||||
#include "Config/ConfigEnv.h"
|
||||
#include "Policies/SingletonImpl.h"
|
||||
|
||||
#include <ctype.h>
|
||||
|
||||
INSTANTIATE_SINGLETON_1( PacketLog );
|
||||
|
||||
PacketLog::PacketLog()
|
||||
{
|
||||
|
||||
if (sConfig.GetBoolDefault("LogRealm", false))
|
||||
{
|
||||
FILE *pFile = fopen("realm.log", "w+");
|
||||
fclose(pFile);
|
||||
}
|
||||
|
||||
if (sConfig.GetBoolDefault("LogWorld", false))
|
||||
{
|
||||
FILE *pFile = fopen("world.log", "w+");
|
||||
fclose(pFile);
|
||||
}
|
||||
}
|
||||
|
||||
PacketLog::~PacketLog()
|
||||
{
|
||||
}
|
||||
|
||||
char PacketLog::makehexchar(int i)
|
||||
{
|
||||
return (i<=9) ? '0'+i : 'A'+(i-10);
|
||||
}
|
||||
|
||||
int PacketLog::hextoint(char c)
|
||||
{
|
||||
c = toupper(c);
|
||||
return (c > '9' ? c - 'A' + 10 : c - '0');
|
||||
}
|
||||
|
||||
void PacketLog::HexDump(const unsigned char* data, size_t length, const char* file)
|
||||
{
|
||||
FILE *pFile;
|
||||
pFile = fopen(file, "a");
|
||||
|
||||
const int char_offset = 16*3 + 2;
|
||||
const int line_size = 16*3 + 16 + 3;
|
||||
char line[line_size+1];
|
||||
|
||||
fprintf(pFile,"OFFSET 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F | 0123456789ABCDEF\n");
|
||||
fprintf(pFile,"--------------------------------------------------------------------------\n");
|
||||
|
||||
line[char_offset - 1] = ' ';
|
||||
line[char_offset - 2] = ' ';
|
||||
|
||||
for (size_t i=0; i<length; )
|
||||
{
|
||||
int bi=0;
|
||||
int ci=0;
|
||||
|
||||
int start_i = i;
|
||||
|
||||
for (int line_i=0; i < length && line_i < 16; i++, line_i++)
|
||||
{
|
||||
line[bi++] = makehexchar(*data>>4);
|
||||
line[bi++] = makehexchar(*data & 0x0f);
|
||||
line[bi++] = ' ';
|
||||
line[char_offset+(ci++)]=(isprint(*data) ? *data : '.');
|
||||
++data;
|
||||
}
|
||||
|
||||
while (bi<16*3)
|
||||
{
|
||||
line[bi++]=' ';
|
||||
}
|
||||
|
||||
line[char_offset+(ci++)]='\n';
|
||||
line[char_offset+ci]=0;
|
||||
|
||||
fprintf(pFile,"%06X %s", start_i, line);
|
||||
}
|
||||
fprintf(pFile, "\n\n");
|
||||
fclose(pFile);
|
||||
}
|
||||
|
||||
void PacketLog::HexDump(const char *data, size_t length, const char* file)
|
||||
{
|
||||
HexDump((unsigned char *)data, length, file);
|
||||
}
|
||||
|
||||
void PacketLog::HexDumpStr(const char *msg, const char *data, size_t len, const char* file)
|
||||
{
|
||||
FILE *pFile;
|
||||
pFile = fopen(file, "a");
|
||||
fprintf(pFile,"%s\n", msg);
|
||||
fclose(pFile);
|
||||
|
||||
HexDump(data, len, file);
|
||||
}
|
||||
|
||||
void PacketLog::RealmHexDump(RealmPacket* data, uint32 socket, bool direction)
|
||||
{
|
||||
if (!sConfig.GetBoolDefault("LogRealm", false))
|
||||
return;
|
||||
|
||||
FILE *pFile;
|
||||
pFile = fopen("realm.log", "a");
|
||||
|
||||
uint16 len = data->size() + 2;
|
||||
uint8 opcode = data->GetOpcode();
|
||||
if (direction)
|
||||
fprintf(pFile, "SERVER:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.2X\nDATA:\n", socket, len, opcode);
|
||||
else
|
||||
fprintf(pFile, "CLIENT:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.2X\nDATA:\n", socket, len, opcode);
|
||||
|
||||
fclose(pFile);
|
||||
HexDump((char *)data->contents(), data->size(), "realm.log");
|
||||
|
||||
}
|
||||
|
||||
void PacketLog::WorldHexDump(WorldPacket* data, uint32 socket, bool direction)
|
||||
{
|
||||
if (!sConfig.GetBoolDefault("LogWorld", false))
|
||||
return;
|
||||
|
||||
FILE *pFile;
|
||||
pFile = fopen("world.log", "a");
|
||||
|
||||
uint16 len = data->size();
|
||||
uint16 opcode = data->GetOpcode();
|
||||
if (direction)
|
||||
fprintf(pFile, "SERVER:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.4X\nDATA:\n", socket, len, opcode);
|
||||
else
|
||||
fprintf(pFile, "CLIENT:\nSOCKET: %d\nLENGTH: %d\nOPCODE: %.4X\nDATA:\n", socket, len, opcode);
|
||||
|
||||
fclose(pFile);
|
||||
HexDump((char *)data->contents(), data->size(), "world.log");
|
||||
|
||||
}
|
||||
46
src/shared/PacketLog.h
Normal file
46
src/shared/PacketLog.h
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOSSERVER_PACKETLOG_H
|
||||
#define MANGOSSERVER_PACKETLOG_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "Policies/Singleton.h"
|
||||
#include "RealmPacket.h"
|
||||
#include "WorldPacket.h"
|
||||
|
||||
class PacketLog
|
||||
{
|
||||
public:
|
||||
PacketLog();
|
||||
~PacketLog();
|
||||
|
||||
int hextoint(char c);
|
||||
char makehexchar(int i);
|
||||
|
||||
void HexDump(const unsigned char* data, size_t length, const char* file);
|
||||
void HexDump(const char *data, size_t length, const char* file);
|
||||
void HexDumpStr(const char *msg, const char *data, size_t len, const char* file);
|
||||
|
||||
void RealmHexDump(RealmPacket * data, uint32 socket, bool direction);
|
||||
|
||||
void WorldHexDump(WorldPacket * data, uint32 socket, bool direction);
|
||||
};
|
||||
|
||||
#define sPacketLog MaNGOS::Singleton<PacketLog>::Instance()
|
||||
#endif
|
||||
80
src/shared/ProgressBar.cpp
Normal file
80
src/shared/ProgressBar.cpp
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ProgressBar.h"
|
||||
|
||||
char const* const barGoLink::empty = " ";
|
||||
#ifdef _WIN32
|
||||
char const* const barGoLink::full = "\x3D";
|
||||
#else
|
||||
char const* const barGoLink::full = "*";
|
||||
#endif
|
||||
|
||||
barGoLink::~barGoLink()
|
||||
{
|
||||
printf( "\n" );
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
barGoLink::barGoLink( int row_count )
|
||||
{
|
||||
rec_no = 0;
|
||||
rec_pos = 0;
|
||||
indic_len = 50;
|
||||
num_rec = row_count;
|
||||
#ifdef _WIN32
|
||||
printf( "\x3D" );
|
||||
#else
|
||||
printf( "[" );
|
||||
#endif
|
||||
for ( int i = 0; i < indic_len; i++ ) printf( empty );
|
||||
#ifdef _WIN32
|
||||
printf( "\x3D 0%%\r\x3D" );
|
||||
#else
|
||||
printf( "] 0%%\r[" );
|
||||
#endif
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
void barGoLink::step( void )
|
||||
{
|
||||
int i, n;
|
||||
|
||||
if ( num_rec == 0 ) return;
|
||||
++rec_no;
|
||||
n = rec_no * indic_len / num_rec;
|
||||
if ( n != rec_pos )
|
||||
{
|
||||
#ifdef _WIN32
|
||||
printf( "\r\x3D" );
|
||||
#else
|
||||
printf( "\r[" );
|
||||
#endif
|
||||
for ( i = 0; i < n; i++ ) printf( full );
|
||||
for ( ; i < indic_len; i++ ) printf( empty );
|
||||
float percent = (((float)n/(float)indic_len)*100);
|
||||
#ifdef _WIN32
|
||||
printf( "\x3D %i%% \r\x3D", (int)percent);
|
||||
#else
|
||||
printf( "] %i%% \r[", (int)percent);
|
||||
#endif
|
||||
fflush(stdout);
|
||||
|
||||
rec_pos = n;
|
||||
}
|
||||
}
|
||||
40
src/shared/ProgressBar.h
Normal file
40
src/shared/ProgressBar.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
#ifndef MANGOSSERVER_PROGRESSBAR_H
|
||||
#define MANGOSSERVER_PROGRESSBAR_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include "Platform/Define.h"
|
||||
|
||||
class MANGOS_DLL_SPEC barGoLink
|
||||
{
|
||||
static char const * const empty;
|
||||
static char const * const full;
|
||||
|
||||
int rec_no;
|
||||
int rec_pos;
|
||||
int num_rec;
|
||||
int indic_len;
|
||||
|
||||
public:
|
||||
|
||||
void step( void );
|
||||
barGoLink( int );
|
||||
~barGoLink();
|
||||
};
|
||||
#endif
|
||||
260
src/shared/ServiceWin32.cpp
Normal file
260
src/shared/ServiceWin32.cpp
Normal file
|
|
@ -0,0 +1,260 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include "Common.h"
|
||||
#include "Log.h"
|
||||
#include <cstring>
|
||||
#include <windows.h>
|
||||
#include <winsvc.h>
|
||||
|
||||
#if !defined(WINADVAPI)
|
||||
#if !defined(_ADVAPI32_)
|
||||
#define WINADVAPI DECLSPEC_IMPORT
|
||||
#else
|
||||
#define WINADVAPI
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern int main(int argc, char ** argv);
|
||||
extern char serviceLongName[];
|
||||
extern char serviceName[];
|
||||
extern char serviceDescription[];
|
||||
|
||||
extern int m_ServiceStatus;
|
||||
|
||||
SERVICE_STATUS serviceStatus;
|
||||
|
||||
SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
|
||||
|
||||
typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
|
||||
|
||||
bool WinServiceInstall()
|
||||
{
|
||||
CSD_T ChangeService_Config2;
|
||||
HMODULE advapi32;
|
||||
SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
|
||||
|
||||
if (serviceControlManager)
|
||||
{
|
||||
char path[_MAX_PATH + 10];
|
||||
if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
|
||||
{
|
||||
SC_HANDLE service;
|
||||
std::strcat(path, " --service");
|
||||
service = CreateService(serviceControlManager,
|
||||
serviceName, // name of service
|
||||
serviceLongName, // service name to display
|
||||
SERVICE_ALL_ACCESS, // desired access
|
||||
// service type
|
||||
SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
|
||||
SERVICE_AUTO_START, // start type
|
||||
SERVICE_ERROR_IGNORE, // error control type
|
||||
path, // service's binary
|
||||
0, // no load ordering group
|
||||
0, // no tag identifier
|
||||
0, // no dependencies
|
||||
0, // LocalSystem account
|
||||
0); // no password
|
||||
if (service)
|
||||
{
|
||||
advapi32 = GetModuleHandle("ADVAPI32.DLL");
|
||||
if(!advapi32)
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
|
||||
if (!ChangeService_Config2)
|
||||
{
|
||||
CloseServiceHandle(service);
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
return false;
|
||||
}
|
||||
|
||||
SERVICE_DESCRIPTION sdBuf;
|
||||
sdBuf.lpDescription = serviceDescription;
|
||||
ChangeService_Config2(
|
||||
service, // handle to service
|
||||
SERVICE_CONFIG_DESCRIPTION, // change: description
|
||||
&sdBuf); // new data
|
||||
|
||||
SC_ACTION _action[1];
|
||||
_action[0].Type = SC_ACTION_RESTART;
|
||||
_action[0].Delay = 10000;
|
||||
SERVICE_FAILURE_ACTIONS sfa;
|
||||
ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
|
||||
sfa.lpsaActions = _action;
|
||||
sfa.cActions = 1;
|
||||
sfa.dwResetPeriod =INFINITE;
|
||||
ChangeService_Config2(
|
||||
service, // handle to service
|
||||
SERVICE_CONFIG_FAILURE_ACTIONS, // information level
|
||||
&sfa); // new data
|
||||
|
||||
CloseServiceHandle(service);
|
||||
|
||||
}
|
||||
}
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WinServiceUninstall()
|
||||
{
|
||||
SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
|
||||
|
||||
if (serviceControlManager)
|
||||
{
|
||||
SC_HANDLE service = OpenService(serviceControlManager,
|
||||
serviceName, SERVICE_QUERY_STATUS | DELETE);
|
||||
if (service)
|
||||
{
|
||||
SERVICE_STATUS serviceStatus;
|
||||
if (QueryServiceStatus(service, &serviceStatus))
|
||||
{
|
||||
if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
|
||||
DeleteService(service);
|
||||
}
|
||||
CloseServiceHandle(service);
|
||||
}
|
||||
|
||||
CloseServiceHandle(serviceControlManager);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void WINAPI ServiceControlHandler(DWORD controlCode)
|
||||
{
|
||||
switch (controlCode)
|
||||
{
|
||||
case SERVICE_CONTROL_INTERROGATE:
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_SHUTDOWN:
|
||||
case SERVICE_CONTROL_STOP:
|
||||
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
m_ServiceStatus = 0;
|
||||
return;
|
||||
|
||||
case SERVICE_CONTROL_PAUSE:
|
||||
m_ServiceStatus = 2;
|
||||
serviceStatus.dwCurrentState = SERVICE_PAUSED;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
break;
|
||||
|
||||
case SERVICE_CONTROL_CONTINUE:
|
||||
serviceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
m_ServiceStatus = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
if ( controlCode >= 128 && controlCode <= 255 )
|
||||
// user defined control code
|
||||
break;
|
||||
else
|
||||
// unrecognized control code
|
||||
break;
|
||||
}
|
||||
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
}
|
||||
|
||||
void WINAPI ServiceMain(DWORD argc, char *argv[])
|
||||
{
|
||||
// initialise service status
|
||||
serviceStatus.dwServiceType = SERVICE_WIN32;
|
||||
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
|
||||
serviceStatus.dwWin32ExitCode = NO_ERROR;
|
||||
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
|
||||
serviceStatus.dwCheckPoint = 0;
|
||||
serviceStatus.dwWaitHint = 0;
|
||||
|
||||
serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
|
||||
|
||||
if ( serviceStatusHandle )
|
||||
{
|
||||
char path[_MAX_PATH + 1];
|
||||
unsigned int i, last_slash = 0;
|
||||
|
||||
GetModuleFileName(0, path, sizeof(path)/sizeof(path[0]));
|
||||
|
||||
for (i = 0; i < std::strlen(path); i++)
|
||||
{
|
||||
if (path[i] == '\\') last_slash = i;
|
||||
}
|
||||
|
||||
path[last_slash] = 0;
|
||||
|
||||
// service is starting
|
||||
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
// do initialisation here
|
||||
SetCurrentDirectory(path);
|
||||
|
||||
// running
|
||||
serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
||||
serviceStatus.dwCurrentState = SERVICE_RUNNING;
|
||||
SetServiceStatus( serviceStatusHandle, &serviceStatus );
|
||||
|
||||
////////////////////////
|
||||
// service main cycle //
|
||||
////////////////////////
|
||||
|
||||
m_ServiceStatus = 1;
|
||||
argc = 1;
|
||||
main(argc , argv);
|
||||
|
||||
// service was stopped
|
||||
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
|
||||
// do cleanup here
|
||||
|
||||
// service is now stopped
|
||||
serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
|
||||
serviceStatus.dwCurrentState = SERVICE_STOPPED;
|
||||
SetServiceStatus(serviceStatusHandle, &serviceStatus);
|
||||
}
|
||||
}
|
||||
|
||||
bool WinServiceRun()
|
||||
{
|
||||
SERVICE_TABLE_ENTRY serviceTable[] =
|
||||
{
|
||||
{ serviceName, ServiceMain },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
if (!StartServiceCtrlDispatcher(serviceTable))
|
||||
{
|
||||
sLog.outError("StartService Failed. Error [%u]", ::GetLastError());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
28
src/shared/ServiceWin32.h
Normal file
28
src/shared/ServiceWin32.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifdef WIN32
|
||||
#ifndef _WIN32_SERVICE_
|
||||
#define _WIN32_SERVICE_
|
||||
|
||||
bool WinServiceInstall();
|
||||
bool WinServiceUninstall();
|
||||
bool WinServiceRun();
|
||||
|
||||
#endif // _WIN32_SERVICE_
|
||||
#endif // WIN32
|
||||
70
src/shared/SystemConfig.h.in
Normal file
70
src/shared/SystemConfig.h.in
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Copyright (C) 2005,2006 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOS_SYSTEMCONFIG_H
|
||||
#define MANGOS_SYSTEMCONFIG_H
|
||||
|
||||
#ifndef _PACKAGENAME
|
||||
#define _PACKAGENAME "MaNGOS"
|
||||
#endif
|
||||
|
||||
#include "Platform/Define.h"
|
||||
#include "svn_revision.h"
|
||||
|
||||
#ifndef _VERSION
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
# define _VERSION "0.12.0-SVN" " (Revision " SVN_REVISION ")"
|
||||
#else
|
||||
# define _VERSION "@VERSION@" " (Revision " SVN_REVISION ")"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Format is YYYYMMDDRR where RR is the change in the conf file
|
||||
// for that day.
|
||||
#ifndef _MANGOSDCONFVERSION
|
||||
# define _MANGOSDCONFVERSION 2008022901
|
||||
#endif
|
||||
#ifndef _REALMDCONFVERSION
|
||||
# define _REALMDCONFVERSION 2007062001
|
||||
#endif
|
||||
|
||||
#if MANGOS_ENDIAN == MANGOS_BIGENDIAN
|
||||
# define _ENDIAN_STRING "big-endian"
|
||||
#else
|
||||
# define _ENDIAN_STRING "little-endian"
|
||||
#endif
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
# ifdef _WIN64
|
||||
# define _FULLVERSION _PACKAGENAME "/" _VERSION " (Win64," _ENDIAN_STRING ")"
|
||||
# else
|
||||
# define _FULLVERSION _PACKAGENAME "/" _VERSION " (Win32," _ENDIAN_STRING ")"
|
||||
# endif
|
||||
# define _MANGOSD_CONFIG "mangosd.conf"
|
||||
# define _REALMD_CONFIG "realmd.conf"
|
||||
#else
|
||||
# define _FULLVERSION _PACKAGENAME "/" _VERSION " (Unix," _ENDIAN_STRING ")"
|
||||
# define _MANGOSD_CONFIG "@sysconfdir@/mangosd.conf"
|
||||
# define _REALMD_CONFIG "@sysconfdir@/realmd.conf"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_PLAYER_LIMIT 100
|
||||
#define DEFAULT_WORLDSERVER_PORT 8085 //8129
|
||||
#define DEFAULT_REALMSERVER_PORT 3724
|
||||
#define DEFAULT_SOCKET_SELECT_TIME 10000
|
||||
#endif
|
||||
96
src/shared/Timer.h
Normal file
96
src/shared/Timer.h
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOS_TIMER_H
|
||||
#define MANGOS_TIMER_H
|
||||
|
||||
#include "Platform/CompilerDefs.h"
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
# include <ace/config-all.h>
|
||||
# include <mmsystem.h>
|
||||
# include <time.h>
|
||||
#else
|
||||
# if defined(__APPLE_CC__)
|
||||
# include <time.h>
|
||||
# endif
|
||||
# include <sys/time.h>
|
||||
# include <sys/timeb.h>
|
||||
#endif
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
inline uint32 getMSTime() { return GetTickCount(); }
|
||||
#else
|
||||
inline uint32 getMSTime()
|
||||
{
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
gettimeofday( &tv, &tz );
|
||||
return (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
|
||||
}
|
||||
#endif
|
||||
|
||||
inline uint32 getMSTimeDiff(uint32 oldMSTime, uint32 newMSTime)
|
||||
{
|
||||
// getMSTime() have limited data range and this is case when it overflow in this tick
|
||||
if (oldMSTime > newMSTime)
|
||||
return (0xFFFFFFFF - oldMSTime) + newMSTime;
|
||||
else
|
||||
return newMSTime - oldMSTime;
|
||||
}
|
||||
|
||||
class IntervalTimer
|
||||
{
|
||||
public:
|
||||
IntervalTimer() : _interval(0), _current(0) {}
|
||||
|
||||
void Update(time_t diff) { _current += diff; if(_current<0) _current=0;}
|
||||
bool Passed() { return _current >= _interval; }
|
||||
void Reset() { if(_current >= _interval) _current -= _interval; }
|
||||
|
||||
void SetCurrent(time_t current) { _current = current; }
|
||||
void SetInterval(time_t interval) { _interval = interval; }
|
||||
time_t GetInterval() const { return _interval; }
|
||||
time_t GetCurrent() const { return _current; }
|
||||
|
||||
private:
|
||||
time_t _interval;
|
||||
time_t _current;
|
||||
};
|
||||
|
||||
struct TimeTracker
|
||||
{
|
||||
TimeTracker(time_t expiry) : i_expiryTime(expiry) {}
|
||||
void Update(time_t diff) { i_expiryTime -= diff; }
|
||||
bool Passed(void) const { return (i_expiryTime <= 0); }
|
||||
void Reset(time_t interval) { i_expiryTime = interval; }
|
||||
time_t GetExpiry(void) const { return i_expiryTime; }
|
||||
time_t i_expiryTime;
|
||||
};
|
||||
|
||||
struct TimeTrackerSmall
|
||||
{
|
||||
TimeTrackerSmall(int32 expiry) : i_expiryTime(expiry) {}
|
||||
void Update(int32 diff) { i_expiryTime -= diff; }
|
||||
bool Passed(void) const { return (i_expiryTime <= 0); }
|
||||
void Reset(int32 interval) { i_expiryTime = interval; }
|
||||
int32 GetExpiry(void) const { return i_expiryTime; }
|
||||
int32 i_expiryTime;
|
||||
};
|
||||
|
||||
#endif
|
||||
425
src/shared/Util.cpp
Normal file
425
src/shared/Util.cpp
Normal file
|
|
@ -0,0 +1,425 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "Util.h"
|
||||
|
||||
#include "sockets/socket_include.h"
|
||||
#include "utf8cpp/utf8.h"
|
||||
#include "mersennetwister/MersenneTwister.h"
|
||||
#include "zthread/ThreadLocal.h"
|
||||
|
||||
typedef ZThread::ThreadLocal<MTRand> MTRandTSS;
|
||||
|
||||
/* NOTE: Not sure if static initialization is ok for TSS objects ,
|
||||
* as I see zthread uses custom implementation of the TSS
|
||||
* ,and in the consturctor there is no code ,so I suppose its ok
|
||||
* If its not ok ,change it to use singleton.
|
||||
*/
|
||||
static MTRandTSS mtRand;
|
||||
|
||||
int32 irand (int32 min, int32 max)
|
||||
{
|
||||
return int32 (mtRand.get ().randInt (max - min)) + min;
|
||||
}
|
||||
|
||||
uint32 urand (uint32 min, uint32 max)
|
||||
{
|
||||
return mtRand.get ().randInt (max - min) + min;
|
||||
}
|
||||
|
||||
int32 rand32 ()
|
||||
{
|
||||
return mtRand.get ().randInt ();
|
||||
}
|
||||
|
||||
double rand_norm(void)
|
||||
{
|
||||
return mtRand.get ().randExc ();
|
||||
}
|
||||
|
||||
double rand_chance (void)
|
||||
{
|
||||
return mtRand.get ().randExc (100.0);
|
||||
}
|
||||
|
||||
Tokens StrSplit(const std::string &src, const std::string &sep)
|
||||
{
|
||||
Tokens r;
|
||||
std::string s;
|
||||
for (std::string::const_iterator i = src.begin(); i != src.end(); i++)
|
||||
{
|
||||
if (sep.find(*i) != std::string::npos)
|
||||
{
|
||||
if (s.length()) r.push_back(s);
|
||||
s = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
s += *i;
|
||||
}
|
||||
}
|
||||
if (s.length()) r.push_back(s);
|
||||
return r;
|
||||
}
|
||||
|
||||
void stripLineInvisibleChars(std::string &str)
|
||||
{
|
||||
static std::string invChars = " \t\7";
|
||||
|
||||
size_t wpos = 0;
|
||||
|
||||
bool space = false;
|
||||
for(size_t pos = 0; pos < str.size(); ++pos)
|
||||
{
|
||||
if(invChars.find(str[pos])!=std::string::npos)
|
||||
{
|
||||
if(!space)
|
||||
{
|
||||
str[wpos++] = ' ';
|
||||
space = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(wpos!=pos)
|
||||
str[wpos++] = str[pos];
|
||||
else
|
||||
++wpos;
|
||||
space = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(wpos < str.size())
|
||||
str.erase(wpos,str.size());
|
||||
}
|
||||
|
||||
std::string secsToTimeString(uint32 timeInSecs, bool shortText, bool hoursOnly)
|
||||
{
|
||||
uint32 secs = timeInSecs % MINUTE;
|
||||
uint32 minutes = timeInSecs % HOUR / MINUTE;
|
||||
uint32 hours = timeInSecs % DAY / HOUR;
|
||||
uint32 days = timeInSecs / DAY;
|
||||
|
||||
std::ostringstream ss;
|
||||
if(days)
|
||||
ss << days << (shortText ? "d" : " Day(s) ");
|
||||
if(hours || hoursOnly)
|
||||
ss << hours << (shortText ? "h" : " Hour(s) ");
|
||||
if(!hoursOnly)
|
||||
{
|
||||
if(minutes)
|
||||
ss << minutes << (shortText ? "m" : " Minute(s) ");
|
||||
if(secs || (!days && !hours && !minutes) )
|
||||
ss << secs << (shortText ? "s" : " Second(s).");
|
||||
}
|
||||
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
uint32 TimeStringToSecs(std::string timestring)
|
||||
{
|
||||
uint32 secs = 0;
|
||||
uint32 buffer = 0;
|
||||
uint32 multiplier = 0;
|
||||
|
||||
for(std::string::iterator itr = timestring.begin(); itr != timestring.end(); itr++ )
|
||||
{
|
||||
if(isdigit(*itr))
|
||||
{
|
||||
std::string str; //very complicated typecast char->const char*; is there no better way?
|
||||
str += *itr;
|
||||
const char* tmp = str.c_str();
|
||||
|
||||
buffer*=10;
|
||||
buffer+=atoi(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(*itr)
|
||||
{
|
||||
case 'd': multiplier = DAY; break;
|
||||
case 'h': multiplier = HOUR; break;
|
||||
case 'm': multiplier = MINUTE; break;
|
||||
case 's': multiplier = 1; break;
|
||||
default : return 0; //bad format
|
||||
}
|
||||
buffer*=multiplier;
|
||||
secs+=buffer;
|
||||
buffer=0;
|
||||
}
|
||||
}
|
||||
|
||||
return secs;
|
||||
}
|
||||
|
||||
std::string TimeToTimestampStr(time_t t)
|
||||
{
|
||||
tm* aTm = localtime(&t);
|
||||
// YYYY year
|
||||
// MM month (2 digits 01-12)
|
||||
// DD day (2 digits 01-31)
|
||||
// HH hour (2 digits 00-23)
|
||||
// MM minutes (2 digits 00-59)
|
||||
// SS seconds (2 digits 00-59)
|
||||
char buf[20];
|
||||
snprintf(buf,20,"%04d-%02d-%02d_%02d-%02d-%02d",aTm->tm_year+1900,aTm->tm_mon+1,aTm->tm_mday,aTm->tm_hour,aTm->tm_min,aTm->tm_sec);
|
||||
return std::string(buf);
|
||||
}
|
||||
|
||||
/// Check if the string is a valid ip address representation
|
||||
bool IsIPAddress(char const* ipaddress)
|
||||
{
|
||||
if(!ipaddress)
|
||||
return false;
|
||||
|
||||
// Let the big boys do it.
|
||||
// Drawback: all valid ip address formats are recognized e.g.: 12.23,121234,0xABCD)
|
||||
return inet_addr(ipaddress) != INADDR_NONE;
|
||||
}
|
||||
|
||||
/// create PID file
|
||||
uint32 CreatePIDFile(std::string filename)
|
||||
{
|
||||
FILE * pid_file = fopen (filename.c_str(), "w" );
|
||||
if (pid_file == NULL)
|
||||
return 0;
|
||||
|
||||
#ifdef WIN32
|
||||
DWORD pid = GetCurrentProcessId();
|
||||
#else
|
||||
pid_t pid = getpid();
|
||||
#endif
|
||||
|
||||
fprintf(pid_file, "%d", pid );
|
||||
fclose(pid_file);
|
||||
|
||||
return (uint32)pid;
|
||||
}
|
||||
|
||||
size_t utf8length(std::string& utf8str)
|
||||
{
|
||||
try
|
||||
{
|
||||
return utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
|
||||
}
|
||||
catch(std::exception)
|
||||
{
|
||||
utf8str = "";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void utf8truncate(std::string& utf8str,size_t len)
|
||||
{
|
||||
try
|
||||
{
|
||||
size_t wlen = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
|
||||
if(wlen <= len)
|
||||
return;
|
||||
|
||||
std::wstring wstr;
|
||||
wstr.resize(wlen);
|
||||
utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
|
||||
wstr.resize(len);
|
||||
char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str[0]);
|
||||
utf8str.resize(oend-(&utf8str[0])); // remove unused tail
|
||||
}
|
||||
catch(std::exception)
|
||||
{
|
||||
utf8str = "";
|
||||
}
|
||||
}
|
||||
|
||||
bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize)
|
||||
{
|
||||
try
|
||||
{
|
||||
size_t len = utf8::distance(utf8str,utf8str+csize);
|
||||
if(len > wsize)
|
||||
{
|
||||
wsize = 0;
|
||||
wstr = L"";
|
||||
return false;
|
||||
}
|
||||
|
||||
wsize = len;
|
||||
utf8::utf8to16(utf8str,utf8str+csize,wstr);
|
||||
wstr[len] = L'\0';
|
||||
}
|
||||
catch(std::exception)
|
||||
{
|
||||
wsize = 0;
|
||||
wstr = L"";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Utf8toWStr(std::string utf8str, std::wstring& wstr)
|
||||
{
|
||||
try
|
||||
{
|
||||
size_t len = utf8::distance(utf8str.c_str(),utf8str.c_str()+utf8str.size());
|
||||
wstr.resize(len);
|
||||
|
||||
utf8::utf8to16(utf8str.c_str(),utf8str.c_str()+utf8str.size(),&wstr[0]);
|
||||
}
|
||||
catch(std::exception)
|
||||
{
|
||||
wstr = L"";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string utf8str2;
|
||||
utf8str2.resize(size*4); // allocate for most long case
|
||||
|
||||
char* oend = utf8::utf16to8(wstr,wstr+size,&utf8str2[0]);
|
||||
utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
|
||||
utf8str = utf8str2;
|
||||
}
|
||||
catch(std::exception)
|
||||
{
|
||||
utf8str = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WStrToUtf8(std::wstring wstr, std::string& utf8str)
|
||||
{
|
||||
try
|
||||
{
|
||||
std::string utf8str2;
|
||||
utf8str2.resize(wstr.size()*4); // allocate for most long case
|
||||
|
||||
char* oend = utf8::utf16to8(wstr.c_str(),wstr.c_str()+wstr.size(),&utf8str2[0]);
|
||||
utf8str2.resize(oend-(&utf8str2[0])); // remove unused tail
|
||||
utf8str = utf8str2;
|
||||
}
|
||||
catch(std::exception)
|
||||
{
|
||||
utf8str = "";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef wchar_t const* const* wstrlist;
|
||||
|
||||
std::wstring GetMainPartOfName(std::wstring wname, uint32 declension)
|
||||
{
|
||||
// supported only Cyrillic cases
|
||||
if(wname.size() < 1 || !isCyrillicCharacter(wname[0]) || declension > 5)
|
||||
return wname;
|
||||
|
||||
// Important: end length must be <= MAX_INTERNAL_PLAYER_NAME-MAX_PLAYER_NAME (3 currently)
|
||||
|
||||
static wchar_t const a_End[] = { wchar_t(1), wchar_t(0x0430),wchar_t(0x0000)};
|
||||
static wchar_t const o_End[] = { wchar_t(1), wchar_t(0x043E),wchar_t(0x0000)};
|
||||
static wchar_t const ya_End[] = { wchar_t(1), wchar_t(0x044F),wchar_t(0x0000)};
|
||||
static wchar_t const ie_End[] = { wchar_t(1), wchar_t(0x0435),wchar_t(0x0000)};
|
||||
static wchar_t const i_End[] = { wchar_t(1), wchar_t(0x0438),wchar_t(0x0000)};
|
||||
static wchar_t const yeru_End[] = { wchar_t(1), wchar_t(0x044B),wchar_t(0x0000)};
|
||||
static wchar_t const u_End[] = { wchar_t(1), wchar_t(0x0443),wchar_t(0x0000)};
|
||||
static wchar_t const yu_End[] = { wchar_t(1), wchar_t(0x044E),wchar_t(0x0000)};
|
||||
static wchar_t const oj_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x0439),wchar_t(0x0000)};
|
||||
static wchar_t const ie_j_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x0439),wchar_t(0x0000)};
|
||||
static wchar_t const io_j_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x0439),wchar_t(0x0000)};
|
||||
static wchar_t const o_m_End[] = { wchar_t(2), wchar_t(0x043E),wchar_t(0x043C),wchar_t(0x0000)};
|
||||
static wchar_t const io_m_End[] = { wchar_t(2), wchar_t(0x0451),wchar_t(0x043C),wchar_t(0x0000)};
|
||||
static wchar_t const ie_m_End[] = { wchar_t(2), wchar_t(0x0435),wchar_t(0x043C),wchar_t(0x0000)};
|
||||
static wchar_t const soft_End[] = { wchar_t(1), wchar_t(0x044C),wchar_t(0x0000)};
|
||||
static wchar_t const j_End[] = { wchar_t(1), wchar_t(0x0439),wchar_t(0x0000)};
|
||||
|
||||
static wchar_t const* const dropEnds[6][8] = {
|
||||
{ &a_End[1], &o_End[1], &ya_End[1], &ie_End[1], &soft_End[1], &j_End[1], NULL, NULL },
|
||||
{ &a_End[1], &ya_End[1], &yeru_End[1], &i_End[1], NULL, NULL, NULL, NULL },
|
||||
{ &ie_End[1], &u_End[1], &yu_End[1], &i_End[1], NULL, NULL, NULL, NULL },
|
||||
{ &u_End[1], &yu_End[1], &o_End[1], &ie_End[1], &soft_End[1], &ya_End[1], &a_End[1], NULL },
|
||||
{ &oj_End[1], &io_j_End[1], &ie_j_End[1], &o_m_End[1], &io_m_End[1], &ie_m_End[1], &yu_End[1], NULL },
|
||||
{ &ie_End[1], &i_End[1], NULL, NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
for(wchar_t const * const* itr = &dropEnds[declension][0]; *itr; ++itr)
|
||||
{
|
||||
size_t len = size_t((*itr)[-1]); // get length from string size field
|
||||
|
||||
if(wname.substr(wname.size()-len,len)==*itr)
|
||||
return wname.substr(0,wname.size()-len);
|
||||
}
|
||||
|
||||
return wname;
|
||||
}
|
||||
|
||||
bool utf8ToConsole(std::string utf8str, std::string& conStr)
|
||||
{
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
std::wstring wstr;
|
||||
if(!Utf8toWStr(utf8str,wstr))
|
||||
return false;
|
||||
|
||||
conStr.resize(wstr.size());
|
||||
CharToOemBuffW(&wstr[0],&conStr[0],wstr.size());
|
||||
#else
|
||||
// not implemented yet
|
||||
conStr = utf8str;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool consoleToUtf8(std::string conStr,std::string& utf8str)
|
||||
{
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
std::wstring wstr;
|
||||
wstr.resize(conStr.size());
|
||||
OemToCharBuffW(&conStr[0],&wstr[0],conStr.size());
|
||||
|
||||
return WStrToUtf8(wstr,utf8str);
|
||||
#else
|
||||
// not implemented yet
|
||||
utf8str = conStr;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool Utf8FitTo(std::string str, std::wstring search)
|
||||
{
|
||||
std::wstring temp;
|
||||
|
||||
if(!Utf8toWStr(str,temp))
|
||||
return false;
|
||||
|
||||
// converting to lower case
|
||||
wstrToLower( temp );
|
||||
|
||||
if(temp.find(search) == std::wstring::npos)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
306
src/shared/Util.h
Normal file
306
src/shared/Util.h
Normal file
|
|
@ -0,0 +1,306 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_H
|
||||
#define _UTIL_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<std::string> Tokens;
|
||||
|
||||
Tokens StrSplit(const std::string &src, const std::string &sep);
|
||||
|
||||
void stripLineInvisibleChars(std::string &src);
|
||||
|
||||
std::string secsToTimeString(uint32 timeInSecs, bool shortText = false, bool hoursOnly = false);
|
||||
uint32 TimeStringToSecs(std::string timestring);
|
||||
std::string TimeToTimestampStr(time_t t);
|
||||
|
||||
inline uint32 secsToTimeBitFields(time_t secs)
|
||||
{
|
||||
tm* lt = localtime(&secs);
|
||||
return (lt->tm_year - 100) << 24 | lt->tm_mon << 20 | (lt->tm_mday - 1) << 14 | lt->tm_wday << 11 | lt->tm_hour << 6 | lt->tm_min;
|
||||
}
|
||||
|
||||
/* Return a random number in the range min..max; (max-min) must be smaller than 32768. */
|
||||
MANGOS_DLL_SPEC int32 irand(int32 min, int32 max);
|
||||
|
||||
/* Return a random number in the range min..max (inclusive). For reliable results, the difference
|
||||
* between max and min should be less than RAND32_MAX. */
|
||||
MANGOS_DLL_SPEC uint32 urand(uint32 min, uint32 max);
|
||||
|
||||
/* Return a random number in the range 0 .. RAND32_MAX. */
|
||||
MANGOS_DLL_SPEC int32 rand32();
|
||||
|
||||
/* Return a random double from 0.0 to 1.0 (exclusive). Floats support only 7 valid decimal digits.
|
||||
* A double supports up to 15 valid decimal digits and is used internally (RAND32_MAX has 10 digits).
|
||||
* With an FPU, there is usually no difference in performance between float and double. */
|
||||
MANGOS_DLL_SPEC double rand_norm(void);
|
||||
|
||||
/* Return a random double from 0.0 to 99.9999999999999. Floats support only 7 valid decimal digits.
|
||||
* A double supports up to 15 valid decimal digits and is used internaly (RAND32_MAX has 10 digits).
|
||||
* With an FPU, there is usually no difference in performance between float and double. */
|
||||
MANGOS_DLL_SPEC double rand_chance(void);
|
||||
|
||||
/* Return true if a random roll fits in the specified chance (range 0-100). */
|
||||
inline bool roll_chance_f(float chance)
|
||||
{
|
||||
return chance > rand_chance();
|
||||
}
|
||||
|
||||
/* Return true if a random roll fits in the specified chance (range 0-100). */
|
||||
inline bool roll_chance_i(int chance)
|
||||
{
|
||||
return chance > irand(0, 99);
|
||||
}
|
||||
|
||||
inline void ApplyModUInt32Var(uint32& var, int32 val, bool apply)
|
||||
{
|
||||
int32 cur = var;
|
||||
cur += (apply ? val : -val);
|
||||
if(cur < 0)
|
||||
cur = 0;
|
||||
var = cur;
|
||||
}
|
||||
|
||||
inline void ApplyModFloatVar(float& var, float val, bool apply)
|
||||
{
|
||||
var += (apply ? val : -val);
|
||||
if(var < 0)
|
||||
var = 0;
|
||||
}
|
||||
|
||||
inline void ApplyPercentModFloatVar(float& var, float val, bool apply)
|
||||
{
|
||||
if (!apply && val == -100.0f)
|
||||
val = -99.99f;
|
||||
var *= (apply?(100.0f+val)/100.0f : 100.0f / (100.0f+val));
|
||||
}
|
||||
|
||||
bool Utf8toWStr(std::string utf8str, std::wstring& wstr);
|
||||
// in wsize==max size of buffer, out wsize==real string size
|
||||
bool Utf8toWStr(char const* utf8str, size_t csize, wchar_t* wstr, size_t& wsize);
|
||||
inline bool Utf8toWStr(std::string utf8str, wchar_t* wstr, size_t& wsize)
|
||||
{
|
||||
return Utf8toWStr(utf8str.c_str(), utf8str.size(), wstr, wsize);
|
||||
}
|
||||
|
||||
bool WStrToUtf8(std::wstring wstr, std::string& utf8str);
|
||||
// size==real string size
|
||||
bool WStrToUtf8(wchar_t* wstr, size_t size, std::string& utf8str);
|
||||
|
||||
size_t utf8length(std::string& utf8str); // set string to "" if invalid utf8 sequence
|
||||
void utf8truncate(std::string& utf8str,size_t len);
|
||||
|
||||
inline bool isBasicLatinCharacter(wchar_t wchar)
|
||||
{
|
||||
if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z
|
||||
return true;
|
||||
if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isExtendedLatinCharacter(wchar_t wchar)
|
||||
{
|
||||
if(isBasicLatinCharacter(wchar))
|
||||
return true;
|
||||
if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||
return true;
|
||||
if(wchar >= 0x00D8 && wchar <= 0x00DF) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN
|
||||
return true;
|
||||
if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
|
||||
return true;
|
||||
if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS
|
||||
return true;
|
||||
if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN
|
||||
return true;
|
||||
if(wchar >= 0x0100 && wchar <= 0x012F) // LATIN CAPITAL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK
|
||||
return true;
|
||||
if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isCyrillicCharacter(wchar_t wchar)
|
||||
{
|
||||
if(wchar >= 0x0410 && wchar <= 0x044F) // CYRILLIC CAPITAL LETTER A - CYRILLIC SMALL LETTER YA
|
||||
return true;
|
||||
if(wchar == 0x0401 || wchar == 0x0451) // CYRILLIC CAPITAL LETTER IO, CYRILLIC SMALL LETTER IO
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isEastAsianCharacter(wchar_t wchar)
|
||||
{
|
||||
if(wchar >= 0x1100 && wchar <= 0x11F9) // Hangul Jamo
|
||||
return true;
|
||||
if(wchar >= 0x3041 && wchar <= 0x30FF) // Hiragana + Katakana
|
||||
return true;
|
||||
if(wchar >= 0x3131 && wchar <= 0x318E) // Hangul Compatibility Jamo
|
||||
return true;
|
||||
if(wchar >= 0x31F0 && wchar <= 0x31FF) // Katakana Phonetic Ext.
|
||||
return true;
|
||||
if(wchar >= 0x3400 && wchar <= 0x4DB5) // CJK Ideographs Ext. A
|
||||
return true;
|
||||
if(wchar >= 0x4E00 && wchar <= 0x9FC3) // Unified CJK Ideographs
|
||||
return true;
|
||||
if(wchar >= 0xAC00 && wchar <= 0xD7A3) // Hangul Syllables
|
||||
return true;
|
||||
if(wchar >= 0xFF01 && wchar <= 0xFFEE) // Halfwidth forms
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool isNumericOrSpace(wchar_t wchar)
|
||||
{
|
||||
return (wchar >= L'0' && wchar <=L'9') || wchar == L' ';
|
||||
}
|
||||
|
||||
inline bool isBasicLatinString(std::wstring wstr, bool numericOrSpace)
|
||||
{
|
||||
for(size_t i = 0; i < wstr.size(); ++i)
|
||||
if(!isBasicLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isExtendedLatinString(std::wstring wstr, bool numericOrSpace)
|
||||
{
|
||||
for(size_t i = 0; i < wstr.size(); ++i)
|
||||
if(!isExtendedLatinCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isCyrillicString(std::wstring wstr, bool numericOrSpace)
|
||||
{
|
||||
for(size_t i = 0; i < wstr.size(); ++i)
|
||||
if(!isCyrillicCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool isEastAsianString(std::wstring wstr, bool numericOrSpace)
|
||||
{
|
||||
for(size_t i = 0; i < wstr.size(); ++i)
|
||||
if(!isEastAsianCharacter(wstr[i]) && (!numericOrSpace || !isNumericOrSpace(wstr[i])))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
inline wchar_t wcharToUpper(wchar_t wchar)
|
||||
{
|
||||
if(wchar >= L'a' && wchar <= L'z') // LATIN SMALL LETTER A - LATIN SMALL LETTER Z
|
||||
return wchar_t(uint16(wchar)-0x0020);
|
||||
if(wchar == 0x00DF) // LATIN SMALL LETTER SHARP S
|
||||
return wchar_t(0x1E9E);
|
||||
if(wchar >= 0x00E0 && wchar <= 0x00F6) // LATIN SMALL LETTER A WITH GRAVE - LATIN SMALL LETTER O WITH DIAERESIS
|
||||
return wchar_t(uint16(wchar)-0x0020);
|
||||
if(wchar >= 0x00F8 && wchar <= 0x00FE) // LATIN SMALL LETTER O WITH STROKE - LATIN SMALL LETTER THORN
|
||||
return wchar_t(uint16(wchar)-0x0020);
|
||||
if(wchar >= 0x0101 && wchar <= 0x012F) // LATIN SMALL LETTER A WITH MACRON - LATIN SMALL LETTER I WITH OGONEK (only %2=1)
|
||||
{
|
||||
if(wchar % 2 == 1)
|
||||
return wchar_t(uint16(wchar)-0x0001);
|
||||
}
|
||||
if(wchar >= 0x0430 && wchar <= 0x044F) // CYRILLIC SMALL LETTER A - CYRILLIC SMALL LETTER YA
|
||||
return wchar_t(uint16(wchar)-0x0020);
|
||||
if(wchar == 0x0451) // CYRILLIC SMALL LETTER IO
|
||||
return wchar_t(0x0401);
|
||||
|
||||
return wchar;
|
||||
}
|
||||
|
||||
inline wchar_t wcharToUpperOnlyLatin(wchar_t wchar)
|
||||
{
|
||||
return isBasicLatinCharacter(wchar) ? wcharToUpper(wchar) : wchar;
|
||||
}
|
||||
|
||||
inline wchar_t wcharToLower(wchar_t wchar)
|
||||
{
|
||||
if(wchar >= L'A' && wchar <= L'Z') // LATIN CAPITAL LETTER A - LATIN CAPITAL LETTER Z
|
||||
return wchar_t(uint16(wchar)+0x0020);
|
||||
if(wchar >= 0x00C0 && wchar <= 0x00D6) // LATIN CAPITAL LETTER A WITH GRAVE - LATIN CAPITAL LETTER O WITH DIAERESIS
|
||||
return wchar_t(uint16(wchar)+0x0020);
|
||||
if(wchar >= 0x00D8 && wchar <= 0x00DE) // LATIN CAPITAL LETTER O WITH STROKE - LATIN CAPITAL LETTER THORN
|
||||
return wchar_t(uint16(wchar)+0x0020);
|
||||
if(wchar >= 0x0100 && wchar <= 0x012E) // LATIN CAPITAL LETTER A WITH MACRON - LATIN CAPITAL LETTER I WITH OGONEK (only %2=0)
|
||||
{
|
||||
if(wchar % 2 == 0)
|
||||
return wchar_t(uint16(wchar)+0x0001);
|
||||
}
|
||||
if(wchar == 0x1E9E) // LATIN CAPITAL LETTER SHARP S
|
||||
return wchar_t(0x00DF);
|
||||
if(wchar == 0x0401) // CYRILLIC CAPITAL LETTER IO
|
||||
return wchar_t(0x0451);
|
||||
if(wchar >= 0x0410 && wchar <= 0x042F) // CYRILLIC CAPITAL LETTER A - CYRILLIC CAPITAL LETTER YA
|
||||
return wchar_t(uint16(wchar)+0x0020);
|
||||
|
||||
return wchar;
|
||||
}
|
||||
|
||||
inline void wstrToUpper(std::wstring& str)
|
||||
{
|
||||
std::transform( str.begin(), str.end(), str.begin(), wcharToUpper );
|
||||
}
|
||||
|
||||
inline void wstrToLower(std::wstring& str)
|
||||
{
|
||||
std::transform( str.begin(), str.end(), str.begin(), wcharToLower );
|
||||
}
|
||||
|
||||
std::wstring GetMainPartOfName(std::wstring wname, uint32 declension);
|
||||
|
||||
bool utf8ToConsole(std::string utf8str, std::string& conStr);
|
||||
bool consoleToUtf8(std::string conStr,std::string& utf8str);
|
||||
bool Utf8FitTo(std::string str, std::wstring search);
|
||||
|
||||
#if PLATFORM == PLATFORM_WINDOWS
|
||||
#define UTF8PRINTF(OUT,FRM,RESERR) \
|
||||
{ \
|
||||
char temp_buf[6000]; \
|
||||
va_list ap; \
|
||||
va_start(ap, FRM); \
|
||||
size_t temp_len = vsnprintf(temp_buf,6000,FRM,ap); \
|
||||
va_end(ap); \
|
||||
\
|
||||
wchar_t wtemp_buf[6000]; \
|
||||
size_t wtemp_len = 6000-1; \
|
||||
if(!Utf8toWStr(temp_buf,temp_len,wtemp_buf,wtemp_len)) \
|
||||
return RESERR; \
|
||||
CharToOemBuffW(&wtemp_buf[0],&temp_buf[0],wtemp_len+1);\
|
||||
fprintf(OUT,temp_buf); \
|
||||
}
|
||||
#else
|
||||
#define UTF8PRINTF(OUT,FRM,RESERR) \
|
||||
{ \
|
||||
va_list ap; \
|
||||
va_start(ap, FRM); \
|
||||
vfprintf(OUT, FRM, ap ); \
|
||||
va_end(ap); \
|
||||
}
|
||||
#endif
|
||||
|
||||
bool IsIPAddress(char const* ipaddress);
|
||||
uint32 CreatePIDFile(std::string filename);
|
||||
|
||||
#endif
|
||||
1013
src/shared/WheatyExceptionReport.cpp
Normal file
1013
src/shared/WheatyExceptionReport.cpp
Normal file
File diff suppressed because it is too large
Load diff
117
src/shared/WheatyExceptionReport.h
Normal file
117
src/shared/WheatyExceptionReport.h
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
#ifndef _WHEATYEXCEPTIONREPORT_
|
||||
#define _WHEATYEXCEPTIONREPORT_
|
||||
|
||||
#include <dbghelp.h>
|
||||
|
||||
#if _MSC_VER < 1400
|
||||
# define countof(array) (sizeof(array) / sizeof(array[0]))
|
||||
#else
|
||||
# include <stdlib.h>
|
||||
# define countof _countof
|
||||
#endif // _MSC_VER < 1400
|
||||
|
||||
enum BasicType // Stolen from CVCONST.H in the DIA 2.0 SDK
|
||||
{
|
||||
btNoType = 0,
|
||||
btVoid = 1,
|
||||
btChar = 2,
|
||||
btWChar = 3,
|
||||
btInt = 6,
|
||||
btUInt = 7,
|
||||
btFloat = 8,
|
||||
btBCD = 9,
|
||||
btBool = 10,
|
||||
btLong = 13,
|
||||
btULong = 14,
|
||||
btCurrency = 25,
|
||||
btDate = 26,
|
||||
btVariant = 27,
|
||||
btComplex = 28,
|
||||
btBit = 29,
|
||||
btBSTR = 30,
|
||||
btHresult = 31
|
||||
};
|
||||
|
||||
const char* const rgBaseType[] =
|
||||
{
|
||||
" <user defined> ", // btNoType = 0,
|
||||
" void ", // btVoid = 1,
|
||||
" char* ", // btChar = 2,
|
||||
" wchar_t* ", // btWChar = 3,
|
||||
" signed char ",
|
||||
" unsigned char ",
|
||||
" int ", // btInt = 6,
|
||||
" unsigned int ", // btUInt = 7,
|
||||
" float ", // btFloat = 8,
|
||||
" <BCD> ", // btBCD = 9,
|
||||
" bool ", // btBool = 10,
|
||||
" short ",
|
||||
" unsigned short ",
|
||||
" long ", // btLong = 13,
|
||||
" unsigned long ", // btULong = 14,
|
||||
" __int8 ",
|
||||
" __int16 ",
|
||||
" __int32 ",
|
||||
" __int64 ",
|
||||
" __int128 ",
|
||||
" unsigned __int8 ",
|
||||
" unsigned __int16 ",
|
||||
" unsigned __int32 ",
|
||||
" unsigned __int64 ",
|
||||
" unsigned __int128 ",
|
||||
" <currency> ", // btCurrency = 25,
|
||||
" <date> ", // btDate = 26,
|
||||
" VARIANT ", // btVariant = 27,
|
||||
" <complex> ", // btComplex = 28,
|
||||
" <bit> ", // btBit = 29,
|
||||
" BSTR ", // btBSTR = 30,
|
||||
" HRESULT " // btHresult = 31
|
||||
};
|
||||
|
||||
class WheatyExceptionReport
|
||||
{
|
||||
public:
|
||||
|
||||
WheatyExceptionReport( );
|
||||
~WheatyExceptionReport( );
|
||||
|
||||
// entry point where control comes on an unhandled exception
|
||||
static LONG WINAPI WheatyUnhandledExceptionFilter(
|
||||
PEXCEPTION_POINTERS pExceptionInfo );
|
||||
|
||||
static void printTracesForAllThreads();
|
||||
private:
|
||||
// where report info is extracted and generated
|
||||
static void GenerateExceptionReport( PEXCEPTION_POINTERS pExceptionInfo );
|
||||
static void PrintSystemInfo();
|
||||
static BOOL _GetWindowsVersion(TCHAR* szVersion, DWORD cntMax);
|
||||
static BOOL _GetProcessorName(TCHAR* sProcessorName, DWORD maxcount);
|
||||
|
||||
// Helper functions
|
||||
static LPTSTR GetExceptionString( DWORD dwCode );
|
||||
static BOOL GetLogicalAddress( PVOID addr, PTSTR szModule, DWORD len,
|
||||
DWORD& section, DWORD_PTR& offset );
|
||||
|
||||
static void WriteStackDetails( PCONTEXT pContext, bool bWriteVariables, HANDLE pThreadHandle);
|
||||
|
||||
static BOOL CALLBACK EnumerateSymbolsCallback(PSYMBOL_INFO,ULONG, PVOID);
|
||||
|
||||
static bool FormatSymbolValue( PSYMBOL_INFO, STACKFRAME *, char * pszBuffer, unsigned cbBuffer );
|
||||
|
||||
static char * DumpTypeIndex( char *, DWORD64, DWORD, unsigned, DWORD_PTR, bool & , char*);
|
||||
|
||||
static char * FormatOutputValue( char * pszCurrBuffer, BasicType basicType, DWORD64 length, PVOID pAddress );
|
||||
|
||||
static BasicType GetBasicType( DWORD typeIndex, DWORD64 modBase );
|
||||
|
||||
static int __cdecl _tprintf(const TCHAR * format, ...);
|
||||
|
||||
// Variables used by the class
|
||||
static TCHAR m_szLogFileName[MAX_PATH];
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER m_previousFilter;
|
||||
static HANDLE m_hReportFile;
|
||||
static HANDLE m_hProcess;
|
||||
};
|
||||
|
||||
extern WheatyExceptionReport g_WheatyExceptionReport; // global instance of class
|
||||
#endif //WheatyExceptionReport
|
||||
51
src/shared/WorldPacket.h
Normal file
51
src/shared/WorldPacket.h
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef MANGOSSERVER_WORLDPACKET_H
|
||||
#define MANGOSSERVER_WORLDPACKET_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "ByteBuffer.h"
|
||||
|
||||
class WorldPacket : public ByteBuffer
|
||||
{
|
||||
public:
|
||||
// just container for later use
|
||||
WorldPacket() : ByteBuffer(0), m_opcode(0)
|
||||
{
|
||||
}
|
||||
explicit WorldPacket(uint16 opcode, size_t res=200) : ByteBuffer(res), m_opcode(opcode) { }
|
||||
// copy constructor
|
||||
WorldPacket(const WorldPacket &packet) : ByteBuffer(packet), m_opcode(packet.m_opcode)
|
||||
{
|
||||
}
|
||||
|
||||
void Initialize(uint16 opcode, size_t newres=200)
|
||||
{
|
||||
clear();
|
||||
_storage.reserve(newres);
|
||||
m_opcode = opcode;
|
||||
}
|
||||
|
||||
uint16 GetOpcode() const { return m_opcode; }
|
||||
void SetOpcode(uint16 opcode) { m_opcode = opcode; }
|
||||
|
||||
protected:
|
||||
uint16 m_opcode;
|
||||
};
|
||||
#endif
|
||||
1620
src/shared/vmap/AABSPTree.h
Normal file
1620
src/shared/vmap/AABSPTree.h
Normal file
File diff suppressed because it is too large
Load diff
95
src/shared/vmap/BaseModel.cpp
Normal file
95
src/shared/vmap/BaseModel.cpp
Normal file
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "BaseModel.h"
|
||||
#include "VMapTools.h"
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
//==========================================================
|
||||
|
||||
void BaseModel::getMember(Array<TriangleBox>& pMembers)
|
||||
{
|
||||
for(unsigned int i=0; i<iNTriangles; i++)
|
||||
{
|
||||
pMembers.append(iTriangles[i]);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
BaseModel::BaseModel(unsigned int pNNodes, unsigned int pNTriangles)
|
||||
{
|
||||
init(pNNodes, pNTriangles);
|
||||
};
|
||||
|
||||
//==========================================================
|
||||
|
||||
void BaseModel::init(unsigned int pNNodes, unsigned int pNTriangles)
|
||||
{
|
||||
iNNodes = pNNodes;
|
||||
iNTriangles = pNTriangles;
|
||||
iTriangles = 0;
|
||||
iTreeNodes = 0;
|
||||
if(iNNodes >0) iTreeNodes = new TreeNode[iNNodes];
|
||||
if(iNTriangles >0) iTriangles = new TriangleBox[iNTriangles];
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
void BaseModel::free()
|
||||
{
|
||||
if(getTriangles() != 0) delete [] getTriangles(); setNTriangles(0);
|
||||
if(getTreeNodes() != 0) delete [] getTreeNodes(); setNNodes(0);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
void BaseModel::intersect(const G3D::AABox& pBox, const G3D::Ray& pRay, float& pMaxDist, G3D::Vector3& pOutLocation, G3D::Vector3& /*pOutNormal*/) const
|
||||
{
|
||||
bool isInside = false;
|
||||
|
||||
float d = MyCollisionDetection::collisionLocationForMovingPointFixedAABox(
|
||||
pRay.origin, pRay.direction,
|
||||
pBox,
|
||||
pOutLocation, isInside);
|
||||
if (!isInside && ((d > 0) && (d < pMaxDist)))
|
||||
{
|
||||
pMaxDist = d;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
bool BaseModel::intersect(const G3D::AABox& pBox, const G3D::Ray& pRay, float& pMaxDist) const
|
||||
{
|
||||
// See if the ray will ever hit this node or its children
|
||||
Vector3 location;
|
||||
bool alreadyInsideBounds = false;
|
||||
bool rayWillHitBounds =
|
||||
MyCollisionDetection::collisionLocationForMovingPointFixedAABox(
|
||||
pRay.origin, pRay.direction, pBox, location, alreadyInsideBounds);
|
||||
|
||||
bool canHitThisNode = (alreadyInsideBounds ||
|
||||
(rayWillHitBounds && ((location - pRay.origin).squaredLength() < (pMaxDist * pMaxDist))));
|
||||
|
||||
return canHitThisNode;
|
||||
}
|
||||
|
||||
} // VMAP
|
||||
99
src/shared/vmap/BaseModel.h
Normal file
99
src/shared/vmap/BaseModel.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _BASEMODEL_H_
|
||||
#define _BASEMODEL_H_
|
||||
|
||||
#include <G3D/AABox.h>
|
||||
#include <G3D/Vector3.h>
|
||||
|
||||
#include "ShortVector.h"
|
||||
#include "ShortBox.h"
|
||||
#include "TreeNode.h"
|
||||
|
||||
/**
|
||||
A model is based on triangles. To be able to check intersection we need a BSP-Tree.
|
||||
This Class holds the array of triangles as well as the management information for the BSP-Tree.
|
||||
Both are stored in static array and index information is used instead of pointers.
|
||||
Therefore we can load the whole object as a binary block.
|
||||
|
||||
The vectors are relative to a base position.
|
||||
*/
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
class BaseModel
|
||||
{
|
||||
protected:
|
||||
TriangleBox *iTriangles;
|
||||
TreeNode *iTreeNodes;
|
||||
unsigned int iNTriangles;
|
||||
unsigned int iNNodes;
|
||||
G3D::Vector3 iBasePosition;
|
||||
public:
|
||||
BaseModel() { iNTriangles = 0; iNNodes = 0; iTriangles = 0; iTreeNodes = 0;};
|
||||
BaseModel(unsigned int pNNodes , TreeNode* pTreeNode, unsigned int pNTriangles, TriangleBox* pTriangleBox)
|
||||
{
|
||||
iNNodes = pNNodes; iNTriangles = pNTriangles; iTriangles = pTriangleBox; iTreeNodes = pTreeNode;
|
||||
};
|
||||
BaseModel(unsigned int pNNodes, unsigned int pNTriangles);
|
||||
|
||||
// destructor does nothing ! The subclass controles the array memory and knows when to free it
|
||||
~BaseModel() {}
|
||||
|
||||
void free();
|
||||
void init(unsigned int pNNodes, unsigned int pNTriangles);
|
||||
|
||||
void getMember(G3D::Array<TriangleBox>& pMembers);
|
||||
|
||||
inline const TriangleBox& getTriangle(int pPos) const { return(iTriangles[pPos]); }
|
||||
inline TriangleBox& getTriangle(int pPos) { return(iTriangles[pPos]); }
|
||||
|
||||
inline void setTriangle(const TriangleBox& pTriangleBox, int pPos) { iTriangles[pPos] = pTriangleBox; }
|
||||
|
||||
inline const TreeNode& getTreeNode(int pPos) const { return(getTreeNodes()[pPos]); }
|
||||
inline TreeNode& getTreeNode(int pPos) { return(getTreeNodes()[pPos]); }
|
||||
|
||||
inline void setTreeNode(const TreeNode& pTreeNode, int pPos) { getTreeNodes()[pPos] = pTreeNode; }
|
||||
|
||||
inline void setBasePosition(const G3D::Vector3& pBasePosition) { iBasePosition = pBasePosition; }
|
||||
|
||||
inline const G3D::Vector3& getBasePosition() const { return(iBasePosition); }
|
||||
|
||||
inline unsigned int getNNodes() const { return(iNNodes); }
|
||||
inline unsigned int getNTriangles() const { return(iNTriangles); }
|
||||
|
||||
inline void setNNodes(unsigned int pNNodes) { iNNodes = pNNodes; }
|
||||
inline void setNTriangles(unsigned int pNTriangles) { iNTriangles = pNTriangles; }
|
||||
|
||||
inline void setTriangleArray(TriangleBox *pGlobalTriangleArray ) { iTriangles = pGlobalTriangleArray ; }
|
||||
inline void setTreeNodeArray(TreeNode *pGlobalTreeNodeArray ) { iTreeNodes = pGlobalTreeNodeArray ; }
|
||||
|
||||
inline TriangleBox* getTriangles() const { return(iTriangles); }
|
||||
|
||||
inline TreeNode* getTreeNodes() const{ return(iTreeNodes); }
|
||||
|
||||
inline size_t getMemUsage() { return(iNTriangles * sizeof(TriangleBox) + iNNodes * sizeof(TreeNode) + sizeof(BaseModel)); }
|
||||
|
||||
void intersect(const G3D::AABox& pBox, const G3D::Ray& pRay, float& pMaxDist, G3D::Vector3& pOutLocation, G3D::Vector3& pOutNormal) const;
|
||||
bool intersect(const G3D::AABox& pBox, const G3D::Ray& pRay, float& pMaxDist) const;
|
||||
};
|
||||
|
||||
}
|
||||
#endif /*BASEMODEL_H_*/
|
||||
187
src/shared/vmap/CoordModelMapping.cpp
Normal file
187
src/shared/vmap/CoordModelMapping.cpp
Normal file
|
|
@ -0,0 +1,187 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "CoordModelMapping.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
//============================================================
|
||||
//============================================================
|
||||
|
||||
void CMappingEntry::addFilename(char *pName)
|
||||
{
|
||||
std::string name = std::string(pName);
|
||||
if(!iFilenames.contains(name))
|
||||
iFilenames.append(std::string(pName));
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
const std::string CMappingEntry::getKeyString() const
|
||||
{
|
||||
return(CMappingEntry::getKeyString(iMapId,xPos, yPos));
|
||||
}
|
||||
|
||||
//============================================================
|
||||
//============================================================
|
||||
//============================================================
|
||||
|
||||
CoordModelMapping::~CoordModelMapping()
|
||||
{
|
||||
Array<std::string> keys = iMapObjectFiles.getKeys();
|
||||
for (int k = 0; k < keys.length(); k++)
|
||||
{
|
||||
CMappingEntry *value = getCMappingEntry(keys[k]);
|
||||
if(value != 0)
|
||||
{
|
||||
iMapObjectFiles.remove(keys[k]);
|
||||
delete value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
int findPosChar(const char *namebuffer, char pSearch, int pCount)
|
||||
{
|
||||
int result = -1;
|
||||
int pos=0;
|
||||
while(namebuffer[pos] != 0)
|
||||
{
|
||||
if(namebuffer[pos] == pSearch)
|
||||
{
|
||||
--pCount;
|
||||
}
|
||||
if(pCount == 0)
|
||||
{
|
||||
result = pos;
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//============================================================
|
||||
bool CoordModelMapping::readCoordinateMapping(const std::string& pDirectoryFileName)
|
||||
{
|
||||
FILE *f = fopen(pDirectoryFileName.c_str(), "rb");
|
||||
bool result = false;
|
||||
char buffer[500+1];
|
||||
|
||||
if(f)
|
||||
{
|
||||
result = true;
|
||||
CMappingEntry* cMappingEntry;
|
||||
while(fgets(buffer, 500, f))
|
||||
{
|
||||
//char namebuffer[500];
|
||||
char positionbuffer[500];
|
||||
int xpos, ypos, noVec;
|
||||
float scale;
|
||||
xpos = ypos = noVec = 0;
|
||||
|
||||
//sscanf(buffer, "%d %d %s %s %f %d", &xpos, &ypos, namebuffer,positionbuffer, &scale, &noVec);
|
||||
|
||||
// this is ugly, but the format has no read delimiter and a space could be in the first part of the name
|
||||
int nameStart = findPosChar(buffer, ' ', 2);// find the 2. space
|
||||
if(nameStart > -1 && (iFilterMethod == NULL || (*iFilterMethod)(buffer)))
|
||||
{
|
||||
++nameStart;
|
||||
// find the 1. / (now a space only can be found at the end of the name)
|
||||
int nameEnd = nameStart + findPosChar(&buffer[nameStart], '/', 1);
|
||||
// find the 1. space (after the name)
|
||||
nameEnd += findPosChar(&buffer[nameEnd], ' ', 1);
|
||||
buffer[nameEnd] = 0; // terminate the name
|
||||
|
||||
sscanf(buffer, "%d %d", &xpos, &ypos);
|
||||
sscanf(&buffer[nameEnd+1], "%s %f %d", positionbuffer, &scale, &noVec);
|
||||
unsigned int mapId = getMapIdFromFilename(std::string(&buffer[nameStart]));
|
||||
if(!iMapIds.contains(mapId))
|
||||
{
|
||||
iMapIds.append(mapId);
|
||||
}
|
||||
if(!isWorldAreaMap(mapId))
|
||||
{
|
||||
xpos = 0; // store all files under the groupKey
|
||||
ypos = 0;
|
||||
}
|
||||
|
||||
std::string key = CMappingEntry::getKeyString(mapId, xpos, ypos);
|
||||
cMappingEntry = getCMappingEntry(key);
|
||||
if(cMappingEntry == 0)
|
||||
{
|
||||
cMappingEntry = new CMappingEntry(mapId, xpos, ypos);
|
||||
addCMappingEntry(cMappingEntry);
|
||||
}
|
||||
char namebuffer2[500];
|
||||
sprintf(namebuffer2, "%d %s#%s_%f", noVec, &buffer[nameStart], positionbuffer, scale);
|
||||
cMappingEntry->addFilename(namebuffer2);
|
||||
//break;
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//============================================================
|
||||
|
||||
const NameCollection CoordModelMapping::getFilenamesForCoordinate(unsigned int pMapId, int xPos, int yPos)
|
||||
{
|
||||
NameCollection result;
|
||||
Array<std::string> rawNames;
|
||||
|
||||
CMappingEntry *entry = getCMappingEntry(CMappingEntry::getKeyString(pMapId, xPos, yPos));
|
||||
if(entry != 0)
|
||||
{
|
||||
rawNames = entry->getFilenames();
|
||||
|
||||
int pos = 0;
|
||||
while(pos < rawNames.size())
|
||||
{
|
||||
char namebuffer[500];
|
||||
int noVerc;
|
||||
int startName = findPosChar(rawNames[pos].c_str(), ' ', 1) + 1;
|
||||
int endName = (int) rawNames[pos].length();
|
||||
sscanf(rawNames[pos].c_str(), "%d", &noVerc);
|
||||
memcpy(namebuffer, &rawNames[pos].c_str()[startName], endName-startName);
|
||||
namebuffer[endName-startName] = 0;
|
||||
sscanf(rawNames[pos].c_str(), "%d", &noVerc);
|
||||
std::string modelPosFileName = std::string(namebuffer);
|
||||
if(noVerc > MIN_VERTICES_FOR_OWN_CONTAINER_FILE)
|
||||
{
|
||||
result.appendToSingle(modelPosFileName);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.appendToMain(modelPosFileName);
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
}
|
||||
144
src/shared/vmap/CoordModelMapping.h
Normal file
144
src/shared/vmap/CoordModelMapping.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _COORDMODELMAPPING_H_
|
||||
#define _COORDMODELMAPPING_H_
|
||||
|
||||
#include <G3D/Table.h>
|
||||
#include <G3D/Array.h>
|
||||
|
||||
/**
|
||||
This Class is a helper Class to convert the raw vector data into BSP-Trees.
|
||||
We read the directory file of the raw data output and build logical groups.
|
||||
Models with a lot of vectors are not merged into a resulting model, but separated into an additional file.
|
||||
*/
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
#define MIN_VERTICES_FOR_OWN_CONTAINER_FILE 65000
|
||||
|
||||
// if we are in an instance
|
||||
#define MIN_INST_VERTICES_FOR_OWN_CONTAINER_FILE 40000
|
||||
|
||||
//=====================================================
|
||||
class NameCollection
|
||||
{
|
||||
public:
|
||||
G3D::Array<std::string> iMainFiles;
|
||||
G3D::Array<std::string> iSingeFiles;
|
||||
|
||||
void appendToMain(std::string pStr) { iMainFiles.append(pStr); }
|
||||
void appendToSingle(std::string pStr) { iSingeFiles.append(pStr); }
|
||||
|
||||
size_t size() { return (iMainFiles.size() + iSingeFiles.size()); }
|
||||
};
|
||||
|
||||
//=====================================================
|
||||
|
||||
class CMappingEntry
|
||||
{
|
||||
private:
|
||||
int xPos;
|
||||
int yPos;
|
||||
unsigned int iMapId;
|
||||
G3D::Array<std::string> iFilenames;
|
||||
|
||||
public:
|
||||
CMappingEntry() { };
|
||||
CMappingEntry(unsigned int pMapId, const int pXPos, const int pYPos)
|
||||
{
|
||||
iMapId = pMapId;
|
||||
xPos = pXPos; yPos = pYPos;
|
||||
};
|
||||
~CMappingEntry() {};
|
||||
|
||||
void addFilename(char *pName);
|
||||
const std::string getKeyString() const;
|
||||
inline const G3D::Array<std::string>& getFilenames() const { return(iFilenames); }
|
||||
|
||||
static const std::string getKeyString(unsigned int pMapId, int pXPos, int pYPos)
|
||||
{
|
||||
char b[100];
|
||||
sprintf(b,"%03u_%d_%d", pMapId, pXPos, pYPos);
|
||||
return(std::string(b));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//=====================================================
|
||||
|
||||
class CoordModelMapping
|
||||
{
|
||||
private:
|
||||
G3D::Table<std::string, CMappingEntry *> iMapObjectFiles;
|
||||
G3D::Table<std::string, std::string> iProcesseSingleFiles;
|
||||
G3D::Array<unsigned int> iMapIds;
|
||||
G3D::Array<unsigned int> iWorldAreaGroups;
|
||||
bool (*iFilterMethod)(char *pName);
|
||||
|
||||
inline void addCMappingEntry(CMappingEntry* pCMappingEntry)
|
||||
{
|
||||
iMapObjectFiles.set(pCMappingEntry->getKeyString(), pCMappingEntry);
|
||||
}
|
||||
|
||||
inline CMappingEntry* getCMappingEntry(const std::string& pKey)
|
||||
{
|
||||
if(iMapObjectFiles.containsKey(pKey))
|
||||
return(iMapObjectFiles.get(pKey));
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
public:
|
||||
CoordModelMapping() { iFilterMethod = NULL; }
|
||||
virtual ~CoordModelMapping();
|
||||
|
||||
bool readCoordinateMapping(const std::string& pDirectoryFileName);
|
||||
|
||||
const NameCollection getFilenamesForCoordinate(unsigned int pMapId, int xPos, int yPos);
|
||||
|
||||
static unsigned int getMapIdFromFilename(std::string pName)
|
||||
{
|
||||
size_t spos;
|
||||
|
||||
spos = pName.find_last_of('/');
|
||||
std::string basename = pName.substr(0, spos);
|
||||
spos = basename.find_last_of('/');
|
||||
std::string groupname = basename.substr(spos+1, basename.length());
|
||||
unsigned int mapId = atoi(groupname.c_str());
|
||||
return(mapId);
|
||||
}
|
||||
|
||||
const G3D::Array<unsigned int>& getMaps() const { return iMapIds; }
|
||||
inline bool isAlreadyProcessedSingleFile(std::string pName) { return(iProcesseSingleFiles.containsKey(pName)); }
|
||||
inline void addAlreadyProcessedSingleFile(std::string pName) { iProcesseSingleFiles.set(pName,pName); }
|
||||
|
||||
inline void addWorldAreaMap(unsigned int pMapId)
|
||||
{
|
||||
if(!iWorldAreaGroups.contains(pMapId))
|
||||
{
|
||||
iWorldAreaGroups.append(pMapId);
|
||||
}
|
||||
}
|
||||
inline bool isWorldAreaMap(unsigned int pMapId) { return(iWorldAreaGroups.contains(pMapId)); }
|
||||
void setModelNameFilterMethod(bool (*pFilterMethod)(char *pName)) { iFilterMethod = pFilterMethod; }
|
||||
|
||||
};
|
||||
}
|
||||
#endif /*_COORDMODELMAPPING_H_*/
|
||||
125
src/shared/vmap/DebugCmdLogger.cpp
Normal file
125
src/shared/vmap/DebugCmdLogger.cpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "DebugCmdLogger.h"
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
bool CommandFileRW::appendCmd(const Command&
|
||||
#ifdef _DEBUG
|
||||
pCommand
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
bool result = false;
|
||||
if(iWritingEnabled || pCommand.isCoreCmd())
|
||||
{
|
||||
FILE* f = fopen(iFileName.c_str(), "ab");
|
||||
if(f)
|
||||
{
|
||||
result = true;
|
||||
if(fwrite(&pCommand, sizeof(Command), 1, f) != 1) { result = false; }
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
||||
bool CommandFileRW::appendCmds(const Array<Command>&
|
||||
#ifdef _DEBUG
|
||||
pCmdArray
|
||||
#endif
|
||||
)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
bool result = false;
|
||||
if(iWritingEnabled)
|
||||
{
|
||||
FILE* f;
|
||||
if(resetfile)
|
||||
f = fopen(iFileName.c_str(), "wb");
|
||||
else
|
||||
f = fopen(iFileName.c_str(), "ab");
|
||||
resetfile = false;
|
||||
|
||||
if(f)
|
||||
{
|
||||
result = true;
|
||||
for(int i=0; i<pCmdArray.size(); ++i)
|
||||
{
|
||||
if(fwrite(&pCmdArray[i], sizeof(Command), 1, f) != 1) { result = false; break; }
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================
|
||||
|
||||
bool CommandFileRW::getNewCommands(Array<Command>& pCmdArray)
|
||||
{
|
||||
bool result = false;
|
||||
FILE* f = fopen(iFileName.c_str(), "rb");
|
||||
if(f)
|
||||
{
|
||||
Command cmd;
|
||||
if(fseek(f, iLastPos, SEEK_SET) == 0) { result = true; }
|
||||
while(result)
|
||||
{
|
||||
if(fread(&cmd, sizeof(Command), 1, f) != 1)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
iLastPos = ftell(f);
|
||||
if(cmd.getType() == STOP)
|
||||
{
|
||||
break;
|
||||
}
|
||||
pCmdArray.append(cmd);
|
||||
}
|
||||
fclose(f);
|
||||
}
|
||||
if(result)
|
||||
{
|
||||
iCommandArray.append(pCmdArray);
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
//========================================================
|
||||
}
|
||||
116
src/shared/vmap/DebugCmdLogger.h
Normal file
116
src/shared/vmap/DebugCmdLogger.h
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _DEBUGCMDLOGGER_H
|
||||
#define _DEBUGCMDLOGGER_H
|
||||
|
||||
#include <G3D/Vector3.h>
|
||||
#include <G3D/Array.h>
|
||||
|
||||
/**
|
||||
Class is used for debugging. We log activities into a file.
|
||||
With an external Class we read that log and display the activity in a graphical view.
|
||||
*/
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
//==========================================
|
||||
enum C_TYPES
|
||||
{
|
||||
STOP,
|
||||
START,
|
||||
LOAD_TILE,
|
||||
UNLOAD_TILE,
|
||||
SET_POS,
|
||||
TEST_VIS,
|
||||
LOAD_INSTANCE,
|
||||
UNLOAD_INSTANCE,
|
||||
TEST_HEIGHT,
|
||||
TEST_OBJECT_HIT,
|
||||
};
|
||||
|
||||
class Command
|
||||
{
|
||||
int iType;
|
||||
float floats[9];
|
||||
int ints[4];
|
||||
char buffer[100];
|
||||
public:
|
||||
|
||||
Command() { iType = STOP; }
|
||||
|
||||
inline int getType() { return iType; }
|
||||
inline G3D::Vector3 getVector(int pos) { return(G3D::Vector3(floats[pos*3+0], floats[pos*3+1], floats[pos*3+2])); }
|
||||
inline int getInt(int pos) { return(ints[pos]); }
|
||||
inline char* getBuffer() { return(buffer); }
|
||||
|
||||
void fillStopCmd() { iType = STOP; }
|
||||
void fillStartCmd() { iType = START; }
|
||||
void fillLoadTileCmd(int x, int y, G3D::uint32 pMapId) { iType = LOAD_TILE; ints[0] = x; ints[1] = y; ints[2] = pMapId; }
|
||||
//void fillLoadTileCmd(int x,int y) { iType = LOAD_TILE; ints[0] = x; ints[1] = y; }
|
||||
void fillUnloadTileCmd(G3D::uint32 pMapId) { iType = UNLOAD_INSTANCE; ints[0] = pMapId; }
|
||||
void fillUnloadTileCmd(unsigned int pMapId, int x,int y) { iType = UNLOAD_TILE; ints[0] = x; ints[1] = y; ints[0]=pMapId; }
|
||||
void fillSetPosCmd(G3D::Vector3 pPos) { iType = SET_POS; floats[0] = pPos.x; floats[1]=pPos.y; floats[2]=pPos.z; }
|
||||
void fillTestVisCmd(int pMapId, G3D::Vector3 pPos1, G3D::Vector3 pPos2, bool result)
|
||||
{
|
||||
iType = TEST_VIS; floats[0] = pPos1.x; floats[1]=pPos1.y; floats[2]=pPos1.z;
|
||||
floats[3] = pPos2.x; floats[4]=pPos2.y; floats[5]=pPos2.z;
|
||||
ints[0] = result; ints[1] = pMapId;
|
||||
}
|
||||
void fillTestHeightCmd(int pMapId, G3D::Vector3 pPos, float result)
|
||||
{
|
||||
iType = TEST_HEIGHT; floats[0] = pPos.x; floats[1]=pPos.y; floats[2]=pPos.z;
|
||||
floats[3] = result; ints[0] = pMapId;
|
||||
}
|
||||
void fillTestObjectHitCmd(int pMapId, G3D::Vector3 pPos1, G3D::Vector3 pPos2, G3D::Vector3 pResultPos, bool result)
|
||||
{
|
||||
iType = TEST_OBJECT_HIT; floats[0] = pPos1.x; floats[1]=pPos1.y; floats[2]=pPos1.z;
|
||||
floats[3] = pPos2.x; floats[4]=pPos2.y; floats[5]=pPos2.z;
|
||||
floats[6] = pResultPos.x; floats[7]=pResultPos.y; floats[8]=pResultPos.z;
|
||||
ints[0] = result; ints[1] = pMapId;
|
||||
}
|
||||
|
||||
bool isCoreCmd() const { return(iType != TEST_VIS); }
|
||||
};
|
||||
|
||||
//==========================================
|
||||
|
||||
class CommandFileRW
|
||||
{
|
||||
private:
|
||||
std::string iFileName;
|
||||
long iLastPos;
|
||||
G3D::Array<G3D::Array<Command> > iCommandArray;
|
||||
bool resetfile;
|
||||
bool iWritingEnabled;
|
||||
public:
|
||||
CommandFileRW() { iLastPos=0; iWritingEnabled = true; resetfile = true;}
|
||||
CommandFileRW(const std::string& pFileName) { iLastPos = 0; iFileName = pFileName; iWritingEnabled = true; resetfile = true; }
|
||||
void setResetFile() { resetfile = true; }
|
||||
void enableWriting(bool pValue) { iWritingEnabled = pValue; }
|
||||
void setFileName(const std::string& pName) { iFileName = pName; }
|
||||
bool getNewCommands(G3D::Array<Command>& commandArray);
|
||||
const G3D::Array<G3D::Array<Command> >& getFullCommandArray() { return iCommandArray; }
|
||||
|
||||
bool appendCmd(const Command& pCommand);
|
||||
bool appendCmds(const G3D::Array<Command>& pCmdArray);
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
99
src/shared/vmap/IVMapManager.h
Normal file
99
src/shared/vmap/IVMapManager.h
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _IVMAPMANAGER_H
|
||||
#define _IVMAPMANAGER_H
|
||||
|
||||
#include<string>
|
||||
|
||||
//===========================================================
|
||||
|
||||
/**
|
||||
This is the minimum interface to the VMapMamager.
|
||||
*/
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
enum VMAP_LOAD_RESULT
|
||||
{
|
||||
VMAP_LOAD_RESULT_ERROR,
|
||||
VMAP_LOAD_RESULT_OK,
|
||||
VMAP_LOAD_RESULT_IGNORED,
|
||||
};
|
||||
|
||||
#define VMAP_INVALID_HEIGHT -100000.0f // for check
|
||||
#define VMAP_INVALID_HEIGHT_VALUE -200000.0f // real assigned value in unknown height case
|
||||
|
||||
//===========================================================
|
||||
class IVMapManager
|
||||
{
|
||||
private:
|
||||
bool iEnableLineOfSightCalc;
|
||||
bool iEnableHeightCalc;
|
||||
|
||||
public:
|
||||
IVMapManager() : iEnableLineOfSightCalc(true), iEnableHeightCalc(true) {}
|
||||
|
||||
virtual ~IVMapManager(void) {}
|
||||
|
||||
virtual int loadMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
|
||||
|
||||
virtual bool existsMap(const char* pBasePath, unsigned int pMapId, int x, int y) = 0;
|
||||
|
||||
virtual void unloadMap(unsigned int pMapId, int x, int y) = 0;
|
||||
virtual void unloadMap(unsigned int pMapId) = 0;
|
||||
|
||||
virtual bool isInLineOfSight(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2) = 0;
|
||||
virtual float getHeight(unsigned int pMapId, float x, float y, float z) = 0;
|
||||
/**
|
||||
test if we hit an object. return true if we hit one. rx,ry,rz will hold the hit position or the dest position, if no intersection was found
|
||||
return a position, that is pReduceDist closer to the origin
|
||||
*/
|
||||
virtual bool getObjectHitPos(unsigned int pMapId, float x1, float y1, float z1, float x2, float y2, float z2, float& rx, float &ry, float& rz, float pModifyDist) = 0;
|
||||
/**
|
||||
send debug commands
|
||||
*/
|
||||
virtual bool processCommand(char *pCommand)= 0;
|
||||
|
||||
/**
|
||||
Enable/disable LOS calculation
|
||||
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
|
||||
*/
|
||||
void setEnableLineOfSightCalc(bool pVal) { iEnableLineOfSightCalc = pVal; }
|
||||
/**
|
||||
Enable/disable model height calculation
|
||||
It is enabled by default. If it is enabled in mid game the maps have to loaded manualy
|
||||
*/
|
||||
void setEnableHeightCalc(bool pVal) { iEnableHeightCalc = pVal; }
|
||||
|
||||
bool isLineOfSightCalcEnabled() const { return(iEnableLineOfSightCalc); }
|
||||
bool isHeightCalcEnabled() const { return(iEnableHeightCalc); }
|
||||
bool isMapLoadingEnabled() const { return(iEnableLineOfSightCalc || iEnableHeightCalc ); }
|
||||
|
||||
virtual std::string getDirFileName(unsigned int pMapId, int x, int y) const =0;
|
||||
/**
|
||||
Block maps from being used.
|
||||
parameter: String of map ids. Delimiter = ","
|
||||
e.g.: "0,1,530"
|
||||
*/
|
||||
virtual void preventMapsFromBeingUsed(const char* pMapIdString) =0;
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
56
src/shared/vmap/Makefile.am
Normal file
56
src/shared/vmap/Makefile.am
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
# Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
## Process this file with automake to produce Makefile.in
|
||||
|
||||
## Sub-directories to parse
|
||||
|
||||
## CPP flags for includes, defines, etc.
|
||||
AM_CPPFLAGS = $(MANGOS_INCLUDES) -I$(top_builddir)/src/shared -I$(srcdir) -I$(srcdir)/../../../dep/include -I$(srcdir)/../../framework -I$(srcdir)/../../shared -I$(srcdir)/../../../dep/include/g3dlite
|
||||
|
||||
## Build MaNGOS shared library and its parts as convenience library.
|
||||
# All libraries will be convenience libraries. Might be changed to shared
|
||||
# later.
|
||||
noinst_LIBRARIES = libmangosvmaps.a
|
||||
|
||||
libmangosvmaps_a_SOURCES = \
|
||||
AABSPTree.h \
|
||||
BaseModel.cpp \
|
||||
BaseModel.h \
|
||||
CoordModelMapping.cpp \
|
||||
CoordModelMapping.h \
|
||||
DebugCmdLogger.cpp \
|
||||
DebugCmdLogger.h \
|
||||
IVMapManager.h \
|
||||
ManagedModelContainer.cpp \
|
||||
ManagedModelContainer.h \
|
||||
ModelContainer.cpp \
|
||||
ModelContainer.h \
|
||||
NodeValueAccess.h \
|
||||
ShortBox.h \
|
||||
ShortVector.h \
|
||||
SubModel.cpp \
|
||||
SubModel.h \
|
||||
TileAssembler.cpp \
|
||||
TileAssembler.h \
|
||||
TreeNode.cpp \
|
||||
TreeNode.h \
|
||||
VMapDefinitions.h \
|
||||
VMapFactory.cpp \
|
||||
VMapFactory.h \
|
||||
VMapManager.cpp \
|
||||
VMapManager.h \
|
||||
VMapTools.h
|
||||
35
src/shared/vmap/ManagedModelContainer.cpp
Normal file
35
src/shared/vmap/ManagedModelContainer.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "ManagedModelContainer.h"
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
ManagedModelContainer::ManagedModelContainer(void) : ModelContainer()
|
||||
{
|
||||
refCount = 0;
|
||||
}
|
||||
|
||||
ManagedModelContainer::~ManagedModelContainer(void)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
49
src/shared/vmap/ManagedModelContainer.h
Normal file
49
src/shared/vmap/ManagedModelContainer.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _MANAGEDMODELCONTAINER_H
|
||||
#define _MANAGEDMODELCONTAINER_H
|
||||
|
||||
#include "ModelContainer.h"
|
||||
|
||||
//=======================================================
|
||||
/**
|
||||
This is a ModelContainer with reference count information.
|
||||
*/
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
//=======================================================
|
||||
|
||||
class ManagedModelContainer :
|
||||
public ModelContainer
|
||||
{
|
||||
private:
|
||||
int refCount;
|
||||
public:
|
||||
ManagedModelContainer(void) ;
|
||||
~ManagedModelContainer(void);
|
||||
|
||||
void incRefCount() { ++refCount; }
|
||||
void decRefCount() { --refCount; if(refCount < 0) refCount = 0; }
|
||||
int getRefCount() { return refCount; }
|
||||
};
|
||||
|
||||
//=======================================================
|
||||
}
|
||||
#endif
|
||||
375
src/shared/vmap/ModelContainer.cpp
Normal file
375
src/shared/vmap/ModelContainer.cpp
Normal file
|
|
@ -0,0 +1,375 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "ModelContainer.h"
|
||||
#include "VMapDefinitions.h"
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
//==========================================================
|
||||
/**
|
||||
Functions to use ModelContainer with a AABSPTree
|
||||
*/
|
||||
size_t hashCode(const ModelContainer& pMc)
|
||||
{
|
||||
return (pMc.getBasePosition() * pMc.getNTriangles()).hashCode();
|
||||
}
|
||||
//==========================================================
|
||||
|
||||
ModelContainer::ModelContainer(unsigned int pNTriangles, unsigned int pNNodes, unsigned int pNSubModel) :
|
||||
BaseModel(pNNodes, pNTriangles)
|
||||
{
|
||||
|
||||
iNSubModel = pNSubModel;
|
||||
iSubModel = 0;
|
||||
if(pNSubModel > 0) iSubModel = new SubModel[iNSubModel];
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
bool ModelContainer::operator==(const ModelContainer& pMc2) const
|
||||
{
|
||||
if (this->iNSubModel == 0 && pMc2.iNSubModel == 0 && this->iSubModel == 0 && pMc2.iSubModel == 0)
|
||||
return true;
|
||||
return this == &pMc2;
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
void ModelContainer::countSubModelsAndNodesAndTriangles(AABSPTree<SubModel *>::Node& pNode, int& nSubModels, int& nNodes, int& nTriangles)
|
||||
{
|
||||
// For this node we will need a TreeNode as well as for the internal nodes
|
||||
++nNodes;
|
||||
|
||||
nSubModels += pNode.valueArray.size();
|
||||
for(int i=0;i<pNode.valueArray.size(); i++)
|
||||
{
|
||||
G3D::_AABSPTree::Handle<SubModel*>* h= pNode.valueArray[i];
|
||||
SubModel *m = h->value;
|
||||
// add the internal nodes as well
|
||||
nNodes += m->getNNodes();
|
||||
nTriangles += m->getNTriangles();
|
||||
}
|
||||
|
||||
if(pNode.child[0] != 0)
|
||||
{
|
||||
countSubModelsAndNodesAndTriangles(*pNode.child[0], nSubModels, nNodes, nTriangles);
|
||||
}
|
||||
if(pNode.child[1] != 0)
|
||||
{
|
||||
countSubModelsAndNodesAndTriangles(*pNode.child[1], nSubModels, nNodes, nTriangles);
|
||||
}
|
||||
}
|
||||
//==========================================================
|
||||
|
||||
void ModelContainer::fillContainer(const AABSPTree<SubModel *>::Node& pNode, int &pSubModelPos, int &pTreeNodePos, int &pTrianglePos, Vector3& pLo, Vector3& pHi, Vector3& pFinalLo, Vector3& pFinalHi)
|
||||
{
|
||||
// TreeNode for the SubModel
|
||||
TreeNode treeNode = TreeNode(pNode.valueArray.size(), pSubModelPos);
|
||||
treeNode.setSplitAxis(pNode.splitAxis);
|
||||
treeNode.setSplitLocation(pNode.splitLocation);
|
||||
int currentTreeNodePos = pTreeNodePos++;
|
||||
|
||||
Vector3 lo = Vector3(inf(),inf(),inf());
|
||||
Vector3 hi = Vector3(-inf(),-inf(),-inf());
|
||||
|
||||
for(int i=0;i<pNode.valueArray.size(); i++)
|
||||
{
|
||||
G3D::_AABSPTree::Handle<SubModel*>* h= pNode.valueArray[i];
|
||||
SubModel *m = h->value;
|
||||
|
||||
memcpy(&getTreeNodes()[pTreeNodePos], &m->getTreeNode(0), sizeof(TreeNode) * m->getNNodes());
|
||||
memcpy(&getTriangles()[pTrianglePos], &m->getTriangle(0), sizeof(TriangleBox) * m->getNTriangles());
|
||||
|
||||
SubModel newModel = SubModel(m->getNTriangles(), getTriangles(), pTrianglePos, m->getNNodes(), getTreeNodes(), pTreeNodePos);
|
||||
newModel.setReletiveBounds(m->getReletiveBounds().getLo(), m->getReletiveBounds().getHi());
|
||||
newModel.setBasePosition(m->getBasePosition());
|
||||
iSubModel[pSubModelPos++] = newModel;
|
||||
|
||||
pTreeNodePos += m->getNNodes();
|
||||
pTrianglePos += m->getNTriangles();
|
||||
|
||||
AABox box = m->getAABoxBounds();
|
||||
lo = lo.min(box.low());
|
||||
hi = hi.max(box.high());
|
||||
pFinalLo = pFinalLo.min(lo);
|
||||
pFinalHi = pFinalHi.max(hi);
|
||||
}
|
||||
/*
|
||||
if(pNode.valueArray.size() == 0) {
|
||||
int xxx = 0; // just for the breakpoint
|
||||
}
|
||||
*/
|
||||
// get absolute bounds
|
||||
|
||||
if(pNode.child[0] != 0)
|
||||
{
|
||||
treeNode.setChildPos(0, pTreeNodePos);
|
||||
fillContainer(*pNode.child[0], pSubModelPos, pTreeNodePos, pTrianglePos, lo, hi,pFinalLo,pFinalHi);
|
||||
}
|
||||
if(pNode.child[1] != 0)
|
||||
{
|
||||
treeNode.setChildPos(1, pTreeNodePos);
|
||||
fillContainer(*pNode.child[1], pSubModelPos, pTreeNodePos, pTrianglePos, lo, hi,pFinalLo,pFinalHi);
|
||||
}
|
||||
|
||||
pLo = pLo.min(lo);
|
||||
pHi = pHi.max(hi);
|
||||
|
||||
treeNode.setBounds(lo,hi);
|
||||
|
||||
setTreeNode(treeNode, currentTreeNodePos);
|
||||
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
/**
|
||||
Create the structure out of a AABSPTree
|
||||
*/
|
||||
|
||||
ModelContainer::ModelContainer(AABSPTree<SubModel *> *pTree)
|
||||
{
|
||||
|
||||
int nSubModels, nNodes, nTriangles;
|
||||
nSubModels = nNodes = nTriangles = 0;
|
||||
countSubModelsAndNodesAndTriangles(*pTree->root, nSubModels, nNodes, nTriangles);
|
||||
|
||||
init(nNodes, nTriangles);
|
||||
|
||||
iNSubModel = nSubModels;
|
||||
|
||||
iSubModel = new SubModel[iNSubModel];
|
||||
|
||||
int subModelPos,treeNodePos, trianglePos;
|
||||
subModelPos = treeNodePos = trianglePos = 0;
|
||||
|
||||
Vector3 lo = Vector3(inf(),inf(),inf());
|
||||
Vector3 hi = Vector3(-inf(),-inf(),-inf());
|
||||
Vector3 finalLo, finalHi;
|
||||
finalLo = lo;
|
||||
finalHi = hi;
|
||||
|
||||
fillContainer(*pTree->root, subModelPos, treeNodePos, trianglePos, lo, hi, finalLo, finalHi);
|
||||
setBounds(finalLo, finalHi);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
ModelContainer::~ModelContainer(void)
|
||||
{
|
||||
free();
|
||||
if(iSubModel != 0) delete [] iSubModel;
|
||||
}
|
||||
//==========================================================
|
||||
|
||||
bool ModelContainer::writeFile(const char *filename)
|
||||
{
|
||||
bool result = false;
|
||||
unsigned int flags=0;
|
||||
unsigned int size;
|
||||
|
||||
FILE *wf =fopen(filename,"wb");
|
||||
if(wf)
|
||||
{
|
||||
fwrite(VMAP_MAGIC,1,8,wf);
|
||||
result = true;
|
||||
if(result && fwrite("CTREE01",8,1,wf) != 1) result = false;
|
||||
if(result && fwrite(&flags,sizeof(unsigned int),1,wf) != 1) result = false;
|
||||
|
||||
if(result && fwrite("POS ",4,1,wf) != 1) result = false;
|
||||
size = sizeof(float)*3;
|
||||
if(result && fwrite(&size,4,1,wf) != 1) result = false;
|
||||
Vector3 basePos = getBasePosition();
|
||||
if(result && fwrite(&basePos,sizeof(float),3,wf) != 3) result = false;
|
||||
|
||||
if(result && fwrite("BOX ",4,1,wf) != 1) result = false;
|
||||
size = sizeof(float)*6;
|
||||
if(result && fwrite(&size,4,1,wf) != 1) result = false;
|
||||
Vector3 low = iBox.low();
|
||||
if(result && fwrite(&low,sizeof(float),3,wf) != 3) result = false;
|
||||
Vector3 high = iBox.high();
|
||||
if(result && fwrite(&high,sizeof(float),3,wf) != 3) result = false;
|
||||
|
||||
if(result && fwrite("NODE",4,1,wf) != 1) result = false;
|
||||
size = sizeof(unsigned int)+ sizeof(TreeNode)*getNNodes();
|
||||
if(result && fwrite(&size,4,1,wf) != 1) result = false;
|
||||
unsigned int val = getNNodes();
|
||||
if(result && fwrite(&val,sizeof(unsigned int),1,wf) != 1) result = false;
|
||||
if(result && fwrite(getTreeNodes(),sizeof(TreeNode),getNNodes(),wf) != getNNodes()) result = false;
|
||||
|
||||
if(result && fwrite("TRIB",4,1,wf) != 1) result = false;
|
||||
size = sizeof(unsigned int)+ sizeof(TriangleBox)*getNTriangles();
|
||||
if(result && fwrite(&size,4,1,wf) != 1) result = false;
|
||||
val = getNTriangles();
|
||||
if(result && fwrite(&val,sizeof(unsigned int),1,wf) != 1) result = false;
|
||||
if(result && fwrite(getTriangles(),sizeof(TriangleBox),getNTriangles(),wf) != getNTriangles()) result = false;
|
||||
|
||||
if(result && fwrite("SUBM",4,1,wf) != 1) result = false;
|
||||
size = sizeof(unsigned int)+ sizeof(SubModel)*iNSubModel;
|
||||
if(result && fwrite(&size,4,1,wf) != 1) result = false;
|
||||
if(result && fwrite(&iNSubModel,sizeof(unsigned int),1,wf) != 1) result = false;
|
||||
if(result && fwrite(iSubModel,sizeof(SubModel),iNSubModel,wf) != iNSubModel) result = false;
|
||||
|
||||
fclose(wf);
|
||||
}
|
||||
|
||||
return(result);
|
||||
}
|
||||
|
||||
//===============================================================
|
||||
|
||||
bool ModelContainer::readFile(const char *filename)
|
||||
{
|
||||
bool result = false;
|
||||
unsigned int flags;
|
||||
unsigned int size;
|
||||
char ident[8];
|
||||
char chunk[4];
|
||||
unsigned int ival;
|
||||
FILE *rf = fopen(filename, "rb");
|
||||
if(rf)
|
||||
{
|
||||
free();
|
||||
|
||||
result = true;
|
||||
char magic[8]; // Ignore the added magic header
|
||||
fread(magic,1,8,rf);
|
||||
if(strncmp(VMAP_MAGIC,magic,8)) result = false;
|
||||
if(result && fread(ident,8,1,rf) != 1) result = false;
|
||||
if(result && fread(&flags,sizeof(unsigned int),1,rf) != 1) result = false;
|
||||
//POS
|
||||
if(result && fread(chunk,4,1,rf) != 1) result = false;
|
||||
if(result && fread(&size,4,1,rf) != 1) result = false;
|
||||
Vector3 basePos;
|
||||
if(result && fread(&basePos,sizeof(float),3,rf) != 3) result = false;
|
||||
setBasePosition(basePos);
|
||||
|
||||
//---- Box
|
||||
if(result && fread(chunk,4,1,rf) != 1) result = false;
|
||||
if(result && fread(&size,4,1,rf) != 1) result = false;
|
||||
Vector3 low,high;
|
||||
if(result && fread(&low,sizeof(float),3,rf) != 3) result = false;
|
||||
if(result && fread(&high,sizeof(float),3,rf) != 3) result = false;
|
||||
setBounds(low, high);
|
||||
|
||||
//---- TreeNodes
|
||||
if(result && fread(chunk,4,1,rf) != 1) result = false;
|
||||
if(result && fread(&size,4,1,rf) != 1) result = false;
|
||||
|
||||
if(result && fread(&ival,sizeof(unsigned int),1,rf) != 1) result = false;
|
||||
if(result) setNNodes(ival);
|
||||
if(result) setTreeNodeArray(new TreeNode[getNNodes()]);
|
||||
if(result && fread(getTreeNodes(),sizeof(TreeNode),getNNodes(),rf) != getNNodes()) result = false;
|
||||
|
||||
//---- TriangleBoxes
|
||||
if(result && fread(chunk,4,1,rf) != 1) result = false;
|
||||
if(result && fread(&size,4,1,rf) != 1) result = false;
|
||||
|
||||
if(result && fread(&ival,sizeof(unsigned int),1,rf) != 1) result = false;
|
||||
setNTriangles(ival);
|
||||
if(result) setTriangleArray(new TriangleBox[getNTriangles()]);
|
||||
if(result && fread(getTriangles(),sizeof(TriangleBox),getNTriangles(),rf) != getNTriangles()) result = false;
|
||||
|
||||
//---- SubModel
|
||||
if(result && fread(chunk,4,1,rf) != 1) result = false;
|
||||
if(result && fread(&size,4,1,rf) != 1) result = false;
|
||||
|
||||
if(result && fread(&iNSubModel,sizeof(unsigned int),1,rf) != 1) result = false;
|
||||
if(result) iSubModel = new SubModel[iNSubModel];
|
||||
|
||||
if(result)
|
||||
{
|
||||
for(unsigned int i=0;i<iNSubModel && result; ++i)
|
||||
{
|
||||
unsigned char readBuffer[52]; // this is the size of SubModel on 32 bit systems
|
||||
if(fread(readBuffer,sizeof(readBuffer),1,rf) != 1) result = false;
|
||||
iSubModel[i].initFromBinBlock(readBuffer);
|
||||
iSubModel[i].setTriangleArray(getTriangles());
|
||||
iSubModel[i].setTreeNodeArray(getTreeNodes());
|
||||
}
|
||||
}
|
||||
fclose(rf);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
size_t ModelContainer::getMemUsage()
|
||||
{
|
||||
// BaseModel is included in ModelContainer
|
||||
return(iNSubModel * sizeof(SubModel) + BaseModel::getMemUsage() + sizeof(ModelContainer) - sizeof(BaseModel));
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
#ifdef _DEBUG_VMAPS
|
||||
#ifndef gBoxArray
|
||||
extern Vector3 p1,p2,p3,p4,p5,p6,p7;
|
||||
extern Array<AABox>gBoxArray;
|
||||
extern int gCount1, gCount2, gCount3, gCount4;
|
||||
extern bool myfound;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void ModelContainer::intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& /*pOutLocation*/, G3D::Vector3& /*pOutNormal*/) const
|
||||
{
|
||||
IntersectionCallBack<SubModel> intersectCallback;
|
||||
NodeValueAccess<TreeNode, SubModel> vna = NodeValueAccess<TreeNode, SubModel>(getTreeNodes(), iSubModel);
|
||||
Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction);
|
||||
iTreeNodes[0].intersectRay(pRay, intersectCallback, pMaxDist, vna, pStopAtFirstHit, false);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
bool ModelContainer::intersect(const G3D::Ray& pRay, float& pMaxDist) const
|
||||
{
|
||||
return BaseModel::intersect(getAABoxBounds(), pRay, pMaxDist);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
template<typename RayCallback>
|
||||
void ModelContainer::intersectRay(const G3D::Ray& pRay, RayCallback& intersectCallback, float& pMaxDist, bool pStopAtFirstHit, bool intersectCallbackIsFast)
|
||||
{
|
||||
if(intersect(pRay, pMaxDist))
|
||||
{
|
||||
NodeValueAccess<TreeNode, SubModel> vna = NodeValueAccess<TreeNode, SubModel>(getTreeNodes(), iSubModel);
|
||||
iTreeNodes[0].intersectRay(pRay, intersectCallback, distance, vna, pStopAtFirstHit, true);
|
||||
}
|
||||
}
|
||||
//=================================================================
|
||||
void getBounds(const ModelContainer& pMc, G3D::AABox& pAABox)
|
||||
{
|
||||
pAABox = pMc.getAABoxBounds();
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
void getBounds(const ModelContainer* pMc, G3D::AABox& pAABox)
|
||||
{
|
||||
pAABox = pMc->getAABoxBounds();
|
||||
}
|
||||
//=================================================================
|
||||
} // VMAP
|
||||
108
src/shared/vmap/ModelContainer.h
Normal file
108
src/shared/vmap/ModelContainer.h
Normal file
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _MODELCONTAINER_H
|
||||
#define _MODELCONTAINER_H
|
||||
|
||||
// load our modified version first !!
|
||||
#include "AABSPTree.h"
|
||||
|
||||
#include <G3D/AABox.h>
|
||||
#include <G3D/Vector3.h>
|
||||
#include <G3D/Ray.h>
|
||||
|
||||
#include "ShortBox.h"
|
||||
#include "TreeNode.h"
|
||||
#include "VMapTools.h"
|
||||
#include "SubModel.h"
|
||||
#include "BaseModel.h"
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
/**
|
||||
The ModelContainer is a balanced BSP-Tree of SubModels.
|
||||
We store a map tile or an instance in one ModelContainer.
|
||||
The ModelContainer manages the memory used for the tree nodes, the SubModels and its triangles in static arrays.
|
||||
The tree nodes are used for the BSP-Tree of SubModels as well as for the BSP-Tree of triangles within one SubModel.
|
||||
The references are done by indexes within these static arrays.
|
||||
Therefore we are able to just load a binary block and do not need to mess around with memory allocation and pointers.
|
||||
*/
|
||||
|
||||
//=====================================================
|
||||
|
||||
class ModelContainer : public BaseModel
|
||||
{
|
||||
private:
|
||||
unsigned int iNSubModel;
|
||||
SubModel *iSubModel;
|
||||
G3D::AABox iBox;
|
||||
|
||||
ModelContainer (const ModelContainer& c): BaseModel(c) {}
|
||||
ModelContainer& operator=(const ModelContainer& ) {}
|
||||
|
||||
public:
|
||||
ModelContainer() : BaseModel() { iNSubModel =0; iSubModel = 0; };
|
||||
|
||||
// for the mainnode
|
||||
ModelContainer(unsigned int pNTriangles, unsigned int pNNodes, unsigned int pNSubModel);
|
||||
|
||||
ModelContainer(G3D::AABSPTree<SubModel *> *pTree);
|
||||
|
||||
~ModelContainer(void);
|
||||
|
||||
inline const void setSubModel(const SubModel& pSubModel, int pPos) { iSubModel[pPos] = pSubModel; }
|
||||
|
||||
inline const SubModel& getSubModel(int pPos) const { return iSubModel[pPos]; }
|
||||
|
||||
inline unsigned int getNSubModel() const { return(iNSubModel); }
|
||||
|
||||
void countSubModelsAndNodesAndTriangles(G3D::AABSPTree<SubModel *>::Node& pNode, int& nSubModels, int& nNodes, int& nTriangles);
|
||||
|
||||
void fillContainer(const G3D::AABSPTree<SubModel *>::Node& pNode, int &pSubModelPos, int &pTreeNodePos, int &pTrianglePos, G3D::Vector3& pLo, G3D::Vector3& pHi, G3D::Vector3& pFinalLo, G3D::Vector3& pFinalHi);
|
||||
|
||||
bool readRawFile(const char *name);
|
||||
|
||||
inline const G3D::AABox& getAABoxBounds() const { return(iBox); }
|
||||
|
||||
inline void setBounds(const G3D::Vector3& lo, const G3D::Vector3& hi) { iBox.set(lo,hi); }
|
||||
|
||||
bool writeFile(const char *filename);
|
||||
|
||||
bool readFile(const char *filename);
|
||||
|
||||
size_t getMemUsage();
|
||||
size_t hashCode() { return (getBasePosition() * getNTriangles()).hashCode(); }
|
||||
|
||||
void intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& pOutLocation, G3D::Vector3& pOutNormal) const;
|
||||
bool intersect(const G3D::Ray& pRay, float& pMaxDist) const;
|
||||
|
||||
template<typename RayCallback>
|
||||
void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& distance, bool pStopAtFirstHit, bool intersectCallbackIsFast = false);
|
||||
|
||||
bool operator==(const ModelContainer& pMc2) const;
|
||||
};
|
||||
|
||||
//=====================================================
|
||||
|
||||
//=====================================================
|
||||
|
||||
size_t hashCode(const ModelContainer& pMc);
|
||||
void getBounds(const ModelContainer& pMc, G3D::AABox& pAABox);
|
||||
void getBounds(const ModelContainer* pMc, G3D::AABox& pAABox);
|
||||
}
|
||||
#endif
|
||||
48
src/shared/vmap/NodeValueAccess.h
Normal file
48
src/shared/vmap/NodeValueAccess.h
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _NODEVALUEACCESS_H
|
||||
#define _NODEVALUEACCESS_H
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
/**
|
||||
This is a helper Class to get access to SubModels or triangles when analyzing the BSP-Tree.
|
||||
*/
|
||||
|
||||
template<class TNode, class TValue> class NodeValueAccess
|
||||
{
|
||||
private:
|
||||
TNode const* iNodeArray;
|
||||
TValue const* iValueArray;
|
||||
|
||||
public:
|
||||
inline NodeValueAccess() : iNodeArray(NULL), iValueArray(NULL) {}
|
||||
|
||||
inline NodeValueAccess(TNode const* pNodeArray, TValue const* pValueArray) : iNodeArray(pNodeArray), iValueArray(pValueArray) {}
|
||||
inline TNode const* getNodePtr() const { return(iNodeArray); }
|
||||
inline TValue const* getValuePtr() const { return(iValueArray); }
|
||||
|
||||
inline TNode const& getNode(unsigned int pPos) const { return(iNodeArray[pPos]); }
|
||||
inline void setNode(const TNode& pNode, unsigned int pPos) { iNodeArray[pPos] = pNode; }
|
||||
|
||||
inline TValue const& getValue(unsigned int pPos) const { return(iValueArray[pPos]); }
|
||||
inline void setValue(const TValue& pValue, unsigned int pPos) { iValueArray[pPos] = pValue; }
|
||||
};
|
||||
}
|
||||
#endif
|
||||
148
src/shared/vmap/ShortBox.h
Normal file
148
src/shared/vmap/ShortBox.h
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _SHORTBOX_H
|
||||
#define _SHORTBOX_H
|
||||
|
||||
#include <G3D/Vector3.h>
|
||||
#include <G3D/AABox.h>
|
||||
#include <G3D/Triangle.h>
|
||||
#include <G3D/Ray.h>
|
||||
|
||||
#include "ShortVector.h"
|
||||
|
||||
/**
|
||||
This is a box and a triangle Class using ShortVectors. Each vector has 16 bit an a fixed point 12.4 representation.
|
||||
*/
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
class ShortBox
|
||||
{
|
||||
private:
|
||||
ShortVector iV1;
|
||||
ShortVector iV2;
|
||||
public:
|
||||
ShortBox() {}
|
||||
inline const ShortVector& getLo() const { return(iV1); }
|
||||
inline const ShortVector& getHi() const { return(iV2); }
|
||||
inline void setLo(const ShortVector& pV){ iV1 = pV; }
|
||||
inline void setHi(const ShortVector& pV){ iV2 = pV; }
|
||||
inline void setLo(const G3D::Vector3& pV){ iV1 = ShortVector(pV); }
|
||||
inline void setHi(const G3D::Vector3& pV){ iV2 = ShortVector(pV); }
|
||||
|
||||
inline bool operator==(const ShortBox& b) const
|
||||
{
|
||||
return ((iV1 == b.iV1) && (iV2 == b.iV2));
|
||||
}
|
||||
|
||||
inline bool operator!=(const ShortBox& b) const
|
||||
{
|
||||
return !((iV1 == b.iV1) && (iV2 == b.iV2));
|
||||
}
|
||||
};
|
||||
|
||||
//=====================================================================
|
||||
#ifdef _DEBUG_VMAPS
|
||||
#ifndef gBoxArray
|
||||
extern G3D::Vector3 p1,p2,p3,p4,p5,p6,p7;
|
||||
extern G3D::Array<G3D::AABox>gBoxArray;
|
||||
extern G3D::Array<G3D::Triangle>gTriArray;
|
||||
extern int gCount1, gCount2, gCount3, gCount4;
|
||||
extern bool myfound;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const G3D::Vector3 dummyZeroPosition = G3D::Vector3(0,0,0);
|
||||
|
||||
class TriangleBox
|
||||
{
|
||||
private:
|
||||
ShortVector _vertex[3];
|
||||
//ShortBox iBox;
|
||||
public:
|
||||
inline TriangleBox() { }
|
||||
inline TriangleBox(const ShortVector& pV1, const ShortVector& pV2, const ShortVector& pV3)
|
||||
{
|
||||
_vertex[0] = pV1;
|
||||
_vertex[1] = pV2;
|
||||
_vertex[2] = pV3;
|
||||
|
||||
}
|
||||
inline const ShortVector& vertex (int n) const
|
||||
{
|
||||
return(_vertex[n]);
|
||||
}
|
||||
|
||||
inline const ShortBox getBounds()const
|
||||
{
|
||||
ShortBox box;
|
||||
|
||||
ShortVector lo = _vertex[0];
|
||||
ShortVector hi = lo;
|
||||
|
||||
for (int i = 1; i < 3; ++i)
|
||||
{
|
||||
lo = lo.min(_vertex[i]);
|
||||
hi = hi.max(_vertex[i]);
|
||||
}
|
||||
box.setLo(lo);
|
||||
box.setHi(hi);
|
||||
return(box);
|
||||
}
|
||||
inline const G3D::Vector3& getBasePosition() { return(dummyZeroPosition); }
|
||||
|
||||
inline const G3D::AABox getAABoxBounds() const { ShortBox box = getBounds(); return(G3D::AABox(box.getLo().getVector3(), box.getHi().getVector3())); }
|
||||
|
||||
inline bool operator==(const TriangleBox& t) const
|
||||
{
|
||||
return ((_vertex[0] == t._vertex[0]) && (_vertex[1] == t._vertex[1]) &&(_vertex[2] == t._vertex[2]));
|
||||
}
|
||||
|
||||
inline bool operator!=(const TriangleBox& t) const
|
||||
{
|
||||
return !((_vertex[0] == t._vertex[0]) && (_vertex[1] == t._vertex[1]) &&(_vertex[2] == t._vertex[2]));
|
||||
}
|
||||
|
||||
inline void intersect(const G3D::Ray& pRay, float& pMaxDist, bool /*pStopAtFirstHitDummy*/, G3D::Vector3& /*pOutLocationDummy*/, G3D::Vector3& /*pOutNormalDummy*/) const
|
||||
{
|
||||
static const double epsilon = 0.00001;
|
||||
G3D::Triangle testT(vertex(0).getVector3(),vertex(1).getVector3(),vertex(2).getVector3());
|
||||
float t = pRay.intersectionTime(testT);
|
||||
if ((t < pMaxDist) || t < (pMaxDist + epsilon))
|
||||
pMaxDist = t;
|
||||
else
|
||||
{
|
||||
testT = G3D::Triangle(vertex(2).getVector3(),vertex(1).getVector3(),vertex(0).getVector3());
|
||||
|
||||
#ifdef _DEBUG_VMAPS
|
||||
{
|
||||
G3D::Triangle myt(testT.vertex(0)+p6, testT.vertex(1)+p6,testT.vertex(2)+p6);
|
||||
gTriArray.push_back(myt);
|
||||
}
|
||||
#endif
|
||||
t = pRay.intersectionTime(testT);
|
||||
if ((t < pMaxDist) || t < (pMaxDist + epsilon))
|
||||
pMaxDist = t;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
134
src/shared/vmap/ShortVector.h
Normal file
134
src/shared/vmap/ShortVector.h
Normal file
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _SHORTVECTOR_H
|
||||
#define _SHORTVECTOR_H
|
||||
|
||||
#include <G3D/Vector3.h>
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
/**
|
||||
Vector with 16 bit fix point values 12.4 bit.
|
||||
*/
|
||||
|
||||
class ShortVector
|
||||
{
|
||||
private:
|
||||
short iX;
|
||||
short iY;
|
||||
short iZ;
|
||||
|
||||
const static short maxvalue = 0x7fff;
|
||||
const static short minvalue = -0x7fff;
|
||||
const static int fixpointdiv = 16;
|
||||
const static short fixpoint_maxvalue = maxvalue / fixpointdiv;
|
||||
const static short fixpoint_minvalue = minvalue / fixpointdiv;
|
||||
|
||||
inline short float2Short(float fv) const
|
||||
{
|
||||
short sv;
|
||||
debugAssert((fv <= fixpoint_maxvalue || fv >= 1000000) && (fv >= fixpoint_minvalue || fv <= -1000000));
|
||||
if(fv >= fixpoint_maxvalue)
|
||||
sv=maxvalue;
|
||||
else if(fv <= fixpoint_minvalue)
|
||||
sv=minvalue;
|
||||
else
|
||||
sv = (short) (fv * fixpointdiv + 0.5);
|
||||
return(sv);
|
||||
}
|
||||
inline float short2Float(short sv) const
|
||||
{
|
||||
float fv;
|
||||
if(sv >= maxvalue)
|
||||
fv=G3D::inf();
|
||||
else if(sv <= minvalue)
|
||||
fv=-G3D::inf();
|
||||
else
|
||||
fv = ((float)sv) / fixpointdiv;
|
||||
return fv;
|
||||
}
|
||||
|
||||
inline float getFX() const { return(short2Float(iX)); }
|
||||
inline float getFY() const { return(short2Float(iY)); }
|
||||
inline float getFZ() const { return(short2Float(iZ)); }
|
||||
public:
|
||||
inline ShortVector() {}
|
||||
inline ShortVector(const G3D::Vector3& pVector)
|
||||
{
|
||||
iX = float2Short(pVector.x);
|
||||
iY = float2Short(pVector.y);
|
||||
iZ = float2Short(pVector.z);
|
||||
}
|
||||
|
||||
inline ShortVector(float pX, float pY, float pZ)
|
||||
{
|
||||
iX = float2Short(pX);
|
||||
iY = float2Short(pY);
|
||||
iZ = float2Short(pZ);
|
||||
}
|
||||
inline ShortVector(short pX, short pY, short pZ)
|
||||
{
|
||||
iX = pX;
|
||||
iY = pY;
|
||||
iZ = pZ;
|
||||
}
|
||||
inline ShortVector(const ShortVector& pShortVector)
|
||||
{
|
||||
iX = pShortVector.iX;
|
||||
iY = pShortVector.iY;
|
||||
iZ = pShortVector.iZ;
|
||||
}
|
||||
|
||||
inline float getX() const { return(iX); }
|
||||
inline float getY() const { return(iY); }
|
||||
inline float getZ() const { return(iZ); }
|
||||
|
||||
inline G3D::Vector3 getVector3() const { return(G3D::Vector3(getFX(), getFY(), getFZ())); }
|
||||
|
||||
inline ShortVector min(const ShortVector pShortVector)
|
||||
{
|
||||
ShortVector result = pShortVector;
|
||||
if(pShortVector.iX > iX) { result.iX = iX; }
|
||||
if(pShortVector.iY > iY) { result.iY = iY; }
|
||||
if(pShortVector.iZ > iZ) { result.iZ = iZ; }
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline ShortVector max(const ShortVector pShortVector)
|
||||
{
|
||||
ShortVector result = pShortVector;
|
||||
if(pShortVector.iX < iX) { result.iX = iX; }
|
||||
if(pShortVector.iY < iY) { result.iY = iY; }
|
||||
if(pShortVector.iZ < iZ) { result.iZ = iZ; }
|
||||
return(result);
|
||||
}
|
||||
|
||||
inline bool operator==(const ShortVector& v) const
|
||||
{
|
||||
return (iX == v.iX && iY == v.iY && iZ == v.iZ);
|
||||
}
|
||||
|
||||
inline bool operator!=(const ShortVector& v) const
|
||||
{
|
||||
return !(iX == v.iX && iY == v.iY && iZ == v.iZ);
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
#endif
|
||||
248
src/shared/vmap/SubModel.cpp
Normal file
248
src/shared/vmap/SubModel.cpp
Normal file
|
|
@ -0,0 +1,248 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "SubModel.h"
|
||||
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
extern FILE *::g_df;
|
||||
#endif
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
|
||||
//==========================================================
|
||||
/**
|
||||
Functions to use ModelContainer with a AABSPTree
|
||||
*/
|
||||
unsigned int hashCode(const SubModel& pSm)
|
||||
{
|
||||
return pSm.getNTriangles();
|
||||
}
|
||||
|
||||
void getBounds(const SubModel& pSm, G3D::AABox& pAABox)
|
||||
{
|
||||
ShortBox box = pSm.getReletiveBounds();
|
||||
pAABox.set(box.getLo().getVector3()+pSm.getBasePosition(), box.getHi().getVector3()+pSm.getBasePosition());
|
||||
}
|
||||
|
||||
void getBounds(const SubModel* pSm, G3D::AABox& pAABox)
|
||||
{
|
||||
ShortBox box = pSm->getReletiveBounds();
|
||||
pAABox.set(box.getLo().getVector3()+pSm->getBasePosition(), box.getHi().getVector3()+pSm->getBasePosition());
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
//==========================================================
|
||||
//==========================================================
|
||||
//==========================================================
|
||||
SubModel::SubModel(unsigned int pNTriangles, TriangleBox *pTriangles, unsigned int pTrianglesPos, unsigned int pNNodes, TreeNode *pTreeNodes, unsigned int pNodesPos) :
|
||||
BaseModel(pNNodes, pTreeNodes, pNTriangles, pTriangles)
|
||||
{
|
||||
iTrianglesPos = pTrianglesPos;
|
||||
iNodesPos = pNodesPos;
|
||||
iHasInternalMemAlloc = false;
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
SubModel::~SubModel(void)
|
||||
{
|
||||
if(iHasInternalMemAlloc)
|
||||
{
|
||||
free();
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
bool SubModel::operator==(const SubModel& pSm2) const
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if(getNNodes() == pSm2.getNNodes() &&
|
||||
getNTriangles() == pSm2.getNTriangles() &&
|
||||
getBasePosition() == pSm2.getBasePosition() &&
|
||||
getNodesPos() == pSm2.getNodesPos() &&
|
||||
getTrianglesPos() == pSm2.getTrianglesPos())
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
//==========================================================
|
||||
|
||||
enum BIN_POSITIONS
|
||||
{
|
||||
BP_iNTriangles=8,
|
||||
BP_iNNodes=12,
|
||||
BP_iBasePosition=16,
|
||||
BP_iNodesPos=28,
|
||||
BP_iTrianglesPos=32,
|
||||
BP_iHasInternalMemAlloc=36,
|
||||
BP_iBox=38,
|
||||
};
|
||||
/**
|
||||
This is ugly, but due to compatibility and 64 bit support we have to do that ... sorry
|
||||
*/
|
||||
void SubModel::initFromBinBlock(void *pBinBlock)
|
||||
{
|
||||
iNTriangles = *((unsigned int *)(((char *) pBinBlock) + BP_iNTriangles));
|
||||
iNNodes = *((unsigned int *) (((char *) pBinBlock) + BP_iNNodes));
|
||||
iBasePosition = *((Vector3 *) (((char *) pBinBlock) + BP_iBasePosition));
|
||||
iNodesPos = *((unsigned int *) (((char *) pBinBlock) + BP_iNodesPos));
|
||||
iTrianglesPos = *((unsigned int *) (((char *) pBinBlock) + BP_iTrianglesPos));
|
||||
iHasInternalMemAlloc = *((bool *) (((char *) pBinBlock) + BP_iHasInternalMemAlloc));
|
||||
iBox = *((ShortBox *) (((char *) pBinBlock) + BP_iBox));
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
void SubModel::countNodesAndTriangles(AABSPTree<Triangle>::Node& pNode, int &pNNodes, int &pNTriabgles)
|
||||
{
|
||||
++pNNodes;
|
||||
pNTriabgles += pNode.valueArray.size();
|
||||
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
fprintf(::g_df, "Nodes: %d, Tris: %d\n",pNNodes, pNTriabgles);
|
||||
#endif
|
||||
|
||||
if(pNode.child[0] != 0)
|
||||
{
|
||||
countNodesAndTriangles(*pNode.child[0], pNNodes, pNTriabgles);
|
||||
}
|
||||
if(pNode.child[1] != 0)
|
||||
{
|
||||
countNodesAndTriangles(*pNode.child[1], pNNodes, pNTriabgles);
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
void SubModel::fillContainer(const AABSPTree<Triangle>::Node& pNode, int &pTreeNodePos, int &pTrianglePos, Vector3& pLo, Vector3& pHi)
|
||||
{
|
||||
TreeNode treeNode = TreeNode(pNode.valueArray.size(), pTrianglePos);
|
||||
treeNode.setSplitAxis(pNode.splitAxis);
|
||||
treeNode.setSplitLocation(pNode.splitLocation);
|
||||
|
||||
int currentTreeNodePos = pTreeNodePos++;
|
||||
|
||||
Vector3 lo = Vector3(inf(),inf(),inf());
|
||||
Vector3 hi = Vector3(-inf(),-inf(),-inf());
|
||||
|
||||
for(int i=0;i<pNode.valueArray.size(); i++)
|
||||
{
|
||||
G3D::_AABSPTree::Handle<Triangle>* h= pNode.valueArray[i];
|
||||
Triangle t = h->value;
|
||||
TriangleBox triangleBox = TriangleBox(t.vertex(0),t.vertex(1), t.vertex(2));
|
||||
lo = lo.min(triangleBox.getBounds().getLo().getVector3());
|
||||
hi = hi.max(triangleBox.getBounds().getHi().getVector3());
|
||||
|
||||
getTriangles()[pTrianglePos++] = triangleBox;
|
||||
}
|
||||
|
||||
if(pNode.child[0] != 0)
|
||||
{
|
||||
treeNode.setChildPos(0, pTreeNodePos);
|
||||
fillContainer(*pNode.child[0], pTreeNodePos, pTrianglePos, lo, hi);
|
||||
}
|
||||
if(pNode.child[1] != 0)
|
||||
{
|
||||
treeNode.setChildPos(1, pTreeNodePos);
|
||||
fillContainer(*pNode.child[1], pTreeNodePos, pTrianglePos, lo, hi);
|
||||
}
|
||||
|
||||
treeNode.setBounds(lo,hi);
|
||||
|
||||
// get absolute bounds
|
||||
pLo = pLo.min(lo);
|
||||
pHi = pHi.max(hi);
|
||||
|
||||
getTreeNodes()[currentTreeNodePos] = treeNode;
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
SubModel::SubModel(AABSPTree<Triangle> *pTree)
|
||||
{
|
||||
int nNodes, nTriangles;
|
||||
nNodes = nTriangles = 0;
|
||||
countNodesAndTriangles(*pTree->root, nNodes, nTriangles);
|
||||
|
||||
init(nNodes, nTriangles);
|
||||
|
||||
iTrianglesPos = 0; // this is the global array
|
||||
iNodesPos = 0; // this is the global array
|
||||
iHasInternalMemAlloc = true;
|
||||
int treeNodePos, trianglePos;
|
||||
treeNodePos = trianglePos = 0;
|
||||
|
||||
Vector3 lo = Vector3(inf(),inf(),inf());
|
||||
Vector3 hi = Vector3(-inf(),-inf(),-inf());
|
||||
|
||||
fillContainer(*pTree->root, treeNodePos, trianglePos, lo, hi);
|
||||
setReletiveBounds(lo, hi);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
#ifdef _DEBUG_VMAPS
|
||||
#ifndef gBoxArray
|
||||
extern Vector3 p1,p2,p3,p4,p5,p6,p7;
|
||||
extern Array<AABox>gBoxArray;
|
||||
extern Array<G3D::Triangle>gTriArray;
|
||||
extern int gCount1, gCount2, gCount3, gCount4;
|
||||
extern bool myfound;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//==========================================================
|
||||
void SubModel::intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& /*pOutLocation*/, G3D::Vector3& /*pOutNormal*/) const
|
||||
{
|
||||
NodeValueAccess<TreeNode, TriangleBox> vna = NodeValueAccess<TreeNode, TriangleBox>(getTreeNodes(), getTriangles());
|
||||
IntersectionCallBack<TriangleBox> intersectCallback;
|
||||
Ray relativeRay = Ray::fromOriginAndDirection(pRay.origin - getBasePosition(), pRay.direction);
|
||||
#ifdef _DEBUG_VMAPS
|
||||
//p6=getBasePosition();
|
||||
//gBoxArray.push_back(getAABoxBounds());
|
||||
#endif
|
||||
getTreeNode(0).intersectRay(relativeRay, intersectCallback, pMaxDist, vna, pStopAtFirstHit, false);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
bool SubModel::intersect(const G3D::Ray& pRay, float& pMaxDist) const
|
||||
{
|
||||
return BaseModel::intersect(getAABoxBounds(), pRay, pMaxDist);
|
||||
}
|
||||
|
||||
//==========================================================
|
||||
|
||||
template<typename RayCallback>
|
||||
void SubModel::intersectRay(const Ray& pRay, RayCallback& pIntersectCallback, float& pMaxDist, bool pStopAtFirstHit, bool intersectCallbackIsFast)
|
||||
{
|
||||
if(intersect(pRay, pMaxDist))
|
||||
{
|
||||
NodeValueAccess<TreeNode, TriangleBox> vna = NodeValueAccess<TreeNode, TriangleBox>(getTreeNodes(), getTriangles());
|
||||
IntersectionCallBack<TriangleBox> intersectCallback;
|
||||
getTreeNode(0).intersectRay(pRay, intersectCallback, pMaxDist, vna, pStopAtFirstHit, false);
|
||||
}
|
||||
}
|
||||
//==========================================================
|
||||
|
||||
}
|
||||
102
src/shared/vmap/SubModel.h
Normal file
102
src/shared/vmap/SubModel.h
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef _SUBMODEL_H
|
||||
#define _SUBMODEL_H
|
||||
|
||||
// load our modified version first !!
|
||||
#include "AABSPTree.h"
|
||||
|
||||
#include "ShortVector.h"
|
||||
#include "ShortBox.h"
|
||||
#include "TreeNode.h"
|
||||
#include "VMapTools.h"
|
||||
#include "BaseModel.h"
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
/**
|
||||
This is a balanced static BSP-Tree of triangles.
|
||||
The memory for the tree nodes and the triangles are managed by the ModelContainer.
|
||||
The exception to this is during the conversion of raw data info balanced BSP-Trees.
|
||||
During this conversion the memory management is done internally.
|
||||
*/
|
||||
class SubModel : public BaseModel
|
||||
{
|
||||
private:
|
||||
unsigned int iNodesPos;
|
||||
unsigned int iTrianglesPos;
|
||||
bool iHasInternalMemAlloc;
|
||||
ShortBox iBox;
|
||||
#ifdef _DEBUG_VIEW
|
||||
G3D::Array<TriangleBox *> iDrawBox;
|
||||
#endif
|
||||
public:
|
||||
SubModel() : BaseModel(){ };
|
||||
|
||||
SubModel(unsigned int pNTriangles, TriangleBox *pTriangles, unsigned int pTrianglesPos, unsigned int pNNodes, TreeNode *pTreeNodes, unsigned int pNodesPos);
|
||||
SubModel(G3D::AABSPTree<G3D::Triangle> *pTree);
|
||||
~SubModel(void);
|
||||
//Gets a 50 byte binary block
|
||||
void initFromBinBlock(void *pBinBlock);
|
||||
|
||||
void fillRenderArray(G3D::Array<TriangleBox> &pArray, const TreeNode* pTreeNode);
|
||||
|
||||
void countNodesAndTriangles(G3D::AABSPTree<G3D::Triangle>::Node& pNode, int &pNNodes, int &pNTriabgles);
|
||||
|
||||
void fillContainer(const G3D::AABSPTree<G3D::Triangle>::Node& pNode, int &pTreeNodePos, int &pTrianglePos, G3D::Vector3& pLo, G3D::Vector3& pHi);
|
||||
|
||||
inline const ShortBox& getReletiveBounds() const { return(iBox); }
|
||||
|
||||
inline void setReletiveBounds(const ShortVector& lo, const ShortVector& hi) { iBox.setLo(lo); iBox.setHi(hi); }
|
||||
|
||||
inline const G3D::AABox getAABoxBounds() const { return(G3D::AABox(iBox.getLo().getVector3() + getBasePosition(), iBox.getHi().getVector3()+ getBasePosition())); }
|
||||
|
||||
// get start pos bases on the global array
|
||||
inline TriangleBox const* getTriangles() const { return &BaseModel::getTriangle(iTrianglesPos); }
|
||||
inline TriangleBox * getTriangles() { return &BaseModel::getTriangle(iTrianglesPos); }
|
||||
|
||||
// get start pos bases on the global array
|
||||
inline TreeNode const* getTreeNodes() const { return &BaseModel::getTreeNode(iNodesPos); }
|
||||
inline TreeNode * getTreeNodes() { return &BaseModel::getTreeNode(iNodesPos); }
|
||||
|
||||
// internal method usign internal offset
|
||||
inline const TreeNode& getTreeNode(int pPos) const { return(SubModel::getTreeNodes()[pPos]); }
|
||||
|
||||
// internal method usign internal offset
|
||||
inline const TriangleBox& getTriangle(int pPos) const { return(SubModel::getTriangles()[pPos]); }
|
||||
|
||||
inline unsigned int getNodesPos() const { return(iNodesPos); }
|
||||
inline unsigned int getTrianglesPos() const { return(iTrianglesPos); }
|
||||
|
||||
//unsigned int hashCode() { return (getBasePosition() * getNTriangles()).hashCode(); }
|
||||
|
||||
void intersect(const G3D::Ray& pRay, float& pMaxDist, bool pStopAtFirstHit, G3D::Vector3& pOutLocation, G3D::Vector3& pOutNormal) const;
|
||||
bool intersect(const G3D::Ray& pRay, float& pMaxDist) const;
|
||||
template<typename RayCallback>
|
||||
void intersectRay(const G3D::Ray& ray, RayCallback& intersectCallback, float& distance, bool pStopAtFirstHit, bool intersectCallbackIsFast = false);
|
||||
bool operator==(const SubModel& pSm2) const;
|
||||
unsigned int hashCode() const { return BaseModel::getNTriangles(); }
|
||||
};
|
||||
|
||||
unsigned int hashCode(const SubModel& pSm);
|
||||
void getBounds(const SubModel& pSm, G3D::AABox& pAABox);
|
||||
void getBounds(const SubModel* pSm, G3D::AABox& pAABox);
|
||||
//====================================
|
||||
} // VMAP
|
||||
#endif
|
||||
571
src/shared/vmap/TileAssembler.cpp
Normal file
571
src/shared/vmap/TileAssembler.cpp
Normal file
|
|
@ -0,0 +1,571 @@
|
|||
/*
|
||||
* Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <G3D/Vector3.h>
|
||||
#include <G3D/Triangle.h>
|
||||
|
||||
#include "TileAssembler.h"
|
||||
#include "CoordModelMapping.h"
|
||||
#include "ModelContainer.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
FILE *g_df = NULL;
|
||||
#endif
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
namespace VMAP
|
||||
{
|
||||
//=================================================================
|
||||
|
||||
Vector3 ModelPosition::transform(const Vector3& pIn) const
|
||||
{
|
||||
//return(pIn);
|
||||
Vector3 out = pIn * iScale;
|
||||
out = izMatrix * out;
|
||||
out = ixMatrix * out;
|
||||
out = iyMatrix * out;
|
||||
return(out);
|
||||
|
||||
}
|
||||
//=================================================================
|
||||
|
||||
TileAssembler::TileAssembler(const std::string& pSrcDirName, const std::string& pDestDirName)
|
||||
{
|
||||
iCurrentUniqueNameId = 0;
|
||||
iFilterMethod = NULL;
|
||||
iSrcDir = pSrcDirName;
|
||||
iDestDir = pDestDirName;
|
||||
//mkdir(iDestDir);
|
||||
init();
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
TileAssembler::~TileAssembler()
|
||||
{
|
||||
delete iCoordModelMapping;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
void TileAssembler::init()
|
||||
{
|
||||
iCoordModelMapping = new CoordModelMapping();
|
||||
addWorldAreaMapId(0); //Azeroth
|
||||
addWorldAreaMapId(1); //Kalimdor
|
||||
addWorldAreaMapId(530); //Expansion01
|
||||
}
|
||||
//=================================================================
|
||||
|
||||
std::string getModNameFromModPosName(const std::string& pModPosName)
|
||||
{
|
||||
|
||||
size_t spos = pModPosName.find_first_of('#');
|
||||
std::string modelFileName = pModPosName.substr(0,spos);
|
||||
return(modelFileName);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
unsigned int TileAssembler::getUniqueNameId(const std::string pName)
|
||||
{
|
||||
unsigned int result;
|
||||
|
||||
if(!iUniqueNameIds.containsKey(pName))
|
||||
{
|
||||
++iCurrentUniqueNameId;
|
||||
iUniqueNameIds.set(pName, iCurrentUniqueNameId);
|
||||
}
|
||||
result = iUniqueNameIds.get(pName);
|
||||
return result;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
std::string TileAssembler::getDirEntryNameFromModName(unsigned int pMapId, const std::string& pModPosName)
|
||||
{
|
||||
size_t spos;
|
||||
char buffer[20];
|
||||
|
||||
std::string modelFileName = getModNameFromModPosName(pModPosName);
|
||||
//std::string fext = pModPosName.substr(modelFileName.length(),pModPosName.length());
|
||||
unsigned int fextId = getUniqueNameId(pModPosName);
|
||||
sprintf(buffer, "_%07d",fextId);
|
||||
std::string fext(buffer);
|
||||
spos = modelFileName.find_last_of('/');
|
||||
std::string fname = modelFileName.substr(spos+1, modelFileName.length());
|
||||
spos = fname.find_last_of('.');
|
||||
fname = fname.substr(0,spos);
|
||||
sprintf(buffer, "%03u", pMapId);
|
||||
std::string dirEntry(buffer);
|
||||
dirEntry.append("_");
|
||||
dirEntry.append(fname);
|
||||
dirEntry.append(fext);
|
||||
dirEntry.append(".vmap");
|
||||
return(dirEntry);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
void emptyArray(Array<ModelContainer*>& mc)
|
||||
{
|
||||
int no=mc.size();
|
||||
while(no > 0)
|
||||
{
|
||||
--no;
|
||||
delete mc[no];
|
||||
mc.remove(no);
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
bool TileAssembler::convertWorld()
|
||||
{
|
||||
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
# ifdef _DEBUG
|
||||
::g_df = fopen("../TileAssembler_debug.txt", "wb");
|
||||
# else
|
||||
::g_df = fopen("../TileAssembler_release.txt", "wb");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
bool result = true;
|
||||
std::string fname = iSrcDir;
|
||||
fname.append("/");
|
||||
fname.append("dir");
|
||||
iCoordModelMapping->setModelNameFilterMethod(iFilterMethod);
|
||||
iCoordModelMapping->readCoordinateMapping(fname);
|
||||
|
||||
Array<unsigned int> mapIds = iCoordModelMapping->getMaps();
|
||||
if(mapIds.size() == 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
for(int i=0; i<mapIds.size() && result; ++i)
|
||||
{
|
||||
unsigned int mapId = mapIds[i];
|
||||
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
if(mapId == 0) // "Azeroth" just for debug
|
||||
{
|
||||
for(int x=28; x<29 && result; ++x) //debug
|
||||
{
|
||||
for(int y=28; y<29 && result; ++y)
|
||||
{
|
||||
#else
|
||||
// ignore DeeprunTram (369) it is too large for short vector and not important
|
||||
// ignore test (13), Test (29) , development (451)
|
||||
if(mapId != 369 && mapId != 13 && mapId != 29 && mapId != 451)
|
||||
{
|
||||
for(int x=0; x<66 && result; ++x)
|
||||
{
|
||||
for(int y=0; y<66 && result; ++y)
|
||||
{
|
||||
#endif
|
||||
Array<ModelContainer*> mc;
|
||||
std::string dirname;
|
||||
char buffer[100];
|
||||
if(iCoordModelMapping->isWorldAreaMap(mapId) && x<65 && y<65)
|
||||
{
|
||||
sprintf(buffer, "%03u_%d_%d",mapId,y,x); // Let's flip x and y here
|
||||
dirname = std::string(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprintf(buffer, "%03u",mapId);
|
||||
dirname = std::string(buffer);
|
||||
}
|
||||
result = fillModelContainerArray(dirname, mapId, x, y, mc);
|
||||
emptyArray(mc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
if(::g_df) fclose(::g_df);
|
||||
#endif
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
bool TileAssembler::fillModelContainerArray(const std::string& pDirFileName, unsigned int pMapId, int pXPos, int pYPos, Array<ModelContainer*>& pMC)
|
||||
{
|
||||
bool result = true;
|
||||
ModelContainer* modelContainer;
|
||||
|
||||
NameCollection nameCollection = iCoordModelMapping->getFilenamesForCoordinate(pMapId, pXPos, pYPos);
|
||||
if(nameCollection.size() > 0)
|
||||
{
|
||||
result = false;
|
||||
char dirfilename[500];
|
||||
sprintf(dirfilename,"%s/%s.vmdir",iDestDir.c_str(),pDirFileName.c_str());
|
||||
FILE *dirfile = fopen(dirfilename, "ab");
|
||||
if(dirfile)
|
||||
{
|
||||
result = true;
|
||||
char destnamebuffer[500];
|
||||
char fullnamedestnamebuffer[500];
|
||||
if(nameCollection.iMainFiles.size() >0)
|
||||
{
|
||||
sprintf(destnamebuffer,"%03u_%i_%i.vmap",pMapId, pYPos, pXPos); // flip it here too
|
||||
std::string checkDoubleStr = std::string(dirfilename);
|
||||
checkDoubleStr.append("##");
|
||||
checkDoubleStr.append(std::string(destnamebuffer));
|
||||
// Check, if same file already is in the same dir file
|
||||
if(!iCoordModelMapping->isAlreadyProcessedSingleFile(checkDoubleStr))
|
||||
{
|
||||
iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
|
||||
fprintf(dirfile, "%s\n",destnamebuffer);
|
||||
sprintf(fullnamedestnamebuffer,"%s/%s",iDestDir.c_str(),destnamebuffer);
|
||||
modelContainer = processNames(nameCollection.iMainFiles, fullnamedestnamebuffer);
|
||||
if(modelContainer)
|
||||
{
|
||||
pMC.append(modelContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// process the large singe files
|
||||
int pos = 0;
|
||||
while(result && (pos < nameCollection.iSingeFiles.size()))
|
||||
{
|
||||
std::string destFileName = iDestDir;
|
||||
destFileName.append("/");
|
||||
std::string dirEntryName = getDirEntryNameFromModName(pMapId,nameCollection.iSingeFiles[pos]);
|
||||
std::string checkDoubleStr = std::string(dirfilename);
|
||||
checkDoubleStr.append("##");
|
||||
checkDoubleStr.append(nameCollection.iSingeFiles[pos]);
|
||||
// Check, if same file already is in the same dir file
|
||||
if(!iCoordModelMapping->isAlreadyProcessedSingleFile(checkDoubleStr))
|
||||
{
|
||||
iCoordModelMapping->addAlreadyProcessedSingleFile(checkDoubleStr);
|
||||
fprintf(dirfile, "%s\n",dirEntryName.c_str());
|
||||
destFileName.append(dirEntryName);
|
||||
|
||||
Array<std::string> positionarray;
|
||||
positionarray.append(nameCollection.iSingeFiles[pos]);
|
||||
|
||||
if(!iCoordModelMapping->isAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]))
|
||||
{
|
||||
modelContainer = processNames(positionarray, destFileName.c_str());
|
||||
iCoordModelMapping->addAlreadyProcessedSingleFile(nameCollection.iSingeFiles[pos]);
|
||||
if(modelContainer)
|
||||
{
|
||||
pMC.append(modelContainer);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
fclose(dirfile);
|
||||
}
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
void removeEntriesFromTree(AABSPTree<SubModel *>* pTree)
|
||||
{
|
||||
Array<SubModel *> submodelArray;
|
||||
pTree->getMembers(submodelArray);
|
||||
int no = submodelArray.size();
|
||||
while(no > 0)
|
||||
{
|
||||
--no;
|
||||
delete submodelArray[no];
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
ModelContainer* TileAssembler::processNames(const Array<std::string>& pPositions, const char* pDestFileName)
|
||||
{
|
||||
ModelContainer *modelContainer = 0;
|
||||
|
||||
Vector3 basepos = Vector3(0,0,0);
|
||||
AABSPTree<SubModel *>* mainTree = new AABSPTree<SubModel *>();
|
||||
|
||||
int pos = 0;
|
||||
|
||||
bool result = true;
|
||||
while(result && (pos < pPositions.size()))
|
||||
{
|
||||
std::string modelPosString = pPositions[pos];
|
||||
std::string modelFileName = getModNameFromModPosName(modelPosString);
|
||||
|
||||
if(!fillModelIntoTree(mainTree, basepos, modelPosString, modelFileName))
|
||||
{
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
++pos;
|
||||
}
|
||||
if(result && mainTree->size() > 0)
|
||||
{
|
||||
mainTree->balance();
|
||||
modelContainer = new ModelContainer(mainTree);
|
||||
modelContainer->writeFile(pDestFileName);
|
||||
}
|
||||
removeEntriesFromTree(mainTree);
|
||||
|
||||
delete mainTree;
|
||||
|
||||
return(modelContainer);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
bool TileAssembler::readRawFile(std::string& pModelFilename, ModelPosition& pModelPosition, AABSPTree<SubModel *> *pMainTree)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
std::string filename = iSrcDir;
|
||||
if(filename.length() >0)
|
||||
filename.append("/");
|
||||
filename.append(pModelFilename);
|
||||
FILE *rf = fopen(filename.c_str(), "rb");
|
||||
if(!rf)
|
||||
{
|
||||
// depending on the extractor version, the data could be located in the root dir
|
||||
std::string baseModelFilename = pModelFilename.substr((pModelFilename.find_first_of("/")+1),pModelFilename.length());
|
||||
filename = iSrcDir;
|
||||
if(filename.length() >0)
|
||||
filename.append("/");
|
||||
filename.append(baseModelFilename);
|
||||
rf = fopen(filename.c_str(), "rb");
|
||||
}
|
||||
char ident[8];
|
||||
|
||||
int trianglecount =0;
|
||||
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
int startgroup = 0; //2;
|
||||
int endgroup = INT_MAX; //2;
|
||||
fprintf(::g_df,"-------------------------------------------------\n");
|
||||
fprintf(::g_df,"%s\n", pModelFilename.c_str());
|
||||
fprintf(::g_df,"-------------------------------------------------\n");
|
||||
#else
|
||||
int startgroup = 0;
|
||||
int endgroup = INT_MAX;
|
||||
#endif
|
||||
|
||||
if(rf)
|
||||
{
|
||||
if(fread(&ident, 8, 1, rf) != 1) { fclose(rf); return(false); }
|
||||
if(strcmp(ident, "VMAP001") == 0)
|
||||
{
|
||||
// OK, do nothing
|
||||
}
|
||||
else if(strcmp(ident, "VMAP002") == 0)
|
||||
{
|
||||
// we have to read one int. This is needed during the export and we have to skip it here
|
||||
int tempNVectors;
|
||||
if(fread(&tempNVectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// wrong version
|
||||
fclose(rf);
|
||||
return(false);
|
||||
}
|
||||
G3D::uint32 groups;
|
||||
char blockId[5];
|
||||
blockId[4] = 0;
|
||||
int blocksize;
|
||||
|
||||
if(fread(&groups, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
|
||||
for(int g=0;g<(int)groups;g++)
|
||||
{
|
||||
// group MUST NOT have more then 65536 indexes !! Array will have a problem with that !! (strange ...)
|
||||
Array<int> tempIndexArray;
|
||||
Array<Vector3> tempVertexArray;
|
||||
|
||||
AABSPTree<Triangle> *gtree = new AABSPTree<Triangle>();
|
||||
|
||||
G3D::uint32 flags;
|
||||
if(fread(&flags, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
|
||||
G3D::uint32 branches;
|
||||
if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
|
||||
if(strcmp(blockId, "GRP ") != 0) { fclose(rf); return(false); }
|
||||
if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
if(fread(&branches, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
for(int b=0;b<(int)branches; b++)
|
||||
{
|
||||
G3D::uint32 indexes;
|
||||
// indexes for each branch (not used jet)
|
||||
if(fread(&indexes, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
}
|
||||
|
||||
// ---- indexes
|
||||
if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
|
||||
if(strcmp(blockId, "INDX") != 0) { fclose(rf); return(false); }
|
||||
if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
unsigned int nindexes;
|
||||
if(fread(&nindexes, sizeof(G3D::uint32), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
if(nindexes >0)
|
||||
{
|
||||
unsigned short *indexarray = new unsigned short[nindexes*sizeof(unsigned short)];
|
||||
if(fread(indexarray, sizeof(unsigned short), nindexes, rf) != nindexes) { fclose(rf); return(false); }
|
||||
for(int i=0;i<(int)nindexes; i++)
|
||||
{
|
||||
unsigned short val = indexarray[i];
|
||||
tempIndexArray.append(val);
|
||||
}
|
||||
delete indexarray;
|
||||
}
|
||||
|
||||
// ---- vectors
|
||||
if(fread(&blockId, 4, 1, rf) != 1) {fclose(rf); return(false); }
|
||||
if(strcmp(blockId, "VERT") != 0) { fclose(rf); return(false); }
|
||||
if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
unsigned int nvectors;
|
||||
if(fread(&nvectors, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
float *vectorarray = 0;
|
||||
if(nvectors >0)
|
||||
{
|
||||
vectorarray = new float[nvectors*sizeof(float)*3];
|
||||
if(fread(vectorarray, sizeof(float)*3, nvectors, rf) != nvectors) { fclose(rf); return(false); }
|
||||
}
|
||||
// ----- liquit
|
||||
if(flags & 1)
|
||||
{
|
||||
// we have liquit -> not handled yet ... skip
|
||||
if(fread(&blockId, 4, 1, rf) != 1) { fclose(rf); return(false); }
|
||||
if(strcmp(blockId, "LIQU") != 0) { fclose(rf); return(false); }
|
||||
if(fread(&blocksize, sizeof(int), 1, rf) != 1) { fclose(rf); return(false); }
|
||||
fseek(rf, blocksize, SEEK_CUR);
|
||||
}
|
||||
|
||||
for(unsigned int i=0, indexNo=0; indexNo<nvectors; indexNo++)
|
||||
{
|
||||
Vector3 v = Vector3(vectorarray[i+2], vectorarray[i+1], vectorarray[i+0]);
|
||||
i+=3;
|
||||
v = pModelPosition.transform(v);
|
||||
|
||||
float swapy = v.y;
|
||||
v.y = v.x;
|
||||
v.x = swapy;
|
||||
|
||||
tempVertexArray.append(v);
|
||||
}
|
||||
|
||||
// ---- calculate triangles
|
||||
int rest = nindexes%3;
|
||||
if(rest != 0)
|
||||
{
|
||||
nindexes -= rest;
|
||||
}
|
||||
|
||||
for(unsigned int i=0;i<(nindexes);)
|
||||
{
|
||||
Triangle t = Triangle(tempVertexArray[tempIndexArray[i+2]], tempVertexArray[tempIndexArray[i+1]], tempVertexArray[tempIndexArray[i+0]] );
|
||||
i+=3;
|
||||
++trianglecount;
|
||||
if(g>= startgroup && g <= endgroup)
|
||||
{
|
||||
gtree->insert(t);
|
||||
}
|
||||
}
|
||||
|
||||
if(vectorarray != 0)
|
||||
{
|
||||
delete vectorarray;
|
||||
}
|
||||
|
||||
if(gtree->size() >0)
|
||||
{
|
||||
gtree->balance();
|
||||
SubModel *sm = new SubModel(gtree);
|
||||
#ifdef _ASSEMBLER_DEBUG
|
||||
if(::g_df) fprintf(::g_df,"group trianglies: %d, Tris: %d, Nodes: %d, gtree.triangles: %d\n", g, sm->getNTriangles(), sm->getNNodes(), gtree->memberTable.size());
|
||||
if(sm->getNTriangles() != gtree->memberTable.size())
|
||||
{
|
||||
if(::g_df) fprintf(::g_df,"ERROR !!!! group trianglies: %d, Tris: %d, Nodes: %d, gtree.triangles: %d\n", g, sm->getNTriangles(), sm->getNNodes(), gtree->memberTable.size());
|
||||
}
|
||||
#endif
|
||||
sm->setBasePosition(pModelPosition.iPos);
|
||||
pMainTree->insert(sm);
|
||||
}
|
||||
delete gtree;
|
||||
}
|
||||
fclose(rf);
|
||||
result = true;
|
||||
}
|
||||
return(result);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
|
||||
bool TileAssembler::fillModelIntoTree(AABSPTree<SubModel *> *pMainTree, const Vector3& pBasePos, std::string& pPos, std::string& pModelFilename)
|
||||
{
|
||||
bool result = false;
|
||||
ModelPosition modelPosition;
|
||||
getModelPosition(pPos, modelPosition);
|
||||
// all should be relative to object base position
|
||||
modelPosition.moveToBasePos(pBasePos);
|
||||
|
||||
modelPosition.init();
|
||||
|
||||
if(readRawFile(pModelFilename, modelPosition, pMainTree))
|
||||
{
|
||||
result = true;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
void TileAssembler::getModelPosition(std::string& pPosString, ModelPosition& pModelPosition)
|
||||
{
|
||||
float vposarray[3];
|
||||
float vdirarray[3];
|
||||
float scale;
|
||||
|
||||
size_t spos = pPosString.find_first_of('#');
|
||||
std::string stripedPosString = pPosString.substr(spos+1,pPosString.length());
|
||||
|
||||
sscanf(stripedPosString.c_str(), "%f,%f,%f_%f,%f,%f_%f",
|
||||
&vposarray[0],&vposarray[1],&vposarray[2],
|
||||
&vdirarray[0],&vdirarray[1],&vdirarray[2],
|
||||
&scale);
|
||||
|
||||
pModelPosition.iPos = Vector3(vposarray[0], vposarray[1], vposarray[2]);
|
||||
pModelPosition.iDir = Vector3(vdirarray[0], vdirarray[1], vdirarray[2]);
|
||||
pModelPosition.iScale = scale;
|
||||
|
||||
}
|
||||
//==========================================
|
||||
|
||||
} // VMAP
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue