1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-07-11 23:07:44 +00:00

Putting things together for FriendList

This commit is contained in:
Maru 2017-12-07 04:15:20 -02:00
parent eec2809b19
commit cd3b2e1567
9 changed files with 197 additions and 141 deletions

View file

@ -1,5 +1,6 @@
#include <cassert>
#include <boost/shared_ptr.hpp>
#include <src/servers/Server_Common/Common.h>
#include <Server_Common/Network/PacketDef/Ipcs.h>
#include <Server_Common/Network/PacketDef/Zone/ServerZoneDef.h>
@ -8,3 +9,43 @@
#include <Server_Zone/ServerZone.h>
#include <Server_Common/Network/GamePacketNew.h>
#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++;
}
}

View file

@ -2,6 +2,7 @@
#define _FRIENDLIST_H
#include <src/servers/Server_Common/Common.h>
#include <Server_Common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <Server_Common/Forwards.h>
#include <Server_Zone/Actor/Group/Group.h>
#include <Server_Zone/Forwards.h>
@ -10,7 +11,8 @@
#include <cstdint>
#include <map>
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; // <recipient, sender>
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;
};
}

View file

@ -7,15 +7,18 @@
#include <Server_Zone/Actor/Actor.h>
#include <Server_Zone/Actor/Player.h>
#include <Server_Zone/ServerZone.h>
#include <Server_Zone/Zone/Zone.h>
#include <Server_Common/Network/GamePacketNew.h>
#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 <id, group>?
// 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;
}

View file

@ -2,6 +2,7 @@
#define _GROUP_H
#include <Server_Common/Common.h>
#include <Server_Common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <Server_Common/Forwards.h>
#include <Server_Zone/Forwards.h>
#include <boost/enable_shared_from_this.hpp>
@ -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 };
@ -55,24 +80,7 @@ private:
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);
};
}

View file

@ -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;
};
}

View file

@ -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;
};
}

View file

@ -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;

View file

@ -5,6 +5,7 @@
#include <src/servers/Server_Common/Common.h>
#include <src/servers/Server_Common/Network/PacketDef/Zone/ServerZoneDef.h>
#include <src/servers/Server_Zone/Actor/Group/FriendList.h>
#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;

View file

@ -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 );