1.在GS这边发送(本地玩家信息)
LocPlayerInfo info;
InitLocalPlayer(rActorEx, info);
SendCmd(s2c_local_player_info, &info, sizeof(info));
这个LocPlayerInfo好像内容比较多
struct LocPlayerInfo
{
int id;
wchar_t name[64];
unsigned int nBodyID;
int mapID;
pos2d pos;
ObjStat stat;
SkillStat skillstats[100]; // 身上技能,最大个数
int nskill; // 当前技能个数
AttInfo m_AttInfo; // 属性值
};
2.进入map,初始化一些信息之后,发送
plchannel->m_fnSendLocalPlayerEnter(m_nMapId, plchannel->tgtPos);
这个位置是纠正后的位置,有可能玩家位置不正确,mapid和位置都已这个为准
3.客户端发送激活玩家的包
服务器在收到激活包之后
//这些都是相当重要的
void Map::ActivatePlayer(int mapChannelId) //激活玩家
{
PlayerChannel* pPC = m_vecPlayerChannel[mapChannelId];
if (pPC->m_bBeActived)
return;
pPC->m_bBeActived = true;
auto& pActorInfoEx = pPC->m_pActorInfoEx;
if (!pActorInfoEx->m_bGaming)
{//第一次进游戏
pActorInfoEx->m_bGaming = true;
StartGame(mapChannelId);//真心没看懂啥意思
}
pos2d& cPlayerMapPos = m_spBase->GetMapPos(pPC->tgtPos);
// SetMapColl(mpos.x, mpos.y, true);
GetAllPlayers()[pPC->objId.id] = pPC;//完全不知道干啥
m_MapCellMgr.AddObj(cPlayerMapPos.x, cPlayerMapPos.y, pPC);//完全不知道干啥
//在新进入块中通知
pos2d newBlockPos = {pPC->m_nBlockX, pPC->m_nBlockY};
pPC->m_fnSendStatChange(pPC->stat);//此处为什么发送状态包
NotifyBlock(pos2d(), newBlockPos, pPC, true);
//让玩家上线就能看到所有附近角色的动作。
m_MapCellMgr.m_vecRolesBlock[pPC->m_nBlockX][pPC->m_nBlockY].Add(pPC);
UpdateRegionInfo(pPC, cPlayerMapPos);//不知干啥的
//判断罪恶值
if(pPC->m_pActorInfoEx->GetSinValue() > 0)
{
m_spSinMgr->AddPlayer(pPC);
}
//宠物(现在主要是切图时宠物携带)
if(pPC->m_pActorInfoEx->IsCarryTempPet())
{
const ShuiHu::PetInfo* pTempPetInfo = pPC->m_pActorInfoEx->GetTempPetInfoPtr();
if (pTempPetInfo->m_nCurHP <= 0)
{
ShuiHu::GetLogger()->Warning("玩家(ID=%d)进入新地图(%d),带了个血量为<=0的宠物(ID=%d)!",
pPC->objId.id, m_nMapId, pTempPetInfo->m_nID);
return;
}
pos2d cPetMapPos = {0};
if (!Round(1, cPlayerMapPos, cPetMapPos))
{
pPC->m_pActorInfoEx->SetNoneTempPet();
return;
}
// 召唤正式宠物
m_pSkill->CallPetByPos(pPC, *pTempPetInfo, cPetMapPos);
}
}
void Map::NotifyBlock(pos2d OlDBlockPos, pos2d NewBlockPos, PlayerInfo* pPlayer, bool bOnlyNewBlock)
{
std::vector<pos2d> vecLeaveBlock;
std::vector<pos2d> vecEnterBlock;
if (bOnlyNewBlock)//玩家进入地图
{
getXxX(5, NewBlockPos.x, NewBlockPos.y, vecEnterBlock);//获取玩家所在格子为中心的5*5的格子
}
else//玩家移动
{
GetLeaveAndEnterBlocks(OlDBlockPos, NewBlockPos, vecLeaveBlock, vecEnterBlock);//针对移动,获取新进入的和离开的格子用于通知,对于没有离开和进入的格子待会再说
}
std::vector<ObjecInfo> vecLeaveObj;
for (auto it : vecLeaveBlock)
{
NotifyItem(it, pPlayer, false);//物品通知
NotifyOrnamental(it, pPlayer, false); //装饰物通知
for (auto it2 : *m_MapCellMgr.m_vecRolesBlock[it.x][it.y].GetAllobj())
{
int id = it2.first.id;
vecLeaveObj.push_back(*it2.second);
if(it2.first.type == ObjID_Player)
{
pPlayer->m_mapNearbyPlayers.erase(id);
//让对方玩家也能看到自己离开
auto pDestPlayer = (PlayerInfo*)it2.second;
pDestPlayer->m_mapNearbyPlayers.erase(pPlayer->objId.id);
if(!pPlayer->m_bHide)//如果是隐身无需此通知
{
std::vector<ObjecInfo> vecLeaveDestView;
vecLeaveDestView.push_back(*pPlayer);
pDestPlayer->m_fnSendObjLeave(vecLeaveDestView);
}
}
else
{//非玩家不需要表现,不用发送消息。
auto pDestNpc = (I_NPC*)it2.second;
pDestNpc->m_mapNearbyPlayers.erase(pPlayer->objId.id);
pPlayer->m_mapNearbyMonsters.erase(id);
}
}
}
if(vecLeaveObj.size())
pPlayer->m_fnSendObjLeave(vecLeaveObj);
std::vector<ObjecInfo> vecNewEnterObj;
for (auto it : vecEnterBlock)
{
NotifyItem(it, pPlayer, true); //掉落物品通知
NotifyOrnamental(it, pPlayer, true); //装饰物通知
for (auto it2 : *m_MapCellMgr.m_vecRolesBlock[it.x][it.y].GetAllobj())
{
ObjecInfoEx* obj_ex = (ObjecInfoEx*)it2.second;
int id = it2.first.id;
vecNewEnterObj.push_back(*it2.second);
if(it2.first.type == ObjID_Player)
{
auto pDestPlayer = (PlayerInfo*)it2.second;
pPlayer->m_mapNearbyPlayers[id] = pDestPlayer;
//让对方玩家也能看到自己进入(针对:对方不移出当前Block格时也能看对方进入)
pDestPlayer->m_mapNearbyPlayers[pPlayer->objId.id] = pPlayer;
if(!pPlayer->m_bHide)
{
std::vector<ObjecInfo> vecEnterDestViewObj;
vecEnterDestViewObj.push_back(*pPlayer);
pDestPlayer->m_fnSendObjEnter(vecEnterDestViewObj);
}
}
else
{//非玩家不需要表现,不用发送消息。
auto pDestNpc = (I_NPC*)it2.second;
pDestNpc->m_mapNearbyPlayers[pPlayer->objId.id] = pPlayer;
pPlayer->m_mapNearbyMonsters[id] = pDestNpc;
}
}
}
if (vecNewEnterObj.size() > 1000)
{
Plug::PlugMessageBox("vecNewEnterObj出错");
}
if(vecNewEnterObj.size())
pPlayer->m_fnSendObjEnter(vecNewEnterObj);
}