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

436 lines
11 KiB
C++
Raw 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.

#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;
}