/** @file Utility.h
@brief
* Copyright (c) 2007,第九城市游戏研发中心
* All rights reserved.
*
* 当前版本:
* 作 者:zhangsongwei
* 完成日期:2007-11-26
*
* 取代版本:
* 作 者:
* 完成日期:
*/
#ifndef UTILITY_H
#define UTILITY_H
#include
#include
#include
#include "aceall.h"
#define AI_SUP_CODE //AI支持相关代码;
#define OPEN_PUNISHMENT //天谴相关代码
#define PUNISHMENT_SKILL_ID 99999999 //天谴固定技能编号
#define OPEN_PET //开启宠物
#define ANTI_ADDICTION //开启防沉迷
#define ITEM_NPC
#define NEW_MONSTER_INFO //使用存于怪物身上的怪物信息,而不是每次填,orgin by hyn,bug修改 by dzj 10.03.17
//组队共享型任务
#define TEAM_SHARE_TASK
#ifdef TEAM_SHARE_TASK
#define TEAM_MAX_TASK 5
#endif
#include "../Test/testthreadque_wait/dslock.h"
#ifdef ACE_WIN32
#define USE_DSIOCP
#endif //ACE_WIN32
#ifndef ACE_WIN32
//linux下开启监控;
//#define TOOL_MONITOR //史亚征监控模块;
//由makefile定义,#define DS_EPOLL //使用新写的epoll实现及对应框架;
#endif //ACE_WIN32
#define PET_SKILL_SHOP //宠物技能商店
#define MAP_SRV_PLAYERNUM_MAX 3000
#define STAGE_MAP_SCRIPT //是否开启关卡地图;
#define LEVELUP_SCRIPT //是否开启升级脚本
#define NEW_NPC_INTERFACE //NPC的新任务接口
//#define TEST_CONCENTRATE //测试集聚情形;
//#define PRINT_PKGNUM //跟踪发包数量;
#define GROUP_NOTI //对gate广播;
#define USE_LOG
#define WAIT_QUEUE
#define NEW_INVITE_INFO //新叹号规则的
#define AUTO_EXP_UNIT //自适应调整每次的遍历数目;
#define NEW_SKILL_SYS //新技能体系
#ifdef AUTO_EXP_UNIT
///调整遍历数,得到本次应遍历的元素数目, by dzj, 09.02.07;
inline void AutoExpNumCal( const int passedtime/*本次大循环以来,逝去的毫秒数*/, const int containersize/*待遍历容器大小*/, int& expnum/*各小循环应遍历的元素数目*/
, int& loopexped/*本次大循环以来按expnum已遍历的元素数*/, int& rstexpnum/*本次小循环应遍历元素数*/, bool& isupdatelasttime/*本轮是否更新用于计算passedtime的上次时刻*/ )
{
if ( passedtime < 10 )
{
//精度小于10ms,视为0,小循环;
rstexpnum = expnum;//本次遍历数;
loopexped += rstexpnum;//小循环已遍历数++;
isupdatelasttime = false;//小循环,不更新用于计算大循环时间的起始时刻;
return;
}
//大循环
//估计期望时间段内可以有几次大循环;
int times = 500 / passedtime;
if ( times <=0 )
{
times = 1;//防止(passedtime > 500);
}
//根据容器大小计算每次大循环应该遍历多少个元素;
int bigloopexpnum = containersize / times;
if ( bigloopexpnum <= loopexped )
{
//在各次小循环中已经遍历完了大循环应遍历的元素数目;
rstexpnum = 0;//本次无需遍历更多元素;
--expnum;//每次可以少遍历些元素;
if ( expnum <= 0 )
{
expnum = 1;//最少遍历一个;
}
} else {
//各次小循环未遍历足够,剩余了部分至此最后时刻遍历;
rstexpnum = bigloopexpnum - loopexped;//大循环应遍历数-本次大循环各小循环已遍历数=大循环结束前应遍历元素数;
++expnum;//每次小循环可以多遍历些元素,将最后一次的遍历数分些到前面的小循环中去;
if ( expnum > bigloopexpnum )
{
expnum = bigloopexpnum;
}
}
loopexped = 0;//本次大循环以来按expnum已遍历的元素数清零;
isupdatelasttime = true;//更新大循环计算起始时刻;
return;
}
#else //AUTO_EXP_UNIT
#define EXPLORE_UNIT_PROP 18 //分块遍历的比例,对于怪物AI以及移动玩家,每次只遍历其中的1/EXPLORE_UNIT_PROP;
#endif //AUTO_EXP_UNIT
#ifdef WIN32
#include
#endif //WIN32
extern bool g_isGlobeStop;
//交互式中止进程执行
void SetTSTP();
///取当前时间;
void GetCurTime( int& cyear/*年*/, int& cmon/*月*/, int& cmday/*日*/
, int& chour/*时*/, int& cmin/*分*/, int& csec/*秒*/, int& cwday/*星期*/
, int& cmsec/*毫秒*/ );
#ifdef ACE_WIN32
#else //ACE_WIN32
#define DWORD_PTR unsigned long
#endif //ACE_WIN32
#define ATTACK_ADJUST 2
#define ROLE_INIT_SPEED 4.0f
#define SP_POWER_PER_ATTACK 10
#ifdef ACE_WIN32
//向char[]型数组中拷贝字符串,注意不能用于向char*目标拷贝,因为sizeof会失去作用;
#define SafeStrCpy( arrDst, arrSrc )\
{\
if ( NULL != arrSrc )\
{\
if ( sizeof(arrDst) > strlen(arrSrc) )\
{\
memset( arrDst, 0, sizeof(arrDst) );\
strcpy_s( arrDst, sizeof(arrDst), arrSrc );\
}\
}\
};
#else //ACE_WIN32
//向char[]型数组中拷贝字符串,注意不能用于向char*目标拷贝,因为sizeof会失去作用;
#define SafeStrCpy( arrDst, arrSrc )\
{\
if ( NULL != arrSrc )\
{\
if ( sizeof(arrDst) > strlen(arrSrc) )\
{\
memset( arrDst, 0, sizeof(arrDst) );\
strcpy( arrDst, arrSrc );\
}\
}\
};
#endif //ACE_WIN32
//获取数组的大小,避免越界
#define ARRAY_SIZE(x) ( sizeof(x)/sizeof(x[0]) )
#define SAFE_SUB( value, subVal) \
if( subVal > value ){\
value = 0;}\
else{\
value -= subVal;\
}
//////////////////////////////////////////////////////////////////////////////////////
//memory leak detect, added by dzj, 08.01.04
#ifdef ACE_WIN32
#ifdef _DEBUG
//#ifdef new
// #undef new
//#endif //new
//#include "ace/Thread_Mutex.h"
//extern ACE_Thread_Mutex g_MemoryAllocLock;
#define _CRTDBG_MAP_ALLOC
#include
#include
//在另建的测试工程里需要定义new操作符以及使用_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF )
//但在现项目中不需要也可以,目前不知道为什么,也许和ACE的使用有关系,但不确定
//void* __cdecl operator new( size_t nSize, const char* lpszFileName, int nLine );
#define NEW new(__FILE__, __LINE__) //直接使用new定义有编译错误解决不了,虽然在另建的工程中定义new操作符后可以定义new
//#define new new(__FILE__, __LINE__)
#else //_DEBUG
#define NEW new
#endif //_DEBUG
#else //ACE_WIN32
#define NEW new
#endif //ACE_WIN32
//////////////////////////////////////////////////////////////////////////////////////
///////////////////////////// log macros /////////////////////////////////////////////
#define DEBUG_PREFIX ACE_TEXT("[DEBUG]-[%t]-[%D]>>> ")
#define INFO_PREFIX ACE_TEXT("[INFO]-[%t]-[%D]>>> ")
#define NOTICE_PREFIX ACE_TEXT("[NOTICE]-[%t]-[%D]>>> ")
#define WARNING_PREFIX ACE_TEXT("[WARNING]-[%t]-[%D]>>> ")
#define ERROR_PREFIX ACE_TEXT("[ERROR]-[%t]-[%D]>>>")
#define CRITICAL_PREFIX ACE_TEXT("[CRITICAL]-[%t]-[%D]>>> ")
#define ALERT_PREFIX ACE_TEXT("[ALERT]-[%t]-[%D]>>> ")
#define EMERGENCY_PREFIX ACE_TEXT("[EMERGENCY]-[%t]-[%D]>>> ")
#define DEBUG_PREFIX_DAY ACE_TEXT("[DEBUG]-[%t]-[%D][%T]>>> ")
//#define USE_LOG //是否开启日志
#ifdef USE_LOG
#define D_FORCE(...) ACE_DEBUG(( LM_INFO, INFO_PREFIX __VA_ARGS__ ))
#define D_DEBUG(...) ACE_DEBUG(( LM_DEBUG, DEBUG_PREFIX __VA_ARGS__ ))
#define D_INFO(...) ACE_DEBUG(( LM_INFO, INFO_PREFIX __VA_ARGS__ ))
#define D_NOTICE(...) ACE_DEBUG(( LM_NOTICE, NOTICE_PREFIX __VA_ARGS__ ))
#define D_WARNING_DAY(...) ACE_DEBUG(( LM_DEBUG, DEBUG_PREFIX_DAY __VA_ARGS__ ))
#define D_WARNING(...) ACE_DEBUG(( LM_WARNING, WARNING_PREFIX __VA_ARGS__ ))
#define D_ERROR(...) ACE_DEBUG(( LM_ERROR, ERROR_PREFIX __VA_ARGS__ ))
#define D_CRITICAL(...) ACE_DEBUG(( LM_CRITICAL, CRITICAL_PREFIX __VA_ARGS__ ))
#define D_ALERT(...) ACE_DEBUG(( LM_ALERT, ALERT_PREFIX __VA_ARGS__ ))
#define D_EMERGENCY(...) ACE_DEBUG(( LM_EMERGENCY, EMERGENCY_PREFIX __VA_ARGS__ ))
#else //USE_LOG
#define D_FORCE(...) ACE_DEBUG(( LM_INFO, INFO_PREFIX __VA_ARGS__ ))
#define D_DEBUG(...)
#define D_INFO(...)
#define D_NOTICE(...)
#define D_WARNING_DAY(...)
#define D_WARNING(...)
#define D_ERROR(...)
#define D_CRITICAL(...)
#define D_ALERT(...)
#define D_EMERGENCY(...)
#endif //USE_LOG
#define RAND ( (unsigned long) ( ( (rand()<<15) | rand()) ) )
#define STRING_TO_NUM(pszString) ((pszString) == NULL ? 0 : atoi(pszString))
#define GEN_DOUBLE_WORD(highWord, lowWord) (unsigned int)((unsigned short)(lowWord) | ((unsigned short)(highWord) << 16))
#define GET_LOW_WORD(dw) (unsigned short)(dw)
#define GET_HIGH_WORD(dw) ((unsigned short)(((unsigned int)(dw) >> 16) & 0xFFFF) )
bool RandRate(float fRate);
int RandNumber(int, int);
bool ReadVersion(const char* pszFileName);
extern char g_szVersion[256]; //版本信息记录
/// 日志设置
extern int g_iLogType;
extern int g_iDaemon;
int Print_usage (int argc, ACE_TCHAR *argv[]);
int Parse_args(int argc, ACE_TCHAR *argv[]);
int SetDaemon(int iDaemon);
int SetLog(const char* pszlogFile, int iLogType);
// 异常记录
class CLogException
{
friend class ACE_Singleton;
private:
CLogException(void);
~CLogException(void);
public:
/// 记录日志
int Log(const char *pszFmt, ...);
private:
/// 检查目录
bool CheckDirectory(const char *pszDirName);
/// 创建目录
bool CheckFile(const char *pszFileName);
/// 检查文件
bool CreateDirectory(const char *pszDirName);
/// 创建文件
bool CreateFile(const char *pszFileName);
private:
/// 目录已创建?
bool m_bDir;
/// 当前打开文件
FILE *m_pFile;
/// 当前时间
char m_szCurrHour[11];
/// 锁
ACE_Thread_Mutex m_lock;
};
typedef ACE_Singleton CLogExceptionSingle;
///////////////////////////// exception handle macros ////////////////////////////////////
//使用信号转异常后,不再使用此宏,by dzj, 09.09.02,#define USE_TRY
#ifdef USE_TRY
#define TRY_BEGIN do { try {
#define TRY_END \
} catch (...) {\
CLogExceptionSingle::instance()->Log( "异常:%s:%d\n", __FILE__, __LINE__ );\
};\
}while (0);
#else //USE_TRY
#define TRY_BEGIN
#define TRY_END
#endif //USE_TRY
/*memset*/
#define StructMemSet( dstStruct, setVal, preferSize )\
{\
if ( sizeof(void*) == sizeof(dstStruct) )\
{\
/*D_DEBUG( "%s:%d,memset tgt pointer?\n", __FILE__, __LINE__ );*/\
}\
if ( (unsigned int)(preferSize) <= sizeof(dstStruct) )\
{\
memset( (&(dstStruct)), (setVal), sizeof(dstStruct) );\
} else {\
D_ERROR( "memset越界, ERROR:%s:%d, tosetsize:%d\n", __FILE__, __LINE__, preferSize );\
}\
}
/*memcpy*/
#define StructMemCpy( dstStruct, ptrSrc, preferSize )\
{\
if ( sizeof(void*) == sizeof(dstStruct) )\
{\
/*D_DEBUG( "%s:%d,memcpy tgt pointer?\n", __FILE__, __LINE__ );*/\
}\
if ( NULL != ptrSrc )\
{\
if ( (unsigned int)(preferSize) <= sizeof(dstStruct) )\
{\
memcpy( (&(dstStruct)), (ptrSrc), (preferSize) );\
} else {\
D_ERROR( "memcpy越界, ERROR:%s:%d, tocpysize:%d\n", __FILE__, __LINE__, preferSize );\
}\
} else {\
D_ERROR( "StructMemCpy, ERROR:%s:%d, NULL == ptrSrc\n", __FILE__, __LINE__ );\
}\
}
class CElement;
bool IsXMLValid( CElement* pEle, const char* attName, int nRecord );
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
///互斥区封装...
#ifdef ACE_WIN32
#include
#define DSCS_SPINCOUNT 500 //循环锁循环次数;
#define DSCS_USESPIN //使用循环锁等待;
class DsCS
{
public:
DsCS() { InitCS(); };
~DsCS() { ReleaseCS(); };
public:
BOOL InitCS()
{
#ifdef DSCS_USESPIN
return InitializeCriticalSectionAndSpinCount( &m_hCS, DSCS_SPINCOUNT );
#else //DSCS_USESPIN
InitializeCriticalSection( &m_hCS );
return TRUE;
#endif //DSCS_USESPIN
}
void ReleaseCS()
{
DeleteCriticalSection( &m_hCS );
}
CRITICAL_SECTION& GetWindowsHandleRef()
{
return m_hCS;
}
private:
CRITICAL_SECTION m_hCS;
};
class DsMutex
{
private:
DsMutex();
public:
explicit DsMutex( DsCS& inCS ) : m_refMutex( inCS.GetWindowsHandleRef() )
{
::EnterCriticalSection( &m_refMutex );
}
~DsMutex()
{
::LeaveCriticalSection( &m_refMutex );
}
private:
CRITICAL_SECTION& m_refMutex;
};
#endif //ACE_WIN32
///...互斥区封装
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
#endif/*UTILITY_H*/