436 lines
11 KiB
C++
436 lines
11 KiB
C++
#pragma once
|
||
|
||
#include "stdafx.h"
|
||
/*
|
||
* 与逻辑服务器通信的类,处理逻辑服务器的各种消息
|
||
* !!!请注意,发送的包一定要在OnEnterGame 以后调用,因为有一个校验密钥的过程,如果前面发数据,可能导致校验密钥失败
|
||
*/
|
||
|
||
CLogicAgent::CLogicAgent()
|
||
{
|
||
m_bHasTrans = false;
|
||
m_NextActionTick = 0;
|
||
}
|
||
|
||
CLogicAgent::~CLogicAgent()
|
||
{
|
||
|
||
}
|
||
|
||
void CLogicAgent::OnConnected()
|
||
{
|
||
SendCreateActor();
|
||
SendLogin();
|
||
}
|
||
|
||
void CLogicAgent::OnDisConnected()
|
||
{
|
||
//m_pClient->
|
||
OutputMsg(rmNormal, "[%s]disconnect from logic ",m_pClient->GetAccount().name);
|
||
DiscardUnHandledMsg();
|
||
m_hasEnterGame =false;
|
||
}
|
||
|
||
void CLogicAgent::OnTimeRun(TICKCOUNT tick)
|
||
{
|
||
// 处理来自服务器的消息
|
||
ProcessNetMsg();
|
||
|
||
if( m_hasEnterGame ==false) return ; //如果没有登录游戏,不执行定时调用
|
||
|
||
// 子系统更新处理
|
||
m_defaultSystem.OnTimeRun(tick); //定期的调用每个子系统
|
||
m_skillSystem.OnTimeRun(tick);
|
||
GetRobotMgr()->GetGlobalConfig().GetAIBehavierTree().Run(m_pClient,tick);
|
||
}
|
||
|
||
void CLogicAgent::OnEvent(INT_PTR nEvtId, INT_PTR nParam1, INT_PTR nParam2, INT_PTR nParam3, INT_PTR nParam4)
|
||
{
|
||
//m_ActionMgr.OnEvent(nEvtId, nParam1, nParam2, nParam3, nParam4);
|
||
}
|
||
|
||
bool CLogicAgent::ProcessNetMsg()
|
||
{
|
||
m_netMsgList.flush();
|
||
INT_PTR nMsgCount = m_netMsgList.count();
|
||
for (INT_PTR i = 0; i < nMsgCount; i++)
|
||
{
|
||
BYTE ucSysId = 0, ucCmd = 0;
|
||
CDataPacket& curPacket = *m_netMsgList[0];
|
||
curPacket >> ucSysId >> ucCmd;
|
||
DispatchMsg(ucSysId, ucCmd, curPacket);
|
||
m_netMsgList.remove(0);
|
||
FreePacket(&curPacket);
|
||
}
|
||
return true;
|
||
}
|
||
|
||
//发送数据包进入游戏
|
||
void CLogicAgent::SendLogin()
|
||
{
|
||
CDataPacket &pack= m_pClient->AllocProtoPacket();
|
||
pack << (BYTE) enLoginSystemId << (BYTE)cCheckUserPasswd;
|
||
LOGINACCOUNT & account = m_pClient->GetAccount(); //获取账户
|
||
pack.writeString(account.name);
|
||
|
||
MD5_CTX ctx;
|
||
unsigned char md5[33];
|
||
|
||
//使用 MD5加密玩家的密码
|
||
MD5Init(&ctx);
|
||
MD5Update(&ctx, (unsigned char *)account.pass, (unsigned int)strlen(account.pass) );
|
||
MD5Final(md5,&ctx);
|
||
md5[32]=0;
|
||
|
||
pack.writeString((const char*)md5);
|
||
pack << GetRobotMgr()->GetServerIndex();
|
||
pack << GetRobotMgr()->GetServerIndex();
|
||
|
||
m_pClient->FlushProtoPacket(pack);
|
||
}
|
||
|
||
//发送数据包创建一个角色
|
||
void CLogicAgent::SendCreateActor()
|
||
{
|
||
CDataPacket &pack= m_pClient->AllocProtoPacket();
|
||
pack << (BYTE) enLoginSystemId << (BYTE) cCreateAccount;
|
||
|
||
LOGINACCOUNT & account = m_pClient->GetAccount(); //获取账户
|
||
|
||
pack.writeString(account.name);
|
||
|
||
MD5_CTX ctx;
|
||
unsigned char md5[33];
|
||
//使用 MD5加密玩家的密码
|
||
MD5Init(&ctx);
|
||
MD5Update(&ctx, (unsigned char *)account.pass, (unsigned int)strlen(account.pass) );
|
||
MD5Final(md5,&ctx);
|
||
md5[32]=0;
|
||
pack.writeString((const char*)md5);
|
||
pack.writeString("430481188112113256"); //乱设一个身份证号码进去
|
||
m_pClient->FlushProtoPacket(pack);
|
||
}
|
||
|
||
void CLogicAgent::DiscardUnHandledMsg()
|
||
{
|
||
FreePacket(m_netMsgList);
|
||
m_netMsgList.clear();
|
||
}
|
||
|
||
void CLogicAgent::DispatchMsg(BYTE ucSysId, BYTE ucMsgId, CDataPacketReader& packet)
|
||
{
|
||
switch (ucSysId)
|
||
{
|
||
case enLoginSystemId:
|
||
OnRecvLoginMsg(ucMsgId, packet);
|
||
break;
|
||
case enDefaultEntitySystemID:
|
||
m_defaultSystem.OnRecvData(ucMsgId, packet);
|
||
break;
|
||
case enMoveSystemID:
|
||
break;
|
||
case enSkillSystemID:
|
||
m_skillSystem.OnRecvData(ucMsgId, packet);
|
||
break;
|
||
case enBagSystemID:
|
||
//m_itemSystem.OnRecvData(ucMsgId, packet);
|
||
break;
|
||
case enEuipSystemID:
|
||
//m_equipSystem.OnRecvData(ucMsgId, packet);
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
char * CLogicAgent::GetLoginErrorStr(INT_PTR nErrorCode)
|
||
{
|
||
switch (nErrorCode)
|
||
{
|
||
case ERR_SQL: //sql错误
|
||
return "sql Error";
|
||
break;
|
||
case ERR_SESS: //用户没登陆
|
||
return "No session Data send from session server";
|
||
break;
|
||
case ERR_GAMESER: //游戏服务没准备好
|
||
return "server not ready";
|
||
break;
|
||
case ERR_DATASAVE: //角色上一次保存数据是否出现异常
|
||
return "User last save data error,forbid login";
|
||
break;
|
||
case ERR_SELACTOR://客户端选择角色的常规错误
|
||
return "client select error";
|
||
break;
|
||
case ERR_NOGATE://客户端无匹配的路由数据的错误
|
||
return "No gate found";
|
||
break;
|
||
case ERR_NOUSER: //角色不存在
|
||
return "No user exist";
|
||
break;
|
||
case ERR_SEX://错误的性别
|
||
return "sex error";
|
||
break;
|
||
case ERR_NORANDOMNAME://随机生成的名字已经分配完
|
||
return "Rand name database is empty";
|
||
break;
|
||
case ERR_ZY://客户端上传的角色阵营参数错误
|
||
return "client camp error";
|
||
break;
|
||
case ERR_JOB: //客户端上传的角色职业参数错误
|
||
return "select job error";
|
||
break;
|
||
default:
|
||
return " Unkown error";
|
||
}
|
||
}
|
||
|
||
//发送数据包去查询角色
|
||
void CLogicAgent::SendQueryActorList()
|
||
{
|
||
CDataPacket &pack= m_pClient->AllocProtoPacket();
|
||
pack << (BYTE) enLoginSystemId <<(BYTE )cGetUserList; //进入游戏的请求
|
||
pack << (int) m_pClient->GetAccountId(); //获取账户的ID
|
||
m_pClient->FlushProtoPacket(pack);
|
||
|
||
}
|
||
|
||
//选择角色进入游戏
|
||
void CLogicAgent::SelActorEnterGame(unsigned int nActorID,char * sName )
|
||
{
|
||
|
||
CDataPacket &pack= m_pClient->AllocProtoPacket();
|
||
pack << (BYTE) enDefaultEntitySystemID <<(BYTE )cLogin; //进入游戏的请求
|
||
pack <<(unsigned int)m_pClient->GetAccountId();
|
||
pack << (unsigned int) nActorID; //玩家的角色
|
||
m_pClient->FlushProtoPacket(pack); //发送消息进入游戏
|
||
|
||
//设置名字和actorid
|
||
m_pClient->SetActorId(nActorID);
|
||
if(sName != NULL)
|
||
{
|
||
m_pClient->SetActorName(sName);
|
||
}
|
||
}
|
||
|
||
//随机一个名字
|
||
void CLogicAgent::RandActorName()
|
||
{
|
||
CDataPacket &pack= m_pClient->AllocProtoPacket();
|
||
pack << (BYTE) enLoginSystemId <<(BYTE )cRandName; //进入游戏的请求
|
||
char sex =rand() %2; //性别
|
||
|
||
pack << sex; //玩家的角色
|
||
m_pClient->FlushProtoPacket(pack); //发送消息进入游戏
|
||
}
|
||
|
||
void CLogicAgent::CreateActor(char * sName,int nSex,int nJob, int nCamp )
|
||
{
|
||
CDataPacket &pack= m_pClient->AllocProtoPacket();
|
||
pack << (BYTE) enLoginSystemId <<(BYTE )cCreateActor; //进入游戏的请求
|
||
pack.writeString(sName);
|
||
pack << (BYTE) nSex << (BYTE) nJob << (BYTE) 0 << (BYTE)nCamp;
|
||
m_pClient->FlushProtoPacket(pack); //发送消息进入游戏
|
||
|
||
}
|
||
|
||
|
||
//收到登陆的消息包
|
||
void CLogicAgent::OnRecvLoginMsg(BYTE ucMsgId, CDataPacketReader & pack)
|
||
{
|
||
unsigned int nAccountId=0,nActorId =0;
|
||
if(sLoginErrorCode ==ucMsgId)
|
||
{
|
||
char bResult =0;
|
||
|
||
pack >> bResult >> nAccountId;
|
||
if(bResult !=0)
|
||
{
|
||
OutputMsg(rmError, "[%s]login on session fail, errorid=%d",m_pClient->GetAccount().name,int(bResult));
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
//OutputMsg(rmNormal, "[%s]login on session ",m_pClient->GetAccount().name);
|
||
}
|
||
|
||
}
|
||
else if(sGetUserList ==ucMsgId )
|
||
{
|
||
|
||
BYTE nErrorCode =0;
|
||
int nOpenDay = 0;
|
||
pack >> nOpenDay;
|
||
BYTE canCreate = 0;
|
||
pack >> canCreate;
|
||
pack >> nAccountId >> nErrorCode;
|
||
|
||
if(nErrorCode >=100)
|
||
{
|
||
OutputMsg(rmError, "[%slogin on get user List, errorid=%d",m_pClient->GetAccount().name, GetLoginErrorStr(nErrorCode));
|
||
return ;
|
||
}
|
||
m_pClient->SetAccountId(nAccountId);//设置账户的ID
|
||
if(nErrorCode ==0) //如果只有一个角色,则需要创建一个角色
|
||
{
|
||
RandActorName(); //随机一个名字
|
||
}
|
||
else
|
||
{
|
||
|
||
pack >> nActorId; //进入游戏
|
||
char name[32];
|
||
pack.readString(name,sizeof(name));
|
||
SelActorEnterGame(nActorId,name);
|
||
}
|
||
}
|
||
else if(sCreateActor == ucMsgId)
|
||
{
|
||
|
||
BYTE bResult =0;
|
||
pack >> nActorId >> bResult; //创建角色的结构
|
||
if(bResult ==0)
|
||
{
|
||
SelActorEnterGame(nActorId);
|
||
}
|
||
else
|
||
{
|
||
OutputMsg(rmWaning,_T("[%s] Create actor fail, errorcode=%s"), m_pClient->GetAccount().name,GetLoginErrorStr((int)bResult));
|
||
//RandActorName(); //重新随一个账户
|
||
}
|
||
}
|
||
else if(sRandNameActor == ucMsgId)
|
||
{
|
||
char bRet =0, bSex=0;
|
||
pack >> bRet >> bSex;
|
||
char sName[32]; //自动产生的名字
|
||
pack.readString(sName,sizeof(sName)); //读取名字
|
||
//随机阵营
|
||
int nCamp = 0; //随机阵营
|
||
int nJob ;
|
||
|
||
//随机一个职业
|
||
nJob = rand()% 3+1 ;
|
||
CreateActor(sName,bSex,nJob,nCamp); //随机一个阵营选择进入游戏
|
||
m_pClient->SetActorName(sName);
|
||
}
|
||
}
|
||
|
||
void CLogicAgent::OnRecv(CDataPacketReader & pack)
|
||
{
|
||
CDataPacket *packet = AllocPacket();
|
||
packet->writeBuf(pack.getOffsetPtr(), pack.getAvaliableLength());
|
||
packet->setPosition(0);
|
||
m_netMsgList.append(packet);
|
||
}
|
||
|
||
CDataPacket* CLogicAgent::AllocPacket()
|
||
{
|
||
static const INT_PTR SINGLE_ALLOC_COUNT = 100;
|
||
CDataPacket* packet;
|
||
if (m_freeMsgList.count() > 0)
|
||
{
|
||
packet = m_freeMsgList.pop();
|
||
}
|
||
else
|
||
{
|
||
m_freeMsgList.flush();
|
||
if (m_freeMsgList.count() <= 0)
|
||
{
|
||
CDataPacket* pkg = (CDataPacket*)m_allocator.AllocBuffer(sizeof(CDataPacket) * SINGLE_ALLOC_COUNT);
|
||
for (INT_PTR i = 0; i < SINGLE_ALLOC_COUNT; i++)
|
||
{
|
||
CDataPacket* curPkg = pkg + i;
|
||
new(curPkg) CDataPacket(&m_allocator);
|
||
m_freeMsgList.add(curPkg);
|
||
}
|
||
|
||
}
|
||
packet = m_freeMsgList.pop();
|
||
}
|
||
|
||
packet->setPosition(0);
|
||
return packet;
|
||
}
|
||
|
||
void CLogicAgent::FreePacket(CDataPacket* packet)
|
||
{
|
||
m_freeMsgList.append(packet);
|
||
}
|
||
|
||
void CLogicAgent::FreePacket(CBaseList<CDataPacket*> &list)
|
||
{
|
||
m_freeMsgList.appendList(list);
|
||
}
|
||
|
||
CClientEntity* CLogicAgent::GetTarget()
|
||
{
|
||
INT_PTR nType = m_TargetHandle.GetType();
|
||
if (enMonster == nType)
|
||
return m_defaultSystem.GetMonster(m_TargetHandle);
|
||
else if (enActor == nType)
|
||
return m_defaultSystem.GetOtherData(m_TargetHandle);
|
||
else if (enPet == nType)
|
||
return m_defaultSystem.GetPet(m_TargetHandle);
|
||
return NULL;
|
||
}
|
||
|
||
bool CLogicAgent::CanCrossCheck(INT_PTR x, INT_PTR y)
|
||
{
|
||
return !m_defaultSystem.HasEntity(x,y);
|
||
}
|
||
|
||
bool CLogicAgent::CalcPath(bool isLoopLimit)
|
||
{
|
||
int curX,curY;
|
||
GetDefaultSystem().GetPosition(curX,curY);
|
||
|
||
int nSceneId = m_pClient->GetActorData().GetSceneId();
|
||
SCENEMAPCONF * pSc = GetRobotMgr()->GetGlobalConfig().GetSceneConfig().GetSceneConfig(nSceneId);
|
||
if (pSc != NULL)
|
||
{
|
||
typedef typename AStar::CrossCheckFuncType FuncType;
|
||
FuncType checkproxy = std::bind(&CLogicAgent::CanCrossCheck,this,std::placeholders::_1,std::placeholders::_2);
|
||
return m_Astar.getPath(curX,curY,m_MovePoint.x,m_MovePoint.y,m_searchNodes,checkproxy,isLoopLimit);
|
||
}
|
||
}
|
||
|
||
void CLogicAgent::SetNextAction(int millsec)
|
||
{
|
||
m_NextActionTick = m_pClient->GetCurTick() + millsec;
|
||
}
|
||
|
||
bool CLogicAgent::CanAction()
|
||
{
|
||
return m_NextActionTick <= m_pClient->GetCurTick();
|
||
}
|
||
|
||
int CLogicAgent::GetAndPopNextMovePosi(int& x,int& y,int& dir)
|
||
{
|
||
int count = m_searchNodes.size();
|
||
if (count < 2) return 0;
|
||
|
||
SMALLCPOINT pos = m_searchNodes[count - 1];
|
||
x = pos.x;
|
||
y = pos.y;
|
||
pos = m_searchNodes[count - 2];
|
||
dir = pos.dir;
|
||
|
||
if (count > 2)
|
||
{
|
||
CClientEntity* pentity = GetTarget();//第一个点 自己, 最后一个点 目标
|
||
int tarX,tarY;
|
||
GetDefaultSystem().GetEntityPos(m_TargetHandle, tarX,tarY);
|
||
SMALLCPOINT pos2 = m_searchNodes[count - 3];
|
||
if (pos2.dir == pos.dir && ((pos2.x != tarX) || (pos2.y != tarY)))
|
||
{
|
||
m_searchNodes.pop_back();
|
||
m_searchNodes.pop_back();
|
||
return 2;
|
||
}
|
||
}
|
||
m_searchNodes.pop_back();
|
||
return 1;
|
||
}
|