mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2024-11-17 03:20:06 +00:00
Refactor group handling
This commit is contained in:
parent
1670dfd830
commit
b3e28ddea3
@ -802,7 +802,7 @@ static void playerTick(CNServer *serv, time_t currTime) {
|
|||||||
|
|
||||||
// group ticks
|
// group ticks
|
||||||
if (plr->group != nullptr)
|
if (plr->group != nullptr)
|
||||||
Groups::groupTickInfo(plr);
|
Groups::groupTickInfo(sock);
|
||||||
|
|
||||||
// do not tick dead players
|
// do not tick dead players
|
||||||
if (plr->HP <= 0)
|
if (plr->HP <= 0)
|
||||||
|
@ -38,6 +38,10 @@ struct EntityRef {
|
|||||||
return id == other.id;
|
return id == other.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool operator!=(const EntityRef& other) const {
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
// arbitrary ordering
|
// arbitrary ordering
|
||||||
bool operator<(const EntityRef& other) const {
|
bool operator<(const EntityRef& other) const {
|
||||||
if (kind == other.kind) {
|
if (kind == other.kind) {
|
||||||
|
329
src/Groups.cpp
329
src/Groups.cpp
@ -15,7 +15,54 @@
|
|||||||
|
|
||||||
using namespace Groups;
|
using namespace Groups;
|
||||||
|
|
||||||
void Groups::addToGroup(EntityRef member, Group* group) {
|
Group::Group(EntityRef leader) {
|
||||||
|
addToGroup(this, leader);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void attachGroupData(std::vector<EntityRef>& pcs, std::vector<EntityRef>& npcs, uint8_t* pivot) {
|
||||||
|
for(EntityRef pcRef : pcs) {
|
||||||
|
sPCGroupMemberInfo* info = (sPCGroupMemberInfo*)pivot;
|
||||||
|
|
||||||
|
Player* plr = PlayerManager::getPlayer(pcRef.sock);
|
||||||
|
info->iPC_ID = plr->iID;
|
||||||
|
info->iPCUID = plr->PCStyle.iPC_UID;
|
||||||
|
info->iNameCheck = plr->PCStyle.iNameCheck;
|
||||||
|
memcpy(info->szFirstName, plr->PCStyle.szFirstName, sizeof(plr->PCStyle.szFirstName));
|
||||||
|
memcpy(info->szLastName, plr->PCStyle.szLastName, sizeof(plr->PCStyle.szLastName));
|
||||||
|
info->iSpecialState = plr->iSpecialState;
|
||||||
|
info->iLv = plr->level;
|
||||||
|
info->iHP = plr->HP;
|
||||||
|
info->iMaxHP = PC_MAXHEALTH(plr->level);
|
||||||
|
// info->iMapType = 0;
|
||||||
|
// info->iMapNum = 0;
|
||||||
|
info->iX = plr->x;
|
||||||
|
info->iY = plr->y;
|
||||||
|
info->iZ = plr->z;
|
||||||
|
if(plr->activeNano > 0) {
|
||||||
|
info->Nano = *plr->getActiveNano();
|
||||||
|
info->bNano = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pivot = (uint8_t*)(info + 1);
|
||||||
|
}
|
||||||
|
for(EntityRef npcRef : npcs) {
|
||||||
|
sNPCGroupMemberInfo* info = (sNPCGroupMemberInfo*)pivot;
|
||||||
|
|
||||||
|
// probably should not assume that the combatant is an
|
||||||
|
// entity, but it works for now
|
||||||
|
BaseNPC* npc = (BaseNPC*)npcRef.getEntity();
|
||||||
|
info->iNPC_ID = npcRef.id;
|
||||||
|
info->iNPC_Type = npc->type;
|
||||||
|
info->iHP = npc->hp;
|
||||||
|
info->iX = npc->x;
|
||||||
|
info->iY = npc->y;
|
||||||
|
info->iZ = npc->z;
|
||||||
|
|
||||||
|
pivot = (uint8_t*)(info + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Groups::addToGroup(Group* group, EntityRef member) {
|
||||||
if (member.kind == EntityKind::PLAYER) {
|
if (member.kind == EntityKind::PLAYER) {
|
||||||
Player* plr = PlayerManager::getPlayer(member.sock);
|
Player* plr = PlayerManager::getPlayer(member.sock);
|
||||||
plr->group = group;
|
plr->group = group;
|
||||||
@ -29,37 +76,102 @@ void Groups::addToGroup(EntityRef member, Group* group) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group->members.push_back(member);
|
group->members.push_back(member);
|
||||||
|
|
||||||
|
if(member.kind == EntityKind::PLAYER) {
|
||||||
|
std::vector<EntityRef> pcs = group->filter(EntityKind::PLAYER);
|
||||||
|
std::vector<EntityRef> npcs = group->filter(EntityKind::COMBAT_NPC);
|
||||||
|
size_t pcCount = pcs.size();
|
||||||
|
size_t npcCount = npcs.size();
|
||||||
|
|
||||||
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||||
|
memset(respbuf, 0, CN_PACKET_BUFFER_SIZE);
|
||||||
|
sP_FE2CL_PC_GROUP_JOIN* pkt = (sP_FE2CL_PC_GROUP_JOIN*)respbuf;
|
||||||
|
|
||||||
|
pkt->iID_NewMember = PlayerManager::getPlayer(member.sock)->iID;
|
||||||
|
pkt->iMemberPCCnt = (int32_t)pcCount;
|
||||||
|
pkt->iMemberNPCCnt = (int32_t)npcCount;
|
||||||
|
|
||||||
|
if(!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_JOIN), pcCount, sizeof(sPCGroupMemberInfo))
|
||||||
|
|| !validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_JOIN) + pcCount * sizeof(sPCGroupMemberInfo), npcCount, sizeof(sNPCGroupMemberInfo))) {
|
||||||
|
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_JOIN packet size" << std::endl;
|
||||||
|
} else {
|
||||||
|
uint8_t* pivot = (uint8_t*)(pkt + 1);
|
||||||
|
attachGroupData(pcs, npcs, pivot);
|
||||||
|
// PC_GROUP_JOIN_SUCC and PC_GROUP_JOIN carry identical payloads but have different IDs
|
||||||
|
// (and the client does care!) so we need to send one to the new member
|
||||||
|
// and the other to the rest
|
||||||
|
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_JOIN) + pcCount * sizeof(sPCGroupMemberInfo) + npcCount * sizeof(sNPCGroupMemberInfo);
|
||||||
|
member.sock->sendPacket(respbuf, P_FE2CL_PC_GROUP_JOIN_SUCC, resplen);
|
||||||
|
sendToGroup(group, member, respbuf, P_FE2CL_PC_GROUP_JOIN, resplen);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Groups::removeFromGroup(EntityRef member, Group* group) {
|
bool Groups::removeFromGroup(Group* group, EntityRef member) {
|
||||||
if (member.kind == EntityKind::PLAYER) {
|
if (member.kind == EntityKind::PLAYER) {
|
||||||
Player* plr = PlayerManager::getPlayer(member.sock);
|
Player* plr = PlayerManager::getPlayer(member.sock);
|
||||||
plr->group = nullptr; // no dangling pointers here muahaahahah
|
plr->group = nullptr; // no dangling pointers here muahaahahah
|
||||||
|
|
||||||
|
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, leavePkt);
|
||||||
|
member.sock->sendPacket(leavePkt, P_FE2CL_PC_GROUP_LEAVE_SUCC);
|
||||||
}
|
}
|
||||||
else if (member.kind == EntityKind::COMBAT_NPC) {
|
else if (member.kind == EntityKind::COMBAT_NPC) {
|
||||||
CombatNPC* npc = (CombatNPC*)member.getEntity();
|
CombatNPC* npc = (CombatNPC*)member.getEntity();
|
||||||
npc->group = nullptr;
|
npc->group = nullptr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
std::cout << "[WARN] Adding a weird entity type to a group" << std::endl;
|
std::cout << "[WARN] Removing a weird entity type from a group" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto it = std::find(group->members.begin(), group->members.end(), member);
|
auto it = std::find(group->members.begin(), group->members.end(), member);
|
||||||
if (it == group->members.end()) {
|
if (it == group->members.end()) {
|
||||||
std::cout << "[WARN] Tried to remove a member that isn't in the group" << std::endl;
|
std::cout << "[WARN] Tried to remove a member that isn't in the group" << std::endl;
|
||||||
return;
|
} else {
|
||||||
|
group->members.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
group->members.erase(it);
|
if(member.kind == EntityKind::PLAYER) {
|
||||||
|
std::vector<EntityRef> pcs = group->filter(EntityKind::PLAYER);
|
||||||
|
std::vector<EntityRef> npcs = group->filter(EntityKind::COMBAT_NPC);
|
||||||
|
size_t pcCount = pcs.size();
|
||||||
|
size_t npcCount = npcs.size();
|
||||||
|
|
||||||
if (group->members.empty()) delete group; // cleanup memory
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||||
|
memset(respbuf, 0, CN_PACKET_BUFFER_SIZE);
|
||||||
|
sP_FE2CL_PC_GROUP_LEAVE* pkt = (sP_FE2CL_PC_GROUP_LEAVE*)respbuf;
|
||||||
|
|
||||||
|
pkt->iID_LeaveMember = PlayerManager::getPlayer(member.sock)->iID;
|
||||||
|
pkt->iMemberPCCnt = (int32_t)pcCount;
|
||||||
|
pkt->iMemberNPCCnt = (int32_t)npcCount;
|
||||||
|
|
||||||
|
if(!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_LEAVE), pcCount, sizeof(sPCGroupMemberInfo))
|
||||||
|
|| !validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_LEAVE) + pcCount * sizeof(sPCGroupMemberInfo), npcCount, sizeof(sNPCGroupMemberInfo))) {
|
||||||
|
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_LEAVE packet size" << std::endl;
|
||||||
|
} else {
|
||||||
|
uint8_t* pivot = (uint8_t*)(pkt + 1);
|
||||||
|
attachGroupData(pcs, npcs, pivot);
|
||||||
|
sendToGroup(group, respbuf, P_FE2CL_PC_GROUP_LEAVE,
|
||||||
|
sizeof(sP_FE2CL_PC_GROUP_LEAVE) + pcCount * sizeof(sPCGroupMemberInfo) + npcCount * sizeof(sNPCGroupMemberInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group->members.size() == 1) {
|
||||||
|
return removeFromGroup(group, group->members.back());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (group->members.empty()) {
|
||||||
|
delete group; // cleanup memory
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Groups::disbandGroup(Group* group) {
|
void Groups::disbandGroup(Group* group) {
|
||||||
// remove everyone from the group!!
|
// remove everyone from the group!!
|
||||||
std::vector<EntityRef> members = group->members;
|
bool done = false;
|
||||||
for (EntityRef member : members) {
|
while(!done) {
|
||||||
removeFromGroup(member, group);
|
EntityRef back = group->members.back();
|
||||||
|
done = removeFromGroup(group, back);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -114,7 +226,7 @@ static void joinGroup(CNSocket* sock, CNPacketData* data) {
|
|||||||
Player* otherPlr = PlayerManager::getPlayerFromID(recv->iID_From);
|
Player* otherPlr = PlayerManager::getPlayerFromID(recv->iID_From);
|
||||||
|
|
||||||
if (otherPlr == nullptr)
|
if (otherPlr == nullptr)
|
||||||
return;
|
return; // disconnect or something
|
||||||
|
|
||||||
int size = otherPlr->group == nullptr ? 1 : otherPlr->group->filter(EntityKind::PLAYER).size();
|
int size = otherPlr->group == nullptr ? 1 : otherPlr->group->filter(EntityKind::PLAYER).size();
|
||||||
|
|
||||||
@ -125,186 +237,69 @@ static void joinGroup(CNSocket* sock, CNPacketData* data) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_JOIN), size + 1, sizeof(sPCGroupMemberInfo))) {
|
|
||||||
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_JOIN packet size\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (otherPlr->group == nullptr) {
|
if (otherPlr->group == nullptr) {
|
||||||
// create group
|
// create group
|
||||||
otherPlr->group = new Group(); // spooky
|
EntityRef otherPlrRef = PlayerManager::getSockFromID(recv->iID_From);
|
||||||
addToGroup(PlayerManager::getSockFromID(recv->iID_From), otherPlr->group);
|
otherPlr->group = new Group(otherPlrRef);
|
||||||
}
|
}
|
||||||
addToGroup(sock, otherPlr->group);
|
addToGroup(otherPlr->group, sock);
|
||||||
auto players = otherPlr->group->filter(EntityKind::PLAYER);
|
|
||||||
|
|
||||||
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_JOIN) + players.size() * sizeof(sPCGroupMemberInfo);
|
|
||||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
|
||||||
|
|
||||||
memset(respbuf, 0, resplen);
|
|
||||||
|
|
||||||
sP_FE2CL_PC_GROUP_JOIN *resp = (sP_FE2CL_PC_GROUP_JOIN*)respbuf;
|
|
||||||
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_JOIN));
|
|
||||||
|
|
||||||
resp->iID_NewMember = plr->iID;
|
|
||||||
resp->iMemberPCCnt = players.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < players.size(); i++) {
|
|
||||||
|
|
||||||
Player* varPlr = PlayerManager::getPlayer(players[i].sock);
|
|
||||||
CNSocket* sockTo = players[i].sock;
|
|
||||||
|
|
||||||
if (varPlr == nullptr || sockTo == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
respdata[i].iPC_ID = varPlr->iID;
|
|
||||||
respdata[i].iPCUID = varPlr->PCStyle.iPC_UID;
|
|
||||||
respdata[i].iNameCheck = varPlr->PCStyle.iNameCheck;
|
|
||||||
memcpy(respdata[i].szFirstName, varPlr->PCStyle.szFirstName, sizeof(varPlr->PCStyle.szFirstName));
|
|
||||||
memcpy(respdata[i].szLastName, varPlr->PCStyle.szLastName, sizeof(varPlr->PCStyle.szLastName));
|
|
||||||
respdata[i].iSpecialState = varPlr->iSpecialState;
|
|
||||||
respdata[i].iLv = varPlr->level;
|
|
||||||
respdata[i].iHP = varPlr->HP;
|
|
||||||
respdata[i].iMaxHP = PC_MAXHEALTH(varPlr->level);
|
|
||||||
//respdata[i].iMapType = 0;
|
|
||||||
//respdata[i].iMapNum = 0;
|
|
||||||
respdata[i].iX = varPlr->x;
|
|
||||||
respdata[i].iY = varPlr->y;
|
|
||||||
respdata[i].iZ = varPlr->z;
|
|
||||||
// client doesnt read nano data here
|
|
||||||
}
|
|
||||||
|
|
||||||
Groups::sendToGroup(otherPlr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void leaveGroup(CNSocket* sock, CNPacketData* data) {
|
static void leaveGroup(CNSocket* sock, CNPacketData* data) {
|
||||||
Player* plr = PlayerManager::getPlayer(sock);
|
Player* plr = PlayerManager::getPlayer(sock);
|
||||||
groupKick(plr);
|
groupKick(plr->group, sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Groups::sendToGroup(Group* group, void* buf, uint32_t type, size_t size) {
|
void Groups::sendToGroup(Group* group, void* buf, uint32_t type, size_t size) {
|
||||||
auto players = group->filter(EntityKind::PLAYER);
|
auto players = group->filter(EntityKind::PLAYER);
|
||||||
for (int i = 0; i < players.size(); i++) {
|
for (EntityRef ref : players) {
|
||||||
CNSocket* sock = players[i].sock;
|
ref.sock->sendPacket(buf, type, size);
|
||||||
sock->sendPacket(buf, type, size);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Groups::groupTickInfo(Player* plr) {
|
void Groups::sendToGroup(Group* group, EntityRef excluded, void* buf, uint32_t type, size_t size) {
|
||||||
|
auto players = group->filter(EntityKind::PLAYER);
|
||||||
auto players = plr->group->filter(EntityKind::PLAYER);
|
for (EntityRef ref : players) {
|
||||||
|
if(ref != excluded) ref.sock->sendPacket(buf, type, size);
|
||||||
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO), players.size(), sizeof(sPCGroupMemberInfo))) {
|
|
||||||
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_JOIN packet size\n";
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO) + players.size() * sizeof(sPCGroupMemberInfo);
|
|
||||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
|
||||||
|
|
||||||
memset(respbuf, 0, resplen);
|
|
||||||
|
|
||||||
sP_FE2CL_PC_GROUP_MEMBER_INFO *resp = (sP_FE2CL_PC_GROUP_MEMBER_INFO*)respbuf;
|
|
||||||
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO));
|
|
||||||
|
|
||||||
resp->iID = plr->iID;
|
|
||||||
resp->iMemberPCCnt = players.size();
|
|
||||||
|
|
||||||
for (int i = 0; i < players.size(); i++) {
|
|
||||||
EntityRef member = players[i];
|
|
||||||
Player* varPlr = PlayerManager::getPlayer(member.sock);
|
|
||||||
|
|
||||||
if (varPlr == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
respdata[i].iPC_ID = varPlr->iID;
|
|
||||||
respdata[i].iPCUID = varPlr->PCStyle.iPC_UID;
|
|
||||||
respdata[i].iNameCheck = varPlr->PCStyle.iNameCheck;
|
|
||||||
memcpy(respdata[i].szFirstName, varPlr->PCStyle.szFirstName, sizeof(varPlr->PCStyle.szFirstName));
|
|
||||||
memcpy(respdata[i].szLastName, varPlr->PCStyle.szLastName, sizeof(varPlr->PCStyle.szLastName));
|
|
||||||
respdata[i].iSpecialState = varPlr->iSpecialState;
|
|
||||||
respdata[i].iLv = varPlr->level;
|
|
||||||
respdata[i].iHP = varPlr->HP;
|
|
||||||
respdata[i].iMaxHP = PC_MAXHEALTH(varPlr->level);
|
|
||||||
//respdata[i].iMapType = 0;
|
|
||||||
//respdata[i].iMapNum = 0;
|
|
||||||
respdata[i].iX = varPlr->x;
|
|
||||||
respdata[i].iY = varPlr->y;
|
|
||||||
respdata[i].iZ = varPlr->z;
|
|
||||||
if (varPlr->activeNano > 0) {
|
|
||||||
respdata[i].bNano = 1;
|
|
||||||
respdata[i].Nano = varPlr->Nanos[varPlr->activeNano];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sendToGroup(plr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO, resplen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Groups::groupKick(Player* plr) {
|
void Groups::groupTickInfo(CNSocket* sock) {
|
||||||
|
Player* plr = PlayerManager::getPlayer(sock);
|
||||||
Group* group = plr->group;
|
Group* group = plr->group;
|
||||||
|
std::vector<EntityRef> pcs = group->filter(EntityKind::PLAYER);
|
||||||
|
std::vector<EntityRef> npcs = group->filter(EntityKind::COMBAT_NPC);
|
||||||
|
size_t pcCount = pcs.size();
|
||||||
|
size_t npcCount = npcs.size();
|
||||||
|
|
||||||
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
||||||
|
memset(respbuf, 0, CN_PACKET_BUFFER_SIZE);
|
||||||
|
sP_FE2CL_PC_GROUP_MEMBER_INFO* pkt = (sP_FE2CL_PC_GROUP_MEMBER_INFO*)respbuf;
|
||||||
|
|
||||||
|
pkt->iID = plr->iID;
|
||||||
|
pkt->iMemberPCCnt = (int32_t)pcCount;
|
||||||
|
pkt->iMemberNPCCnt = (int32_t)npcCount;
|
||||||
|
|
||||||
|
if(!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO), pcCount, sizeof(sPCGroupMemberInfo))
|
||||||
|
|| !validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO) + pcCount * sizeof(sPCGroupMemberInfo), npcCount, sizeof(sNPCGroupMemberInfo))) {
|
||||||
|
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_MEMBER_INFO packet size" << std::endl;
|
||||||
|
} else {
|
||||||
|
uint8_t* pivot = (uint8_t*)(pkt + 1);
|
||||||
|
attachGroupData(pcs, npcs, pivot);
|
||||||
|
sock->sendPacket(respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO,
|
||||||
|
sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO) + pcCount * sizeof(sPCGroupMemberInfo) + npcCount * sizeof(sNPCGroupMemberInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Groups::groupKick(Group* group, EntityRef ref) {
|
||||||
|
|
||||||
// if you are the group leader, destroy your own group and kick everybody
|
// if you are the group leader, destroy your own group and kick everybody
|
||||||
if (plr->group->members[0] == PlayerManager::getSockFromID(plr->iID)) {
|
if (group->members[0] == ref) {
|
||||||
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1);
|
disbandGroup(group);
|
||||||
sendToGroup(plr->group, (void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
|
|
||||||
disbandGroup(plr->group);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto players = group->filter(EntityKind::PLAYER);
|
removeFromGroup(group, ref);
|
||||||
|
|
||||||
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_LEAVE), players.size() - 1, sizeof(sPCGroupMemberInfo))) {
|
|
||||||
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_LEAVE packet size\n";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_LEAVE) + (players.size() - 1) * sizeof(sPCGroupMemberInfo);
|
|
||||||
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
|
||||||
|
|
||||||
memset(respbuf, 0, resplen);
|
|
||||||
|
|
||||||
sP_FE2CL_PC_GROUP_LEAVE *resp = (sP_FE2CL_PC_GROUP_LEAVE*)respbuf;
|
|
||||||
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_LEAVE));
|
|
||||||
|
|
||||||
resp->iID_LeaveMember = plr->iID;
|
|
||||||
resp->iMemberPCCnt = players.size() - 1;
|
|
||||||
|
|
||||||
CNSocket* sock = PlayerManager::getSockFromID(plr->iID);
|
|
||||||
|
|
||||||
if (sock == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
removeFromGroup(sock, group);
|
|
||||||
|
|
||||||
players = group->filter(EntityKind::PLAYER);
|
|
||||||
for (int i = 0; i < players.size(); i++) {
|
|
||||||
CNSocket* sockTo = players[i].sock;
|
|
||||||
Player* varPlr = PlayerManager::getPlayer(sock);
|
|
||||||
|
|
||||||
if (varPlr == nullptr || sockTo == nullptr)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
respdata[i].iPC_ID = varPlr->iID;
|
|
||||||
respdata[i].iPCUID = varPlr->PCStyle.iPC_UID;
|
|
||||||
respdata[i].iNameCheck = varPlr->PCStyle.iNameCheck;
|
|
||||||
memcpy(respdata[i].szFirstName, varPlr->PCStyle.szFirstName, sizeof(varPlr->PCStyle.szFirstName));
|
|
||||||
memcpy(respdata[i].szLastName, varPlr->PCStyle.szLastName, sizeof(varPlr->PCStyle.szLastName));
|
|
||||||
respdata[i].iSpecialState = varPlr->iSpecialState;
|
|
||||||
respdata[i].iLv = varPlr->level;
|
|
||||||
respdata[i].iHP = varPlr->HP;
|
|
||||||
respdata[i].iMaxHP = PC_MAXHEALTH(varPlr->level);
|
|
||||||
// respdata[i]].iMapType = 0;
|
|
||||||
// respdata[i]].iMapNum = 0;
|
|
||||||
respdata[i].iX = varPlr->x;
|
|
||||||
respdata[i].iY = varPlr->y;
|
|
||||||
respdata[i].iZ = varPlr->z;
|
|
||||||
// client doesnt read nano data here
|
|
||||||
}
|
|
||||||
|
|
||||||
sendToGroup(group, (void*)&respbuf, P_FE2CL_PC_GROUP_LEAVE, resplen);
|
|
||||||
|
|
||||||
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1);
|
|
||||||
sock->sendPacket((void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Groups::init() {
|
void Groups::init() {
|
||||||
|
@ -19,16 +19,19 @@ struct Group {
|
|||||||
});
|
});
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Group(EntityRef leader);
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Groups {
|
namespace Groups {
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
void sendToGroup(Group* group, void* buf, uint32_t type, size_t size);
|
void sendToGroup(Group* group, void* buf, uint32_t type, size_t size);
|
||||||
void groupTickInfo(Player* plr);
|
void sendToGroup(Group* group, EntityRef excluded, void* buf, uint32_t type, size_t size);
|
||||||
void groupKick(Player* plr);
|
void groupTickInfo(CNSocket* sock);
|
||||||
|
|
||||||
void addToGroup(EntityRef member, Group* group);
|
void groupKick(Group* group, EntityRef ref);
|
||||||
void removeFromGroup(EntityRef member, Group* group);
|
void addToGroup(Group* group, EntityRef member);
|
||||||
|
bool removeFromGroup(Group* group, EntityRef member); // true iff group deleted
|
||||||
void disbandGroup(Group* group);
|
void disbandGroup(Group* group);
|
||||||
}
|
}
|
||||||
|
@ -139,7 +139,6 @@ void Nanos::summonNano(CNSocket *sock, int slot, bool silent) {
|
|||||||
if (slot != -1 && skill != nullptr && skill->drainType == SkillDrainType::PASSIVE) {
|
if (slot != -1 && skill != nullptr && skill->drainType == SkillDrainType::PASSIVE) {
|
||||||
// passive buff effect
|
// passive buff effect
|
||||||
resp.eCSTB___Add = 1;
|
resp.eCSTB___Add = 1;
|
||||||
int boost = Nanos::getNanoBoost(plr);
|
|
||||||
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
std::vector<ICombatant*> affectedCombatants = applyNanoBuff(skill, plr);
|
||||||
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, nano, affectedCombatants);
|
if(!affectedCombatants.empty()) Abilities::useNanoSkill(sock, nano, affectedCombatants);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ void PlayerManager::removePlayer(CNSocket* key) {
|
|||||||
|
|
||||||
// leave group
|
// leave group
|
||||||
if(plr->group != nullptr)
|
if(plr->group != nullptr)
|
||||||
Groups::groupKick(plr);
|
Groups::groupKick(plr->group, key);
|
||||||
|
|
||||||
// remove player's bullets
|
// remove player's bullets
|
||||||
Combat::Bullets.erase(plr->iID);
|
Combat::Bullets.erase(plr->iID);
|
||||||
|
Loading…
Reference in New Issue
Block a user