2020-09-19 19:07:09 +00:00
# include "CNShardServer.hpp"
# include "CNStructs.hpp"
# include "ChatManager.hpp"
# include "PlayerManager.hpp"
# include "BuddyManager.hpp"
2020-11-08 17:42:27 +00:00
# include "Database.hpp"
2020-11-05 05:40:45 +00:00
# include "ItemManager.hpp"
2020-11-07 02:10:41 +00:00
# include "Database.hpp"
2020-09-19 19:07:09 +00:00
2020-09-23 17:52:21 +00:00
# include <iostream>
# include <chrono>
2020-09-19 19:07:09 +00:00
# include <algorithm>
2020-09-23 17:52:21 +00:00
# include <thread>
2020-09-19 19:07:09 +00:00
void BuddyManager : : init ( ) {
2020-10-05 00:03:13 +00:00
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_SEND_BUDDY_FREECHAT_MESSAGE , reqBuddyFreechat ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE , reqBuddyMenuchat ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_GET_BUDDY_STATE , reqPktGetBuddyState ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_SET_BUDDY_BLOCK , reqBuddyBlock ) ;
2020-12-05 00:29:08 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_SET_PC_BLOCK , reqPlayerBlock ) ;
2020-10-05 00:03:13 +00:00
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_REMOVE_BUDDY , reqBuddyDelete ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_BUDDY_WARP , reqBuddyWarp ) ;
2020-11-05 05:40:45 +00:00
//
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_EMAIL_UPDATE_CHECK , emailUpdateCheck ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_RECV_EMAIL_PAGE_LIST , emailReceivePageList ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_READ_EMAIL , emailRead ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_RECV_EMAIL_CANDY , emailReceiveTaros ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_RECV_EMAIL_ITEM , emailReceiveItemSingle ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_RECV_EMAIL_ITEM_ALL , emailReceiveItemAll ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_DELETE_EMAIL , emailDelete ) ;
REGISTER_SHARD_PACKET ( P_CL2FE_REQ_PC_SEND_EMAIL , emailSend ) ;
2020-09-19 19:07:09 +00:00
}
2020-11-08 17:42:27 +00:00
// Refresh buddy list
void BuddyManager : : 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 = { } ;
2020-12-03 00:40:36 +00:00
Player buddyPlayerData = { } ;
Database : : getPlayer ( & buddyPlayerData , buddyID ) ;
if ( buddyPlayerData . iID = = 0 )
2020-11-10 23:00:34 +00:00
continue ;
2020-12-05 00:29:08 +00:00
buddyInfo . bBlocked = plr - > isBuddyBlocked [ i ] ;
2020-11-08 17:42:27 +00:00
buddyInfo . bFreeChat = 1 ;
2020-12-03 00:40:36 +00:00
buddyInfo . iGender = buddyPlayerData . PCStyle . iGender ;
2020-11-08 17:42:27 +00:00
buddyInfo . iID = buddyID ;
buddyInfo . iPCUID = buddyID ;
2020-12-03 00:40:36 +00:00
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 ) ) ;
2020-11-08 17:42:27 +00:00
respdata [ buddyIndex ] = buddyInfo ;
buddyIndex + + ;
}
}
sock - > sendPacket ( ( void * ) respbuf , P_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC , resplen ) ;
}
2020-10-19 17:26:14 +00:00
// Buddy request
2020-09-19 19:07:09 +00:00
void BuddyManager : : requestBuddy ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_REQUEST_MAKE_BUDDY ) )
return ; // malformed packet
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
sP_CL2FE_REQ_REQUEST_MAKE_BUDDY * req = ( sP_CL2FE_REQ_REQUEST_MAKE_BUDDY * ) data - > buf ;
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
Player * otherPlr = PlayerManager : : getPlayerFromID ( req - > iBuddyID ) ;
2020-11-27 03:28:18 +00:00
if ( otherPlr = = nullptr )
return ;
2020-11-08 04:11:56 +00:00
if ( getAvailableBuddySlot ( plr ) = = - 1 | | getAvailableBuddySlot ( otherPlr ) = = - 1 )
2020-10-27 15:28:37 +00:00
{
INITSTRUCT ( sP_FE2CL_REP_REQUEST_MAKE_BUDDY_FAIL , failResp ) ;
sock - > sendPacket ( ( void * ) & failResp , P_FE2CL_REP_REQUEST_MAKE_BUDDY_FAIL , sizeof ( sP_FE2CL_REP_REQUEST_MAKE_BUDDY_FAIL ) ) ;
return ;
}
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
CNSocket * otherSock = PlayerManager : : getSockFromID ( otherPlr - > iID ) ;
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
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 ;
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
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 ) ) ;
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
std : : cout < < " Buddy ID: " < < req - > iBuddyID < < std : : endl ;
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC ) ) ;
otherSock - > sendPacket ( ( void * ) & otherResp , P_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC_TO_ACCEPTER , sizeof ( sP_FE2CL_REP_REQUEST_MAKE_BUDDY_SUCC_TO_ACCEPTER ) ) ;
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Sending buddy request by player name
2020-09-19 19:07:09 +00:00
void BuddyManager : : reqBuddyByName ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_FIND_NAME_MAKE_BUDDY ) ) {
return ; // malformed packet
}
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
sP_CL2FE_REQ_PC_FIND_NAME_MAKE_BUDDY * pkt = ( sP_CL2FE_REQ_PC_FIND_NAME_MAKE_BUDDY * ) data - > buf ;
Player * plrReq = PlayerManager : : getPlayer ( sock ) ;
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_SUCC , resp ) ;
2020-09-19 19:07:09 +00:00
2020-11-11 14:06:41 +00:00
CNSocket * otherSock = nullptr ;
2020-09-19 19:07:09 +00:00
2020-11-11 14:06:41 +00:00
for ( auto & pair : PlayerManager : : players ) {
2020-11-17 23:16:16 +00:00
Player * plr = pair . second ;
2020-11-11 14:06:41 +00:00
if ( strcmp ( U16toU8 ( plr - > PCStyle . szFirstName ) . c_str ( ) , U16toU8 ( pkt - > szFirstName ) . c_str ( ) ) = = 0
& & strcmp ( U16toU8 ( plr - > PCStyle . szLastName ) . c_str ( ) , U16toU8 ( pkt - > szLastName ) . c_str ( ) ) = = 0
& & ! playerHasBuddyWithID ( plrReq , plr - > iID ) ) {
2020-10-05 00:03:13 +00:00
otherSock = pair . first ;
2020-09-26 22:16:15 +00:00
break ;
2020-10-05 00:03:13 +00:00
}
}
2020-09-19 19:07:09 +00:00
2020-11-11 14:06:41 +00:00
if ( otherSock = = nullptr )
return ; // no player found
2020-10-05 00:03:13 +00:00
resp . iPCUID = plrReq - > PCStyle . iPC_UID ;
resp . iNameCheckFlag = plrReq - > PCStyle . iNameCheck ;
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
memcpy ( resp . szFirstName , plrReq - > PCStyle . szFirstName , sizeof ( plrReq - > PCStyle . szFirstName ) ) ;
memcpy ( resp . szLastName , plrReq - > PCStyle . szLastName , sizeof ( plrReq - > PCStyle . szLastName ) ) ;
otherSock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_PC_FIND_NAME_MAKE_BUDDY_SUCC ) ) ;
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Accepting buddy request
2020-09-19 19:07:09 +00:00
void BuddyManager : : reqAcceptBuddy ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_ACCEPT_MAKE_BUDDY ) )
return ; // malformed packet
2020-09-19 19:07:09 +00:00
2020-10-27 15:28:37 +00:00
sP_CL2FE_REQ_ACCEPT_MAKE_BUDDY * req = ( sP_CL2FE_REQ_ACCEPT_MAKE_BUDDY * ) data - > buf ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
Player * otherPlr = PlayerManager : : getPlayerFromID ( req - > iBuddyID ) ;
2020-09-19 19:07:09 +00:00
2020-11-27 03:28:18 +00:00
if ( otherPlr = = nullptr )
return ; // sanity check
2020-10-27 15:28:37 +00:00
CNSocket * otherSock = PlayerManager : : getSockFromID ( otherPlr - > iID ) ;
2020-11-08 04:11:56 +00:00
int slotA = getAvailableBuddySlot ( plr ) ;
int slotB = getAvailableBuddySlot ( otherPlr ) ;
if ( slotA = = - 1 | | slotB = = - 1 )
return ; // sanity check
2020-11-09 09:41:20 +00:00
if ( req - > iAcceptFlag = = 1 & & plr - > iID ! = otherPlr - > iID & & ! playerHasBuddyWithID ( plr , otherPlr - > iID ) )
2020-10-27 15:28:37 +00:00
{
2020-11-08 04:11:56 +00:00
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 ) ) ;
2020-10-05 00:03:13 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC ) ) ;
2020-11-08 04:11:56 +00:00
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 ( ( void * ) & resp , P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC ) ) ;
otherPlr - > buddyIDs [ slotB ] = plr - > PCStyle . iPC_UID ;
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotB] << std::endl;
2020-11-09 10:01:51 +00:00
// add record to db
Database : : addBuddyship ( plr - > iID , otherPlr - > iID ) ;
2020-10-27 15:28:37 +00:00
}
else
{
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL , declineResp ) ;
2020-10-19 17:26:14 +00:00
declineResp . iErrorCode = 6 ; // Buddy declined notification
2020-10-27 15:28:37 +00:00
declineResp . iBuddyID = req - > iBuddyID ;
declineResp . iBuddyPCUID = req - > iBuddyPCUID ;
2020-10-05 00:03:13 +00:00
2020-10-27 15:28:37 +00:00
otherSock - > sendPacket ( ( void * ) & declineResp , P_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL , sizeof ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL ) ) ;
2020-10-05 00:03:13 +00:00
}
2020-10-27 15:28:37 +00:00
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Accepting buddy request from the find name request
2020-09-19 19:07:09 +00:00
void BuddyManager : : reqFindNameBuddyAccept ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_FIND_NAME_ACCEPT_BUDDY ) ) {
return ; // malformed packet
}
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
sP_CL2FE_REQ_PC_FIND_NAME_ACCEPT_BUDDY * pkt = ( sP_CL2FE_REQ_PC_FIND_NAME_ACCEPT_BUDDY * ) data - > buf ;
2020-09-19 19:07:09 +00:00
2020-11-11 14:06:41 +00:00
Player * plrReq = PlayerManager : : getPlayer ( sock ) ;
2020-09-28 18:11:13 +00:00
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC , resp ) ;
2020-09-19 19:07:09 +00:00
2020-11-11 14:06:41 +00:00
Player * otherPlr = PlayerManager : : getPlayerFromID ( pkt - > iBuddyPCUID ) ;
2020-09-19 19:07:09 +00:00
2020-11-11 14:06:41 +00:00
if ( otherPlr = = nullptr )
return ;
2020-10-05 00:03:13 +00:00
2020-11-11 14:06:41 +00:00
CNSocket * otherSock = PlayerManager : : getSockFromID ( pkt - > iBuddyPCUID ) ;
2020-11-08 04:11:56 +00:00
2020-11-11 14:06:41 +00:00
int slotA = getAvailableBuddySlot ( plrReq ) ;
2020-11-08 04:11:56 +00:00
int slotB = getAvailableBuddySlot ( otherPlr ) ;
if ( slotA = = - 1 | | slotB = = - 1 )
return ; // sanity check
2020-11-11 14:06:41 +00:00
if ( pkt - > iAcceptFlag = = 1 & & plrReq - > iID ! = otherPlr - > iID & & ! playerHasBuddyWithID ( plrReq , otherPlr - > iID ) ) {
2020-11-08 04:11:56 +00:00
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 ) ) ;
2020-10-05 00:03:13 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC ) ) ;
2020-11-11 14:06:41 +00:00
plrReq - > buddyIDs [ slotA ] = otherPlr - > PCStyle . iPC_UID ;
2020-11-08 04:11:56 +00:00
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotA] << std::endl;
// B to A, using the same struct
resp . iBuddySlot = slotB ;
2020-11-11 14:06:41 +00:00
resp . BuddyInfo . iID = plrReq - > iID ;
resp . BuddyInfo . iPCUID = plrReq - > PCStyle . iPC_UID ;
2020-11-08 04:11:56 +00:00
resp . BuddyInfo . iPCState = 1 ;
resp . BuddyInfo . bBlocked = 0 ;
2020-11-11 14:06:41 +00:00
resp . BuddyInfo . iGender = plrReq - > PCStyle . iGender ;
2020-11-08 04:11:56 +00:00
resp . BuddyInfo . bFreeChat = 1 ;
2020-11-11 14:06:41 +00:00
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 ) ) ;
2020-11-08 04:11:56 +00:00
otherSock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_SUCC ) ) ;
2020-11-11 14:06:41 +00:00
otherPlr - > buddyIDs [ slotB ] = plrReq - > PCStyle . iPC_UID ;
2020-11-08 04:11:56 +00:00
//std::cout << "Buddy's ID: " << plr->buddyIDs[slotB] << std::endl;
2020-11-09 10:01:51 +00:00
// add record to db
2020-11-11 14:06:41 +00:00
Database : : addBuddyship ( plrReq - > iID , otherPlr - > iID ) ;
2020-11-08 04:11:56 +00:00
}
2020-10-27 15:28:37 +00:00
else
{
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL , declineResp ) ;
2020-10-19 17:26:14 +00:00
declineResp . iErrorCode = 6 ; // Buddy declined notification
2020-10-05 00:03:13 +00:00
declineResp . iBuddyPCUID = pkt - > iBuddyPCUID ;
otherSock - > sendPacket ( ( void * ) & declineResp , P_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL , sizeof ( sP_FE2CL_REP_ACCEPT_MAKE_BUDDY_FAIL ) ) ;
}
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Buddy freechatting
2020-09-19 19:07:09 +00:00
void BuddyManager : : reqBuddyFreechat ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_SEND_BUDDY_FREECHAT_MESSAGE ) )
return ; // malformed packet
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
sP_CL2FE_REQ_SEND_BUDDY_FREECHAT_MESSAGE * pkt = ( sP_CL2FE_REQ_SEND_BUDDY_FREECHAT_MESSAGE * ) data - > buf ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC , resp ) ;
2020-09-19 19:07:09 +00:00
2020-11-08 04:11:56 +00:00
CNSocket * otherSock = PlayerManager : : getSockFromID ( pkt - > iBuddyPCUID ) ;
if ( otherSock = = nullptr )
return ; // buddy offline
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
resp . iFromPCUID = plr - > PCStyle . iPC_UID ;
resp . iToPCUID = pkt - > iBuddyPCUID ;
resp . iEmoteCode = pkt - > iEmoteCode ;
2020-11-08 18:31:10 +00:00
std : : string fullChat = ChatManager : : sanitizeText ( U16toU8 ( pkt - > szFreeChat ) ) ;
U8toU16 ( fullChat , ( char16_t * ) & resp . szFreeChat , sizeof ( resp . szFreeChat ) ) ;
2020-11-08 04:11:56 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC , sizeof ( sP_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC ) ) ; // confirm send to sender
otherSock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC , sizeof ( sP_FE2CL_REP_SEND_BUDDY_FREECHAT_MESSAGE_SUCC ) ) ; // broadcast send to receiver
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Buddy menuchat
2020-09-19 19:07:09 +00:00
void BuddyManager : : reqBuddyMenuchat ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE ) )
return ; // malformed packet
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
sP_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE * pkt = ( sP_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE * ) data - > buf ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-19 19:07:09 +00:00
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC , resp ) ;
2020-09-19 19:07:09 +00:00
2020-11-08 04:11:56 +00:00
CNSocket * otherSock = PlayerManager : : getSockFromID ( pkt - > iBuddyPCUID ) ;
if ( otherSock = = nullptr )
return ; // buddy offline
2020-09-21 18:28:04 +00:00
2020-10-05 00:03:13 +00:00
resp . iFromPCUID = plr - > PCStyle . iPC_UID ;
resp . iToPCUID = pkt - > iBuddyPCUID ;
resp . iEmoteCode = pkt - > iEmoteCode ;
2020-11-08 18:31:10 +00:00
std : : string fullChat = ChatManager : : sanitizeText ( U16toU8 ( pkt - > szFreeChat ) ) ;
U8toU16 ( fullChat , ( char16_t * ) & resp . szFreeChat , sizeof ( resp . szFreeChat ) ) ;
2020-11-08 04:11:56 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC , sizeof ( sP_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC ) ) ; // confirm send to sender
otherSock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC , sizeof ( sP_FE2CL_REP_SEND_BUDDY_MENUCHAT_MESSAGE_SUCC ) ) ; // broadcast send to receiver
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Getting buddy state
2020-09-19 19:07:09 +00:00
void BuddyManager : : reqPktGetBuddyState ( CNSocket * sock , CNPacketData * data ) {
2020-10-27 15:28:37 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-11-08 18:58:44 +00:00
/*
* 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 ;
}
2020-10-27 15:28:37 +00:00
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_GET_BUDDY_STATE_SUCC , resp ) ;
2020-10-27 15:28:37 +00:00
2020-11-08 04:11:56 +00:00
for ( int slot = 0 ; slot < 50 ; slot + + ) {
resp . aBuddyState [ slot ] = PlayerManager : : getPlayerFromID ( plr - > buddyIDs [ slot ] ) ! = nullptr ? 1 : 0 ;
resp . aBuddyID [ slot ] = plr - > buddyIDs [ slot ] ;
2020-10-05 00:03:13 +00:00
}
2020-11-08 04:11:56 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_GET_BUDDY_STATE_SUCC , sizeof ( sP_FE2CL_REP_GET_BUDDY_STATE_SUCC ) ) ;
2020-09-19 19:07:09 +00:00
}
2020-10-19 17:26:14 +00:00
// Blocking the buddy
2020-09-21 18:28:04 +00:00
void BuddyManager : : reqBuddyBlock ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_SET_BUDDY_BLOCK ) )
return ; // malformed packet
2020-09-21 18:28:04 +00:00
2020-10-05 00:03:13 +00:00
sP_CL2FE_REQ_SET_BUDDY_BLOCK * pkt = ( sP_CL2FE_REQ_SET_BUDDY_BLOCK * ) data - > buf ;
2020-12-05 00:29:08 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-09-21 18:28:04 +00:00
2020-12-05 00:29:08 +00:00
// 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 ;
2020-09-21 18:28:04 +00:00
2020-12-05 00:29:08 +00:00
// send response
INITSTRUCT ( sP_FE2CL_REP_SET_BUDDY_BLOCK_SUCC , resp ) ;
2020-10-05 00:03:13 +00:00
resp . iBuddyPCUID = pkt - > iBuddyPCUID ;
resp . iBuddySlot = pkt - > iBuddySlot ;
2020-12-05 00:29:08 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_SET_BUDDY_BLOCK_SUCC , sizeof ( sP_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 ( ( void * ) & otherResp , P_FE2CL_REP_REMOVE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_REMOVE_BUDDY_SUCC ) ) ;
return ;
}
}
}
2020-09-21 18:28:04 +00:00
2020-12-05 00:29:08 +00:00
// block non-buddy
void BuddyManager : : reqPlayerBlock ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_SET_PC_BLOCK ) )
return ;
2020-11-08 04:11:56 +00:00
2020-12-05 00:29:08 +00:00
sP_CL2FE_REQ_SET_PC_BLOCK * pkt = ( sP_CL2FE_REQ_SET_PC_BLOCK * ) data - > buf ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
int buddySlot = getAvailableBuddySlot ( plr ) ;
if ( buddySlot = = - 1 )
return ;
2020-09-21 18:28:04 +00:00
2020-12-05 00:29:08 +00:00
// 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 ( ( void * ) & resp , P_FE2CL_REP_SET_PC_BLOCK_SUCC , sizeof ( sP_FE2CL_REP_SET_PC_BLOCK_SUCC ) ) ;
2020-09-21 18:28:04 +00:00
}
2020-10-19 17:26:14 +00:00
// Deleting the buddy
2020-09-21 18:28:04 +00:00
void BuddyManager : : reqBuddyDelete ( CNSocket * sock , CNPacketData * data ) {
2020-10-05 00:03:13 +00:00
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_REMOVE_BUDDY ) )
2020-10-19 17:26:14 +00:00
return ; // malformed packet
2020-09-21 18:28:04 +00:00
2020-12-05 00:29:08 +00:00
// note! this packet is used both for removing buddies and blocks
2020-10-05 00:03:13 +00:00
sP_CL2FE_REQ_REMOVE_BUDDY * pkt = ( sP_CL2FE_REQ_REMOVE_BUDDY * ) data - > buf ;
2020-09-21 18:28:04 +00:00
2020-10-27 15:28:37 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-11-08 17:42:27 +00:00
// remove buddy on our side
2020-10-05 00:03:13 +00:00
INITSTRUCT ( sP_FE2CL_REP_REMOVE_BUDDY_SUCC , resp ) ;
resp . iBuddyPCUID = pkt - > iBuddyPCUID ;
resp . iBuddySlot = pkt - > iBuddySlot ;
2020-12-05 00:29:08 +00:00
if ( pkt - > iBuddySlot < 0 | | pkt - > iBuddySlot > = 50 | | plr - > buddyIDs [ pkt - > iBuddySlot ] ! = pkt - > iBuddyPCUID )
2020-11-08 04:11:56 +00:00
return ; // sanity check
2020-12-05 00:29:08 +00:00
bool wasBlocked = plr - > isBuddyBlocked [ resp . iBuddySlot ] ;
2020-11-08 04:11:56 +00:00
plr - > buddyIDs [ resp . iBuddySlot ] = 0 ;
2020-12-05 00:29:08 +00:00
plr - > isBuddyBlocked [ resp . iBuddySlot ] = false ;
2020-11-08 17:42:27 +00:00
2020-12-05 00:29:08 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_REMOVE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_REMOVE_BUDDY_SUCC ) ) ;
2020-11-09 10:01:51 +00:00
// remove record from db
Database : : removeBuddyship ( plr - > PCStyle . iPC_UID , pkt - > iBuddyPCUID ) ;
2020-12-05 00:29:08 +00:00
// try this too
Database : : removeBlock ( plr - > PCStyle . iPC_UID , pkt - > iBuddyPCUID ) ;
if ( wasBlocked )
return ;
2020-11-09 10:01:51 +00:00
2020-11-08 17:42:27 +00:00
// 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 ( ( void * ) & resp , P_FE2CL_REP_REMOVE_BUDDY_SUCC , sizeof ( sP_FE2CL_REP_REMOVE_BUDDY_SUCC ) ) ;
return ;
}
}
2020-09-21 18:28:04 +00:00
}
2020-10-19 17:26:14 +00:00
// Warping to buddy
2020-11-08 17:54:05 +00:00
void BuddyManager : : reqBuddyWarp ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_BUDDY_WARP ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_BUDDY_WARP * 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 ( otherPlr - > instanceID ! = INSTANCE_OVERWORLD ) {
// player is instanced; no warp allowed
INITSTRUCT ( sP_FE2CL_REP_PC_BUDDY_WARP_FAIL , resp ) ;
resp . iBuddyPCUID = pkt - > iBuddyPCUID ;
resp . iErrorCode = 0 ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_BUDDY_WARP_FAIL , sizeof ( sP_FE2CL_REP_PC_BUDDY_WARP_FAIL ) ) ;
return ;
}
2020-12-14 00:05:11 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
if ( otherPlr - > PCStyle2 . iPayzoneFlag ! = plr - > PCStyle2 . iPayzoneFlag ) {
// players are not at the same point in time
INITSTRUCT ( sP_FE2CL_REP_PC_BUDDY_WARP_FAIL , resp ) ;
resp . iBuddyPCUID = pkt - > iBuddyPCUID ;
resp . iErrorCode = 0 ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_BUDDY_WARP_FAIL , sizeof ( sP_FE2CL_REP_PC_BUDDY_WARP_FAIL ) ) ;
return ;
}
2020-11-08 17:54:05 +00:00
PlayerManager : : sendPlayerTo ( sock , otherPlr - > x , otherPlr - > y , otherPlr - > z ) ;
}
2020-09-22 17:02:00 +00:00
2020-11-05 05:40:45 +00:00
void BuddyManager : : emailUpdateCheck ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_EMAIL_UPDATE_CHECK ) )
return ; // malformed packet
INITSTRUCT ( sP_FE2CL_REP_PC_NEW_EMAIL , resp ) ;
2020-11-07 02:10:41 +00:00
resp . iNewEmailCnt = Database : : getUnreadEmailCount ( PlayerManager : : getPlayer ( sock ) - > iID ) ;
2020-11-05 05:40:45 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_NEW_EMAIL , sizeof ( sP_FE2CL_REP_PC_NEW_EMAIL ) ) ;
}
void BuddyManager : : emailReceivePageList ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_RECV_EMAIL_PAGE_LIST ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_RECV_EMAIL_PAGE_LIST * pkt = ( sP_CL2FE_REQ_PC_RECV_EMAIL_PAGE_LIST * ) data - > buf ;
INITSTRUCT ( sP_FE2CL_REP_PC_RECV_EMAIL_PAGE_LIST_SUCC , resp ) ;
resp . iPageNum = pkt - > iPageNum ;
2020-11-07 02:10:41 +00:00
std : : vector < Database : : EmailData > emails = Database : : getEmails ( PlayerManager : : getPlayer ( sock ) - > iID , pkt - > iPageNum ) ;
for ( int i = 0 ; i < emails . size ( ) ; i + + ) {
// convert each email and load them into the packet
Database : : EmailData * email = & emails . at ( i ) ;
sEmailInfo * emailInfo = new sEmailInfo ( ) ;
emailInfo - > iEmailIndex = email - > MsgIndex ;
emailInfo - > iReadFlag = email - > ReadFlag ;
emailInfo - > iItemCandyFlag = email - > ItemFlag ;
emailInfo - > iFromPCUID = email - > SenderId ;
emailInfo - > SendTime = timeStampToStruct ( email - > SendTime ) ;
emailInfo - > DeleteTime = timeStampToStruct ( email - > DeleteTime ) ;
U8toU16 ( email - > SenderFirstName , emailInfo - > szFirstName , sizeof ( emailInfo - > szFirstName ) ) ;
U8toU16 ( email - > SenderLastName , emailInfo - > szLastName , sizeof ( emailInfo - > szLastName ) ) ;
U8toU16 ( email - > SubjectLine , emailInfo - > szSubject , sizeof ( emailInfo - > szSubject ) ) ;
resp . aEmailInfo [ i ] = * emailInfo ;
}
2020-11-05 05:40:45 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_RECV_EMAIL_PAGE_LIST_SUCC , sizeof ( sP_FE2CL_REP_PC_RECV_EMAIL_PAGE_LIST_SUCC ) ) ;
}
void BuddyManager : : emailRead ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_READ_EMAIL ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_READ_EMAIL * pkt = ( sP_CL2FE_REQ_PC_READ_EMAIL * ) data - > buf ;
2020-11-07 02:10:41 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
Database : : EmailData email = Database : : getEmail ( plr - > iID , pkt - > iEmailIndex ) ;
sItemBase * attachments = Database : : getEmailAttachments ( plr - > iID , pkt - > iEmailIndex ) ;
email . ReadFlag = 1 ; // mark as read
Database : : updateEmailContent ( & email ) ;
2020-11-05 05:40:45 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_READ_EMAIL_SUCC , resp ) ;
resp . iEmailIndex = pkt - > iEmailIndex ;
2020-11-07 02:10:41 +00:00
resp . iCash = email . Taros ;
2020-11-05 05:40:45 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
resp . aItem [ i ] = attachments [ i ] ;
}
2020-11-07 02:10:41 +00:00
U8toU16 ( email . MsgBody , ( char16_t * ) resp . szContent , sizeof ( resp . szContent ) ) ;
2020-11-05 05:40:45 +00:00
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_READ_EMAIL_SUCC , sizeof ( sP_FE2CL_REP_PC_READ_EMAIL_SUCC ) ) ;
}
void BuddyManager : : emailReceiveTaros ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_RECV_EMAIL_CANDY ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_RECV_EMAIL_CANDY * pkt = ( sP_CL2FE_REQ_PC_RECV_EMAIL_CANDY * ) data - > buf ;
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-11-07 02:10:41 +00:00
Database : : EmailData email = Database : : getEmail ( plr - > iID , pkt - > iEmailIndex ) ;
// money transfer
plr - > money + = email . Taros ;
email . Taros = 0 ;
// update Taros in email
Database : : updateEmailContent ( & email ) ;
2020-11-05 05:40:45 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_RECV_EMAIL_CANDY_SUCC , resp ) ;
resp . iCandy = plr - > money ;
resp . iEmailIndex = pkt - > iEmailIndex ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_RECV_EMAIL_CANDY_SUCC , sizeof ( sP_FE2CL_REP_PC_RECV_EMAIL_CANDY_SUCC ) ) ;
}
void BuddyManager : : emailReceiveItemSingle ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_RECV_EMAIL_ITEM ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_RECV_EMAIL_ITEM * pkt = ( sP_CL2FE_REQ_PC_RECV_EMAIL_ITEM * ) data - > buf ;
2020-11-07 02:10:41 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-11-05 05:40:45 +00:00
2020-11-07 02:10:41 +00:00
// get email item from db and delete it
sItemBase * attachments = Database : : getEmailAttachments ( plr - > iID , pkt - > iEmailIndex ) ;
sItemBase itemFrom = attachments [ pkt - > iEmailItemSlot - 1 ] ;
Database : : deleteEmailAttachments ( plr - > iID , pkt - > iEmailIndex , pkt - > iEmailItemSlot ) ;
2020-11-05 05:40:45 +00:00
// move item to player inventory
if ( pkt - > iSlotNum < 0 | | pkt - > iSlotNum > = AINVEN_COUNT )
return ; // sanity check
sItemBase & itemTo = plr - > Inven [ pkt - > iSlotNum ] ;
itemTo . iID = itemFrom . iID ;
itemTo . iOpt = itemFrom . iOpt ;
itemTo . iTimeLimit = itemFrom . iTimeLimit ;
itemTo . iType = itemFrom . iType ;
INITSTRUCT ( sP_FE2CL_REP_PC_RECV_EMAIL_ITEM_SUCC , resp ) ;
resp . iEmailIndex = pkt - > iEmailIndex ;
resp . iEmailItemSlot = pkt - > iEmailItemSlot ;
resp . iSlotNum = pkt - > iSlotNum ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_RECV_EMAIL_ITEM_SUCC , sizeof ( sP_FE2CL_REP_PC_RECV_EMAIL_ITEM_SUCC ) ) ;
// update inventory
INITSTRUCT ( sP_FE2CL_REP_PC_GIVE_ITEM_SUCC , resp2 ) ;
resp2 . eIL = 1 ;
resp2 . iSlotNum = resp . iSlotNum ;
resp2 . Item = itemTo ;
sock - > sendPacket ( ( void * ) & resp2 , P_FE2CL_REP_PC_GIVE_ITEM_SUCC , sizeof ( sP_FE2CL_REP_PC_GIVE_ITEM_SUCC ) ) ;
}
void BuddyManager : : emailReceiveItemAll ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_RECV_EMAIL_ITEM_ALL ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_RECV_EMAIL_ITEM_ALL * pkt = ( sP_CL2FE_REQ_PC_RECV_EMAIL_ITEM_ALL * ) data - > buf ;
// move items to player inventory
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-11-07 02:10:41 +00:00
sItemBase * itemsFrom = Database : : getEmailAttachments ( plr - > iID , pkt - > iEmailIndex ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
2020-11-05 05:40:45 +00:00
int slot = ItemManager : : findFreeSlot ( plr ) ;
if ( slot < 0 | | slot > = AINVEN_COUNT ) {
INITSTRUCT ( sP_FE2CL_REP_PC_RECV_EMAIL_ITEM_ALL_FAIL , failResp ) ;
failResp . iEmailIndex = pkt - > iEmailIndex ;
failResp . iErrorCode = 0 ; // ???
2020-11-07 02:10:41 +00:00
break ; // sanity check; should never happen
2020-11-05 05:40:45 +00:00
}
2020-11-07 02:10:41 +00:00
// copy data over
sItemBase itemFrom = itemsFrom [ i ] ;
2020-11-05 05:40:45 +00:00
sItemBase & itemTo = plr - > Inven [ slot ] ;
itemTo . iID = itemFrom . iID ;
itemTo . iOpt = itemFrom . iOpt ;
itemTo . iTimeLimit = itemFrom . iTimeLimit ;
itemTo . iType = itemFrom . iType ;
// update inventory
INITSTRUCT ( sP_FE2CL_REP_PC_GIVE_ITEM_SUCC , resp2 ) ;
resp2 . eIL = 1 ;
resp2 . iSlotNum = slot ;
resp2 . Item = itemTo ;
sock - > sendPacket ( ( void * ) & resp2 , P_FE2CL_REP_PC_GIVE_ITEM_SUCC , sizeof ( sP_FE2CL_REP_PC_GIVE_ITEM_SUCC ) ) ;
}
2020-11-07 02:10:41 +00:00
// delete all items from db
Database : : deleteEmailAttachments ( plr - > iID , pkt - > iEmailIndex , - 1 ) ;
2020-11-05 05:40:45 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_RECV_EMAIL_ITEM_ALL_SUCC , resp ) ;
resp . iEmailIndex = pkt - > iEmailIndex ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_RECV_EMAIL_ITEM_ALL_SUCC , sizeof ( sP_FE2CL_REP_PC_RECV_EMAIL_ITEM_ALL_SUCC ) ) ;
}
void BuddyManager : : emailDelete ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_DELETE_EMAIL ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_DELETE_EMAIL * pkt = ( sP_CL2FE_REQ_PC_DELETE_EMAIL * ) data - > buf ;
2020-11-07 02:10:41 +00:00
Database : : deleteEmails ( PlayerManager : : getPlayer ( sock ) - > iID , pkt - > iEmailIndexArray ) ;
2020-11-05 05:40:45 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_DELETE_EMAIL_SUCC , resp ) ;
for ( int i = 0 ; i < 5 ; i + + ) {
resp . iEmailIndexArray [ i ] = pkt - > iEmailIndexArray [ i ] ; // i'm scared of memcpy
}
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_DELETE_EMAIL_SUCC , sizeof ( sP_FE2CL_REP_PC_DELETE_EMAIL_SUCC ) ) ;
}
void BuddyManager : : emailSend ( CNSocket * sock , CNPacketData * data ) {
if ( data - > size ! = sizeof ( sP_CL2FE_REQ_PC_SEND_EMAIL ) )
return ; // malformed packet
sP_CL2FE_REQ_PC_SEND_EMAIL * pkt = ( sP_CL2FE_REQ_PC_SEND_EMAIL * ) data - > buf ;
2020-11-07 02:10:41 +00:00
Player * plr = PlayerManager : : getPlayer ( sock ) ;
2020-11-05 05:40:45 +00:00
INITSTRUCT ( sP_FE2CL_REP_PC_SEND_EMAIL_SUCC , resp ) ;
2020-11-07 02:10:41 +00:00
2020-12-14 00:05:11 +00:00
if ( pkt - > iCash | | pkt - > aItem [ 0 ] . ItemInven . iID ) {
// if there are item or taro attachments
Database : : DbPlayer otherPlayerData = Database : : getDbPlayerById ( pkt - > iTo_PCUID ) ;
if ( otherPlayerData . PlayerID ! = - 1 & & plr - > PCStyle2 . iPayzoneFlag ! = otherPlayerData . PayZoneFlag ) {
// if the players are not in the same time period
INITSTRUCT ( sP_FE2CL_REP_PC_SEND_EMAIL_FAIL , resp ) ;
resp . iErrorCode = 9 ; //error code 9 tells the player they can't send attachments across time
resp . iTo_PCUID = pkt - > iTo_PCUID ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_SEND_EMAIL_FAIL , sizeof ( sP_FE2CL_REP_PC_SEND_EMAIL_FAIL ) ) ;
return ;
}
}
2020-11-07 02:10:41 +00:00
// handle items
std : : vector < sItemBase > attachments ;
2020-12-14 00:05:11 +00:00
2020-11-05 05:40:45 +00:00
for ( int i = 0 ; i < 4 ; i + + ) {
2020-11-07 02:10:41 +00:00
sEmailItemInfoFromCL attachment = pkt - > aItem [ i ] ;
resp . aItem [ i ] = attachment ;
2020-11-10 02:29:28 +00:00
if ( attachment . iSlotNum < 0 | | attachment . iSlotNum > = AINVEN_COUNT
| | attachment . ItemInven . iID < = 0 | | attachment . ItemInven . iType < 0 )
continue ; // sanity check
attachments . push_back ( attachment . ItemInven ) ;
// delete item
plr - > Inven [ attachment . iSlotNum ] = { 0 , 0 , 0 , 0 } ;
2020-11-05 05:40:45 +00:00
}
2020-11-07 02:10:41 +00:00
int cost = pkt - > iCash + 50 + 20 * attachments . size ( ) ; // attached taros + postage
plr - > money - = cost ;
Database : : EmailData email = {
( int ) pkt - > iTo_PCUID , // PlayerId
Database : : getNextEmailIndex ( pkt - > iTo_PCUID ) , // MsgIndex
0 , // ReadFlag (unread)
( pkt - > iCash > 0 | | attachments . size ( ) > 0 ) ? 1 : 0 , // ItemFlag
plr - > iID , // SenderID
U16toU8 ( plr - > PCStyle . szFirstName ) , // SenderFirstName
U16toU8 ( plr - > PCStyle . szLastName ) , // SenderLastName
2020-11-08 20:37:17 +00:00
ChatManager : : sanitizeText ( U16toU8 ( pkt - > szSubject ) ) , // SubjectLine
2020-12-03 00:40:36 +00:00
ChatManager : : sanitizeText ( U16toU8 ( pkt - > szContent ) ) , // MsgBody
2020-11-07 02:10:41 +00:00
pkt - > iCash , // Taros
( uint64_t ) getTimestamp ( ) , // SendTime
0 // DeleteTime (unimplemented)
} ;
Database : : sendEmail ( & email , attachments ) ;
// HACK: use set value packet to force GUI taros update
INITSTRUCT ( sP_FE2CL_GM_REP_PC_SET_VALUE , tarosResp ) ;
tarosResp . iPC_ID = plr - > iID ;
tarosResp . iSetValueType = 5 ;
tarosResp . iSetValue = plr - > money ;
sock - > sendPacket ( ( void * ) & tarosResp , P_FE2CL_GM_REP_PC_SET_VALUE , sizeof ( sP_FE2CL_GM_REP_PC_SET_VALUE ) ) ;
resp . iCandy = plr - > money ;
2020-11-05 05:40:45 +00:00
resp . iTo_PCUID = pkt - > iTo_PCUID ;
sock - > sendPacket ( ( void * ) & resp , P_FE2CL_REP_PC_SEND_EMAIL_SUCC , sizeof ( sP_FE2CL_REP_PC_SEND_EMAIL_SUCC ) ) ;
}
2020-09-19 19:07:09 +00:00
# pragma region Helper methods
2020-11-08 04:11:56 +00:00
int BuddyManager : : getAvailableBuddySlot ( Player * plr ) {
int slot = - 1 ;
for ( int i = 0 ; i < 50 ; i + + ) {
if ( plr - > buddyIDs [ i ] = = 0 )
return i ;
}
return slot ;
}
2020-11-09 09:41:20 +00:00
bool BuddyManager : : playerHasBuddyWithID ( Player * plr , int buddyID ) {
for ( int i = 0 ; i < 50 ; i + + ) {
if ( plr - > buddyIDs [ i ] = = buddyID )
return true ;
}
return false ;
}
2020-09-19 19:07:09 +00:00
# pragma endregion