/** @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*/