Implement player blocking

This commit is contained in:
Kamil 2020-12-05 01:29:08 +01:00 committed by Gent S
parent 3e855cbdac
commit 4dc48198ab
5 changed files with 150 additions and 15 deletions

View File

@ -21,6 +21,7 @@ void BuddyManager::init() {
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SEND_BUDDY_MENUCHAT_MESSAGE, reqBuddyMenuchat); 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_GET_BUDDY_STATE, reqPktGetBuddyState);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_SET_BUDDY_BLOCK, reqBuddyBlock); 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_REMOVE_BUDDY, reqBuddyDelete);
REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BUDDY_WARP, reqBuddyWarp); REGISTER_SHARD_PACKET(P_CL2FE_REQ_PC_BUDDY_WARP, reqBuddyWarp);
// //
@ -68,7 +69,7 @@ void BuddyManager::refreshBuddyList(CNSocket* sock) {
Database::getPlayer(&buddyPlayerData, buddyID); Database::getPlayer(&buddyPlayerData, buddyID);
if (buddyPlayerData.iID == 0) if (buddyPlayerData.iID == 0)
continue; continue;
buddyInfo.bBlocked = 0; buddyInfo.bBlocked = plr->isBuddyBlocked[i];
buddyInfo.bFreeChat = 1; buddyInfo.bFreeChat = 1;
buddyInfo.iGender = buddyPlayerData.PCStyle.iGender; buddyInfo.iGender = buddyPlayerData.PCStyle.iGender;
buddyInfo.iID = buddyID; buddyInfo.iID = buddyID;
@ -382,16 +383,72 @@ void BuddyManager::reqBuddyBlock(CNSocket* sock, CNPacketData* data) {
return; // malformed packet return; // malformed packet
sP_CL2FE_REQ_SET_BUDDY_BLOCK* pkt = (sP_CL2FE_REQ_SET_BUDDY_BLOCK*)data->buf; sP_CL2FE_REQ_SET_BUDDY_BLOCK* 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); INITSTRUCT(sP_FE2CL_REP_SET_BUDDY_BLOCK_SUCC, resp);
resp.iBuddyPCUID = pkt->iBuddyPCUID; resp.iBuddyPCUID = pkt->iBuddyPCUID;
resp.iBuddySlot = pkt->iBuddySlot; resp.iBuddySlot = pkt->iBuddySlot;
// TODO: handle this?
sock->sendPacket((void*)&resp, P_FE2CL_REP_SET_BUDDY_BLOCK_SUCC, sizeof(sP_FE2CL_REP_SET_BUDDY_BLOCK_SUCC)); 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;
}
}
}
// block non-buddy
void BuddyManager::reqPlayerBlock(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_SET_PC_BLOCK))
return;
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;
// 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));
} }
// Deleting the buddy // Deleting the buddy
@ -399,6 +456,7 @@ void BuddyManager::reqBuddyDelete(CNSocket* sock, CNPacketData* data) {
if (data->size != sizeof(sP_CL2FE_REQ_REMOVE_BUDDY)) if (data->size != sizeof(sP_CL2FE_REQ_REMOVE_BUDDY))
return; // malformed packet return; // malformed packet
// note! this packet is used both for removing buddies and blocks
sP_CL2FE_REQ_REMOVE_BUDDY* pkt = (sP_CL2FE_REQ_REMOVE_BUDDY*)data->buf; sP_CL2FE_REQ_REMOVE_BUDDY* pkt = (sP_CL2FE_REQ_REMOVE_BUDDY*)data->buf;
Player* plr = PlayerManager::getPlayer(sock); Player* plr = PlayerManager::getPlayer(sock);
@ -407,13 +465,22 @@ void BuddyManager::reqBuddyDelete(CNSocket* sock, CNPacketData* data) {
INITSTRUCT(sP_FE2CL_REP_REMOVE_BUDDY_SUCC, resp); INITSTRUCT(sP_FE2CL_REP_REMOVE_BUDDY_SUCC, resp);
resp.iBuddyPCUID = pkt->iBuddyPCUID; resp.iBuddyPCUID = pkt->iBuddyPCUID;
resp.iBuddySlot = pkt->iBuddySlot; resp.iBuddySlot = pkt->iBuddySlot;
if (pkt->iBuddySlot < 0 || pkt->iBuddySlot >= 50) if (pkt->iBuddySlot < 0 || pkt->iBuddySlot >= 50 || plr->buddyIDs[pkt->iBuddySlot] != pkt->iBuddyPCUID)
return; // sanity check 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));
bool wasBlocked = plr->isBuddyBlocked[resp.iBuddySlot];
plr->buddyIDs[resp.iBuddySlot] = 0;
plr->isBuddyBlocked[resp.iBuddySlot] = false;
sock->sendPacket((void*)&resp, P_FE2CL_REP_REMOVE_BUDDY_SUCC, sizeof(sP_FE2CL_REP_REMOVE_BUDDY_SUCC));
// remove record from db // remove record from db
Database::removeBuddyship(plr->PCStyle.iPC_UID, pkt->iBuddyPCUID); 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 // remove buddy on their side, reusing the struct
CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID); CNSocket* otherSock = PlayerManager::getSockFromID(pkt->iBuddyPCUID);

View File

@ -31,6 +31,7 @@ namespace BuddyManager {
// Blocking/removing buddies // Blocking/removing buddies
void reqBuddyBlock(CNSocket* sock, CNPacketData* data); void reqBuddyBlock(CNSocket* sock, CNPacketData* data);
void reqPlayerBlock(CNSocket* sock, CNPacketData* data);
void reqBuddyDelete(CNSocket* sock, CNPacketData* data); void reqBuddyDelete(CNSocket* sock, CNPacketData* data);
// Buddy warping // Buddy warping

View File

@ -161,11 +161,17 @@ void Database::createTables() {
CREATE TABLE IF NOT EXISTS "Buddyships" ( CREATE TABLE IF NOT EXISTS "Buddyships" (
"PlayerAId" INTEGER NOT NULL, "PlayerAId" INTEGER NOT NULL,
"PlayerBId" INTEGER NOT NULL, "PlayerBId" INTEGER NOT NULL,
"Status" INTEGER NOT NULL,
FOREIGN KEY("PlayerAId") REFERENCES "Players"("PlayerID") ON DELETE CASCADE, FOREIGN KEY("PlayerAId") REFERENCES "Players"("PlayerID") ON DELETE CASCADE,
FOREIGN KEY("PlayerBId") REFERENCES "Players"("PlayerID") ON DELETE CASCADE FOREIGN KEY("PlayerBId") REFERENCES "Players"("PlayerID") ON DELETE CASCADE
); );
CREATE TABLE IF NOT EXISTS "Blocks" (
"PlayerId" INTEGER NOT NULL,
"BlockedPlayerId" INTEGER NOT NULL,
FOREIGN KEY("PlayerId") REFERENCES "Players"("PlayerID") ON DELETE CASCADE,
FOREIGN KEY("BlockedPlayerId") REFERENCES "Players"("PlayerID") ON DELETE CASCADE
);
CREATE TABLE IF NOT EXISTS "EmailData" ( CREATE TABLE IF NOT EXISTS "EmailData" (
"PlayerId" INTEGER NOT NULL, "PlayerId" INTEGER NOT NULL,
"MsgIndex" INTEGER NOT NULL, "MsgIndex" INTEGER NOT NULL,
@ -970,6 +976,23 @@ void Database::getPlayer(Player* plr, int id) {
int PlayerBId = sqlite3_column_int(stmt, 1); int PlayerBId = sqlite3_column_int(stmt, 1);
plr->buddyIDs[i] = id == PlayerAId ? PlayerBId : PlayerAId; plr->buddyIDs[i] = id == PlayerAId ? PlayerBId : PlayerAId;
plr->isBuddyBlocked[i] = false;
i++;
}
// get blocked players
sql = R"(
SELECT "BlockedPlayerId" FROM "Blocks"
WHERE "PlayerId" = ?;
)";
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, id);
// i remains from adding buddies!
while (sqlite3_step(stmt) == SQLITE_ROW && i < 50) {
plr->buddyIDs[i] = sqlite3_column_int(stmt, 0);
plr->isBuddyBlocked[i] = true;
i++; i++;
} }
@ -1268,6 +1291,7 @@ void Database::removeExpiredVehicles(Player* player) {
} }
// buddies // buddies
/// returns num of buddies + blocked players
int Database::getNumBuddies(Player* player) { int Database::getNumBuddies(Player* player) {
std::lock_guard<std::mutex> lock(dbCrit); std::lock_guard<std::mutex> lock(dbCrit);
@ -1281,7 +1305,15 @@ int Database::getNumBuddies(Player* player) {
sqlite3_bind_int(stmt, 2, player->iID); sqlite3_bind_int(stmt, 2, player->iID);
sqlite3_step(stmt); sqlite3_step(stmt);
int result = sqlite3_column_int(stmt, 0); int result = sqlite3_column_int(stmt, 0);
sqlite3_finalize(stmt);
sql = R"(
SELECT COUNT(*) FROM "Blocks"
WHERE "PlayerId" = ?;
)";
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, player->iID);
sqlite3_step(stmt);
result += sqlite3_column_int(stmt, 0);
// again, for peace of mind // again, for peace of mind
return result > 50 ? 50 : result; return result > 50 ? 50 : result;
@ -1292,15 +1324,13 @@ void Database::addBuddyship(int playerA, int playerB) {
const char* sql = R"( const char* sql = R"(
INSERT INTO "Buddyships" INSERT INTO "Buddyships"
("PlayerAId", "PlayerBId", "Status") ("PlayerAId", "PlayerBId")
VALUES (?, ?, ?); VALUES (?, ?);
)"; )";
sqlite3_stmt* stmt; sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, 0); sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, playerA); sqlite3_bind_int(stmt, 1, playerA);
sqlite3_bind_int(stmt, 2, playerB); sqlite3_bind_int(stmt, 2, playerB);
// blocking???
sqlite3_bind_int(stmt, 3, 0);
if (sqlite3_step(stmt) != SQLITE_DONE) if (sqlite3_step(stmt) != SQLITE_DONE)
std::cout << "[WARN] Database: failed to add buddies" << std::endl; std::cout << "[WARN] Database: failed to add buddies" << std::endl;
@ -1321,8 +1351,40 @@ void Database::removeBuddyship(int playerA, int playerB) {
sqlite3_bind_int(stmt, 3, playerB); sqlite3_bind_int(stmt, 3, playerB);
sqlite3_bind_int(stmt, 4, playerA); sqlite3_bind_int(stmt, 4, playerA);
sqlite3_step(stmt);
sqlite3_finalize(stmt);
}
// blocking
void Database::addBlock(int playerId, int blockedPlayerId) {
std::lock_guard<std::mutex> lock(dbCrit);
const char* sql = R"(
INSERT INTO "Blocks"
("PlayerId", "BlockedPlayerId")
VALUES (?, ?);
)";
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, playerId);
sqlite3_bind_int(stmt, 2, blockedPlayerId);
if (sqlite3_step(stmt) != SQLITE_DONE) if (sqlite3_step(stmt) != SQLITE_DONE)
std::cout << "[WARN] Database: failed to remove buddies" << std::endl; std::cout << "[WARN] Database: failed to block player" << std::endl;
sqlite3_finalize(stmt);
}
void Database::removeBlock(int playerId, int blockedPlayerId) {
const char* sql = R"(
DELETE FROM "Blocks"
WHERE "PlayerId" = ? AND "BlockedPlayerId" = ?;
)";
sqlite3_stmt* stmt;
sqlite3_prepare_v2(db, sql, -1, &stmt, 0);
sqlite3_bind_int(stmt, 1, playerId);
sqlite3_bind_int(stmt, 2, blockedPlayerId);
sqlite3_step(stmt);
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
} }

View File

@ -85,6 +85,10 @@ namespace Database {
int getNumBuddies(Player* player); int getNumBuddies(Player* player);
void addBuddyship(int playerA, int playerB); void addBuddyship(int playerA, int playerB);
void removeBuddyship(int playerA, int playerB); void removeBuddyship(int playerA, int playerB);
// blocking
void addBlock(int playerId, int blockedPlayerId);
void removeBlock(int playerId, int blockedPlayerId);
// email // email
int getUnreadEmailCount(int playerID); int getUnreadEmailCount(int playerID);

View File

@ -77,6 +77,7 @@ struct Player {
bool buddiesSynced; bool buddiesSynced;
int64_t buddyIDs[50]; int64_t buddyIDs[50];
bool isBuddyBlocked[50];
ChunkPos chunkPos; ChunkPos chunkPos;
std::set<Chunk*>* viewableChunks; std::set<Chunk*>* viewableChunks;