2021-03-16 22:29:13 +00:00
|
|
|
#include "Groups.hpp"
|
2020-10-04 23:54:08 +00:00
|
|
|
|
2022-07-16 23:19:40 +00:00
|
|
|
#include "servers/CNShardServer.hpp"
|
|
|
|
|
|
|
|
#include "Player.hpp"
|
|
|
|
#include "PlayerManager.hpp"
|
2020-10-04 23:54:08 +00:00
|
|
|
|
2021-03-19 21:28:25 +00:00
|
|
|
/*
|
|
|
|
* NOTE: Variadic response packets that list group members are technically
|
|
|
|
* double-variadic, as they have two count members with trailing struct counts,
|
|
|
|
* and are thus incompatible with the generic sendPacket() wrapper.
|
|
|
|
* That means we still have to (carefully) use validOutVarPacket() in this
|
|
|
|
* source file.
|
|
|
|
*/
|
|
|
|
|
2021-03-16 22:29:13 +00:00
|
|
|
using namespace Groups;
|
2020-10-04 23:54:08 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 21:06:10 +00:00
|
|
|
static void requestGroup(CNSocket* sock, CNPacketData* data) {
|
2020-10-04 23:54:08 +00:00
|
|
|
sP_CL2FE_REQ_PC_GROUP_INVITE* recv = (sP_CL2FE_REQ_PC_GROUP_INVITE*)data->buf;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
2020-10-04 23:54:08 +00:00
|
|
|
Player* otherPlr = PlayerManager::getPlayerFromID(recv->iID_To);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
if (otherPlr == nullptr)
|
2020-10-21 05:24:51 +00:00
|
|
|
return;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
// fail if the group is full or the other player is already in a group
|
2022-04-24 20:50:03 +00:00
|
|
|
if ((plr->group != nullptr && plr->group->filter(EntityKind::PLAYER).size() >= 4) || otherPlr->group != nullptr) {
|
2020-10-04 23:54:08 +00:00
|
|
|
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;
|
|
|
|
}
|
2020-10-05 00:03:13 +00:00
|
|
|
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(recv->iID_To);
|
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
if (otherSock == nullptr)
|
|
|
|
return;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_GROUP_INVITE, resp);
|
|
|
|
|
2020-12-31 03:54:48 +00:00
|
|
|
resp.iHostID = plr->iID;
|
2020-10-04 23:54:08 +00:00
|
|
|
|
2020-10-21 05:24:51 +00:00
|
|
|
otherSock->sendPacket((void*)&resp, P_FE2CL_PC_GROUP_INVITE, sizeof(sP_FE2CL_PC_GROUP_INVITE));
|
2020-10-04 23:54:08 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 21:06:10 +00:00
|
|
|
static void refuseGroup(CNSocket* sock, CNPacketData* data) {
|
2020-10-04 23:54:08 +00:00
|
|
|
sP_CL2FE_REQ_PC_GROUP_INVITE_REFUSE* recv = (sP_CL2FE_REQ_PC_GROUP_INVITE_REFUSE*)data->buf;
|
|
|
|
|
2020-10-21 05:24:51 +00:00
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(recv->iID_From);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
if (otherSock == nullptr)
|
|
|
|
return;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_GROUP_INVITE_REFUSE, resp);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
resp.iID_To = plr->iID;
|
|
|
|
|
2020-10-21 05:24:51 +00:00
|
|
|
otherSock->sendPacket((void*)&resp, P_FE2CL_PC_GROUP_INVITE_REFUSE, sizeof(sP_FE2CL_PC_GROUP_INVITE_REFUSE));
|
2020-10-04 23:54:08 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 21:06:10 +00:00
|
|
|
static void joinGroup(CNSocket* sock, CNPacketData* data) {
|
2020-10-04 23:54:08 +00:00
|
|
|
sP_CL2FE_REQ_PC_GROUP_JOIN* recv = (sP_CL2FE_REQ_PC_GROUP_JOIN*)data->buf;
|
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
Player* otherPlr = PlayerManager::getPlayerFromID(recv->iID_From);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
if (otherPlr == nullptr)
|
2020-10-21 05:24:51 +00:00
|
|
|
return;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-24 20:50:03 +00:00
|
|
|
int size = otherPlr->group == nullptr ? 1 : otherPlr->group->filter(EntityKind::PLAYER).size();
|
2022-04-23 19:58:08 +00:00
|
|
|
|
2020-10-09 00:01:35 +00:00
|
|
|
// fail if the group is full or the other player is already in a group
|
2022-04-23 19:58:08 +00:00
|
|
|
if (plr->group != nullptr || size + 1 > 4) {
|
2020-10-09 16:24:16 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_GROUP_JOIN_FAIL, resp);
|
2020-10-04 23:54:08 +00:00
|
|
|
sock->sendPacket((void*)&resp, P_FE2CL_PC_GROUP_JOIN_FAIL, sizeof(sP_FE2CL_PC_GROUP_JOIN_FAIL));
|
|
|
|
return;
|
|
|
|
}
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 19:58:08 +00:00
|
|
|
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_JOIN), size + 1, sizeof(sPCGroupMemberInfo))) {
|
2020-10-04 23:54:08 +00:00
|
|
|
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_JOIN packet size\n";
|
|
|
|
return;
|
|
|
|
}
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
if (otherPlr->group == nullptr) {
|
|
|
|
// create group
|
|
|
|
otherPlr->group = new Group(); // spooky
|
|
|
|
addToGroup(PlayerManager::getSockFromID(recv->iID_From), otherPlr->group);
|
|
|
|
}
|
|
|
|
addToGroup(sock, otherPlr->group);
|
2022-04-24 20:50:03 +00:00
|
|
|
auto players = otherPlr->group->filter(EntityKind::PLAYER);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_JOIN) + players.size() * sizeof(sPCGroupMemberInfo);
|
2020-10-04 23:54:08 +00:00
|
|
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
memset(respbuf, 0, resplen);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
sP_FE2CL_PC_GROUP_JOIN *resp = (sP_FE2CL_PC_GROUP_JOIN*)respbuf;
|
|
|
|
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_JOIN));
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
resp->iID_NewMember = plr->iID;
|
2022-04-23 01:13:00 +00:00
|
|
|
resp->iMemberPCCnt = players.size();
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
for (int i = 0; i < players.size(); i++) {
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
Player* varPlr = PlayerManager::getPlayer(players[i].sock);
|
|
|
|
CNSocket* sockTo = players[i].sock;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-09 00:01:35 +00:00
|
|
|
if (varPlr == nullptr || sockTo == nullptr)
|
2020-10-04 23:54:08 +00:00
|
|
|
continue;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
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
|
|
|
|
}
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
Groups::sendToGroup(otherPlr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_JOIN, resplen);
|
2020-10-04 23:54:08 +00:00
|
|
|
}
|
|
|
|
|
2021-03-16 21:06:10 +00:00
|
|
|
static void leaveGroup(CNSocket* sock, CNPacketData* data) {
|
2020-10-04 23:54:08 +00:00
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
2022-04-23 01:13:00 +00:00
|
|
|
groupKick(plr);
|
2020-10-04 23:54:08 +00:00
|
|
|
}
|
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
void Groups::sendToGroup(Group* group, void* buf, uint32_t type, size_t size) {
|
2022-04-24 20:50:03 +00:00
|
|
|
auto players = group->filter(EntityKind::PLAYER);
|
2022-04-23 01:13:00 +00:00
|
|
|
for (int i = 0; i < players.size(); i++) {
|
|
|
|
CNSocket* sock = players[i].sock;
|
2020-10-04 23:54:08 +00:00
|
|
|
sock->sendPacket(buf, type, size);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-16 22:29:13 +00:00
|
|
|
void Groups::groupTickInfo(Player* plr) {
|
2022-04-23 01:13:00 +00:00
|
|
|
|
2022-04-24 20:50:03 +00:00
|
|
|
auto players = plr->group->filter(EntityKind::PLAYER);
|
2022-04-23 01:13:00 +00:00
|
|
|
|
|
|
|
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO), players.size(), sizeof(sPCGroupMemberInfo))) {
|
2020-10-04 23:54:08 +00:00
|
|
|
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_JOIN packet size\n";
|
|
|
|
return;
|
|
|
|
}
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_MEMBER_INFO) + players.size() * sizeof(sPCGroupMemberInfo);
|
2020-10-04 23:54:08 +00:00
|
|
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
memset(respbuf, 0, resplen);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
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));
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
resp->iID = plr->iID;
|
2022-04-23 01:13:00 +00:00
|
|
|
resp->iMemberPCCnt = players.size();
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
for (int i = 0; i < players.size(); i++) {
|
|
|
|
EntityRef member = players[i];
|
|
|
|
Player* varPlr = PlayerManager::getPlayer(member.sock);
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
if (varPlr == nullptr)
|
|
|
|
continue;
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
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];
|
|
|
|
}
|
|
|
|
}
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
sendToGroup(plr->group, (void*)&respbuf, P_FE2CL_PC_GROUP_MEMBER_INFO, resplen);
|
2020-10-04 23:54:08 +00:00
|
|
|
}
|
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
void Groups::groupKick(Player* plr) {
|
|
|
|
Group* group = plr->group;
|
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
// if you are the group leader, destroy your own group and kick everybody
|
2022-04-23 01:13:00 +00:00
|
|
|
if (plr->group->members[0] == PlayerManager::getSockFromID(plr->iID)) {
|
2020-10-04 23:54:08 +00:00
|
|
|
INITSTRUCT(sP_FE2CL_PC_GROUP_LEAVE_SUCC, resp1);
|
2022-04-23 01:13:00 +00:00
|
|
|
sendToGroup(plr->group, (void*)&resp1, P_FE2CL_PC_GROUP_LEAVE_SUCC, sizeof(sP_FE2CL_PC_GROUP_LEAVE_SUCC));
|
|
|
|
disbandGroup(plr->group);
|
2020-10-04 23:54:08 +00:00
|
|
|
return;
|
|
|
|
}
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-24 20:50:03 +00:00
|
|
|
auto players = group->filter(EntityKind::PLAYER);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
if (!validOutVarPacket(sizeof(sP_FE2CL_PC_GROUP_LEAVE), players.size() - 1, sizeof(sPCGroupMemberInfo))) {
|
2020-10-04 23:54:08 +00:00
|
|
|
std::cout << "[WARN] bad sP_FE2CL_PC_GROUP_LEAVE packet size\n";
|
|
|
|
return;
|
|
|
|
}
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
size_t resplen = sizeof(sP_FE2CL_PC_GROUP_LEAVE) + (players.size() - 1) * sizeof(sPCGroupMemberInfo);
|
2020-10-04 23:54:08 +00:00
|
|
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
memset(respbuf, 0, resplen);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
sP_FE2CL_PC_GROUP_LEAVE *resp = (sP_FE2CL_PC_GROUP_LEAVE*)respbuf;
|
|
|
|
sPCGroupMemberInfo *respdata = (sPCGroupMemberInfo*)(respbuf+sizeof(sP_FE2CL_PC_GROUP_LEAVE));
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
resp->iID_LeaveMember = plr->iID;
|
2022-04-23 01:13:00 +00:00
|
|
|
resp->iMemberPCCnt = players.size() - 1;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-11-08 00:26:44 +00:00
|
|
|
CNSocket* sock = PlayerManager::getSockFromID(plr->iID);
|
|
|
|
|
|
|
|
if (sock == nullptr)
|
|
|
|
return;
|
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
removeFromGroup(sock, group);
|
|
|
|
|
2022-04-24 20:50:03 +00:00
|
|
|
players = group->filter(EntityKind::PLAYER);
|
2022-04-23 01:13:00 +00:00
|
|
|
for (int i = 0; i < players.size(); i++) {
|
|
|
|
CNSocket* sockTo = players[i].sock;
|
|
|
|
Player* varPlr = PlayerManager::getPlayer(sock);
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2020-10-09 00:01:35 +00:00
|
|
|
if (varPlr == nullptr || sockTo == nullptr)
|
2020-10-04 23:54:08 +00:00
|
|
|
continue;
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
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;
|
2020-10-04 23:54:08 +00:00
|
|
|
// client doesnt read nano data here
|
|
|
|
}
|
2020-10-05 00:03:13 +00:00
|
|
|
|
2022-04-23 01:13:00 +00:00
|
|
|
sendToGroup(group, (void*)&respbuf, P_FE2CL_PC_GROUP_LEAVE, resplen);
|
2020-10-19 17:26:14 +00:00
|
|
|
|
2020-10-04 23:54:08 +00:00
|
|
|
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));
|
|
|
|
}
|
2020-10-09 00:01:35 +00:00
|
|
|
|
2021-03-16 22:29:13 +00:00
|
|
|
void Groups::init() {
|
2021-03-16 21:06:10 +00:00
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GROUP_INVITE, requestGroup);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GROUP_INVITE_REFUSE, refuseGroup);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GROUP_JOIN, joinGroup);
|
|
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_GROUP_LEAVE, leaveGroup);
|
|
|
|
}
|