Files
mir_server/server/DBServer/DBGate.cpp
aixianling 5c9f1dae4a init
2025-01-09 17:45:40 +08:00

1022 lines
28 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "StdAfx.h"
bool CDBGate::m_bGableIsClose =false;
CDBGate::CDBGate()
:Inherited()
{
ZeroMemory(&m_MaxTimeUserMsgPerformance, sizeof(m_MaxTimeUserMsgPerformance));
AddAllGateUsersToFreeList();
}
CDBGate::~CDBGate()
{
}
VOID CDBGate::AddAllGateUsersToFreeList()
{
int i;
m_FreeUserList.clear();
for ( i=ArrayCount(m_GateUsers)-1; i>-1; --i )
{
m_FreeUserList.add( &m_GateUsers[i] );
}
}
CCustomServerGateUser* CDBGate::CreateGateUser()
{
INT_PTR nCount = m_FreeUserList.count();
if ( nCount > 0 )
{
nCount--;
CCustomServerGateUser* pUser = m_FreeUserList[nCount];
m_FreeUserList.remove(nCount);
return pUser;
}
return NULL;
}
VOID CDBGate::DestroyGateUser(CCustomServerGateUser* pUser)
{
m_FreeUserList.add(pUser);
}
VOID CDBGate::OnOpenUser(CCustomServerGateUser *pGateUser)
{
CDBGateUser* pDBGateUser = (CDBGateUser*)pGateUser;
pDBGateUser->nGlobalSessionId = 0;
pDBGateUser->sAccount[0] = 0;
pDBGateUser->dwCreateCharTimeOut = 0;
pDBGateUser->pCreateCharStruct = NULL;
}
VOID CDBGate::OnCloseUser(CCustomServerGateUser *pGateUser)
{
//OutputMsg(rmTip,"DBGate OnCloseUser!");
CDBGateUser* pDBGateUser = (CDBGateUser*)pGateUser;
int nSessionId = pDBGateUser->nGlobalSessionId;
pDBGateUser->nGlobalSessionId = 0;
pDBGateUser->sAccount[0] = 0;
pDBGateUser->dwCreateCharTimeOut = 0;
if ( pDBGateUser->pCreateCharStruct )
{
m_Allocator.FreeBuffer(pDBGateUser->pCreateCharStruct);
pDBGateUser->pCreateCharStruct = NULL;
}
if ( nSessionId != 0 )
{
//如果会话状态不是“查询角色”则关闭会话w
/*
GLOBALSESSIONOPENDATA session;
if (m_pDBServer->GetSessionData(nSessionId, &session) && session.eState != gsSelChar)
{
m_pDBServer->PostSSClientUserClosed(nSessionId);
}
*/
}
}
VOID CDBGate::OnGateClosed()
{
}
void CDBGate::OnDispatchUserMsg(CCustomServerGateUser *pGateUser, char* lpData, SIZE_T nSize)
{
CDBGateUser* pDBGateUser = (CDBGateUser*)pGateUser;
DECLARE_FUN_TIME_PROF()
m_MaxTimeUserMsgPerformance.dwTickBegin = _getTickCount();
CDataPacket* pResult = NULL;
WORD nCmdId = (WORD)(*lpData);
switch (nCmdId)
{
case QUERYACTORLISTREQ_CMD://处理查询角色请求包
{
pResult = QueryActorList(pDBGateUser,lpData,nSize);
DeleteOldActor(pDBGateUser);
break;
}
case CREATEACTORDATAREQ_CMD:
{
pResult = CreateActor(pDBGateUser,lpData,nSize);
break;
}
case DELETEACTORDATAREQ_CMD:
{
pResult = DeleteActor(pDBGateUser,lpData,nSize);
break;
}
case ENTRYGAMEREQ_CMD:
{
pResult = EntryGameReq(pDBGateUser,lpData,nSize);
break;
}
case RANDNAMEREQ_CMD:
{
pResult = RandNameReq(pDBGateUser,lpData,nSize);
break;
}
case LESSJOBREQ_CMD:
{
pResult = QueryLessJobReq(pDBGateUser,lpData,nSize);
break;
}
case LESSZYREQ_CMD:
{
pResult = QueryZYReq(pDBGateUser,lpData,nSize);
break;
}
default:
break;
}
/********end zac*********/
/********zac 2010-11-23*/
if (pResult != NULL)
{
//发送结果包
FlushGateSendPacket(*pResult);
}
m_MaxTimeUserMsgPerformance.dwLastTick = _getTickCount() - m_MaxTimeUserMsgPerformance.dwTickBegin;
if ( m_MaxTimeUserMsgPerformance.dwLastTick < m_MaxTimeUserMsgPerformance.dwMinTick )
{
m_MaxTimeUserMsgPerformance.dwMinTick = m_MaxTimeUserMsgPerformance.dwLastTick;
}
if ( m_MaxTimeUserMsgPerformance.dwLastTick > m_MaxTimeUserMsgPerformance.dwMaxTick )
{
m_MaxTimeUserMsgPerformance.dwMaxTick = m_MaxTimeUserMsgPerformance.dwLastTick;
}
return;
}
VOID CDBGate::OnRun()
{
Inherited::OnRun();
ProcessUsers();
}
int CDBGate::UserSelCharEntryGame(CDBGateUser *pGateUser, int nCharId,
char* sGateHost,SIZE_T nHostLen,PINT_PTR nGatePort)
{
DECLARE_FUN_TIME_PROF()
//DECLARE_FUN_TIME_PROF();
GLOBALSESSIONOPENDATA SessionData;
int nError;
//首先判断网关用户是否通过查询角色消息设定了全局会话ID和帐号
if ( !pGateUser->nGlobalSessionId || !pGateUser->sAccount[0] )
{
OutputMsg( rmError, _T("未发送查询包就开始进入游戏!") );
return ERR_SESS;
}
//检查会话是否有效
//TRACE(_T("%s选择角色进入游戏检查会话\n"), pGateUser->sAccount);
if ( !m_pDBServer->GetSessionData(pGateUser->nGlobalSessionId, &SessionData)
|| SessionData.eState != jxSrvDef::gsSelChar )
{
//会话已经过期
OutputMsg( rmError, _T("选择进入游戏时会话已经过期state:%d,nGlobalSessionId:%d,Sessionid:%d"),SessionData. eState,pGateUser->nGlobalSessionId,SessionData.nSessionId);
//return ERR_SESS;
}
//角色上一次保存数据是否出现异常
//TRACE(_T("%s选择角色进入游戏检查数据是否异常\n"), pGateUser->sAccount);
if ( m_pDBServer->getDataServer()->IsCharSavedFailure(nCharId) )
{
//为保护数据安全,在保存失败的数据被成功保存前禁止进入游戏
OutputMsg( rmError, _T("角色上一次保存数据出现异常!禁止进入游戏!") );
return ERR_DATASAVE;
}
//#pragma __CPMSG__(暂时屏蔽了这个判断“服务器是否已就绪”)
//服务器是否已就绪
//TRACE(_T("%s选择角色进入游戏检查服务器是否已就绪\n"), pGateUser->sAccount);
if ( m_pDBServer->getDataServer()->GetAvailableDataClientCount(SessionData.nServerIndex) <= 0 )
{
//逻辑服务器未就绪
OutputMsg( rmError, _T("逻辑服务器未就绪!") );
return ERR_GAMESER;
}
//数据库是否连接就绪
//TRACE(_T("%s选择角色进入游戏检查数据库连接是否已就绪\n"), pGateUser->sAccount);
if ( !m_pSQLConnection->Connected() )
{
OutputMsg( rmError, _T("数据库连接没就绪!") );
return ERR_SQL;
}
//从数据库中更新角色登录的关联数据
//TRACE(_T("%s选择角色进入游戏从数据库更新信息\n"), pGateUser->sAccount);
/*nError = m_pSQLConnection->Query(szSQLSP_ClientStartPlay, SessionData.nServerIndex, nCharId,
SessionData.sAccount,SessionData.nSessionId,SessionData.nClientIPAddr);
if ( !nError )
{
pRow = m_pSQLConnection->CurrentRow();
if (pRow[0] && StrToInt(pRow[0]))
{
nError = NOERR;
}
else
{
nError = ERR_NOUSER;
}
m_pSQLConnection->ResetQuery();
}*/
nError = m_reqHandler.StartEnterGame(SessionData.nServerIndex,
SessionData.nRawServerId,
SessionData.nSessionId,
nCharId,
SessionData.sAccount,
SessionData.nClientIPAddr);
if ( nError )
{
OutputMsg( rmError, _T("选择角色错误!") );
return ERR_SELACTOR;
}
//获取游戏网关路由地址
//TRACE(_T("为%s选择路由服务器ID:%d\n"), Session.sAccount, Session.nServerIndex);
if ( !m_pDBServer->SelectGameServerRoute(SessionData.nServerIndex, sGateHost, nHostLen, nGatePort) )
{
//无匹配的路由数据
OutputMsg( rmError, _T("无匹配的路由数据!") );
return ERR_NOGATE;
}
//向会话客户端投递改变会话状态的内部消息
m_pDBServer->PostChangeSessionState(SessionData.nSessionId, jxSrvDef::gsWaitEntryGame);
//OutputMsg( rmTip, _T("通知会话服务器改状态sessionid:%d,状态gsWaitEntryGame"), SessionData.nSessionId);
//记录日志
/*
char sActorid[32];
sprintf_s(sActorid,sizeof(sActorid),"%d",nCharId);
m_pDBServer->getLogClient()->SendLoginLog(ltEntryGame,SessionData.nSessionId,SessionData.sAccount,
pGateUser->sIPAddr,sActorid);
*/
//向数据服务器投递打开角色加载认证的消息
TICKCOUNT nCurrentTick =_getTickCount(); //获得当前的时间
m_pDBServer->PostDBServerOpenCharLoad(SessionData.nServerIndex, SessionData.nSessionId, nCharId,nCurrentTick);
//OutputMsg( rmTip, _T("向数据服务器投递打开角色加载认证的消息"));
return NOERR;
}
BOOL CDBGate::NameServerAllocCharIdResult(const int nSessionId, const INT_PTR nError, const int nCharId)
{
/*
CDBGateUser *pGateUser = GetGateUserPtrBySessionId(nSessionId, NULL);
if ( pGateUser )
{
if ( !pGateUser->boMarkToClose && pGateUser->sAccount[0] && pGateUser->pCreateCharStruct )
{
// 错误码在tagNameServerOPError里定义
if ( pGateUser->pCreateCharStruct )
{
ProcessNameSrvResult(pGateUser,nCharId,nError);
//释放前需要在判断以便因为用户可能在此前被关闭而关闭用户会导致释放pCreateCharStruct指针
m_Allocator.FreeBuffer(pGateUser->pCreateCharStruct);
}
else
{
OutputMsg( rmError, _T("名称服务器返回正确结果,但会话已被关闭!"));
}
if (nError != jxInterSrvComm::NameServerProto::neSuccess)
{
OutputMsg( rmWaning, _T("名称服务器返回创建角色申请失败,错误码:(%d)"), nError);
OutputMsg( rmWaning, _T("alloc name[%s] failed."), pGateUser->sRandomName);
}
if (pGateUser->nNameLibIndex >= 0)
{
PCREATEACTORDATAREQ data = pGateUser->pCreateCharStruct;
if (data)
m_pDBServer->AllocRandomName(pGateUser->nNameLibIndex, data->Sex);
}
pGateUser->pCreateCharStruct = NULL;
}
else
{
OutputMsg( rmWaning, _T("名称服务器返回创建角色申请ID结果(%d/%d),但用户已经不处于创建角色状态,isClose=%d,account=%s,charstruct=%d"),
nError, nCharId,(int)pGateUser->boMarkToClose,pGateUser->sAccount,(long long)pGateUser->pCreateCharStruct);
}
return TRUE;
}
return FALSE;
*/
return true;
}
void CDBGate::OnLogicRsponseSessionData(const unsigned int nSessionID,const unsigned int nActorId)
{
PINT_PTR lpIndex=NULL;
CDBGateUser * pUser= GetGateUserPtrBySessionId(nSessionID,lpIndex);
if(pUser ==NULL) return;
Inherited::PostInternalMessage(SSM_LOGIC_RESPONSE_SESSION_DATA,nSessionID,nActorId,0);
}
VOID CDBGate::DispatchInternalMessage(UINT uMsg, UINT64 uParam1, UINT64 uParam2, UINT64 uParam3,UINT64 uParam4)
{
Inherited::DispatchInternalMessage(uMsg,uParam1,uParam2,uParam3,uParam4); //先执行父类的消息处理
if(uMsg == SSM_LOGIC_RESPONSE_SESSION_DATA)
{
SendClientLogin((const unsigned int)uParam1,(const unsigned int)uParam2);
}
}
void CDBGate::SendClientLogin(const unsigned int nSessionID,const unsigned int nActorId)
{
PINT_PTR lpIndex=NULL;
CDBGateUser * pUser= GetGateUserPtrBySessionId(nSessionID,lpIndex);
if(pUser ==NULL)
{
OutputMsg( rmWaning, _T("SendClientLogin 找不到 nSessionID=%d"),nSessionID);
return;
}
//回应包
CDataPacket& Packet = AllocGateSendPacket(pUser->nSocket,pUser->nGateSessionIndex,pUser->nServerSessionIndex);
Packet << (WORD)ENTRYGAMERESP_CMD;//设置包类型
Packet << (char)NOERR;
Packet <<pUser->szIP;
Packet << (int)pUser->nPort ;
Packet << (bool)CDBGate::m_bGableIsClose ;
FlushGateSendPacket(Packet);//发送结果
}
CDBGateUser* CDBGate::GetGateUserPtrBySessionId(const int nSessionId, PINT_PTR lpIndex)
{
INT_PTR i;
CDBGateUser *pGateUser, *pResult = NULL;
for ( i=m_UserList.count()-1; i>-1; --i )
{
pGateUser = (CDBGateUser*)m_UserList[i];
if ( pGateUser && pGateUser->nGlobalSessionId == nSessionId && !pGateUser->boMarkToClose )
{
if ( lpIndex ) *lpIndex = i;
pResult = pGateUser;
break;
}
}
return pResult;
}
VOID CDBGate::ProcessUsers()
{
INT_PTR i;
CDBGateUser *pGateUser;
TICKCOUNT dwCurTick = _getTickCount();
//必须降序循环
for (i=m_UserList.count()-1; i>-1; --i)
{
pGateUser = (CDBGateUser*)m_UserList[i];
if ( !pGateUser )
continue;
//检查延时关闭
if ( pGateUser->dwDelayCloseTick && dwCurTick >= pGateUser->dwDelayCloseTick )
pGateUser->boMarkToClose = TRUE;
//如果长时间无通信数据则关闭用户
if ( pGateUser->boMarkToClose || dwCurTick - pGateUser->dwLastMsgTick >= 10 * 60 * 1000 )
{
OutputMsg(rmWaning,_T("expired kick out, accountid=%d"),pGateUser->nGlobalSessionId);
CloseUser( pGateUser->nSocket, pGateUser->nServerSessionIndex );
continue;
}
}
}
//void CDBGate::GetActorList(const int nAccountId, const int nServerId, CDataPacket &packet)
//{
//
//}
VOID CDBGate::DeleteOldActor(CDBGateUser *pSqlGateUser)
{
int nAccountId = pSqlGateUser->nGlobalSessionId;
if(nAccountId ==0) return;
//必须降序循环
for (INT_PTR i=m_UserList.count()-1; i>-1; --i)
{
CDBGateUser * pGateUser = (CDBGateUser*)m_UserList[i];
if ( !pGateUser )
continue;
//检查延时关闭
if(pGateUser->boMarkToClose ) continue;
if(pGateUser->nGlobalSessionId == nAccountId && pGateUser!= pSqlGateUser)
{
OutputMsg(rmWaning,"DeleteOldActor account=[%d] old gate user found,delete",nAccountId);
pGateUser->boMarkToClose =true;
}
}
}
CDataPacket* CDBGate::QueryActorList(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize)
{
DECLARE_FUN_TIME_PROF()
GLOBALSESSIONOPENDATA Session;
QUERYACTORLISTREQ ReqData;
CDataPacketReader Reader(lpData,nSize);
Reader >> ReqData.CmdId;
Reader >> ReqData.AccountId;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket, pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << (WORD)QUERYACTORLISTRESP_CMD;//设置包类型
Packet << ReqData.AccountId;//帐号id
if ( !m_pDBServer->GetSessionData(ReqData.AccountId, &Session) )
{
Packet << (char)ERR_SESS;
OutputMsg( rmTip, _T("收到未登陆的用户连接accountid=%d"),ReqData.AccountId );
return &Packet;
}
pGateUser->nGlobalSessionId = Session.nSessionId;
_asncpytA(pGateUser->sAccount, Session.sAccount);
//首先要传递状态给会话服务器,状态改成 gsSelChar=已经连接到DB服务器出于创建、选择角色状态
//m_pDBServer->PostChangeSessionState(ReqData.AccountId,gsSelChar);
pGateUser->nGlobalSessionId = ReqData.AccountId;
// 发送到日志服务器中
/*
m_pDBServer->getLogClient()->SendLoginLog(ltQueryActor,pGateUser->nGlobalSessionId,pGateUser->sAccount,
pGateUser->sIPAddr,NULL);
*/
//OutputMsg( rmTip, _T("传递状态给会话服务器状态gsSelChar") );
m_reqHandler.GetActorList(ReqData.AccountId, Session.nServerIndex, Packet);
return &Packet;
}
CDataPacket* CDBGate::CreateActor(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize)
{
DECLARE_FUN_TIME_PROF()
INT_PTR resultCode = NOERR;
//读出数据包内容,主要就是角色名称
CDataPacketReader Reader(lpData,nSize);
PCREATEACTORDATAREQ ReqData = (PCREATEACTORDATAREQ)m_Allocator.AllocBuffer(sizeof(CREATEACTORDATAREQ));
//首先判断网关用户是否通过查询角色消息设定了全局会话ID和帐号
GLOBALSESSIONOPENDATA Session;
if ( !pGateUser->nGlobalSessionId || !pGateUser->sAccount[0] ||
!m_pDBServer->GetSessionData(pGateUser->nGlobalSessionId, &Session) )
{
OutputMsg( rmTip, _T("未发送查询包就开始创建角色!") );
resultCode = ERR_SESS;
}
else
{
Reader >> ReqData->CmdId;
Reader.readString(ReqData->ActorName,ArrayCount(ReqData->ActorName));
ReqData->ActorName[sizeof(ReqData->ActorName)-1] = 0;
//要改成小写
m_pDBServer->LowerCaseNameStr(ReqData->ActorName,sizeof(ReqData->ActorName));
INT_PTR nLen = m_pDBServer->GetStrLenUtf8(ReqData->ActorName);
if ( nLen <= 0 || nLen > 6 || !m_pDBServer->CheckNameStr(ReqData->ActorName))
{
resultCode = jxInterSrvComm::NameServerProto::neInvalidName;
}
else
{
Reader >> ReqData->Sex;
Reader >> ReqData->Job;
Reader >> ReqData->Icon;
Reader >> ReqData->Zy;
// 检测阵营合法性
bool zyVali = true;
if (ReqData->Zy < 0 || ReqData->Zy > 3)
{
zyVali = false;
}
if ( !zyVali )//选择的阵营必须是之前服务器下发给他的
{
resultCode = ERR_ZY;
}
else
{
////第一个创建的角色,阵营是不能选择的,只能分配个最少人选的
//if (QueryActorCount(pGateUser->nGlobalSessionId,Session.nServerIndex) <= 0)
//{
// ReqData->Zy = 0;
//}
if (ReqData->Zy == 0)//如果是选了随机,则给个最少人选的阵营
{
resultCode = QueryZYReq(ReqData->Zy,Session.nServerIndex);
}
if (ReqData->Job <= enVocNone || ReqData->Job >= enMaxVocCount )
{
resultCode = ERR_JOB;
}
}
}
}
if (resultCode != NOERR)
{
CREATEACTORDATARESP Resp;
Resp.CmdId = CREATEACTORDATARESP_CMD;
Resp.ActorId = 0;
Resp.Ret = (BYTE)resultCode;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << Resp.CmdId;
Packet << Resp.ActorId;
Packet << Resp.Ret;
if (Resp.Ret != 0)
{
OutputMsg(rmError, _T("Create Actor Failed, code=%d"), (int)Resp.Ret);
}
//OutputMsg( rmTip, _T("create actor error!actorid:%d,actorname:%s,error:%d"),Resp.ActorId,ReqData->ActorName,Resp.Ret);
m_Allocator.FreeBuffer(ReqData);
return &Packet;
}
// 向名称服务器查询该名字是否可用
//m_pDBServer->getNameSyncClient()->PostAllocateCharId(pGateUser->nGlobalSessionId,Session.nServerIndex,ReqData->ActorName);
// 保存创建角色所需要的数据
((CDBGateUser*)pGateUser)->pCreateCharStruct = ReqData;
//保存到日志服务器
/*
m_pDBServer->getLogClient()->SendLoginLog(ltCreateActor,pGateUser->nGlobalSessionId,pGateUser->sAccount,
pGateUser->sIPAddr,ReqData->ActorName);//最后的描述字段保存用户申请的角色名称
*/
return NULL;
}
VOID CDBGate::ProcessNameSrvResult(CDBGateUser* pGateUser,int nCharId,INT_PTR nError)
{
/*
DECLARE_FUN_TIME_PROF()
char szSql[500];
PCREATEACTORDATAREQ data = pGateUser->pCreateCharStruct;
CREATEACTORDATARESP Resp;
Resp.CmdId = CREATEACTORDATARESP_CMD;
Resp.ActorId = nCharId;
//名称服务器返回正确结果,才执行插入数据库操作
if (nError == jxInterSrvComm::NameServerProto::neSuccess)
{
bool boLogin = false;
GLOBALSESSIONOPENDATA Session;
if ( !pGateUser->nGlobalSessionId || !pGateUser->sAccount[0] )
{
//会话数据异常
boLogin = false;
}
else
{
if ( !m_pDBServer->GetSessionData(pGateUser->nGlobalSessionId, &Session) )
{
boLogin = false;
}
else
{
boLogin = true;
}
}
if (boLogin)
{
unsigned long long sip = (inet_addr(pGateUser->sIPAddr));
sprintf(szSql,szSQLSP_ClientCreateNewCharactor,pGateUser->nGlobalSessionId,pGateUser->sAccount,
sip,
nCharId,data->ActorName,data->Icon,data->Sex,data->Job,data->Zy,Session.nServerIndex);
nError = m_pSQLConnection->RealExec(szSql,strlen(szSql));
if (nError == 0)
{
m_pSQLConnection->ResetQuery();
// 插入数据库成功
if (m_pGateMgr)
m_pGateMgr->OnNewPlayerCreated(Session.nServerIndex, (tagZhenying)data->Zy, (tagActorVocation)data->Job);
Resp.Ret = 0;
}
else
{
Resp.Ret = ERR_SQL;
}
}else
{
Resp.Ret = ERR_SESS;
}
}
else
{
Resp.Ret = (char)nError;//名称服务器返回的错误
if (Resp.Ret != 0)
{
OutputMsg(rmError, _T("Create Actor Failed, code=%d"), (int)Resp.Ret);
}
}
//返回结果给客户端
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << Resp.CmdId;
Packet << Resp.ActorId;
Packet << Resp.Ret;
FlushGateSendPacket(Packet);//发送结果
//OutputMsg( rmTip, _T("send create actor response!actorid:%d,actorname:%s,errcode:%d"),Resp.ActorId,data->ActorName,Resp.Ret);
char* szAN = NULL;
if (Resp.Ret == jxInterSrvComm::NameServerProto::neSuccess)
{
//成功
szAN = data->ActorName;
//如果这个名字是随机生成的,要把这个名字设置成不可再用
if (pGateUser->nNameLibIndex >= 0 && pGateUser->sRandomName != NULL && strcmp(pGateUser->sRandomName,data->ActorName) == 0)
{
m_pDBServer->AllocRandomName(pGateUser->nNameLibIndex,data->Sex);
}
}
/*
m_pDBServer->getLogClient()->SendLoginLog(ltCreateActorResult,pGateUser->nGlobalSessionId,pGateUser->sAccount,
pGateUser->sIPAddr,szAN);//最后的描述字段保存用户申请的角色名称
*/
}
CDataPacket* CDBGate::DeleteActor(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize)
{
DECLARE_FUN_TIME_PROF()
//首先判断网关用户是否通过查询角色消息设定了全局会话ID和帐号
if ( !pGateUser->nGlobalSessionId || !pGateUser->sAccount[0] )
{
OutputMsg( rmTip, _T("未发送查询包就开始删除角色!") );
//返回结果给客户端
DELETEACTORDATARESP Resp;
Resp.CmdId = DELETEACTORDATARESP_CMD;
Resp.Actorid = 0;
Resp.Ret = ERR_SESS;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << Resp.CmdId;
Packet << Resp.Actorid;
Packet << Resp.Ret;
return &Packet;
}
DELETEACTORDATAREQ ReqData;
CDataPacketReader Reader(lpData,nSize);
Reader >> ReqData.CmdId;
Reader >> ReqData.Actoid;
//数据库连接是否就绪
if ( !m_pSQLConnection->Connected() )
{
return NULL;
}
MYSQL_ROW pRow;
//回应包
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << (WORD)DELETEACTORDATARESP_CMD;//设置包类型
Packet << ReqData.Actoid;
int nError = m_pSQLConnection->Query(szSQLSP_SelecteGuildData,ReqData.Actoid);
bool errFlag = false;
if ( !nError )
{
pRow = m_pSQLConnection->CurrentRow();
if (pRow[0] && StrToInt(pRow[0]) >=1)
{
errFlag = true;
Packet << (char)ERR_GUILD;
}
m_pSQLConnection->ResetQuery();
}
else
{
errFlag = true;
Packet << (char)ERR_SQL; //执行sql错误
}
if(errFlag == false)
{
//查询数据库
char szSql[100];
sprintf(szSql,szSQLSP_ClientDeleteCharactor,ReqData.Actoid,pGateUser->sAccount);
nError = m_pSQLConnection->RealExec(szSql,strlen(szSql));
if (nError != 0)
{
Packet << (char)ERR_SQL;//-1是错误码
}
else
{
m_pSQLConnection->ResetQuery();
Packet << (char)0;
/*
char szAn[32];
sprintf(szAn,"%d",ReqData.Actoid);
m_pDBServer->getLogClient()->SendLoginLog(ltDelActor,pGateUser->nGlobalSessionId,pGateUser->sAccount,
pGateUser->sIPAddr,szAn);//最后的描述字段保存用户删除的角色id
*/
//OutputMsg( rmTip, _T("发送删除角色列表回应包用户id:%d,角色:%d,错误码0"),pGateUser->nGlobalSessionId,ReqData.Actoid);
}
}
return &Packet;
}
CDataPacket* CDBGate::EntryGameReq(CDBGateUser *pGateUser, char* lpData,SIZE_T nSize)
{
DECLARE_FUN_TIME_PROF()
//首先判断网关用户是否通过查询角色消息设定了全局会话ID和帐号
if ( !pGateUser->nGlobalSessionId || !pGateUser->sAccount[0] )
{
OutputMsg( rmTip, _T("未登陆就发送进入游戏包!") );
//返回结果给客户端
ENTRYGAMERESP Resp;
Resp.CmdId = ENTRYGAMERESP_CMD;
Resp.Ret = ERR_SESS;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << Resp.CmdId;
Packet << Resp.Ret;
return &Packet;
}
ENTRYGAMEREQ ReqData;
CDataPacketReader Reader(lpData,nSize);
Reader >> ReqData.CmdId;
Reader >> ReqData.Actorid;
ENTRYGAMERESP Resp;
Resp.CmdId = ENTRYGAMERESP_CMD;
int nError = UserSelCharEntryGame((CDBGateUser*)pGateUser,ReqData.Actorid,Resp.szIP,sizeof(Resp.szIP),(PINT_PTR)&Resp.Port);
if (nError != NOERR)
{
//出现错误
//返回结果给客户端
Resp.szIP[0] = 0;
Resp.Port = 0;
Resp.Ret = nError;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << Resp.CmdId;
Packet << Resp.Ret;
OutputMsg(rmTip,"Enter Game Error!Errorcode = %d",Resp.Ret);
return &Packet;
}
else
{
pGateUser->nPort = Resp.Port;
strcpy(pGateUser->szIP,Resp.szIP);
}
Resp.Ret = nError;
return NULL;
}
CDataPacket* CDBGate::RandNameReq( CDBGateUser *pGateUser, char* lpData,SIZE_T nSize )
{
/*
DECLARE_FUN_TIME_PROF()
GLOBALSESSIONOPENDATA Session;
LPCSTR sActorName = NULL;
INT_PTR index = -1;
pGateUser->nNameLibIndex = index;
pGateUser->sRandomName[0] = 0;
CDataPacketReader Reader(lpData,nSize);
WORD wCmdId = 0;
BYTE bSex = 0, Ret = NOERR;
Reader >> wCmdId;
Reader >> bSex;
//首先判断网关用户是否通过查询角色消息设定了全局会话ID和帐号
if ( !pGateUser->nGlobalSessionId || !pGateUser->sAccount[0] )
{
Ret = ERR_SESS;
}
else if ( !m_pDBServer->GetSessionData(pGateUser->nGlobalSessionId, &Session) )
{
Ret = ERR_SESS;
}
else if (!m_pSQLConnection->Connected())
{
Ret = ERR_SQL;
}
else
{
if (m_pDBServer->GetEnableRandomCharName())
{
while(true)
{
DECLARE_TIME_PROF("RandNameReq_GetRandomName")
index = m_pDBServer->GetRandomName(sActorName,bSex);
if (index < 0)
{
Ret = ERR_NORANDOMNAME;
break;
}
// 如果此名字属于屏蔽字,过滤掉
if (m_pDBServer->hasFilterWordsInclude(sActorName))
{
m_pDBServer->AllocRandomName(index, bSex);
continue;
}
//查找本地数据库有没有这个名字
INT_PTR nError = m_pSQLConnection->Query(szSQLSP_GetCharactorIdByName, sActorName, Session.nServerIndex);
if ( !nError )
{
//如果角色名称存在或者不符合基本要求则继续获取下一个名字
if ( m_pSQLConnection->CurrentRow() || strlen(sActorName) < 4 || !m_pDBServer->CheckNameStr(sActorName))
{
m_pDBServer->AllocRandomName(index,bSex);
m_pSQLConnection->ResetQuery();
continue;
}
else //找到一个可用的名字
{
m_pSQLConnection->ResetQuery();
break;
}
}
else //查询失败
{
index = -1;
m_pSQLConnection->ResetQuery();
Ret = ERR_SQL;
break;
}
}
}
}
if (Ret != NOERR)
{
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << (WORD)RANDNAMERESP_CMD;
Packet << (BYTE)Ret;
return &Packet;
}
//回应包
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << (WORD)RANDNAMERESP_CMD;//设置包类型
Packet << (BYTE)Ret;
Packet << bSex;
if (Ret == NOERR)
{
Packet.writeString(sActorName);
pGateUser->nNameLibIndex = index;
_asncpytA(pGateUser->sRandomName,sActorName);
}
return &Packet;
*/
return NULL;
}
CDataPacket* CDBGate::QueryLessJobReq( CDBGateUser *pGateUser, char* lpData,SIZE_T nSize )
{
DECLARE_FUN_TIME_PROF()
BYTE bJob = 0,bRet =0;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << (WORD)LESSJOBRESP_CMD;//设置包类型
GLOBALSESSIONOPENDATA Session;
if ( !m_pDBServer->GetSessionData(pGateUser->nGlobalSessionId, &Session) )
{
Packet << (BYTE)ERR_SESS;
return &Packet;
}
bRet = QueryLessJobReq(bJob,Session.nServerIndex);
Packet << (BYTE)bRet;
Packet << (BYTE)bJob;
return &Packet;
}
BYTE CDBGate::QueryLessJobReq( BYTE &bJob, int serverindex )
{
DECLARE_FUN_TIME_PROF()
BYTE bRet = 1; // 默认是华山
if (m_pGateMgr)
bJob = m_pGateMgr->GetPriorityJob(serverindex);
return reSucc;
}
CDataPacket* CDBGate::QueryZYReq( CDBGateUser *pGateUser, char* lpData,SIZE_T nSize )
{
DECLARE_FUN_TIME_PROF()
BYTE bZY = 0,bRet =0;
CDataPacket& Packet = AllocGateSendPacket(pGateUser->nSocket,pGateUser->nGateSessionIndex,pGateUser->nServerSessionIndex);
Packet << (WORD)LESSZYRESP_CMD;//设置包类型
GLOBALSESSIONOPENDATA Session;
if ( !m_pDBServer->GetSessionData(pGateUser->nGlobalSessionId, &Session) )
{
Packet << (BYTE)ERR_SESS;
return &Packet;
}
bRet = QueryZYReq(bZY,Session.nServerIndex);
Packet << (BYTE)bRet;
Packet << (BYTE)bZY;
return &Packet;
}
BYTE CDBGate::QueryZYReq( BYTE& bZY ,int serverindex)
{
DECLARE_FUN_TIME_PROF()
// 修改为直接从内存中查询数据 by cap 2011.9.22
bZY = zyWuJi;
if (m_pGateMgr)
bZY = m_pGateMgr->GetPriorityZY(serverindex);
return reSucc;
}
INT_PTR CDBGate::QueryActorCount( INT_PTR nAccountId, INT_PTR nServerIndex )
{
DECLARE_FUN_TIME_PROF()
BYTE result = 0;
if (!m_pSQLConnection->Connected())
{
result = 0;
}
else
{
int nError = m_pSQLConnection->Query(szSQLSP_QueryActorCount,nAccountId,nServerIndex);
if (nError != 0)
{
result = 0;
}
else{
MYSQL_ROW pRow;
pRow = m_pSQLConnection->CurrentRow();
if (pRow && pRow[0])
{
result = StrToInt(pRow[0]);
}
else
{
result = 0;//数据库无数据
}
m_pSQLConnection->ResetQuery();
}
}
return result;
}
WORD CDBGate::QueryZyList( INT_PTR nServerIndex )
{
DECLARE_FUN_TIME_PROF()
WORD result = 7;
if (m_pGateMgr)
result = (WORD)m_pGateMgr->GetOptionalZy((int)nServerIndex);
return result;
}