Buddy DB integration

This commit is contained in:
Gent 2020-11-08 12:42:27 -05:00
parent 803f1a246a
commit 7be79010fc
5 changed files with 135 additions and 4 deletions

View File

@ -3,6 +3,7 @@
#include "ChatManager.hpp"
#include "PlayerManager.hpp"
#include "BuddyManager.hpp"
#include "Database.hpp"
#include <iostream>
#include <chrono>
@ -22,6 +23,54 @@ void BuddyManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BUDDY_WARP, reqBuddyWarp);
}
// 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 = {};
Database::DbPlayer buddyPlayerData = Database::getDbPlayerById(buddyID);
buddyInfo.bBlocked = 0;
buddyInfo.bFreeChat = 1;
buddyInfo.iGender = buddyPlayerData.Gender;
buddyInfo.iID = buddyID;
buddyInfo.iPCUID = buddyID;
buddyInfo.iNameCheckFlag = buddyPlayerData.NameCheck;
buddyInfo.iPCState = buddyPlayerData.PCState;
U8toU16(buddyPlayerData.FirstName, buddyInfo.szFirstName, sizeof(buddyInfo.szFirstName));
U8toU16(buddyPlayerData.LastName, buddyInfo.szLastName, sizeof(buddyInfo.szLastName));
respdata[buddyIndex] = buddyInfo;
buddyIndex++;
}
}
sock->sendPacket((void*)respbuf, P_FE2CL_REP_PC_BUDDYLIST_INFO_SUCC, resplen);
}
// Buddy request
void BuddyManager::requestBuddy(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_REQUEST_MAKE_BUDDY))
@ -321,17 +370,32 @@ void BuddyManager::reqBuddyDelete(CNSocket* sock, CNPacketData* data) {
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)
return; // sanity check
plr->buddyIDs[resp.iBuddySlot] = 0;
sock->sendPacket((void*)&resp, P_FE2CL_REP_REMOVE_BUDDY_SUCC, sizeof(sP_FE2CL_REP_REMOVE_BUDDY_SUCC));
// 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;
}
}
}
// Warping to buddy

View File

@ -11,6 +11,9 @@
namespace BuddyManager {
void init();
// Buddy list
void refreshBuddyList(CNSocket* sock);
// Buddy requests
void requestBuddy(CNSocket* sock, CNPacketData* data);
void reqBuddyByName(CNSocket* sock, CNPacketData* data);

View File

@ -93,6 +93,11 @@ auto db = make_storage("database.db",
make_column("RemainingNPCCount1", &Database::DbQuest::RemainingNPCCount1),
make_column("RemainingNPCCount2", &Database::DbQuest::RemainingNPCCount2),
make_column("RemainingNPCCount3", &Database::DbQuest::RemainingNPCCount3)
),
make_table("Buddyships",
make_column("PlayerAId", &Database::Buddyship::PlayerAId),
make_column("PlayerBId", &Database::Buddyship::PlayerBId),
make_column("Status", &Database::Buddyship::Status)
)
);
@ -463,6 +468,7 @@ Player Database::DbToPlayer(DbPlayer player) {
Database::removeExpiredVehicles(&result);
Database::getNanos(&result);
Database::getQuests(&result);
Database::getBuddies(&result);
// load completed quests
memcpy(&result.aQuestFlag, player.QuestFlag.data(), std::min(sizeof(result.aQuestFlag), player.QuestFlag.size()));
@ -492,6 +498,7 @@ void Database::updatePlayer(Player *player) {
updateInventory(player);
updateNanos(player);
updateQuests(player);
updateBuddies(player);
}
void Database::updateInventory(Player *player){
@ -604,6 +611,27 @@ void Database::updateQuests(Player* player) {
db.commit();
}
void Database::updateBuddies(Player* player) {
db.begin_transaction();
db.remove_all<Buddyship>( // remove all buddyships with this player involved
where(c(&Buddyship::PlayerAId) == player->iID || c(&Buddyship::PlayerBId) == player->iID)
);
// iterate through player's buddies and add records for each non-zero entry
for (int i = 0; i < 50; i++) {
if (player->buddyIDs[i] != 0) {
Buddyship record;
record.PlayerAId = player->iID;
record.PlayerBId = player->buddyIDs[i];
record.Status = 0; // still not sure how we'll handle blocking
db.insert(record);
}
}
db.commit();
}
void Database::getInventory(Player* player) {
// get items from DB
auto items = db.get_all<Inventory>(
@ -691,4 +719,28 @@ void Database::getQuests(Player* player) {
}
}
void Database::getBuddies(Player* player) {
auto buddies = db.get_all<Buddyship>( // player can be on either side
where(c(&Buddyship::PlayerAId) == player->iID || c(&Buddyship::PlayerBId) == player->iID)
);
// there should never be more than 50 buddyships per player, but just in case
for (int i = 0; i < 50 && i < buddies.size(); i++) {
// if the player is player A, then the buddy is player B, and vice versa
player->buddyIDs[i] = player->iID == buddies.at(i).PlayerAId
? buddies.at(i).PlayerBId : buddies.at(i).PlayerAId;
}
}
int Database::getNumBuddies(Player* player) {
std::lock_guard<std::mutex> lock(dbCrit);
auto buddies = db.get_all<Buddyship>( // player can be on either side
where(c(&Buddyship::PlayerAId) == player->iID || c(&Buddyship::PlayerBId) == player->iID)
);
// again, for peace of mind
return buddies.size() > 50 ? 50 : buddies.size();
}
#pragma endregion ShardServer

View File

@ -79,6 +79,11 @@ namespace Database {
int RemainingNPCCount2;
int RemainingNPCCount3;
};
struct Buddyship {
int PlayerAId;
int PlayerBId;
int16_t Status;
};
#pragma endregion DatabaseStructs
@ -121,11 +126,14 @@ namespace Database {
void updateInventory(Player *player);
void updateNanos(Player *player);
void updateQuests(Player* player);
void updateBuddies(Player* player);
void getInventory(Player* player);
void removeExpiredVehicles(Player* player);
void getNanos(Player* player);
void getQuests(Player* player);
void getBuddies(Player* player);
int getNumBuddies(Player* player);
// parsing blobs
void appendBlob(std::vector<char>*blob, int64_t input);

View File

@ -9,6 +9,7 @@
#include "GroupManager.hpp"
#include "ChatManager.hpp"
#include "Database.hpp"
#include "BuddyManager.hpp"
#include "settings.hpp"
@ -403,6 +404,9 @@ void PlayerManager::enterPlayer(CNSocket* sock, CNPacketData* data) {
MissionManager::failInstancedMissions(sock);
// send over buddy list
BuddyManager::refreshBuddyList(sock);
for (auto& pair : PlayerManager::players)
if (pair.second.plr->notify)
ChatManager::sendServerMessage(pair.first, "[ADMIN]" + getPlayerName(&plr) + " has joined.");