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