From e506a42dea6d7dc74d904ece6a8068d41b5bebdb Mon Sep 17 00:00:00 2001 From: Maru Date: Tue, 20 Mar 2018 01:44:04 -0300 Subject: [PATCH] Structure changes, adjustments to flow; --- src/common/Common.h | 6 +- src/common/Network/PacketDef/Ipcs.h | 1 + src/servers/sapphire_zone/Actor/PlayerSql.cpp | 8 +- .../sapphire_zone/Network/GameConnection.cpp | 1 + .../sapphire_zone/Network/GameConnection.h | 2 +- .../Network/Handlers/PacketHandlers.cpp | 27 ++++++- .../sapphire_zone/Social/FriendList.cpp | 76 ++++++++++++++++++- src/servers/sapphire_zone/Social/FriendList.h | 7 ++ src/servers/sapphire_zone/Social/Group.cpp | 12 ++- src/servers/sapphire_zone/Social/Group.h | 7 +- .../sapphire_zone/Social/Manager/SocialMgr.h | 17 +++-- 11 files changed, 144 insertions(+), 20 deletions(-) diff --git a/src/common/Common.h b/src/common/Common.h index 288880ab..da735fcb 100644 --- a/src/common/Common.h +++ b/src/common/Common.h @@ -736,9 +736,9 @@ namespace Core { enum class SocialRequestResponse : uint8_t { - Decline, - Accept, - Cancel, + Decline = 0, + Accept = 1, + Cancel = 2 }; typedef std::vector< PlayerStateFlag > PlayerStateFlagList; diff --git a/src/common/Network/PacketDef/Ipcs.h b/src/common/Network/PacketDef/Ipcs.h index d00bf1fd..2eab9af9 100644 --- a/src/common/Network/PacketDef/Ipcs.h +++ b/src/common/Network/PacketDef/Ipcs.h @@ -199,6 +199,7 @@ namespace Packets { CFDutyInfoHandler = 0x0078, // updated 4.2 SocialReqSendHandler = 0x00CA, // updated 4.2 + SocialReqProcessHandler = 0x00CC, // updated 4.2 ChatHandler = 0x00C7, // updated 4.2 diff --git a/src/servers/sapphire_zone/Actor/PlayerSql.cpp b/src/servers/sapphire_zone/Actor/PlayerSql.cpp index 7862165c..cd5154ad 100644 --- a/src/servers/sapphire_zone/Actor/PlayerSql.cpp +++ b/src/servers/sapphire_zone/Actor/PlayerSql.cpp @@ -207,7 +207,13 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession ) calculateStats(); - m_friendsListId = g_fw.get< Social::SocialMgr < Social::FriendList > >()->loadFriendsList( m_id ); + auto friendListMgr = g_fw.get< Social::SocialMgr < Social::FriendList > >(); + + if( !friendListMgr->loadFriendsList( m_id ) ) + { + pLog->error( "[" + char_id_str + "] Failed to load friends list!" ); + } + pLog->debug( std::to_string( m_id ) + " ID, has group ID: " + std::to_string( m_friendsListId ) ); // first login, run the script event diff --git a/src/servers/sapphire_zone/Network/GameConnection.cpp b/src/servers/sapphire_zone/Network/GameConnection.cpp index 318abe70..45715595 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.cpp +++ b/src/servers/sapphire_zone/Network/GameConnection.cpp @@ -55,6 +55,7 @@ Core::Network::GameConnection::GameConnection( Core::Network::HivePtr pHive, setZoneHandler( ClientZoneIpcType::LogoutHandler, "LogoutHandler", &GameConnection::logoutHandler ); setZoneHandler( ClientZoneIpcType::SocialReqSendHandler, "SocialReqSendHandler", &GameConnection::socialReqSendHandler ); + setZoneHandler( ClientZoneIpcType::SocialReqProcessHandler, "SocialReqProcessHandler", &GameConnection::socialReqProcessHandler ); setZoneHandler( ClientZoneIpcType::SocialListHandler, "SocialListHandler", &GameConnection::socialListHandler ); setZoneHandler( ClientZoneIpcType::SetSearchInfoHandler, "SetSearchInfoHandler", &GameConnection::setSearchInfoHandler ); setZoneHandler( ClientZoneIpcType::ReqSearchInfoHandler, "ReqSearchInfoHandler", &GameConnection::reqSearchInfoHandler ); diff --git a/src/servers/sapphire_zone/Network/GameConnection.h b/src/servers/sapphire_zone/Network/GameConnection.h index 3cb2e107..855fab5d 100644 --- a/src/servers/sapphire_zone/Network/GameConnection.h +++ b/src/servers/sapphire_zone/Network/GameConnection.h @@ -86,7 +86,7 @@ public: DECLARE_HANDLER( initHandler ); DECLARE_HANDLER( finishLoadingHandler ); DECLARE_HANDLER( blackListHandler ); - DECLARE_HANDLER( socialReqResponseHandler ); + DECLARE_HANDLER( socialReqProcessHandler ); DECLARE_HANDLER( socialReqSendHandler ); DECLARE_HANDLER( socialListHandler ); DECLARE_HANDLER( linkshellListHandler ); diff --git a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp index 1d07db29..230ae710 100644 --- a/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/sapphire_zone/Network/Handlers/PacketHandlers.cpp @@ -511,19 +511,44 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket } -void Core::Network::GameConnection::socialReqResponseHandler( const Packets::GamePacket& inPacket, +void Core::Network::GameConnection::socialReqProcessHandler( const Packets::GamePacket& inPacket, Entity::Player& player ) { auto targetId = inPacket.getValAt< uint32_t >( 0x20 ); auto category = inPacket.getValAt< Common::SocialCategory >( 0x28 ); auto action = inPacket.getValAt< Common::SocialRequestAction >( 0x29 ); + auto friendListMgr = g_fw.get< Social::SocialMgr< Social::FriendList > >(); + ZoneChannelPacket< FFXIVIpcSocialRequestError > info( targetId, player.getId() ); ZoneChannelPacket< FFXIVIpcSocialRequestResponse > response( targetId, player.getId() ); info.data().category = category; response.data().category = category; + switch( action ) + { + case SocialRequestAction::Accept: + { + auto recipientFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( player.getId() ); + + // Load our target's friendlist, hoping it's still in memory.. (target could have gone offline at this point) + if( !friendListMgr->loadFriendsList( targetId ) ) + { + g_fw.get< Logger >()->error( "Failed to load friend list for character ID " + std::to_string( targetId ) + ", removing entry." ); + } + + auto senderFriendsList = friendListMgr->findGroupById( targetId ); + + senderFriendsList->processInvite( player.getContentId(), SocialRequestAction::Accept ); + //todo: FICK + recipientFriendsList->processInvite( targetId, SocialRequestAction::Accept ); + + } + default: + break; + } + //auto pQR = g_database.query( "SELECT Name FROM dbchara WHERE CharacterId = " + to_string( targetId ) ); auto name = player.getName(); /* diff --git a/src/servers/sapphire_zone/Social/FriendList.cpp b/src/servers/sapphire_zone/Social/FriendList.cpp index fc0c2d25..b7826ed7 100644 --- a/src/servers/sapphire_zone/Social/FriendList.cpp +++ b/src/servers/sapphire_zone/Social/FriendList.cpp @@ -33,7 +33,9 @@ uint32_t FriendList::addMember( uint64_t contentId, FriendEntryType friendEntryT uint32_t logMessage = 0; - m_members.push_back( contentId ); + // todo: index logmessage.. report error (-1) + + const int32_t index = Group::findNextAvailableIndex(); FriendEntry friendEntry; friendEntry.timestamp = std::time( nullptr ); @@ -41,11 +43,74 @@ uint32_t FriendList::addMember( uint64_t contentId, FriendEntryType friendEntryT friendEntry.entryStatus = friendEntryType; friendEntry.unknown = 0; - m_entries.push_back( friendEntry ); + m_members[index] = contentId; + m_entries[index] = friendEntry; return logMessage; } +uint32_t FriendList::removeMember( uint64_t contentId ) +{ + assert( contentId != 0 ); + + uint32_t logMessage = 0; + + // todo: index logmessage.. report error (-1) + + const uint32_t index = getFriendIndex( contentId ); + + m_members[index] = 0; + + auto entry = m_entries[index]; + entry.entryStatus = FriendEntryType::Invalid; + entry.friendGroup = 0; + entry.timestamp = 0; + entry.unknown = 0; + + return logMessage; +} + + +uint32_t FriendList::processInvite( uint64_t contentId, Common::SocialRequestAction action ) +{ + uint32_t logMessage = 0; + + std::vector< uint64_t >::iterator it; + + it = std::find( m_members.begin(), m_members.end(), contentId ); + + auto dataIndex = std::distance( m_members.begin(), it ); + + auto friendEntryData = m_entries.at( dataIndex ); + + // todo: check timestamp, if expired etc. + + switch( action ) + { + case Common::SocialRequestAction::Accept: + { + friendEntryData.entryStatus = FriendEntryType::Added; + break; + } + case Common::SocialRequestAction::Decline: + { + removeMember( contentId ); + } + default: + break; + } + +} + +uint32_t FriendList::getFriendIndex( uint64_t contentId ) +{ + std::vector< uint64_t >::iterator it; + + it = std::find( m_members.begin(), m_members.end(), contentId ); + + return std::distance( m_members.begin(), it ); +} + std::vector< FriendEntry >& FriendList::getEntries() { return m_entries; @@ -86,11 +151,14 @@ std::vector< PlayerEntry > FriendList::getFriendListEntries( uint16_t entryAmoun std::vector< PlayerEntry > entryList = {}; uint16_t limit = 0; - for ( const auto& member : m_members ) + for( const auto& member : m_members ) { - if ( limit == entryAmount ) + if( limit == entryAmount ) break; + if( member == 0 ) + continue; + entryList.push_back( generatePlayerEntry( member ) ); limit++; } diff --git a/src/servers/sapphire_zone/Social/FriendList.h b/src/servers/sapphire_zone/Social/FriendList.h index e3df54d1..1ed5b2a5 100644 --- a/src/servers/sapphire_zone/Social/FriendList.h +++ b/src/servers/sapphire_zone/Social/FriendList.h @@ -17,6 +17,7 @@ namespace Social { enum FriendEntryType : uint8_t { + Invalid = 0, Added = 0x10, SentRequest = 0x20, ReceivedRequest = 0x30 @@ -44,6 +45,12 @@ public: uint32_t addMember( uint64_t contentId, FriendEntryType friendEntryType ); + uint32_t processInvite( uint64_t contentId, Common::SocialRequestAction ); + + uint32_t removeMember( uint64_t contentId ); + + uint32_t getFriendIndex( uint64_t contentId ); + /*! access entry vector */ std::vector< FriendEntry >& getEntries(); diff --git a/src/servers/sapphire_zone/Social/Group.cpp b/src/servers/sapphire_zone/Social/Group.cpp index 53fe0de8..a1c22ccb 100644 --- a/src/servers/sapphire_zone/Social/Group.cpp +++ b/src/servers/sapphire_zone/Social/Group.cpp @@ -15,15 +15,25 @@ #include "Framework.h" #include "Forwards.h" +#include + extern Core::Framework g_fw; using namespace Core::Social; using namespace Core::Network; -uint32_t Group::findNextAvailableIndex() const +int32_t Group::findNextAvailableIndex() const { + // todo: perhaps throw an exception instead of returning -1 if not available? + auto const it = std::find( std::begin( m_members ), std::end( m_members ), 0 ); + if( it == m_members.end() ) + { + return -1; + } + + return std::distance( m_members.begin(), it ); } // todo: invite map in g_serverZone.getGroupMgr(GroupType) and look up diff --git a/src/servers/sapphire_zone/Social/Group.h b/src/servers/sapphire_zone/Social/Group.h index 0752856c..e7dce0d7 100644 --- a/src/servers/sapphire_zone/Social/Group.h +++ b/src/servers/sapphire_zone/Social/Group.h @@ -64,7 +64,7 @@ public: //virtual void populateGroupMembers(); - uint32_t findNextAvailableIndex() const; + int32_t findNextAvailableIndex() const; /*! access member vector */ std::vector< uint64_t >& getMembers(); @@ -72,6 +72,9 @@ public: /*! get container limit */ uint32_t getCapacity() const; + /*! get group id */ + uint64_t getId() const; + /*! get total size of group (members + invites) */ uint32_t Group::getTotalSize() const; @@ -87,6 +90,8 @@ protected: uint32_t m_maxRoles{ 50 }; std::chrono::steady_clock::time_point m_createTime{ std::chrono::steady_clock::now() }; + // todo: it might be interesting to consider moving to a map with entries and sorting that out. + // it does imply useless information being stored in the case of a few groups, which is why I'm not doing it atm std::vector< uint64_t > m_members; private: diff --git a/src/servers/sapphire_zone/Social/Manager/SocialMgr.h b/src/servers/sapphire_zone/Social/Manager/SocialMgr.h index 722b7f03..b766f45e 100644 --- a/src/servers/sapphire_zone/Social/Manager/SocialMgr.h +++ b/src/servers/sapphire_zone/Social/Manager/SocialMgr.h @@ -72,7 +72,7 @@ public: return false; } - uint64_t loadFriendsList( uint32_t characterId ); + bool loadFriendsList( uint32_t characterId ); protected: // those would be implemented in T, so you'd have T.m_type and T.m_maxEntries @@ -109,8 +109,12 @@ bool Core::Social::SocialMgr< T >::init() } template<> inline -uint64_t Core::Social::SocialMgr< Core::Social::FriendList >::loadFriendsList( uint32_t characterId ) +bool Core::Social::SocialMgr< Core::Social::FriendList >::loadFriendsList( uint32_t characterId ) { + // Check if our group has already been loaded.. + auto group = findGroupById( characterId ); + if( group ) + return true; auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >(); auto res = pDb->query( "SELECT CharacterId, CharacterIdList, InviteDataList " @@ -135,10 +139,7 @@ uint64_t Core::Social::SocialMgr< Core::Social::FriendList >::loadFriendsList( u { std::vector< uint64_t > list( friends.size() / 8 ); // todo: fix this garbage check - if( list.at( 0 ) != 0 ) - { - friendsList.getMembers() = list; - } + friendsList.getMembers() = list; } // Insert invite data from binary data @@ -155,9 +156,9 @@ uint64_t Core::Social::SocialMgr< Core::Social::FriendList >::loadFriendsList( u auto friendListPtr = boost::make_shared< Social::FriendList >( friendsList ); - m_groups[groupID] = friendListPtr; + m_groups.emplace( characterId, friendListPtr ); - return groupID; + return true; }