diff --git a/src/servers/Server_Zone/Actor/Group/FriendList.cpp b/src/servers/Server_Zone/Actor/Group/FriendList.cpp index 058fdab2..7d87a039 100644 --- a/src/servers/Server_Zone/Actor/Group/FriendList.cpp +++ b/src/servers/Server_Zone/Actor/Group/FriendList.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -8,3 +9,43 @@ #include #include #include "FriendList.h" + +extern Core::ServerZone g_serverZone; + +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; + +std::vector< PlayerEntry > Core::Entity::Group::FriendList::getFriendListEntries( uint16_t entryAmount ) +{ + std::vector< PlayerEntry > entryList = {}; + uint16_t limit = 0; + + for ( const auto& member : m_members ) + { + if ( limit == entryAmount ) + break; + + entryList.push_back( generatePlayerEntry( member.second ) ); + limit++; + } +} + +//todo: make this function generic for all groups, and override if needed? +ZoneChannelPacket< FFXIVIpcSocialList > Core::Entity::Group::FriendList::generateFriendsListPacket( PlayerPtr pPlayer ) +{ + ZoneChannelPacket< FFXIVIpcSocialList > listPacket( pPlayer->getId() ); + listPacket.data().type = 0x0B; + listPacket.data().sequence = 10; + memset( listPacket.data().entries, 0, sizeof( listPacket.data().entries ) ); + + uint16_t i = 0; + + for ( const auto& member : m_members ) + { + if ( i == 10 ) + break; + + listPacket.data().entries[i] = generatePlayerEntry( member.second ); + i++; + } +} diff --git a/src/servers/Server_Zone/Actor/Group/FriendList.h b/src/servers/Server_Zone/Actor/Group/FriendList.h index e0f0625c..ba8aedd4 100644 --- a/src/servers/Server_Zone/Actor/Group/FriendList.h +++ b/src/servers/Server_Zone/Actor/Group/FriendList.h @@ -2,6 +2,7 @@ #define _FRIENDLIST_H #include +#include #include #include #include @@ -10,7 +11,8 @@ #include #include - +using namespace Core::Network::Packets; +using namespace Core::Network::Packets::Server; namespace Core { namespace Entity { @@ -19,28 +21,38 @@ namespace Group { class FriendList; using FriendListPtr = boost::shared_ptr< FriendList >; -struct GroupMember -{ - uint64_t contentId; - char name[32]; - uint32_t category; - uint64_t inviterId; -}; - -enum class GroupType : uint8_t -{ - None, - Party, - FriendList, - FreeCompany, - Linkshell, - FreeCompanyPetition, - Blacklist, - ContentGroup -}; - class FriendList : public Group { + +public: + FriendList( uint64_t id, uint64_t ownerId, uint32_t maxCapacity, time_point createTime ) : + Group( id, ownerId, maxCapacity, createTime ), + m_id( id ), m_ownerId( m_ownerId ), m_maxCapacity( maxCapacity ), m_createTime( createTime ) {}; + + ~FriendList() {}; + + virtual Core::Network::Packets::GamePacketPtr addMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual Core::Network::Packets::GamePacketPtr inviteMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual Core::Network::Packets::GamePacketPtr removeMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual Core::Network::Packets::GamePacketPtr kickMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual void sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo = false ); + + virtual void load(); + virtual void update(); + virtual void disband(); + + bool isParty() const; + bool isFriendList() const; + bool isFreeCompany() const; + bool isLinkshell() const; + bool isFreeCompanyPetition() const; + bool isBlacklist() const; + bool isContentGroup() const; + + std::vector< Core::Network::Packets::Server::PlayerEntry > getFriendListEntries( uint16_t entryAmount ); + + Core::Network::Packets::ZoneChannelPacket< FFXIVIpcSocialList > generateFriendsListPacket( PlayerPtr pPlayer ); + private: GroupType m_type{ GroupType::FriendList }; uint64_t m_id{ 0 }; @@ -52,27 +64,8 @@ private: std::map< uint64_t, uint64_t > m_invites; // - virtual Core::Network::Packets::GamePacketPtr addMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); - virtual Core::Network::Packets::GamePacketPtr inviteMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); - virtual Core::Network::Packets::GamePacketPtr removeMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); - virtual Core::Network::Packets::GamePacketPtr kickMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); - virtual void sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo = false ); + - virtual void load(); - virtual void update(); - virtual void disband(); -public: - FriendList( uint64_t id, uint64_t ownerId, uint32_t maxCapacity, time_point createTime ) : - m_id( id ), m_ownerId( m_ownerId ), m_maxCapacity( maxCapacity ), m_createTime( createTime ){}; - ~FriendList(){}; - - bool isParty() const; - bool isFriendList() const; - bool isFreeCompany() const; - bool isLinkshell() const; - bool isFreeCompanyPetition() const; - bool isBlacklist() const; - bool isContentGroup() const; }; } diff --git a/src/servers/Server_Zone/Actor/Group/Group.cpp b/src/servers/Server_Zone/Actor/Group/Group.cpp index 83f490f4..79ecb406 100644 --- a/src/servers/Server_Zone/Actor/Group/Group.cpp +++ b/src/servers/Server_Zone/Actor/Group/Group.cpp @@ -7,15 +7,18 @@ #include #include #include +#include #include #include "Group.h" extern Core::ServerZone g_serverZone; +using namespace Core::Entity::Group; + // todo: i fuckin have no fuckin clue how to use group manager classes, why not just have a map of ? // todo: invite map in g_serverZone.getGroupMgr(GroupType) and look up -Core::Network::Packets::GamePacketPtr Core::Entity::Group::Group::addMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId ) +Core::Network::Packets::GamePacketPtr Group::addMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId ) { constexpr uint32_t logMessages[] = { 0, // @@ -59,7 +62,7 @@ Core::Network::Packets::GamePacketPtr Core::Entity::Group::Group::addMember( Pla return packet; } -void Core::Entity::Group::Group::sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo ) +void Group::sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo ) { assert( pPacket ); for( const auto& member : m_members ) @@ -72,37 +75,80 @@ void Core::Entity::Group::Group::sendPacketToMembers( Core::Network::Packets::Ga } } -bool Core::Entity::Group::Group::isParty() const +Core::Network::Packets::Server::PlayerEntry Group::generatePlayerEntry( GroupMember groupMember ) +{ + Core::Network::Packets::Server::PlayerEntry entry = {}; + + memcpy( entry.name, groupMember.name.c_str(), strlen( groupMember.name.c_str() ) ); + entry.contentId = groupMember.contentId; + + // We check if player is online. If so, we can pull more data - otherwise just name + // todo: set as offline in one of the unknown values, if session does not exist + + auto pSession = g_serverZone.getSession( groupMember.name ); // todo: aa i don't like this. maybe just store their ID instead of contentID??? + + if( pSession ) + { + auto pPlayer = pSession->getPlayer(); + + entry.bytes[2] = pPlayer->getCurrentZone()->getId(); + entry.bytes[3] = 0x80; + entry.bytes[4] = 0x02; + entry.bytes[6] = 0x3B; + entry.bytes[11] = 0x10; + entry.classJob = pPlayer->getClass(); + + entry.level = pPlayer->getLevel(); + entry.zoneId = pPlayer->getCurrentZone()->getId(); + entry.grandCompany = pPlayer->getGc(); + memcpy( &entry.fcTag[0], "Meme", 9 ); + entry.clientLanguage = 2; + entry.knownLanguages = 0x0F; + entry.onlineStatusMask = pPlayer->getOnlineStatusMask(); + } + + // TODO: no idea what this does - me neither + //listPacket.data().entries[0].one = 1; + + return entry; +} + +uint32_t Group::getCapacity() const +{ + return m_maxCapacity; +} + +bool Group::isParty() const { return m_type == GroupType::Party; } -bool Core::Entity::Group::Group::isFriendList() const +bool Group::isFriendList() const { return m_type == GroupType::FriendList; } -bool Core::Entity::Group::Group::isFreeCompany() const +bool Group::isFreeCompany() const { return m_type == GroupType::FreeCompany; } -bool Core::Entity::Group::Group::isLinkshell() const +bool Group::isLinkshell() const { return m_type == GroupType::Linkshell; } -bool Core::Entity::Group::Group::isFreeCompanyPetition() const +bool Group::isFreeCompanyPetition() const { return m_type == GroupType::FreeCompanyPetition; } -bool Core::Entity::Group::Group::isBlacklist() const +bool Group::isBlacklist() const { return m_type == GroupType::Blacklist; } -bool Core::Entity::Group::Group::isContentGroup() const +bool Group::isContentGroup() const { return m_type == GroupType::ContentGroup; } \ No newline at end of file diff --git a/src/servers/Server_Zone/Actor/Group/Group.h b/src/servers/Server_Zone/Actor/Group/Group.h index d44df05b..1b25d2f4 100644 --- a/src/servers/Server_Zone/Actor/Group/Group.h +++ b/src/servers/Server_Zone/Actor/Group/Group.h @@ -2,6 +2,7 @@ #define _GROUP_H #include +#include #include #include #include @@ -19,7 +20,7 @@ using GroupPtr = boost::shared_ptr< Group >; struct GroupMember { uint64_t inviterId; - uint64_t contentId; + uint64_t contentId; // todo: maybe just use id.. std::string name; uint32_t role; }; @@ -31,7 +32,6 @@ enum class GroupType : uint8_t FriendList, FreeCompany, Linkshell, - FreeCompanyPetition, Blacklist, ContentGroup @@ -39,6 +39,31 @@ enum class GroupType : uint8_t class Group : public boost::enable_shared_from_this< Group > { +public: + Group( uint64_t id, uint64_t ownerId, uint32_t maxCapacity, time_point createTime ) : + m_id( id ), m_ownerId( m_ownerId ), m_maxCapacity( maxCapacity ), m_createTime( createTime ) {}; + ~Group() {}; + + bool isParty() const; + bool isFriendList() const; + bool isFreeCompany() const; + bool isLinkshell() const; + bool isFreeCompanyPetition() const; + bool isBlacklist() const; + bool isContentGroup() const; + + virtual Core::Network::Packets::GamePacketPtr addMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual Core::Network::Packets::GamePacketPtr inviteMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual Core::Network::Packets::GamePacketPtr removeMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual Core::Network::Packets::GamePacketPtr kickMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 ); + virtual void sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo = false ); + + /*! generates a player entry used for lists (social, etc) */ + Core::Network::Packets::Server::PlayerEntry generatePlayerEntry( GroupMember groupMember ); + + /*! get container limit */ + uint32_t getCapacity() const; + private: GroupType m_type{ GroupType::None }; uint64_t m_id{ 0 }; @@ -50,29 +75,12 @@ private: std::map< uint64_t, uint64_t > m_invites; // - + virtual void load(); virtual void update(); virtual void disband(); -public: - Group( uint64_t id, uint64_t ownerId, uint32_t maxCapacity, time_point createTime ) : - m_id( id ), m_ownerId( m_ownerId ), m_maxCapacity( maxCapacity ), m_createTime( createTime ){}; - ~Group(){}; - bool isParty() const; - bool isFriendList() const; - bool isFreeCompany() const; - bool isLinkshell() const; - bool isFreeCompanyPetition() const; - bool isBlacklist() const; - bool isContentGroup() const; - - virtual Core::Network::Packets::GamePacketPtr addMember(PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0); - virtual Core::Network::Packets::GamePacketPtr inviteMember(PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0); - virtual Core::Network::Packets::GamePacketPtr removeMember(PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0); - virtual Core::Network::Packets::GamePacketPtr kickMember(PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0); - virtual void sendPacketToMembers(Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo = false); }; } diff --git a/src/servers/Server_Zone/Actor/Group/Manager/FriendListMgr.h b/src/servers/Server_Zone/Actor/Group/Manager/FriendListMgr.h index 0b490137..1ac6376e 100644 --- a/src/servers/Server_Zone/Actor/Group/Manager/FriendListMgr.h +++ b/src/servers/Server_Zone/Actor/Group/Manager/FriendListMgr.h @@ -16,6 +16,15 @@ namespace Group { class FriendListMgr : public GroupMgr { +public: + FriendListMgr( GroupType type, uint32_t maxEntries ) : + GroupMgr( type, maxEntries ), + m_type( type ), m_maxEntries( maxEntries ) {}; + ~FriendListMgr() {}; + + GroupPtr findGroupByInviteIdForPlayer( uint64_t playerId ) const; + GroupPtr findGroupById( uint64_t groupId ) const; + private: GroupType m_type{ GroupType::None }; uint64_t m_groupCount{ 0 }; @@ -24,13 +33,6 @@ private: std::map< uint64_t, uint64_t > m_invites; // < recipient, groupid > virtual GroupPtr createGroup( PlayerPtr pOwner ) = 0; -public: - FriendListMgr( GroupType type, uint32_t maxEntries ) : - m_type( type ), m_maxEntries( maxEntries ){}; - ~FriendListMgr(){}; - - GroupPtr findGroupByInviteIdForPlayer( uint64_t playerId ) const; - GroupPtr findGroupById( uint64_t groupId ) const; }; } diff --git a/src/servers/Server_Zone/Actor/Group/Manager/GroupMgr.h b/src/servers/Server_Zone/Actor/Group/Manager/GroupMgr.h index a26e19ba..521a72df 100644 --- a/src/servers/Server_Zone/Actor/Group/Manager/GroupMgr.h +++ b/src/servers/Server_Zone/Actor/Group/Manager/GroupMgr.h @@ -14,6 +14,14 @@ namespace Group { class GroupMgr : public boost::enable_shared_from_this< GroupMgr > { +public: + GroupMgr( GroupType type, uint32_t maxEntries ) : + m_type( type ), m_maxEntries( maxEntries ) {}; + ~GroupMgr() {}; + + GroupPtr findGroupByInviteIdForPlayer( uint64_t playerId ) const; + GroupPtr findGroupById( uint64_t groupId ) const; + private: GroupType m_type{ GroupType::None }; uint64_t m_groupCount{ 0 }; @@ -33,13 +41,7 @@ private: friend virtual void update(); friend virtual void disband(); */ -public: - GroupMgr( GroupType type, uint32_t maxEntries ) : - m_type( type ), m_maxEntries( maxEntries ){}; - ~GroupMgr(){}; - GroupPtr findGroupByInviteIdForPlayer( uint64_t playerId ) const; - GroupPtr findGroupById( uint64_t groupId ) const; }; } diff --git a/src/servers/Server_Zone/Actor/Player.cpp b/src/servers/Server_Zone/Actor/Player.cpp index 6ad05126..f4300417 100644 --- a/src/servers/Server_Zone/Actor/Player.cpp +++ b/src/servers/Server_Zone/Actor/Player.cpp @@ -300,6 +300,11 @@ void Core::Entity::Player::sendStats() queuePacket( statPacket ); } +Group::FriendListPtr Core::Entity::Player::getFriendsList() const +{ + return m_friendsList; +} + void Core::Entity::Player::teleport( uint16_t aetheryteId, uint8_t type ) { auto data = g_exdData.getAetheryteInfo( aetheryteId ); @@ -900,33 +905,6 @@ Core::Entity::ActorPtr Core::Entity::Player::lookupTargetById( uint64_t targetId return targetActor; } -Core::Network::Packets::Server::PlayerEntry Core::Entity::Player::generatePlayerEntry() -{ - Core::Network::Packets::Server::PlayerEntry entry = {}; - - entry.bytes[2] = getCurrentZone()->getId(); - entry.bytes[3] = 0x80; - entry.bytes[4] = 0x02; - entry.bytes[6] = 0x3B; - entry.bytes[11] = 0x10; - entry.classJob = getClass(); - entry.contentId = getContentId(); - entry.level = getLevel(); - entry.zoneId = getCurrentZone()->getId(); - entry.grandCompany = getGc(); - memcpy( &entry.fcTag[0], "Meme", 9 ); - entry.clientLanguage = 2; - entry.knownLanguages = 0x0F; - // TODO: no idea what this does - me neither - //listPacket.data().entries[0].one = 1; - - memcpy( entry.name, getName().c_str(), strlen( getName().c_str() ) ); - - entry.onlineStatusMask = getOnlineStatusMask(); - - return entry; -} - void Core::Entity::Player::setLastPing( uint32_t ping ) { m_lastPing = ping; diff --git a/src/servers/Server_Zone/Actor/Player.h b/src/servers/Server_Zone/Actor/Player.h index 9039c10c..40015bcf 100644 --- a/src/servers/Server_Zone/Actor/Player.h +++ b/src/servers/Server_Zone/Actor/Player.h @@ -5,6 +5,7 @@ #include #include +#include #include "Actor.h" #include "src/servers/Server_Zone/Inventory/Inventory.h" @@ -351,6 +352,11 @@ public: void calculateStats() override; void sendStats(); + // Social-based + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + Group::FriendListPtr getFriendsList() const; + // Aetheryte / Action / Attribute bitmasks ////////////////////////////////////////////////////////////////////////////////////////////////////// @@ -481,9 +487,6 @@ public: void sendUrgent( const std::string& message ); void sendDebug( const std::string& message ); - /*! generates a player entry used for lists (social, etc) */ - Core::Network::Packets::Server::PlayerEntry generatePlayerEntry(); - // Player Battle Handling ////////////////////////////////////////////////////////////////////////////////////////////////////// void onMobAggro( BattleNpcPtr pBNpc ); @@ -610,6 +613,10 @@ private: uint8_t m_gmRank; uint16_t zoneId; + // Social-based + + Group::FriendListPtr m_friendsList; + uint8_t m_equipDisplayFlags; bool m_bInCombat; diff --git a/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp b/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp index ccd33a27..e603a996 100644 --- a/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp +++ b/src/servers/Server_Zone/Network/Handlers/PacketHandlers.cpp @@ -436,7 +436,7 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket if( type == SocialListType::PartyList ) { // party list - ZoneChannelPacket< FFXIVIpcSocialList > listPacket( pPlayer->getId() );; + /*ZoneChannelPacket< FFXIVIpcSocialList > listPacket( pPlayer->getId() );; listPacket.data().type = 2; listPacket.data().sequence = count; @@ -446,37 +446,13 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket listPacket.data().entries[0] = pPlayer->generatePlayerEntry(); - queueOutPacket( listPacket ); + queueOutPacket( listPacket );*/ } else if( type == SocialListType::FriendList ) { // friend list - ZoneChannelPacket< FFXIVIpcSocialList > listPacket( pPlayer->getId() ); - listPacket.data().type = 0x0B; - listPacket.data().sequence = count; - memset( listPacket.data().entries, 0, sizeof( listPacket.data().entries ) ); - - // todo: for now.. just grab all actors in range and add them in. just replace logic later by using manager - - uint8_t i = 0; - - for( auto actor : pPlayer->getInRangeActors() ) - { - auto pFriend = actor->getAsPlayer(); - if( pFriend ) - { - /*listPacket.data().entries[i] = pFriend->generatePlayerEntry(); - i++;*/ - } - - // todo: remove this branch entirely when using manager. physically hurts - if( i >= 200 ) - { - break; - } - - } + ZoneChannelPacket< FFXIVIpcSocialList > listPacket = pPlayer->getFriendsList()->generateFriendsListPacket( pPlayer ); queueOutPacket( listPacket ); @@ -675,6 +651,9 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac pRecipient->queuePacket( packet ); pRecipient->sendDebug( "ding ding" ); + + pRecipient->getFriendsList()->addMember( pPlayer, pRecipient, pPlayer->getId(), pRecipient->getId() ); + response.data().messageId = typeMessage[category]; } } @@ -803,7 +782,7 @@ void Core::Network::GameConnection::tellHandler( const Packets::GamePacket& inPa void Core::Network::GameConnection::performNoteHandler( const Packets::GamePacket& inPacket, Entity::PlayerPtr pPlayer ) { - GamePacketNew< FFXIVIpcPerformNote, ServerZoneIpcType > performPacket( pPlayer->getId() ); + GamePacketNew< FFXIVIpcPerformNote, ServerZoneIpcType > performPacket( pPlayer->getId() ); // todo: change to zonepacket uint8_t inVal = inPacket.getValAt< uint8_t >( 0x20 ); memcpy( &performPacket.data().data[0], &inVal, 32 );