[refactor] Refactor groups

This commit is contained in:
gsemaj
2022-04-22 21:13:00 -04:00
committed by gsemaj
parent 4b834579c5
commit 03d28bf4e4
11 changed files with 182 additions and 160 deletions

View File

@@ -19,22 +19,65 @@
using namespace Groups;
void Groups::addToGroup(EntityRef member, Group* group) {
if (member.kind == EntityKind::PLAYER) {
Player* plr = PlayerManager::getPlayer(member.sock);
plr->group = group;
}
else if (member.kind == EntityKind::COMBAT_NPC) {
CombatNPC* npc = (CombatNPC*)member.getEntity();
npc->group = group;
}
else {
std::cout << "[WARN] Adding a weird entity type to a group" << std::endl;
}
group->members.push_back(member);
}
void Groups::removeFromGroup(EntityRef member, Group* group) {
if (member.kind == EntityKind::PLAYER) {
Player* plr = PlayerManager::getPlayer(member.sock);
plr->group = nullptr; // no dangling pointers here muahaahahah
}
else if (member.kind == EntityKind::COMBAT_NPC) {
CombatNPC* npc = (CombatNPC*)member.getEntity();
npc->group = nullptr;
}
else {
std::cout << "[WARN] Adding a weird entity type to a group" << std::endl;
}
auto it = std::find(group->members.begin(), group->members.end(), member);
if (it == group->members.end()) {
std::cout << "[WARN] Tried to remove a member that isn't in the group" << std::endl;
return;
}
group->members.erase(it);
if (group->members.empty()) delete group; // cleanup memory
}
void Groups::disbandGroup(Group* group) {
// remove everyone from the group!!
std::vector<EntityRef> members = group->members;
for (EntityRef member : members) {
removeFromGroup(member, group);
}
}
static void requestGroup(CNSocket* sock, CNPacketData* data) {
sP_CL2FE_REQ_PC_GROUP_INVITE* recv = (sP_CL2FE_REQ_PC_GROUP_INVITE*)data->buf;
Player* plr = PlayerManager::getPlayer(sock);
Player* otherPlr = PlayerManager::getPlayerFromID(recv->iID_To);
if (otherPlr == nullptr)
return;
otherPlr = PlayerManager::getPlayerFromID(otherPlr->iIDGroup);
if (otherPlr == nullptr)
return;
// fail if the group is full or the other player is already in a group
if (plr->groupCnt >= 4 || otherPlr->iIDGroup != otherPlr->iID || otherPlr->groupCnt > 1) {
if ((plr->group != nullptr && (*plr->group)[EntityKind::PLAYER].size() >= 4) || otherPlr->group != nullptr) {
INITSTRUCT(sP_FE2CL_PC_GROUP_INVITE_FAIL, resp);
sock->sendPacket((void*)&resp, P_FE2CL_PC_GROUP_INVITE_FAIL, sizeof(sP_FE2CL_PC_GROUP_INVITE_FAIL));
return;
@@ -77,28 +120,29 @@ static void joinGroup(CNSocket* sock, CNPacketData* data) {
if (otherPlr == nullptr)
return;
otherPlr = PlayerManager::getPlayerFromID(otherPlr->iIDGroup);
if (otherPlr == nullptr)
return;
int size = otherPlr->group == nullptr ? 1 : (*otherPlr->group)[EntityKind::PLAYER].size();
// fail if the group is full or the other player is already in a group
if (plr->groupCnt > 1 || plr->iIDGroup != plr->iID || otherPlr->groupCnt >= 4) {
if (plr->group != nullptr || size + 1 > 4) {
INITSTRUCT(sP_FE2CL_PC_GROUP_JOIN_FAIL, resp);
sock->sendPacket((void*)&resp, P_FE2CL_PC_GROUP_JOIN_FAIL, sizeof(sP_FE2CL_PC_GROUP_JOIN_FAIL));
return;
}
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_JOIN), otherPlr->groupCnt + 1, sizeof(sPCGroupMemberInfo))) {
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;
}
plr->iIDGroup = otherPlr->iID;
otherPlr->groupCnt += 1;
otherPlr->groupIDs[otherPlr->groupCnt-1] = plr->iID;
if (otherPlr->group == nullptr) {
// create group
otherPlr->group = new Group(); // spooky
addToGroup(PlayerManager::getSockFromID(recv->iID_From), otherPlr->group);
}
addToGroup(sock, otherPlr->group);
auto players = (*otherPlr->group)[EntityKind::PLAYER];
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_JOIN) + otherPlr->groupCnt * sizeof(sPCGroupMemberInfo);
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_JOIN) + players.size() * sizeof(sPCGroupMemberInfo);
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
memset(respbuf, 0, resplen);
@@ -107,13 +151,13 @@ static void joinGroup(CNSocket* sock, CNPacketData* data) {
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_JOIN));
resp->iID_NewMember = plr->iID;
resp->iMemberPCCnt = otherPlr->groupCnt;
resp->iMemberPCCnt = players.size();
int bitFlag = getGroupFlags(otherPlr);
int bitFlag = otherPlr->group->conditionBitFlag;
for (int i = 0; i < players.size(); i++) {
for (int i = 0; i < otherPlr->groupCnt; i++) {
Player* varPlr = PlayerManager::getPlayerFromID(otherPlr->groupIDs[i]);
CNSocket* sockTo = PlayerManager::getSockFromID(otherPlr->groupIDs[i]);
Player* varPlr = PlayerManager::getPlayer(players[i].sock);
CNSocket* sockTo = players[i].sock;
if (varPlr == nullptr || sockTo == nullptr)
continue;
@@ -143,37 +187,32 @@ static void joinGroup(CNSocket* sock, CNPacketData* data) {
}
}
sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen);
Groups::sendToGroup(otherPlr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen);
}
static void leaveGroup(CNSocket* sock, CNPacketData* data) {
Player* plr = PlayerManager::getPlayer(sock);
groupKickPlayer(plr);
groupKick(plr);
}
void Groups::sendToGroup(Player* plr, void* buf, uint32_t type, size_t size) {
for (int i = 0; i < plr->groupCnt; i++) {
CNSocket* sock = PlayerManager::getSockFromID(plr->groupIDs[i]);
if (sock == nullptr)
continue;
if (type == P_FE2CL_PC_GROUP_LEAVE_SUCC) {
Player* leavingPlr = PlayerManager::getPlayer(sock);
leavingPlr->iIDGroup = leavingPlr->iID;
}
void Groups::sendToGroup(Group* group, void* buf, uint32_t type, size_t size) {
auto players = (*group)[EntityKind::PLAYER];
for (int i = 0; i < players.size(); i++) {
CNSocket* sock = players[i].sock;
sock->sendPacket(buf, type, size);
}
}
void Groups::groupTickInfo(Player* plr) {
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO), plr->groupCnt, sizeof(sPCGroupMemberInfo))) {
auto players = (*plr->group)[EntityKind::PLAYER];
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) + plr->groupCnt * sizeof(sPCGroupMemberInfo);
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);
@@ -182,10 +221,11 @@ void Groups::groupTickInfo(Player* plr) {
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO));
resp->iID = plr->iID;
resp->iMemberPCCnt = plr->groupCnt;
resp->iMemberPCCnt = players.size();
for (int i = 0; i < plr->groupCnt; i++) {
Player* varPlr = PlayerManager::getPlayerFromID(plr->groupIDs[i]);
for (int i = 0; i < players.size(); i++) {
EntityRef member = players[i];
Player* varPlr = PlayerManager::getPlayer(member.sock);
if (varPlr == nullptr)
continue;
@@ -210,17 +250,17 @@ void Groups::groupTickInfo(Player* plr) {
}
}
sendToGroup(plr, (void*)&respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO, resplen);
sendToGroup(plr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO, resplen);
}
static void groupUnbuff(Player* plr) {
for (int i = 0; i < plr->groupCnt; i++) {
for (int n = 0; n < plr->groupCnt; n++) {
Group* group = plr->group;
for (int i = 0; i < group->members.size(); i++) {
for (int n = 0; n < group->members.size(); n++) {
if (i == n)
continue;
Player* otherPlr = PlayerManager::getPlayerFromID(plr->groupIDs[i]);
CNSocket* sock = PlayerManager::getSockFromID(plr->groupIDs[n]);
EntityRef other = group->members[n];
// TODO ABILITIES
//Abilities::applyBuff(sock, otherPlr->Nanos[otherPlr->activeNano].iSkillID, 2, 1, 0);
@@ -228,27 +268,26 @@ static void groupUnbuff(Player* plr) {
}
}
void Groups::groupKickPlayer(Player* plr) {
void Groups::groupKick(Player* plr) {
Group* group = plr->group;
// if you are the group leader, destroy your own group and kick everybody
if (plr->iID == plr->iIDGroup) {
if (plr->group->members[0] == PlayerManager::getSockFromID(plr->iID)) {
groupUnbuff(plr);
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1);
sendToGroup(plr, (void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
plr->groupCnt = 1;
sendToGroup(plr->group, (void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
disbandGroup(plr->group);
return;
}
Player* otherPlr = PlayerManager::getPlayerFromID(plr->iIDGroup);
auto players = (*group)[EntityKind::PLAYER];
if (otherPlr == nullptr)
return;
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_LEAVE), otherPlr->groupCnt - 1, sizeof(sPCGroupMemberInfo))) {
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) + (otherPlr->groupCnt - 1) * sizeof(sPCGroupMemberInfo);
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);
@@ -257,78 +296,55 @@ void Groups::groupKickPlayer(Player* plr) {
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_LEAVE));
resp->iID_LeaveMember = plr->iID;
resp->iMemberPCCnt = otherPlr->groupCnt - 1;
resp->iMemberPCCnt = players.size() - 1;
int bitFlag = getGroupFlags(otherPlr) & ~plr->iGroupConditionBitFlag;
int moveDown = 0;
int bitFlag = 0; // TODO ABILITIES getGroupFlags(otherPlr) & ~plr->iGroupConditionBitFlag;
CNSocket* sock = PlayerManager::getSockFromID(plr->iID);
if (sock == nullptr)
return;
for (int i = 0; i < otherPlr->groupCnt; i++) {
Player* varPlr = PlayerManager::getPlayerFromID(otherPlr->groupIDs[i]);
CNSocket* sockTo = PlayerManager::getSockFromID(otherPlr->groupIDs[i]);
removeFromGroup(sock, group);
players = (*group)[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;
if (moveDown == 1)
otherPlr->groupIDs[i-1] = otherPlr->groupIDs[i];
respdata[i-moveDown].iPC_ID = varPlr->iID;
respdata[i-moveDown].iPCUID = varPlr->PCStyle.iPC_UID;
respdata[i-moveDown].iNameCheck = varPlr->PCStyle.iNameCheck;
memcpy(respdata[i-moveDown].szFirstName, varPlr->PCStyle.szFirstName, sizeof(varPlr->PCStyle.szFirstName));
memcpy(respdata[i-moveDown].szLastName, varPlr->PCStyle.szLastName, sizeof(varPlr->PCStyle.szLastName));
respdata[i-moveDown].iSpecialState = varPlr->iSpecialState;
respdata[i-moveDown].iLv = varPlr->level;
respdata[i-moveDown].iHP = varPlr->HP;
respdata[i-moveDown].iMaxHP = PC_MAXHEALTH(varPlr->level);
// respdata[i-moveDown]].iMapType = 0;
// respdata[i-moveDown]].iMapNum = 0;
respdata[i-moveDown].iX = varPlr->x;
respdata[i-moveDown].iY = varPlr->y;
respdata[i-moveDown].iZ = varPlr->z;
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
if (varPlr == plr) {
moveDown = 1;
otherPlr->groupIDs[i] = 0;
} else { // remove the leaving member's buffs from the group and remove the group buffs from the leaving member.
// remove the leaving member's buffs from the group and remove the group buffs from the leaving member.
// TODO ABILITIES
/*if (Abilities::SkillTable[varPlr->Nanos[varPlr->activeNano].iSkillID].targetType == 3)
Abilities::applyBuff(sock, varPlr->Nanos[varPlr->activeNano].iSkillID, 2, 1, 0);
if (Abilities::SkillTable[plr->Nanos[varPlr->activeNano].iSkillID].targetType == 3)
Abilities::applyBuff(sockTo, plr->Nanos[plr->activeNano].iSkillID, 2, 1, bitFlag);*/
}
}
plr->iIDGroup = plr->iID;
otherPlr->groupCnt -= 1;
sendToGroup(otherPlr, (void*)&respbuf, P_FE2CL_PC_GROUP_LEAVE, resplen);
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));
}
int Groups::getGroupFlags(Player* plr) {
int bitFlag = 0;
for (int i = 0; i < plr->groupCnt; i++) {
Player* otherPlr = PlayerManager::getPlayerFromID(plr->groupIDs[i]);
if (otherPlr == nullptr)
continue;
bitFlag |= otherPlr->iGroupConditionBitFlag;
}
return bitFlag;
}
void Groups::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GROUP_INVITE, requestGroup);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GROUP_INVITE_REFUSE, refuseGroup);