mirror of
https://github.com/OpenFusionProject/OpenFusion.git
synced 2025-06-25 13:50:10 +00:00

Was getting frustrated by the inconsistency in our include statements, which were causing me problems. As a result, I went through and manually re-organized every include statement in non-core files. I'm just gonna copy my rant from Discord: FOR HEADER FILES (.hpp): - everything you use IN THE HEADER must be EXPLICITLY INCLUDED with the exception of things that fall under Core.hpp - you may NOT include ANYTHING ELSE FOR SOURCE FILES (.cpp): - you can #include whatever you want as long as the partner header is included first - anything that gets included by another include is fair game - redundant includes are ok because they'll be harmless AS LONG AS our header files stay lean. the point of this is NOT to optimize the number of includes used all around or make things more efficient necessarily. it's to improve readability & coherence and make it easier to avoid cyclical issues
466 lines
17 KiB
C++
466 lines
17 KiB
C++
#include "Buddies.hpp"
|
|
|
|
#include "db/Database.hpp"
|
|
#include "servers/CNShardServer.hpp"
|
|
|
|
#include "Player.hpp"
|
|
#include "PlayerManager.hpp"
|
|
|
|
using namespace Buddies;
|
|
|
|
#pragma region Helper methods
|
|
|
|
static int getAvailableBuddySlot(Player* plr) {
|
|
int slot = -1;
|
|
for (int i = 0; i < 50; i++) {
|
|
if (plr->buddyIDs[i] == 0)
|
|
return i;
|
|
}
|
|
return slot;
|
|
}
|
|
|
|
static bool playerHasBuddyWithID(Player* plr, int buddyID) {
|
|
for (int i = 0; i < 50; i++) {
|
|
if (plr->buddyIDs[i] == buddyID)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
#pragma endregion
|
|
|
|
// Refresh buddy list
|
|
void Buddies::refreshBuddyList(CNSocket* sock) {
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
int buddyCnt = Database::getNumBuddies(plr);
|
|
|
|
if (!validOutVarPacket(sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC), buddyCnt, sizeof(sBuddyBaseInfo))) {
|
|
std::cout << "[WARN] bad sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC packet size\n";
|
|
return;
|
|
}
|
|
|
|
// initialize response struct
|
|
size_t resplen = sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC) + buddyCnt * sizeof(sBuddyBaseInfo);
|
|
uint8_t respbuf[CN_PACKET_BUFFER_SIZE];
|
|
|
|
memset(respbuf, 0, resplen);
|
|
|
|
sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC* resp = (sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC*)respbuf;
|
|
sBuddyBaseInfo* respdata = (sBuddyBaseInfo*)(respbuf + sizeof(sP_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC));
|
|
|
|
// base response fields
|
|
resp->iBuddyCnt = buddyCnt;
|
|
resp->iID = plr->iID;
|
|
resp->iPCUID = plr->PCStyle.iPC_UID;
|
|
resp->iListNum = 0; // ???
|
|
|
|
int buddyIndex = 0;
|
|
for (int i = 0; i < 50; i++) {
|
|
int64_t buddyID = plr->buddyIDs[i];
|
|
if (buddyID != 0) {
|
|
sBuddyBaseInfo buddyInfo = {};
|
|
Player buddyPlayerData = {};
|
|
Database::getPlayer(&buddyPlayerData, buddyID);
|
|
if (buddyPlayerData.iID == 0)
|
|
continue;
|
|
buddyInfo.bBlocked = plr->isBuddyBlocked[i];
|
|
buddyInfo.bFreeChat = 1;
|
|
buddyInfo.iGender = buddyPlayerData.PCStyle.iGender;
|
|
buddyInfo.iID = buddyID;
|
|
buddyInfo.iPCUID = buddyID;
|
|
buddyInfo.iNameCheckFlag = buddyPlayerData.PCStyle.iNameCheck;
|
|
buddyInfo.iPCState = buddyPlayerData.iPCState;
|
|
memcpy(buddyInfo.szFirstName, buddyPlayerData.PCStyle.szFirstName, sizeof(buddyInfo.szFirstName));
|
|
memcpy(buddyInfo.szLastName, buddyPlayerData.PCStyle.szLastName, sizeof(buddyInfo.szLastName));
|
|
respdata[buddyIndex] = buddyInfo;
|
|
buddyIndex++;
|
|
}
|
|
}
|
|
|
|
sock->sendPacket((void*)respbuf, P_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC, resplen);
|
|
}
|
|
|
|
// Buddy request
|
|
static void requestBuddy(CNSocket* sock, CNPacketData* data) {
|
|
auto req = (sP_CL2FE_REQ_REQUEST_MAKE_BUDDY*)data->buf;
|
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
Player* otherPlr = PlayerManager::getPlayerFromID(req->iBuddyID);
|
|
|
|
if (otherPlr == nullptr)
|
|
return;
|
|
|
|
if (getAvailableBuddySlot(plr) == -1 || getAvailableBuddySlot(otherPlr) == -1)
|
|
{
|
|
INITSTRUCT(sP_FE2CL_REP_REQUEST_MAKE_BUDDY_FAIL, failResp);
|
|
sock->sendPacket(failResp, P_FE2CL_REP_REQUEST_MAKE_BUDDY_FAIL);
|
|
return;
|
|
}
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(otherPlr->iID);
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC, resp);
|
|
INITSTRUCT(sP_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC_TO_ACCEPTER, otherResp);
|
|
|
|
resp.iRequestID = plr->iID;
|
|
resp.iBuddyID = req->iBuddyID;
|
|
resp.iBuddyPCUID = req->iBuddyPCUID;
|
|
|
|
otherResp.iRequestID = plr->iID;
|
|
otherResp.iBuddyID = req->iBuddyID;
|
|
memcpy(otherResp.szFirstName, plr->PCStyle.szFirstName, sizeof(plr->PCStyle.szFirstName));
|
|
memcpy(otherResp.szLastName, plr->PCStyle.szLastName, sizeof(plr->PCStyle.szLastName));
|
|
|
|
std::cout << "Buddy ID: " << req->iBuddyID << std::endl;
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC);
|
|
otherSock->sendPacket(otherResp, P_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC_TO_ACCEPTER);
|
|
|
|
}
|
|
|
|
// Sending buddy request by player name
|
|
static void reqBuddyByName(CNSocket* sock, CNPacketData* data) {
|
|
auto pkt = (sP_CL2FE_REQ_PC_FIND_NAME_MAKE_BUDDY*)data->buf;
|
|
Player* plrReq = PlayerManager::getPlayer(sock);
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_SUCC, resp);
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromName(AUTOU16TOU8(pkt->szFirstName), AUTOU16TOU8(pkt->szLastName));
|
|
if (otherSock == nullptr)
|
|
return; // no player found
|
|
|
|
Player *otherPlr = PlayerManager::getPlayer(otherSock);
|
|
if (playerHasBuddyWithID(plrReq, otherPlr->iID))
|
|
return;
|
|
|
|
resp.iPCUID = plrReq->PCStyle.iPC_UID;
|
|
resp.iNameCheckFlag = plrReq->PCStyle.iNameCheck;
|
|
|
|
memcpy(resp.szFirstName, plrReq->PCStyle.szFirstName, sizeof(plrReq->PCStyle.szFirstName));
|
|
memcpy(resp.szLastName, plrReq->PCStyle.szLastName, sizeof(plrReq->PCStyle.szLastName));
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_SUCC);
|
|
}
|
|
|
|
// Accepting buddy request
|
|
static void reqAcceptBuddy(CNSocket* sock, CNPacketData* data) {
|
|
auto req = (sP_CL2FE_REQ_ACCEPT_MAKE_BUDDY*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
Player* otherPlr = PlayerManager::getPlayerFromID(req->iBuddyID);
|
|
|
|
if (otherPlr == nullptr)
|
|
return; // sanity check
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(otherPlr->iID);
|
|
|
|
int slotA = getAvailableBuddySlot(plr);
|
|
int slotB = getAvailableBuddySlot(otherPlr);
|
|
if (slotA == -1 || slotB == -1)
|
|
return; // sanity check
|
|
|
|
if (req->iAcceptFlag == 1 && plr->iID != otherPlr->iID && !playerHasBuddyWithID(plr, otherPlr->iID))
|
|
{
|
|
INITSTRUCT(sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC, resp);
|
|
|
|
// A to B
|
|
resp.iBuddySlot = slotA;
|
|
resp.BuddyInfo.iID = otherPlr->iID;
|
|
resp.BuddyInfo.iPCUID = otherPlr->PCStyle.iPC_UID;
|
|
resp.BuddyInfo.iPCState = 1; // assumed to be online
|
|
resp.BuddyInfo.bBlocked = 0; // not blocked by default
|
|
resp.BuddyInfo.iGender = otherPlr->PCStyle.iGender; // shows the other player's gender
|
|
resp.BuddyInfo.bFreeChat = 1; // shows whether or not the other player has freechat on (hardcoded for now)
|
|
resp.BuddyInfo.iNameCheckFlag = otherPlr->PCStyle.iNameCheck;
|
|
memcpy(resp.BuddyInfo.szFirstName, otherPlr->PCStyle.szFirstName, sizeof(resp.BuddyInfo.szFirstName));
|
|
memcpy(resp.BuddyInfo.szLastName, otherPlr->PCStyle.szLastName, sizeof(resp.BuddyInfo.szLastName));
|
|
sock->sendPacket(resp, P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC);
|
|
plr->buddyIDs[slotA] = otherPlr->PCStyle.iPC_UID;
|
|
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotA] << std::endl;
|
|
|
|
// B to A, using the same struct
|
|
resp.iBuddySlot = slotB;
|
|
resp.BuddyInfo.iID = plr->iID;
|
|
resp.BuddyInfo.iPCUID = plr->PCStyle.iPC_UID;
|
|
resp.BuddyInfo.iPCState = 1;
|
|
resp.BuddyInfo.bBlocked = 0;
|
|
resp.BuddyInfo.iGender = plr->PCStyle.iGender;
|
|
resp.BuddyInfo.bFreeChat = 1;
|
|
resp.BuddyInfo.iNameCheckFlag = plr->PCStyle.iNameCheck;
|
|
memcpy(resp.BuddyInfo.szFirstName, plr->PCStyle.szFirstName, sizeof(resp.BuddyInfo.szFirstName));
|
|
memcpy(resp.BuddyInfo.szLastName, plr->PCStyle.szLastName, sizeof(resp.BuddyInfo.szLastName));
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC);
|
|
otherPlr->buddyIDs[slotB] = plr->PCStyle.iPC_UID;
|
|
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotB] << std::endl;
|
|
|
|
// add record to db
|
|
Database::addBuddyship(plr->iID, otherPlr->iID);
|
|
}
|
|
else
|
|
{
|
|
INITSTRUCT(sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL, declineResp);
|
|
|
|
declineResp.iErrorCode = 6; // Buddy declined notification
|
|
declineResp.iBuddyID = req->iBuddyID;
|
|
declineResp.iBuddyPCUID = req->iBuddyPCUID;
|
|
|
|
otherSock->sendPacket(declineResp, P_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL);
|
|
}
|
|
|
|
}
|
|
|
|
// Accepting buddy request from the find name request
|
|
static void reqFindNameBuddyAccept(CNSocket* sock, CNPacketData* data) {
|
|
auto pkt = (sP_CL2FE_REQ_PC_FIND_NAME_ACCEPT_BUDDY*)data->buf;
|
|
|
|
Player* plrReq = PlayerManager::getPlayer(sock);
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC, resp);
|
|
|
|
Player* otherPlr = PlayerManager::getPlayerFromID(pkt->iBuddyPCUID);
|
|
|
|
if (otherPlr == nullptr)
|
|
return;
|
|
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID);
|
|
|
|
int slotA = getAvailableBuddySlot(plrReq);
|
|
int slotB = getAvailableBuddySlot(otherPlr);
|
|
if (slotA == -1 || slotB == -1)
|
|
return; // sanity check
|
|
|
|
if (pkt->iAcceptFlag == 1 && plrReq->iID != otherPlr->iID && !playerHasBuddyWithID(plrReq, otherPlr->iID)) {
|
|
INITSTRUCT(sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC, resp);
|
|
|
|
// A to B
|
|
resp.iBuddySlot = slotA;
|
|
resp.BuddyInfo.iID = otherPlr->iID;
|
|
resp.BuddyInfo.iPCUID = otherPlr->PCStyle.iPC_UID;
|
|
resp.BuddyInfo.iPCState = 1; // assumed to be online
|
|
resp.BuddyInfo.bBlocked = 0; // not blocked by default
|
|
resp.BuddyInfo.iGender = otherPlr->PCStyle.iGender; // shows the other player's gender
|
|
resp.BuddyInfo.bFreeChat = 1; // shows whether or not the other player has freechat on (hardcoded for now)
|
|
resp.BuddyInfo.iNameCheckFlag = otherPlr->PCStyle.iNameCheck;
|
|
memcpy(resp.BuddyInfo.szFirstName, otherPlr->PCStyle.szFirstName, sizeof(resp.BuddyInfo.szFirstName));
|
|
memcpy(resp.BuddyInfo.szLastName, otherPlr->PCStyle.szLastName, sizeof(resp.BuddyInfo.szLastName));
|
|
sock->sendPacket(resp, P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC);
|
|
plrReq->buddyIDs[slotA] = otherPlr->PCStyle.iPC_UID;
|
|
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotA] << std::endl;
|
|
|
|
// B to A, using the same struct
|
|
resp.iBuddySlot = slotB;
|
|
resp.BuddyInfo.iID = plrReq->iID;
|
|
resp.BuddyInfo.iPCUID = plrReq->PCStyle.iPC_UID;
|
|
resp.BuddyInfo.iPCState = 1;
|
|
resp.BuddyInfo.bBlocked = 0;
|
|
resp.BuddyInfo.iGender = plrReq->PCStyle.iGender;
|
|
resp.BuddyInfo.bFreeChat = 1;
|
|
resp.BuddyInfo.iNameCheckFlag = plrReq->PCStyle.iNameCheck;
|
|
memcpy(resp.BuddyInfo.szFirstName, plrReq->PCStyle.szFirstName, sizeof(resp.BuddyInfo.szFirstName));
|
|
memcpy(resp.BuddyInfo.szLastName, plrReq->PCStyle.szLastName, sizeof(resp.BuddyInfo.szLastName));
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC);
|
|
otherPlr->buddyIDs[slotB] = plrReq->PCStyle.iPC_UID;
|
|
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotB] << std::endl;
|
|
|
|
// add record to db
|
|
Database::addBuddyship(plrReq->iID, otherPlr->iID);
|
|
}
|
|
else
|
|
{
|
|
INITSTRUCT(sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL, declineResp);
|
|
|
|
declineResp.iErrorCode = 6; // Buddy declined notification
|
|
declineResp.iBuddyPCUID = pkt->iBuddyPCUID;
|
|
otherSock->sendPacket(declineResp, P_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL);
|
|
}
|
|
|
|
}
|
|
|
|
// Getting buddy state
|
|
static void reqPktGetBuddyState(CNSocket* sock, CNPacketData* data) {
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
/*
|
|
* If the buddy list wasn't synced a second time yet, sync it.
|
|
* Not sure why we have to do it again for the client not to trip up.
|
|
*/
|
|
if (!plr->buddiesSynced) {
|
|
refreshBuddyList(sock);
|
|
plr->buddiesSynced = true;
|
|
}
|
|
|
|
INITSTRUCT(sP_FE2CL_REP_GET_BUDDY_STATE_SUCC, resp);
|
|
|
|
for (int slot = 0; slot < 50; slot++) {
|
|
resp.aBuddyState[slot] = PlayerManager::getPlayerFromID(plr->buddyIDs[slot]) != nullptr ? 1 : 0;
|
|
resp.aBuddyID[slot] = plr->buddyIDs[slot];
|
|
}
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_GET_BUDDY_STATE_SUCC);
|
|
}
|
|
|
|
// Blocking the buddy
|
|
static void reqBuddyBlock(CNSocket* sock, CNPacketData* data) {
|
|
auto pkt = (sP_CL2FE_REQ_SET_BUDDY_BLOCK*)data->buf;
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
// sanity checks
|
|
if (pkt->iBuddySlot < 0 || pkt->iBuddySlot >= 50 || plr->buddyIDs[pkt->iBuddySlot] != pkt->iBuddyPCUID)
|
|
return;
|
|
|
|
// save in DB
|
|
Database::removeBuddyship(plr->iID, pkt->iBuddyPCUID);
|
|
Database::addBlock(plr->iID, pkt->iBuddyPCUID);
|
|
|
|
// save serverside
|
|
// since ID is already in the array, just set it to blocked
|
|
plr->isBuddyBlocked[pkt->iBuddySlot] = true;
|
|
|
|
// send response
|
|
INITSTRUCT(sP_FE2CL_REP_SET_BUDDY_BLOCK_SUCC, resp);
|
|
resp.iBuddyPCUID = pkt->iBuddyPCUID;
|
|
resp.iBuddySlot = pkt->iBuddySlot;
|
|
sock->sendPacket(resp, P_FE2CL_REP_SET_BUDDY_BLOCK_SUCC);
|
|
|
|
// notify the other player he isn't a buddy anymore
|
|
INITSTRUCT(sP_FE2CL_REP_REMOVE_BUDDY_SUCC, otherResp);
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID);
|
|
if (otherSock == nullptr)
|
|
return; // other player isn't online, no broadcast needed
|
|
Player* otherPlr = PlayerManager::getPlayer(otherSock);
|
|
// search for the slot with the requesting player's ID
|
|
otherResp.iBuddyPCUID = plr->PCStyle.iPC_UID;
|
|
for (int i = 0; i < 50; i++) {
|
|
if (otherPlr->buddyIDs[i] == plr->PCStyle.iPC_UID) {
|
|
// remove buddy
|
|
otherPlr->buddyIDs[i] = 0;
|
|
// broadcast
|
|
otherResp.iBuddySlot = i;
|
|
otherSock->sendPacket(otherResp, P_FE2CL_REP_REMOVE_BUDDY_SUCC);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// block non-buddy
|
|
static void reqPlayerBlock(CNSocket* sock, CNPacketData* data) {
|
|
auto pkt = (sP_CL2FE_REQ_SET_PC_BLOCK*)data->buf;
|
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
int buddySlot = getAvailableBuddySlot(plr);
|
|
if (buddySlot == -1)
|
|
return;
|
|
|
|
// save in DB
|
|
Database::addBlock(plr->iID, pkt->iBlock_PCUID);
|
|
|
|
// save serverside
|
|
plr->buddyIDs[buddySlot] = pkt->iBlock_PCUID;
|
|
plr->isBuddyBlocked[buddySlot] = true;
|
|
|
|
// send response
|
|
INITSTRUCT(sP_FE2CL_REP_SET_PC_BLOCK_SUCC, resp);
|
|
resp.iBlock_ID = pkt->iBlock_ID;
|
|
resp.iBlock_PCUID = pkt->iBlock_PCUID;
|
|
resp.iBuddySlot = buddySlot;
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_SET_PC_BLOCK_SUCC);
|
|
}
|
|
|
|
// Deleting the buddy
|
|
static void reqBuddyDelete(CNSocket* sock, CNPacketData* data) {
|
|
// note! this packet is used both for removing buddies and blocks
|
|
auto pkt = (sP_CL2FE_REQ_REMOVE_BUDDY*)data->buf;
|
|
|
|
Player* plr = PlayerManager::getPlayer(sock);
|
|
|
|
// remove buddy on our side
|
|
INITSTRUCT(sP_FE2CL_REP_REMOVE_BUDDY_SUCC, resp);
|
|
resp.iBuddyPCUID = pkt->iBuddyPCUID;
|
|
resp.iBuddySlot = pkt->iBuddySlot;
|
|
if (pkt->iBuddySlot < 0 || pkt->iBuddySlot >= 50 || plr->buddyIDs[pkt->iBuddySlot] != pkt->iBuddyPCUID)
|
|
return; // sanity check
|
|
|
|
bool wasBlocked = plr->isBuddyBlocked[resp.iBuddySlot];
|
|
plr->buddyIDs[resp.iBuddySlot] = 0;
|
|
plr->isBuddyBlocked[resp.iBuddySlot] = false;
|
|
|
|
sock->sendPacket(resp, P_FE2CL_REP_REMOVE_BUDDY_SUCC);
|
|
|
|
// remove record from db
|
|
Database::removeBuddyship(plr->PCStyle.iPC_UID, pkt->iBuddyPCUID);
|
|
// try this too
|
|
Database::removeBlock(plr->PCStyle.iPC_UID, pkt->iBuddyPCUID);
|
|
|
|
if (wasBlocked)
|
|
return;
|
|
|
|
// remove buddy on their side, reusing the struct
|
|
CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID);
|
|
if (otherSock == nullptr)
|
|
return; // other player isn't online, no broadcast needed
|
|
Player* otherPlr = PlayerManager::getPlayer(otherSock);
|
|
// search for the slot with the requesting player's ID
|
|
resp.iBuddyPCUID = plr->PCStyle.iPC_UID;
|
|
for (int i = 0; i < 50; i++) {
|
|
if (otherPlr->buddyIDs[i] == plr->PCStyle.iPC_UID) {
|
|
// remove buddy
|
|
otherPlr->buddyIDs[i] = 0;
|
|
// broadcast
|
|
resp.iBuddySlot = i;
|
|
otherSock->sendPacket(resp, P_FE2CL_REP_REMOVE_BUDDY_SUCC);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Warping to buddy
|
|
static void reqBuddyWarp(CNSocket* sock, CNPacketData* data) {
|
|
Player *plr = PlayerManager::getPlayer(sock);
|
|
|
|
auto pkt = (sP_CL2FE_REQ_PC_BUDDY_WARP*)data->buf;
|
|
|
|
if (pkt->iSlotNum < 0 || pkt->iSlotNum >= 50)
|
|
return; // sanity check
|
|
|
|
Player* otherPlr = PlayerManager::getPlayerFromID(pkt->iBuddyPCUID);
|
|
if (otherPlr == nullptr)
|
|
return; // buddy offline
|
|
|
|
// if the player is instanced; no warp allowed
|
|
if (otherPlr->instanceID != INSTANCE_OVERWORLD)
|
|
goto fail;
|
|
|
|
// check if the players are at the same point in time (or in the training area or not)
|
|
if (otherPlr->PCStyle2.iPayzoneFlag != plr->PCStyle2.iPayzoneFlag)
|
|
goto fail;
|
|
|
|
// do not warp to players on monkeys
|
|
if (otherPlr->onMonkey)
|
|
goto fail;
|
|
|
|
// does the player disallow warping?
|
|
if (otherPlr->unwarpable)
|
|
goto fail;
|
|
|
|
// otherPlr->instanceID should always be INSTANCE_OVERWORLD at this point
|
|
PlayerManager::sendPlayerTo(sock, otherPlr->x, otherPlr->y, otherPlr->z, otherPlr->instanceID);
|
|
return;
|
|
|
|
fail:
|
|
INITSTRUCT(sP_FE2CL_REP_PC_BUDDY_WARP_FAIL, resp);
|
|
resp.iBuddyPCUID = pkt->iBuddyPCUID;
|
|
resp.iErrorCode = 0;
|
|
sock->sendPacket(resp, P_FE2CL_REP_PC_BUDDY_WARP_FAIL);
|
|
}
|
|
|
|
void Buddies::init() {
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_REQUEST_MAKE_BUDDY, requestBuddy);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIND_NAME_MAKE_BUDDY, reqBuddyByName);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_ACCEPT_MAKE_BUDDY, reqAcceptBuddy);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_FIND_NAME_ACCEPT_BUDDY, reqFindNameBuddyAccept);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_GET_BUDDY_STATE, reqPktGetBuddyState);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SET_BUDDY_BLOCK, reqBuddyBlock);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SET_PC_BLOCK, reqPlayerBlock);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_REMOVE_BUDDY, reqBuddyDelete);
|
|
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BUDDY_WARP, reqBuddyWarp);
|
|
}
|