1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-27 14:57:44 +00:00

Merge pull request #743 from hkAlice/3.0-blacklist

[3.0] blacklist support;
This commit is contained in:
Mordred 2021-12-14 20:19:52 +01:00 committed by GitHub
commit 2fe3b3d3de
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
19 changed files with 435 additions and 50 deletions

3
.gitignore vendored
View file

@ -99,7 +99,6 @@ CTestTestfile.cmake
*.cache *.cache
*.dat *.dat
*.suo *.suo
*.pch
*.ipch *.ipch
*.g.cs *.g.cs
*.g.i.cs *.g.i.cs
@ -112,7 +111,6 @@ CTestTestfile.cmake
*.ilk *.ilk
/Sapphire.VC.VC.opendb /Sapphire.VC.VC.opendb
*.user *.user
*.dat
*.metagen *.metagen
*.ipdb *.ipdb
*.iobj *.iobj
@ -145,3 +143,4 @@ doxygen/*.tmp
# ignore config directory contents except the default file # ignore config directory contents except the default file
config/*.ini config/*.ini
!config/config.ini.default !config/config.ini.default
/CMakeSettings.json

View file

@ -273,10 +273,13 @@ void PlayerMinimal::saveAsNew()
std::vector< uint8_t > friendIds( 1600, 0 ); std::vector< uint8_t > friendIds( 1600, 0 );
std::vector< uint8_t > inviteIds( 1600, 0 ); std::vector< uint8_t > inviteIds( 1600, 0 );
stmtFriendList->setUInt64( 1, m_characterId ); // Blacklist related
stmtFriendList->setBinary( 2, friendIds ); auto stmtBlacklist = g_charaDb.getPreparedStatement( Db::ZoneDbStatements::CHARA_BLACKLIST_INS );
stmtFriendList->setBinary( 3, inviteIds ); std::vector< uint8_t > blIds( 1600, 0 );
g_charaDb.directExecute( stmtFriendList );
stmtBlacklist->setUInt64( 1, m_characterId );
stmtBlacklist->setBinary( 2, blIds );
g_charaDb.directExecute( stmtBlacklist );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// SET UP INVENTORIES /// SET UP INVENTORIES

View file

@ -236,6 +236,21 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
"WHERE CharacterId = ?;", "WHERE CharacterId = ?;",
CONNECTION_SYNC ); CONNECTION_SYNC );
/// CHARA FRIENDLIST
prepareStatement( CHARA_BLACKLIST_INS,
"INSERT INTO charainfoblacklist ( CharacterId, CharacterIdList, UPDATE_DATE ) "
" VALUES ( ?, ?, NOW() );",
CONNECTION_SYNC );
prepareStatement( CHARA_BLACKLIST_UP, "UPDATE charainfoblacklist "
" SET CharacterIdList = ?"
" WHERE CharacterId = ?;",
CONNECTION_ASYNC );
prepareStatement( CHARA_BLACKLIST_SEL, "SELECT CharacterIdList FROM charainfoblacklist "
" WHERE CharacterId = ?;",
CONNECTION_SYNC );
/// CHARA LINKSHELL /// CHARA LINKSHELL
prepareStatement( CHARA_LINKSHELL_INS, prepareStatement( CHARA_LINKSHELL_INS,
"INSERT INTO infolinkshell ( LinkshellId, MasterCharacterId, CharacterIdList, " "INSERT INTO infolinkshell ( LinkshellId, MasterCharacterId, CharacterIdList, "

View file

@ -84,6 +84,10 @@ namespace Sapphire::Db
CHARA_FRIENDLIST_UP, CHARA_FRIENDLIST_UP,
CHARA_FRIENDLIST_SEL, CHARA_FRIENDLIST_SEL,
CHARA_BLACKLIST_INS,
CHARA_BLACKLIST_UP,
CHARA_BLACKLIST_SEL,
CHARA_LINKSHELL_INS, CHARA_LINKSHELL_INS,
ZONE_SEL_BNPCS, ZONE_SEL_BNPCS,

View file

@ -590,6 +590,17 @@ struct FFXIVIpcGetBlacklist : FFXIVIpcBasePacket< GetBlacklist >
uint8_t RequestKey; uint8_t RequestKey;
}; };
struct FFXIVIpcBlacklistAdd : FFXIVIpcBasePacket< BlacklistAdd >
{
char TargetCharacterName[32];
};
struct FFXIVIpcBlacklistRemove : FFXIVIpcBasePacket< BlacklistRemove >
{
uint64_t TargetCharacterID;
char TargetCharacterName[32];
};
/* 60986 */ /* 60986 */
struct FFXIVIpcInvite : FFXIVIpcBasePacket< Invite > struct FFXIVIpcInvite : FFXIVIpcBasePacket< Invite >
{ {

View file

@ -98,7 +98,7 @@ Sapphire::Entity::Player::Player() :
memset( m_classArray.data(), 0, sizeof( m_classArray.data() ) ); memset( m_classArray.data(), 0, sizeof( m_classArray.data() ) );
memset( m_expArray.data(), 0, sizeof( m_expArray.data() ) ); memset( m_expArray.data(), 0, sizeof( m_expArray.data() ) );
for( uint8_t i = 0; i < 80; i++ ) for( uint8_t i = 0; i < 80; ++i )
{ {
m_recast[ i ] = 0.0f; m_recast[ i ] = 0.0f;
m_recastMax[ i ] = 0.0f; m_recastMax[ i ] = 0.0f;
@ -2138,11 +2138,17 @@ Sapphire::Entity::Player::FriendListIDVec& Sapphire::Entity::Player::getFriendLi
{ {
return m_friendList; return m_friendList;
} }
Sapphire::Entity::Player::FriendListDataVec& Sapphire::Entity::Player::getFriendListData() Sapphire::Entity::Player::FriendListDataVec& Sapphire::Entity::Player::getFriendListData()
{ {
return m_friendInviteList; return m_friendInviteList;
} }
Sapphire::Entity::Player::FriendListIDVec& Sapphire::Entity::Player::getBlacklistID()
{
return m_blacklist;
}
void Sapphire::Entity::Player::setLastPcSearchResult( std::vector< uint32_t > result ) void Sapphire::Entity::Player::setLastPcSearchResult( std::vector< uint32_t > result )
{ {
m_lastPcSearch = std::move( result ); m_lastPcSearch = std::move( result );

View file

@ -559,7 +559,10 @@ namespace Sapphire::Entity
bool loadHuntingLog(); bool loadHuntingLog();
/*! load friendlist */ /*! load friendlist */
bool loadFriendlist(); bool loadFriendList();
/*! load blacklist */
bool loadBlacklist();
/*! update latest sync with db */ /*! update latest sync with db */
bool syncLastDBWrite(); bool syncLastDBWrite();
@ -704,6 +707,8 @@ namespace Sapphire::Entity
void updateDbFriendList(); void updateDbFriendList();
void updateDbBlacklist();
void updateDbChara() const; void updateDbChara() const;
/////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////
@ -801,6 +806,7 @@ namespace Sapphire::Entity
using FriendListIDVec = std::array< uint64_t, 200 >; using FriendListIDVec = std::array< uint64_t, 200 >;
using FriendListDataVec = std::array< Common::HierarchyData, 200 >; using FriendListDataVec = std::array< Common::HierarchyData, 200 >;
using BlacklistIDVec = std::array< uint64_t, 200 >;
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index ); Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );
@ -814,6 +820,8 @@ namespace Sapphire::Entity
FriendListIDVec& getFriendListID(); FriendListIDVec& getFriendListID();
FriendListDataVec& getFriendListData(); FriendListDataVec& getFriendListData();
BlacklistIDVec& getBlacklistID();
uint64_t m_lastMoveTime{}; uint64_t m_lastMoveTime{};
uint8_t m_lastMoveflag{}; uint8_t m_lastMoveflag{};
bool m_falling; bool m_falling;
@ -972,6 +980,8 @@ namespace Sapphire::Entity
FriendListIDVec m_friendList{}; FriendListIDVec m_friendList{};
FriendListDataVec m_friendInviteList{}; FriendListDataVec m_friendInviteList{};
BlacklistIDVec m_blacklist{};
uint64_t m_partyId; uint64_t m_partyId;
std::vector< uint32_t > m_lastPcSearch; std::vector< uint32_t > m_lastPcSearch;

View file

@ -140,7 +140,7 @@ bool Sapphire::Entity::Player::loadFromDb( uint64_t characterId )
res->free(); res->free();
if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() || !loadHuntingLog() || !loadFriendlist() ) if( !loadActiveQuests() || !loadClassData() || !loadSearchInfo() || !loadHuntingLog() || !loadFriendList() || !loadBlacklist() )
{ {
Logger::error( "chara#{0} data corrupt!", m_characterId ); Logger::error( "chara#{0} data corrupt!", m_characterId );
} }
@ -296,6 +296,9 @@ void Sapphire::Entity::Player::updateSql()
////// FriendList ////// FriendList
updateDbFriendList(); updateDbFriendList();
////// Blacklist
updateDbBlacklist();
///// Store last write ///// Store last write
syncLastDBWrite(); syncLastDBWrite();
} }
@ -481,6 +484,20 @@ void Sapphire::Entity::Player::updateDbFriendList()
} }
void Sapphire::Entity::Player::updateDbBlacklist()
{
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::CHARA_BLACKLIST_UP );
std::vector< uint8_t > blIds( 1600 );
memcpy( blIds.data(), m_blacklist.data(), 1600 );
stmt->setBinary( 1, blIds );
stmt->setUInt64( 2, m_characterId );
db.execute( stmt );
}
void Sapphire::Entity::Player::insertDbClass( const uint8_t classJobIndex, uint8_t level ) const void Sapphire::Entity::Player::insertDbClass( const uint8_t classJobIndex, uint8_t level ) const
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
@ -680,7 +697,7 @@ bool Sapphire::Entity::Player::loadInventory()
return true; return true;
} }
bool Sapphire::Entity::Player::loadFriendlist() bool Sapphire::Entity::Player::loadFriendList()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_FRIENDLIST_SEL ); auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_FRIENDLIST_SEL );
@ -705,6 +722,28 @@ bool Sapphire::Entity::Player::loadFriendlist()
return true; return true;
} }
bool Sapphire::Entity::Player::loadBlacklist()
{
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto stmt = db.getPreparedStatement( Db::ZoneDbStatements::CHARA_BLACKLIST_SEL );
stmt->setUInt64( 1, m_characterId );
auto res = db.query( stmt );
if( !res->next() )
{
Logger::error( "Failed to load blacklist data for character#{}", m_characterId );
return false;
}
auto blacklist = res->getBlobVector( "CharacterIdList" );
if( !blacklist.empty() )
std::memcpy( m_blacklist.data(), blacklist.data(), blacklist.size() );
return true;
}
bool Sapphire::Entity::Player::syncLastDBWrite() bool Sapphire::Entity::Player::syncLastDBWrite()
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();

View file

@ -0,0 +1,224 @@
#include <algorithm>
#include <iterator>
#include <Logging/Logger.h>
#include <Service.h>
#include <Util/Util.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h>
#include <Network/PacketContainer.h>
#include "Actor/Player.h"
#include "BlacklistMgr.h"
#include "FriendListMgr.h"
#include "WorldServer.h"
using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets;
bool Sapphire::World::Manager::BlacklistMgr::onAddCharacter( Entity::Player& source, const std::string& targetName )
{
// add target to blacklist
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto pTarget = server.getPlayer( targetName );
if( !pTarget )
{
// target doesn't exist in server player table
sendAddResultPacket( source, pTarget, 0x7 );
return false;
}
auto& target = *pTarget;
if( source.getCharacterId() == target.getCharacterId() )
{
// can't add self to blacklist
sendAddResultPacket( source, pTarget, 0x7 );
return false;
}
if( isBlacklisted( source, target ) )
{
// target already added to blacklist
sendAddResultPacket( source, pTarget, 0x7 );
return false;
}
// get next available slot in blacklist
auto sourceIdx = getEntryIndex( source, 0 );
if( sourceIdx == -1 )
{
// no slots left in blacklist (max capacity)
return false;
}
// add target ID to blacklist
auto& sourceBL = source.getBlacklistID();
sourceBL[sourceIdx] = target.getCharacterId();
source.updateDbBlacklist();
sendAddResultPacket( source, pTarget, 0 );
// check if player is friends with target
auto& flMgr = Common::Service< Sapphire::World::Manager::FriendListMgr >::ref();
if( flMgr.isFriend( source, target ) )
flMgr.onRemoveFriend( source, target );
return true;
}
bool Sapphire::World::Manager::BlacklistMgr::onRemoveCharacter( Entity::Player& source, const std::string& targetName )
{
// remove target from blacklist
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto pTarget = server.getPlayer( targetName );
if( !pTarget )
{
// target doesn't exist in server player table
sendRemoveResultPacket( source, pTarget, 0x7 );
return false;
}
auto& target = *pTarget;
auto sourceIdx = getEntryIndex( source, target.getCharacterId() );
if( !isBlacklisted( source, target ) )
{
// target not in blacklist
sendRemoveResultPacket( source, pTarget, 0x7 );
return false;
}
// set target slot to 0
auto& sourceBL = source.getBlacklistID();
sourceBL[sourceIdx] = 0;
source.updateDbBlacklist();
sendRemoveResultPacket( source, pTarget, 0 );
return true;
}
bool Sapphire::World::Manager::BlacklistMgr::onGetBlacklistPage( Entity::Player& source, uint8_t key, uint8_t nextIdx )
{
// this function will handle client side indexing and paginate blacklist entries
// it'll also be called multiple times sequentially until there are no more entries left (id == 0)
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
std::vector< Server::BlacklistCharacter > entries;
// blacklist entries are sent in pages of 20
const size_t itemsPerPage = 20;
// get array offset/last page sent from client packet
auto offset = nextIdx;
auto& idVec = source.getBlacklistID();
for( size_t i = offset; i < offset + itemsPerPage; ++i )
{
if( idVec.size() <= i )
{
break;
}
auto id = idVec[ i ];
auto pPlayer = server.getPlayer( id );
if( !pPlayer )
continue;
// build our packet entry for current iterated id
Server::BlacklistCharacter entry{};
entry.CharacterID = pPlayer->getCharacterId();
strcpy( entry.CharacterName, pPlayer->getName().c_str() );
// add to current page
entries.emplace_back( entry );
}
// if the page is empty, then we've reached the last page
bool isLast = entries.empty();
// configure paging state for client so that it knows whether to request more entries or not
auto blacklistPacket = makeZonePacket< Server::FFXIVIpcGetBlacklistResult >( source.getId() );
blacklistPacket->data().Index = offset;
blacklistPacket->data().NextIndex = isLast ? 0 : nextIdx + itemsPerPage;
blacklistPacket->data().RequestKey = key;
memcpy( &blacklistPacket->data().Blacklist[ 0 ], entries.data(), sizeof( Server::BlacklistCharacter ) * entries.size() );
server.queueForPlayer( source.getCharacterId(), blacklistPacket );
return true;
}
bool Sapphire::World::Manager::BlacklistMgr::isBlacklisted( Entity::Player& source, const Entity::Player& target ) const
{
return getEntryIndex( source, target.getCharacterId() ) != -1;
}
ptrdiff_t Sapphire::World::Manager::BlacklistMgr::getEntryIndex( Entity::Player& source, uint64_t characterId ) const
{
auto& sourceBL = source.getBlacklistID();
auto sourceBlIt = std::find( std::begin( sourceBL ), std::end( sourceBL ), characterId );
// not found
if( sourceBlIt == sourceBL.end() )
return -1;
return sourceBlIt - std::begin( sourceBL );
}
void Sapphire::World::Manager::BlacklistMgr::sendAddResultPacket( Entity::Player& source, const Entity::PlayerPtr pTarget, uint32_t result )
{
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto resultPacket = makeZonePacket< Server::FFXIVIpcBlacklistAddResult >( source.getId() );
if( pTarget )
{
Server::BlacklistCharacter blChar;
blChar.CharacterID = pTarget->getCharacterId();
strcpy( blChar.CharacterName, pTarget->getName().c_str() );
resultPacket->data().AddedCharacter = blChar;
resultPacket->data().Identity = pTarget->getGender();
}
resultPacket->data().Result = result;
server.queueForPlayer( source.getCharacterId(), resultPacket );
}
void Sapphire::World::Manager::BlacklistMgr::sendRemoveResultPacket( Entity::Player& source, const Entity::PlayerPtr pTarget, uint32_t result )
{
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto resultPacket = makeZonePacket< Server::FFXIVIpcBlacklistRemoveResult >( source.getId() );
if( pTarget )
{
Server::BlacklistCharacter blChar;
blChar.CharacterID = pTarget->getCharacterId();
strcpy( blChar.CharacterName, pTarget->getName().c_str() );
resultPacket->data().RemovedCharacter = blChar;
resultPacket->data().Identity = pTarget->getGender();
}
resultPacket->data().Result = result;
server.queueForPlayer( source.getCharacterId(), resultPacket );
}

View file

@ -0,0 +1,27 @@
#pragma once
#include <memory>
#include <vector>
#include "ForwardsZone.h"
namespace Sapphire::World::Manager
{
class BlacklistMgr
{
public:
BlacklistMgr() = default;
bool onAddCharacter( Entity::Player& source, const std::string& targetName );
bool onRemoveCharacter( Entity::Player& source, const std::string& targetName );
bool onGetBlacklistPage( Entity::Player& source, uint8_t key, uint8_t nextIdx );
bool isBlacklisted( Entity::Player& source, const Entity::Player& target ) const;
private:
ptrdiff_t getEntryIndex( Entity::Player& source, uint64_t characterId ) const;
void sendAddResultPacket( Entity::Player& source, const Entity::PlayerPtr pTarget, uint32_t result );
void sendRemoveResultPacket( Entity::Player& source, const Entity::PlayerPtr pTarget, uint32_t result );
};
}

View file

@ -14,7 +14,7 @@ bool Sapphire::World::Manager::FriendListMgr::onInviteCreate( Entity::Player& so
auto& targetFL = target.getFriendListID(); auto& targetFL = target.getFriendListID();
// check if player already has been invited or friends // check if player already has been invited or friends
if( getEntryIndex( source, target.getCharacterId() ) != -1 ) if( isFriend( source, target ) )
{ {
// already invited/friends // already invited/friends
return false; return false;
@ -41,12 +41,13 @@ bool Sapphire::World::Manager::FriendListMgr::onInviteCreate( Entity::Player& so
Common::HierarchyData hierarchy; Common::HierarchyData hierarchy;
hierarchy.data.dateAdded = Common::Util::getTimeSeconds(); hierarchy.data.dateAdded = Common::Util::getTimeSeconds();
hierarchy.data.group = 0; hierarchy.data.group = 0;
hierarchy.data.status = Common::HierarchyStatus::SentRequest; // set type for invite sender
hierarchy.data.type = Common::HierarchyType::FRIENDLIST; hierarchy.data.type = Common::HierarchyType::FRIENDLIST;
// set hierarchy status for invite sender
hierarchy.data.status = Common::HierarchyStatus::SentRequest;
sourceFLData[ sourceIdx ] = hierarchy; sourceFLData[ sourceIdx ] = hierarchy;
// set type for invite receiver // set hierarchy status for invite receiver
hierarchy.data.status = Common::HierarchyStatus::ReceivedRequest; hierarchy.data.status = Common::HierarchyStatus::ReceivedRequest;
targetFLData[ targetIdx ] = hierarchy; targetFLData[ targetIdx ] = hierarchy;
@ -72,6 +73,7 @@ bool Sapphire::World::Manager::FriendListMgr::onInviteAccept( Entity::Player& so
auto& sourceFLData = source.getFriendListData(); auto& sourceFLData = source.getFriendListData();
auto& targetFLData = target.getFriendListData(); auto& targetFLData = target.getFriendListData();
// currently, type on hierarchy indicates invite type - since it is no longer an invite, set type to NONE
sourceFLData[ sourceIdx ].data.status = Common::HierarchyStatus::Added; sourceFLData[ sourceIdx ].data.status = Common::HierarchyStatus::Added;
sourceFLData[ sourceIdx ].data.type = Common::HierarchyType::NONE_2; sourceFLData[ sourceIdx ].data.type = Common::HierarchyType::NONE_2;
targetFLData[ targetIdx ].data.status = Common::HierarchyStatus::Added; targetFLData[ targetIdx ].data.status = Common::HierarchyStatus::Added;
@ -140,7 +142,12 @@ bool Sapphire::World::Manager::FriendListMgr::onAssignGroup( Entity::Player& sou
return true; return true;
} }
ptrdiff_t Sapphire::World::Manager::FriendListMgr::getEntryIndex( Entity::Player& source, uint64_t characterId ) bool Sapphire::World::Manager::FriendListMgr::isFriend( Entity::Player& source, Entity::Player& target ) const
{
return getEntryIndex( source, target.getCharacterId() ) != -1;
}
ptrdiff_t Sapphire::World::Manager::FriendListMgr::getEntryIndex( Entity::Player& source, uint64_t characterId ) const
{ {
auto& sourceFL = source.getFriendListID(); auto& sourceFL = source.getFriendListID();
auto sourceInvIt = std::find( std::begin( sourceFL ), std::end( sourceFL ), characterId ); auto sourceInvIt = std::find( std::begin( sourceFL ), std::end( sourceFL ), characterId );

View file

@ -19,7 +19,9 @@ namespace Sapphire::World::Manager
bool onRemoveFriend( Entity::Player& source, Entity::Player& target ); bool onRemoveFriend( Entity::Player& source, Entity::Player& target );
bool onAssignGroup( Entity::Player& source, Entity::Player& target, uint8_t group ); bool onAssignGroup( Entity::Player& source, Entity::Player& target, uint8_t group );
bool isFriend( Entity::Player& source, Entity::Player& target ) const;
private: private:
ptrdiff_t getEntryIndex( Entity::Player& source, uint64_t characterId ); ptrdiff_t getEntryIndex( Entity::Player& source, uint64_t characterId ) const;
}; };
} }

View file

@ -58,7 +58,6 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
setZoneHandler( SetProfile, "SetProfile", &GameConnection::setProfileHandler ); setZoneHandler( SetProfile, "SetProfile", &GameConnection::setProfileHandler );
setZoneHandler( GetProfile, "GetProfile", &GameConnection::getProfileHandler ); setZoneHandler( GetProfile, "GetProfile", &GameConnection::getProfileHandler );
setZoneHandler( GetSearchComment, "GetSearchComment", &GameConnection::getSearchCommentHandler ); setZoneHandler( GetSearchComment, "GetSearchComment", &GameConnection::getSearchCommentHandler );
setZoneHandler( GetBlacklist, "GetBlacklist", &GameConnection::getBlacklistHandler );
setZoneHandler( PcSearch, "PcSearch", &GameConnection::pcSearchHandler ); setZoneHandler( PcSearch, "PcSearch", &GameConnection::pcSearchHandler );
setZoneHandler( GetCommonlist, "GetCommonlist", &GameConnection::getCommonlistHandler ); setZoneHandler( GetCommonlist, "GetCommonlist", &GameConnection::getCommonlistHandler );
@ -163,7 +162,9 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
setZoneHandler( FriendlistRemove, "FriendlistRemove", &GameConnection::friendlistRemoveHandler ); setZoneHandler( FriendlistRemove, "FriendlistRemove", &GameConnection::friendlistRemoveHandler );
setZoneHandler( SetFriendlistGroup, "SetFriendlistGroup", &GameConnection::setFriendlistGroupHandler ); setZoneHandler( SetFriendlistGroup, "SetFriendlistGroup", &GameConnection::setFriendlistGroupHandler );
setZoneHandler( GetBlacklist, "GetBlacklist", &GameConnection::getBlacklistHandler );
setZoneHandler( BlacklistAdd, "BlacklistAdd", &GameConnection::blacklistAddHandler );
setZoneHandler( BlacklistRemove, "BlacklistRemove", &GameConnection::blacklistRemoveHandler );
} }
Sapphire::Network::GameConnection::~GameConnection() = default; Sapphire::Network::GameConnection::~GameConnection() = default;

View file

@ -100,8 +100,6 @@ namespace Sapphire::Network
DECLARE_HANDLER( setLanguageHandler ); DECLARE_HANDLER( setLanguageHandler );
DECLARE_HANDLER( getBlacklistHandler );
DECLARE_HANDLER( getCommonlistHandler ); DECLARE_HANDLER( getCommonlistHandler );
DECLARE_HANDLER( getCommonlistDetailHandler ); DECLARE_HANDLER( getCommonlistDetailHandler );
@ -238,7 +236,9 @@ namespace Sapphire::Network
DECLARE_HANDLER( friendlistRemoveHandler ); DECLARE_HANDLER( friendlistRemoveHandler );
DECLARE_HANDLER( setFriendlistGroupHandler ); DECLARE_HANDLER( setFriendlistGroupHandler );
DECLARE_HANDLER( getBlacklistHandler );
DECLARE_HANDLER( blacklistAddHandler );
DECLARE_HANDLER( blacklistRemoveHandler );
}; };
} }

View file

@ -0,0 +1,55 @@
#include <Common.h>
#include <Network/CommonNetwork.h>
#include <Network/GamePacket.h>
#include <Network/PacketContainer.h>
#include <Exd/ExdData.h>
#include <Service.h>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h>
#include "Manager/BlacklistMgr.h"
#include "Network/GameConnection.h"
#include "Actor/Player.h"
#include "WorldServer.h"
using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets;
using namespace Sapphire::World::Manager;
void Sapphire::Network::GameConnection::getBlacklistHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{
auto& blMgr = Common::Service< Sapphire::World::Manager::BlacklistMgr >::ref();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcGetBlacklist >( inPacket );
auto& data = packet.data();
blMgr.onGetBlacklistPage( player, data.RequestKey, data.NextIndex );
}
void Sapphire::Network::GameConnection::blacklistAddHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{
auto& blMgr = Common::Service< Sapphire::World::Manager::BlacklistMgr >::ref();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcBlacklistAdd >( inPacket );
auto& data = packet.data();
std::string targetName( data.TargetCharacterName );
blMgr.onAddCharacter( player, targetName );
}
void Sapphire::Network::GameConnection::blacklistRemoveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{
auto& blMgr = Common::Service< Sapphire::World::Manager::BlacklistMgr >::ref();
const auto packet = ZoneChannelPacket< Client::FFXIVIpcBlacklistRemove >( inPacket );
auto& data = packet.data();
std::string targetName( data.TargetCharacterName );
blMgr.onRemoveCharacter( player, targetName );
}

View file

@ -75,16 +75,16 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
// TODO: possibly move lambda func to util // TODO: possibly move lambda func to util
auto& server = Common::Service< World::WorldServer >::ref(); auto& server = Common::Service< World::WorldServer >::ref();
const size_t itemsPerPage = 10;
// this func paginates any commonlist entry, associating them with online player data and hierarchy ID (optional) // this func paginates any commonlist entry, associating them with online player data and hierarchy ID (optional)
auto generateEntries = [&]( const auto& idVec, size_t offset, const std::vector< Common::HierarchyData >& hierarchyVec ) -> std::vector< PlayerEntry > auto generateEntries = [&]( const auto& idVec, size_t offset, const std::vector< Common::HierarchyData >& hierarchyVec ) -> std::vector< PlayerEntry >
{ {
std::vector< PlayerEntry > entries; std::vector< PlayerEntry > entries;
const size_t itemsPerPage = 10; for( size_t i = offset; i < offset + itemsPerPage; ++i )
for( size_t i = offset; i < offset + 10; ++i )
{ {
if( idVec.size() <= offset + i ) if( idVec.size() <= i )
{ {
break; break;
} }
@ -259,7 +259,7 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
memcpy( &listPacket->data().entries[ 0 ], page.data(), sizeof( PlayerEntry ) * page.size() ); memcpy( &listPacket->data().entries[ 0 ], page.data(), sizeof( PlayerEntry ) * page.size() );
listPacket->data().Index = offset; listPacket->data().Index = offset;
listPacket->data().NextIndex = isLast ? 0 : data.NextIndex + 10; listPacket->data().NextIndex = isLast ? 0 : data.NextIndex + itemsPerPage;
queueOutPacket( listPacket ); queueOutPacket( listPacket );
} }

View file

@ -35,7 +35,7 @@ void Sapphire::Network::GameConnection::friendlistRemoveHandler( const Packets::
flMgr.onRemoveFriend( player, *target ); flMgr.onRemoveFriend( player, *target );
auto replyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcFriendlistRemoveResult >( player.getId() ); auto replyPacket = makeZonePacket< Server::FFXIVIpcFriendlistRemoveResult >( player.getId() );
auto& replyData = replyPacket->data(); auto& replyData = replyPacket->data();
replyData.RemovedCharacterID = target->getCharacterId(); replyData.RemovedCharacterID = target->getCharacterId();

View file

@ -388,8 +388,6 @@ void Sapphire::Network::GameConnection::newDiscoveryHandler( const Packets::FFXI
} }
void Sapphire::Network::GameConnection::loginHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) void Sapphire::Network::GameConnection::loginHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{ {
auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref(); auto& teriMgr = Common::Service< World::Manager::TerritoryMgr >::ref();
@ -398,24 +396,6 @@ void Sapphire::Network::GameConnection::loginHandler( const Packets::FFXIVARR_PA
teriMgr.joinWorld( player ); teriMgr.joinWorld( player );
} }
void Sapphire::Network::GameConnection::getBlacklistHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{
const auto packet = ZoneChannelPacket< Client::FFXIVIpcGetBlacklist >( inPacket );
auto& data = packet.data();
auto blackListPacket = makeZonePacket< FFXIVIpcGetBlacklistResult >( player.getId() );
blackListPacket->data().Index = data.NextIndex;
blackListPacket->data().RequestKey = data.RequestKey;
// TODO: Fill with actual blacklist data
//blackListPacket.data().entry[0].contentId = 1;
//sprintf( blackListPacket.data().entry[0].name, "Test Test" );
queueOutPacket( blackListPacket );
}
void Sapphire::Network::GameConnection::syncHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, void Sapphire::Network::GameConnection::syncHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player ) Entity::Player& player )
{ {
@ -432,7 +412,6 @@ void Sapphire::Network::GameConnection::syncHandler( const Packets::FFXIVARR_PAC
pSession->setLastPing( Common::Util::getTimeSeconds() ); pSession->setLastPing( Common::Util::getTimeSeconds() );
} }
void Sapphire::Network::GameConnection::setLanguageHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, void Sapphire::Network::GameConnection::setLanguageHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player ) Entity::Player& player )
{ {

View file

@ -43,6 +43,7 @@
#include "Manager/QuestMgr.h" #include "Manager/QuestMgr.h"
#include "Manager/PartyMgr.h" #include "Manager/PartyMgr.h"
#include "Manager/FriendListMgr.h" #include "Manager/FriendListMgr.h"
#include "Manager/BlacklistMgr.h"
#include "ContentFinder/ContentFinder.h" #include "ContentFinder/ContentFinder.h"
@ -241,6 +242,7 @@ void Sapphire::World::WorldServer::run( int32_t argc, char* argv[] )
auto pQuestMgr = std::make_shared< Manager::QuestMgr >(); auto pQuestMgr = std::make_shared< Manager::QuestMgr >();
auto pPartyMgr = std::make_shared< Manager::PartyMgr >(); auto pPartyMgr = std::make_shared< Manager::PartyMgr >();
auto pFriendMgr = std::make_shared< Manager::FriendListMgr >(); auto pFriendMgr = std::make_shared< Manager::FriendListMgr >();
auto pBlacklistMgr = std::make_shared< Manager::BlacklistMgr >();
auto contentFinder = std::make_shared< ContentFinder >(); auto contentFinder = std::make_shared< ContentFinder >();
Common::Service< DebugCommandMgr >::set( pDebugCom ); Common::Service< DebugCommandMgr >::set( pDebugCom );
@ -253,6 +255,7 @@ void Sapphire::World::WorldServer::run( int32_t argc, char* argv[] )
Common::Service< Manager::QuestMgr >::set( pQuestMgr ); Common::Service< Manager::QuestMgr >::set( pQuestMgr );
Common::Service< Manager::PartyMgr >::set( pPartyMgr ); Common::Service< Manager::PartyMgr >::set( pPartyMgr );
Common::Service< Manager::FriendListMgr >::set( pFriendMgr ); Common::Service< Manager::FriendListMgr >::set( pFriendMgr );
Common::Service< Manager::BlacklistMgr >::set( pBlacklistMgr );
Common::Service< ContentFinder >::set( contentFinder ); Common::Service< ContentFinder >::set( contentFinder );
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref(); auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();
@ -558,7 +561,7 @@ Sapphire::Entity::PlayerPtr Sapphire::World::WorldServer::loadPlayer( uint32_t e
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto res = db.query( "SELECT CharacterId FROM charainfo WHERE EntityId = " + std::to_string( entityId ) ); auto res = db.query( "SELECT CharacterId FROM charainfo WHERE EntityId = " + std::to_string( entityId ) );
if( !res->next() ) if( !res || !res->next() )
return nullptr; return nullptr;
uint64_t characterId = res->getUInt64( 1 ); uint64_t characterId = res->getUInt64( 1 );
@ -575,7 +578,7 @@ Sapphire::Entity::PlayerPtr Sapphire::World::WorldServer::loadPlayer( const std:
{ {
auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref(); auto& db = Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::ref();
auto res = db.query( "SELECT CharacterId FROM charainfo WHERE Name = " + playerName ); auto res = db.query( "SELECT CharacterId FROM charainfo WHERE Name = " + playerName );
if( !res->next() ) if( !res || !res->next() )
return nullptr; return nullptr;
uint64_t characterId = res->getUInt64( 1 ); uint64_t characterId = res->getUInt64( 1 );