1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-28 20:27:46 +00:00

Begin refactor of social system

This commit is contained in:
Maru 2018-03-15 13:21:17 -03:00
parent b36402119e
commit 5069bdd3e0
15 changed files with 385 additions and 164 deletions

View file

@ -133,7 +133,7 @@ void Core::Db::CharaDbConnection::doPrepareStatements()
/// ITEM GLOBAL
prepareStatement( CHARA_ITEMGLOBAL_INS, "INSERT INTO charaglobalitem ( CharacterId, ItemId, catalogId, UPDATE_DATE ) VALUES ( ?, ?, ?, NOW() );", CONNECTION_BOTH );
// SOCIAL GROUPS
prepareStatement( CHARA_SOCIAL_FRIENDS_INS, "INSERT INTO charainfofriendlist ( CharacterId, CharacterIdList, InviteDataList, UPDATE_DATE ) VALUES ( ?, ?, ?, NOW() );", CONNECTION_SYNC ); // todo: maybe not sync
}

View file

@ -75,6 +75,8 @@ enum CharaDbStatements : uint32_t
CHARA_ITEMGLOBAL_INS,
CHARA_SOCIAL_FRIENDS_INS,
MAX_STATEMENTS
};

View file

@ -198,7 +198,7 @@ namespace Packets {
CFDutyInfoHandler = 0x0078, // updated 4.2
SocialReqSendHandler = 0x00AE, // updated 4.1
SocialReqSendHandler = 0x00CA, // updated 4.2
ChatHandler = 0x00C7, // updated 4.2

View file

@ -137,6 +137,7 @@ struct FFXIVIpcSocialRequestResponse : FFXIVIpcBasePacket<SocialRequestResponse>
uint32_t unknown;
Common::SocialCategory category; // Common::SocialCategory
Common::SocialRequestResponse response; // Common::SocialRequestResponse
uint8_t unknown2; // possibly padding
char name[0x20];
uint16_t padding;
};

View file

@ -290,6 +290,11 @@ namespace Core {
createInvDbContainer( InventoryType::Currency );
createInvDbContainer( InventoryType::Crystal );
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// SET UP SOCIAL GROUPS
createFriendsListContainer( m_id );
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// SETUP EQUIPMENT / STARTING GEAR
auto classJobInfo = g_exdDataGen.get< Core::Data::ClassJob >( m_class );
@ -364,6 +369,21 @@ namespace Core {
g_charaDb.directExecute( stmtCreateInv );
}
void PlayerMinimal::createFriendsListContainer( uint32_t characterId ) const
{
// todo: check if size is a-ok
std::vector< uint8_t > friendsList( 800 );
std::vector< uint8_t > inviteDateList( 800 );
auto stmtCreateFrnList = g_charaDb.getPreparedStatement( Db::CHARA_SOCIAL_FRIENDS_INS );
stmtCreateFrnList->setInt( 1, characterId );
stmtCreateFrnList->setBinary( 2, friendsList );
stmtCreateFrnList->setBinary( 3, inviteDateList );
g_charaDb.directExecute( stmtCreateFrnList );
}
uint64_t PlayerMinimal::getNextUId64() const
{
g_charaDb.directExecute( std::string( "INSERT INTO uniqueiddata( IdName ) VALUES( 'NOT_SET' );" ) );

View file

@ -152,6 +152,8 @@ namespace Core {
void createInvDbContainer( uint16_t slot ) const;
void createFriendsListContainer( uint32_t characterId ) const;
uint32_t m_modelEquip[10];
uint64_t getNextUId64() const;

View file

@ -26,6 +26,8 @@
#include "Forwards.h"
#include "Framework.h"
#include "Social/Manager/SocialMgr.h"
extern Core::Framework g_fw;
using namespace Core::Common;
@ -205,6 +207,9 @@ bool Core::Entity::Player::load( uint32_t charId, SessionPtr pSession )
calculateStats();
m_friendsListId = g_fw.get< Social::SocialMgr < Social::FriendList > >()->loadFriendsList( m_id );
pLog->debug( std::to_string( m_id ) + " ID, has group ID: " + std::to_string( m_friendsListId ) );
// first login, run the script event
if( m_bNewGame )
{

View file

@ -489,14 +489,15 @@ void Core::Network::GameConnection::socialListHandler( const Packets::GamePacket
auto playerFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( player.getFriendsListId() );
// todo: move this garbage else fucking where
for ( auto member : playerFriendsList.getMembers() )
for ( auto member : playerFriendsList->getMembers() )
{
// more elegant way to break over list entries pls
if ( i == 10 )
break;
g_fw.get< Logger >()->debug( "aaa" + std::to_string( i ) + ": " + member.second.name );
listPacket.data().entries[i] = Core::Social::Group::generatePlayerEntry( member.second );
g_fw.get< Logger >()->debug( "aaa" + std::to_string( i ) );
// todo: replace this with call for generating the entire vector
listPacket.data().entries[i] = Core::Social::FriendList::generatePlayerEntry( member, false );
i++;
}
@ -554,7 +555,7 @@ void Core::Network::GameConnection::socialReqResponseHandler( const Packets::Gam
if( pSession )
{
g_fw.get< Logger >()->debug( std::to_string(static_cast<uint8_t>(action)) );
g_fw.get< Logger >()->debug( std::to_string( static_cast< uint8_t >( action ) ) );
}
response.data().response = Common::SocialRequestResponse::Accept;
memcpy( &( response.data().name ), name.c_str(), 32 );
@ -584,7 +585,7 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
bool successful = false;
Entity::PlayerPtr pRecipient = pSession->getPlayer();
std::array<std::string, 5> typeVar{ "", "PartyInvite", "FriendInvite", "FreeCompanyPetition", "FreeCompanyInvite" };
std::array< std::string, 5 > typeVar{ "", "PartyInvite", "FriendInvite", "FreeCompanyPetition", "FreeCompanyInvite" };
// todo: proper handling of invites already sent
// todo: move this to world server
@ -647,7 +648,9 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
{
// todo: check if already on friends list or invite pending
/*
if( pPlayer->getFriendList()->find(name) )
auto playerFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( pPlayer->getgetFriendsListId() );
if( playerFriendsList )
{
response.data().messageId = 312; // That player is already a friend or has been sent a request.
}
@ -672,11 +675,11 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
{
ZoneChannelPacket< FFXIVIpcSocialRequestReceive > packet( player.getId(), pRecipient->getId() );
std::array<uint16_t, 5> typeMessage{ 0,
std::array< uint16_t, 5 > typeMessage{ 0,
1, // You invite <name> to a party.
10, // You send a friend request to <name>.
1884, // You invite <name> to your free company.
3044, // Free company petition signature request sent to <name>
2, // You send a friend request to <name>.
4, // Free company petition signature request sent to <name>
5, // You invite <name> to your free company.
};
// TODO: confirm the timers on retail
@ -690,7 +693,7 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
packet.data().actorId = player.getId();
packet.data().category = category;
packet.data().action = Core::Common::SocialRequestAction::Invite;
packet.data().unknown3 = 80;
packet.data().unknown3 = 80; // these seem like bitmasks!
packet.data().unknown = 46;
packet.data().unknown2 = 64;
memcpy( &( packet.data().name ), player.getName().c_str(), 32 );
@ -700,11 +703,21 @@ void Core::Network::GameConnection::socialReqSendHandler( const Packets::GamePac
auto recipientFriendsList = g_fw.get< Social::SocialMgr< Social::FriendList > >()->findGroupById( pRecipient->getFriendsListId() );
auto senderResultPacket = recipientFriendsList.inviteMember( player.getAsPlayer(), pRecipient, player.getId(), pRecipient->getId() );
auto senderResultPacketResult = recipientFriendsList->addInvite( pRecipient->getId() );
recipientFriendsList->addInvite( player.getId() );
auto senderResultPacket = GamePacketNew< Server::FFXIVIpcSocialRequestResponse, ServerZoneIpcType >( pRecipient->getId(), player.getId() );
senderResultPacket.data().contentId = pRecipient->getId();
senderResultPacket.data().category = Common::SocialCategory::Friends;
senderResultPacket.data().response = Common::SocialRequestResponse::Cancel;
memcpy( &( senderResultPacket.data().name ), pRecipient->getName().c_str(), 32 );
//todo: build packet from packetresult here
player.queuePacket( senderResultPacket );
if ( recipientFriendsList.isFriendList() )
if( recipientFriendsList->isFriendList() )
{
g_fw.get< Logger >()->debug( "he HAA HAAA" );
}

View file

@ -167,6 +167,7 @@ void Core::ServerZone::run( int32_t argc, char* argv[] )
auto pScript = g_fw.get< Scripting::ScriptMgr >();
auto pLsMgr = g_fw.get< LinkshellMgr >();
auto pTeriMgr = g_fw.get< TerritoryMgr >();
auto pFriendListMgr = g_fw.get< Social::SocialMgr< Social::FriendList > >();
printBanner();
@ -175,6 +176,14 @@ void Core::ServerZone::run( int32_t argc, char* argv[] )
pLog->fatal( "Unable to load settings!" );
return;
}
pLog->info( "Initializing social groups" );
if( !pFriendListMgr->init() )
{
pLog->fatal( "Unable to initialize friend list manager!" );
return;
}
pLog->info( "LinkshellMgr: Caching linkshells" );
if( !pLsMgr->loadLinkshells() )

View file

@ -10,26 +10,130 @@
#include <sapphire_zone/ServerZone.h>
#include <sapphire_zone/Zone/Zone.h>
#include <Database/DatabaseDef.h>
#include <Network/GamePacketNew.h>
#include "Group.h"
#include "FriendList.h"
#include "Framework.h"
extern Core::Framework g_fw;
using namespace Core::Network::Packets;
using namespace Core::Network::Packets::Server;
using namespace Core::Social;
std::vector< PlayerEntry > Core::Social::FriendList::getFriendListEntries( uint16_t entryAmount )
{
std::vector< PlayerEntry > entryList = {};
uint16_t limit = 0;
for ( const auto& member : m_members )
for ( const auto& member : m_groupMembers )
{
if ( limit == entryAmount )
break;
entryList.push_back( generatePlayerEntry( member.second ) );
entryList.push_back( generatePlayerEntry( member, false ) );
limit++;
}
for ( const auto& invite : m_groupInvites )
{
if ( limit == entryAmount )
break;
entryList.push_back( generatePlayerEntry( invite, true ) );
limit++;
}
return entryList;
}
//todo: generalize this for linkshell etc
Core::Network::Packets::Server::PlayerEntry FriendList::generatePlayerEntry( uint64_t characterId, bool isInvite )
{
// We check if player is online. If so, we can pull data from existing session in memory
// Otherwise, we pull from SQL. We can optimize this later, there are quite a few choices here
auto pSession = g_fw.get< ServerZone >()->getSession( characterId );
// todo: set as offline in one of the unknown values, if session does not exist
Core::Network::Packets::Server::PlayerEntry entry = {};
entry.contentId = characterId;
entry.timestamp = 1512799339;
// todo: if invite change these
entry.status = 2;
entry.unknown = 0;
//entry.entryIcon = 0xf;
entry.unavailable = 0; // unavailable (other world)
entry.one = 0;
if ( pSession )
{
auto pPlayer = pSession->getPlayer();
//entry.contentId = pPlayer->getContentId();
//entry.bytes[2] = pPlayer->getCurrentZone()->getId();
memcpy( entry.name, pPlayer->getName().c_str(), strlen( pPlayer->getName().c_str() ) );
entry.classJob = pPlayer->getClass();
entry.level = pPlayer->getLevel();
entry.zoneId = pPlayer->getCurrentZone()->getGuId();
entry.grandCompany = pPlayer->getGc();
memcpy( &entry.fcTag[0], "Meme", 4 );
entry.clientLanguage = 2;
entry.knownLanguages = 0x0F;
entry.onlineStatusMask = pPlayer->getOnlineStatusMask();
g_fw.get< Logger >()->debug( std::to_string( pPlayer->getContentId() ) );
}
else
{
//todo: lets grab it from the db
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
//const std::string char_id_str = std::to_string( characterId );
auto stmt = pDb->getPreparedStatement( Db::CharaDbStatements::CHARA_SEL );
stmt->setUInt( 1, characterId );
auto res = pDb->query( stmt );
// todo: Is this correct? Seems so judging from retail
if ( !res->next() )
{
entry.unavailable = 1;
}
else
{
// Todo: Can we make PlayerSQL a static function and use it for this?
auto name = res->getString( "Name" );
strcpy( entry.name, name.c_str() );
//memcpy( entry.name, res->getString( "Name" ), strlen( pPlayer->getName().c_str() ) );
//todo: pull actual FC name
memcpy( &entry.fcTag[0], "Ao", 4 );
entry.clientLanguage = res->getUInt8( "Language" );
entry.knownLanguages = 0x0F;
//entry.onlineStatusMask = pPlayer->getOnlineStatusMask();
}
}
// TODO: no idea what this does - me neither
//listPacket.data().entries[0].one = 1;
g_fw.get< Logger >()->debug( std::to_string( characterId ) );
//g_fw.get< Logger >()->debug( std::to_string( entry.contentId ) );
return entry;
}

View file

@ -25,6 +25,8 @@ public:
std::vector< Network::Packets::Server::PlayerEntry > getFriendListEntries( uint16_t entryAmount );
static Core::Network::Packets::Server::PlayerEntry generatePlayerEntry( uint64_t characterId, bool isInvite );
protected:
uint64_t m_id{ 0 };
uint64_t m_ownerId{ 0 };

View file

@ -22,7 +22,64 @@ using namespace Core::Network;
// todo: invite map in g_serverZone.getGroupMgr(GroupType) and look up
Core::Network::Packets::GamePacketPtr Group::addMember( Core::Entity::PlayerPtr pSender, Core::Entity::PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId )
uint32_t Group::addMember( uint64_t characterId )
{
assert( characterId != 0 );
uint32_t logMessage = 0;
m_groupMembers.insert( characterId );
return 0;
}
uint32_t Group::addInvite( uint64_t characterId )
{
assert( characterId != 0 );
uint32_t logMessage = 0;
m_groupInvites.insert( characterId );
return 0;
}
Core::Network::Packets::GamePacketPtr Group::processInvite( uint64_t recipientId, uint64_t senderId )
{
constexpr uint32_t logMessages[] = {
0, //
1
};
assert( senderId != 0 );
using namespace Core::Network::Packets;
uint64_t recipientContentId = 0;
auto packet = GamePacketNew< Server::FFXIVIpcSocialRequestResponse, ServerZoneIpcType >( recipientId, senderId );
packet.data().contentId = recipientContentId;
packet.data().category = Common::SocialCategory::Friends;
packet.data().response = Common::SocialRequestResponse::Accept;
//packet.data().
if ( m_members.size() < m_maxCapacity )
{
// todo: broadcast join message
m_groupInvites.erase( recipientId );
m_groupMembers.emplace( recipientId );
}
else
{
}
return packet;
}
Core::Network::Packets::GamePacketPtr Group::addMember2( Core::Entity::PlayerPtr pSender, Core::Entity::PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId )
{
constexpr uint32_t logMessages[] = {
0, //
@ -55,10 +112,10 @@ Core::Network::Packets::GamePacketPtr Group::addMember( Core::Entity::PlayerPtr
m_invites.erase( m_invites.find( recipientId ), m_invites.end() );
GroupMember member;
member.inviterId = senderId;
//member.inviterId = senderId;
member.role = 0;
member.contentId = recipientId;
member.name = pSender->getName();
//member.contentId = recipientId;
//member.name = pSender->getName();
m_members.emplace( recipientId, member );
}
else
@ -68,7 +125,7 @@ Core::Network::Packets::GamePacketPtr Group::addMember( Core::Entity::PlayerPtr
return packet;
}
Packets::GamePacketPtr Group::inviteMember( Core::Entity::PlayerPtr pSender, Core::Entity::PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId )
Packets::GamePacketPtr Group::inviteMember2( Core::Entity::PlayerPtr pSender, Core::Entity::PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId )
{
assert( pSender != nullptr || senderId != 0 );
@ -77,13 +134,13 @@ Packets::GamePacketPtr Group::inviteMember( Core::Entity::PlayerPtr pSender, Cor
packet.data().contentId = recipientId;
packet.data().category = Common::SocialCategory::Friends;
if ( m_invites.size() < m_maxCapacity )
if( m_invites.size() < m_maxCapacity )
{
GroupMember member;
member.inviterId = senderId;
//member.inviterId = senderId;
member.role = 0;
member.contentId = recipientId;
member.name = pSender->getName();
//member.contentId = recipientId;
//member.name = pSender->getName();
m_invites.emplace( recipientId, member );
}
@ -92,7 +149,7 @@ Packets::GamePacketPtr Group::inviteMember( Core::Entity::PlayerPtr pSender, Cor
}
// todo: fix
Core::Network::Packets::GamePacketPtr Group::removeMember( Core::Entity::PlayerPtr pSender, Core::Entity::PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId )
Core::Network::Packets::GamePacketPtr Group::removeMember2( Core::Entity::PlayerPtr pSender, Core::Entity::PlayerPtr pRecipient, uint64_t senderId, uint64_t recipientId )
{
assert( pSender != nullptr || senderId != 0 );
@ -108,7 +165,7 @@ void Group::sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket,
assert( pPacket );
for( const auto& member : m_members )
{
auto pSession = g_fw.get< ServerZone >()->getSession( member.second.name );
auto pSession = g_fw.get< ServerZone >()->getSession( member.second.characterId );
if( pSession )
{
pSession->getPlayer()->queuePacket( pPacket );
@ -116,57 +173,16 @@ void Group::sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket,
}
}
Core::Network::Packets::Server::PlayerEntry Group::generatePlayerEntry( GroupMember groupMember )
std::set< uint64_t >& Group::getMembers()
{
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_fw.get< ServerZone >()->getSession( groupMember.name ); // todo: aa i don't like this. maybe just store their ID instead of contentID???
entry.timestamp = 1512799339;
entry.status = 2;
entry.unknown = 0;
//entry.entryIcon = 0xf;
entry.unavailable = 0; // unavailable (other world)
entry.one = 0;
if( pSession )
{
auto pPlayer = pSession->getPlayer();
entry.contentId = pPlayer->getContentId();
//entry.bytes[2] = pPlayer->getCurrentZone()->getId();
entry.classJob = pPlayer->getClass();
entry.level = pPlayer->getLevel();
entry.zoneId = pPlayer->getCurrentZone()->getGuId();
entry.grandCompany = pPlayer->getGc();
memcpy( &entry.fcTag[0], "Meme", 4 );
entry.clientLanguage = 2;
entry.knownLanguages = 0x0F;
entry.onlineStatusMask = pPlayer->getOnlineStatusMask();
g_fw.get< Logger >()->debug( std::to_string( pPlayer->getContentId() ) );
}
// TODO: no idea what this does - me neither
//listPacket.data().entries[0].one = 1;
g_fw.get< Logger >()->debug( std::to_string(groupMember.contentId) );
g_fw.get< Logger >()->debug( std::to_string( entry.contentId ) );
return entry;
return m_groupMembers;
}
std::map< uint64_t, GroupMember > Group::getMembers() const
std::set< uint64_t >& Group::getInvites()
{
return m_members;
return m_groupInvites;
}
uint32_t Group::getCapacity() const
@ -174,6 +190,11 @@ uint32_t Group::getCapacity() const
return m_maxCapacity;
}
uint32_t Group::getTotalSize() const
{
return m_groupMembers.size() + m_groupInvites.size();
}
bool Group::isParty() const
{
return m_type == GroupType::Party;

View file

@ -16,9 +16,9 @@ namespace Social {
struct GroupMember
{
uint64_t inviterId;
uint64_t contentId; // todo: maybe just use id..
std::string name;
//uint64_t inviterId;
uint64_t characterId; // todo: maybe just use id..
//std::string name;
uint32_t role;
};
@ -48,23 +48,38 @@ public:
bool isBlacklist() const;
bool isContentGroup() const;
virtual Core::Network::Packets::GamePacketPtr addMember( Entity::PlayerPtr pSender, Entity::PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
// New group system: return error code for logmessage
//TODO: change the member models!!!!!!!
virtual uint32_t addMember( uint64_t characterId );
virtual uint32_t addInvite( uint64_t characterId );
virtual Core::Network::Packets::GamePacketPtr inviteMember( Entity::PlayerPtr pSender, Entity::PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
virtual Core::Network::Packets::GamePacketPtr removeMember( Entity::PlayerPtr pSender, Entity::PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
virtual Core::Network::Packets::GamePacketPtr processInvite( uint64_t recipientId, uint64_t senderId );
virtual Core::Network::Packets::GamePacketPtr addMember2( Entity::PlayerPtr pSender, Entity::PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
virtual Core::Network::Packets::GamePacketPtr inviteMember2( Entity::PlayerPtr pSender, Entity::PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
virtual Core::Network::Packets::GamePacketPtr removeMember2( Entity::PlayerPtr pSender, Entity::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 populateGroupMembers();
/*! generates a player entry used for lists (social, etc) */
static Core::Network::Packets::Server::PlayerEntry generatePlayerEntry( GroupMember groupMember );
//
/*! access GroupMember vector */
/*! access member vector */
std::set< uint64_t >& getMembers();
std::map< uint64_t, GroupMember > getMembers() const;
/*! access invite vector */
std::set< uint64_t >& getInvites();
/*! get container limit */
uint32_t getCapacity() const;
/*! get total size of group (members + invites) */
uint32_t Group::getTotalSize() const;
protected:
GroupType m_type{ GroupType::None };
uint64_t m_id{ 0 };
@ -72,6 +87,10 @@ protected:
uint32_t m_maxCapacity{ 250 };
uint32_t m_maxRoles{ 50 };
std::chrono::steady_clock::time_point m_createTime{ std::chrono::steady_clock::now() };
std::set< uint64_t > m_groupMembers;
std::set< uint64_t > m_groupInvites;
std::map< uint64_t, GroupMember > m_members;
std::map< uint64_t, GroupMember > m_invites; // <recipient, groupmember (which contains senderId)>

View file

@ -5,57 +5,3 @@
#include <boost/make_shared.hpp>
#include "Forwards.h"
template< class T >
Core::Social::SocialMgr< T >::SocialMgr()
: m_groupCount( 0 ),
m_lastGroupId( 0 ),
m_groups{}
{
}
template< class T >
Core::Social::SocialMgr< T >::~SocialMgr()
{
}
template< class T >
T Core::Social::SocialMgr< T >::findGroupByInviteIdForPlayer( uint64_t playerId ) const
{
auto it = m_invites.find( playerId );
if( it != m_invites.end() )
{
return findGroupById( it->second );
}
return nullptr;
}
template< class T >
T Core::Social::SocialMgr< T >::findGroupById( uint64_t groupId ) const
{
auto it = m_groups.find( groupId );
if( it != m_groups.end() )
{
return it->second;
}
return nullptr;
}
template< class T >
uint64_t Core::Social::SocialMgr< T >::generateGroupId()
{
m_lastGroupId++;
return m_lastGroupId;
}
template< class T >
bool Core::Social::SocialMgr< T >::hasInvite( uint64_t playerId ) const
{
auto it = m_invites.find( playerId );
if ( it != m_invites.end() )
{
return true;
}
return false;
}

View file

@ -7,10 +7,17 @@
#include <cstdint>
#include <boost/enable_shared_from_this.hpp>
#include <boost/shared_ptr.hpp>
#include <sapphire_zone/Forwards.h>
#include <Social/Group.h>
#include "Forwards.h"
#include <Social/FriendList.h>
#include <Database/DatabaseDef.h>
#include "Framework.h"
extern Core::Framework g_fw;
namespace Core {
namespace Social {
@ -20,14 +27,32 @@ class SocialMgr
{
public:
SocialMgr();
~SocialMgr();
SocialMgr() : m_groupCount( 0 ),
m_lastGroupId( 0 ),
m_groups{}
{
T findGroupByInviteIdForPlayer( uint64_t playerId ) const;
T findGroupById( uint64_t groupId ) const;
/*
}
T findGroup( uint64_t groupId )
~SocialMgr()
{
}
bool init();
//bool< FriendList > init();
boost::shared_ptr< T > findGroupByInviteIdForPlayer( uint64_t playerId ) const
{
auto it = m_invites.find( playerId );
if ( it != m_invites.end() )
{
return findGroupById( it->second );
}
return nullptr;
}
boost::shared_ptr< T > findGroupById( uint64_t groupId ) const
{
auto it = m_groups.find( groupId );
if ( it != m_groups.end() )
@ -35,37 +60,37 @@ public:
return it->second;
}
return nullptr;
}*/
}
bool hasInvite( uint64_t playerId ) const;
bool hasInvite( uint64_t playerId ) const
{
auto it = m_invites.find( playerId );
if ( it != m_invites.end() )
{
return true;
}
return false;
}
uint64_t loadFriendsList( uint32_t characterId );
protected:
// those would be implemented in T, so you'd have T.m_type and T.m_maxEntries
// GroupType m_type{ GroupType::None };
// uint32_t m_maxEntries{ 0xFFFFFFFF };
uint64_t generateGroupId()
{
m_lastGroupId++;
return m_lastGroupId;
}
uint64_t m_groupCount;
std::map< uint64_t, uint64_t > m_invites;
uint64_t m_lastGroupId;
// < recipient, groupid >
//virtual GroupPtr createGroup( PlayerPtr pOwner ) = 0;
/*
friend virtual Core::Network::Packets::GamePacketPtr Core::Entity::Group::Group::addMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
friend virtual Core::Network::Packets::GamePacketPtr Core::Entity::Group::Group::inviteMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
friend virtual Core::Network::Packets::GamePacketPtr Core::Entity::Group::Group::removeMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
friend virtual Core::Network::Packets::GamePacketPtr Core::Entity::Group::Group::kickMember( PlayerPtr pSender, PlayerPtr pRecipient, uint64_t senderId = 0, uint64_t recipientId = 0 );
friend virtual void sendPacketToMembers( Core::Network::Packets::GamePacketPtr pPacket, bool invitesToo = false );
friend virtual void load();
friend virtual void update();
friend virtual void disband();
*/
uint64_t generateGroupId();
std::map< uint64_t, T > m_groups;
std::map< uint64_t, boost::shared_ptr< T > > m_groups;
private:
@ -74,4 +99,56 @@ private:
}
};
// Specialization
template< class T >
bool Core::Social::SocialMgr< T >::init()
{
return true;
}
template<> inline
uint64_t Core::Social::SocialMgr< Core::Social::FriendList >::loadFriendsList( uint32_t characterId )
{
auto pDb = g_fw.get< Db::DbWorkerPool< Db::CharaDbConnection > >();
auto res = pDb->query( "SELECT CharacterId, CharacterIdList, InviteDataList "
"FROM charainfofriendlist "
"WHERE CharacterId = " + std::to_string( characterId ) );
if ( !res->next() )
return false;
uint64_t ownerId = res->getUInt64( 1 );
auto groupID = generateGroupId();
auto friendsList = Core::Social::FriendList( groupID, ownerId );
auto func = []( std::set< uint64_t >& outList, std::vector< char >& inData )
{
if ( inData.size() )
{
std::vector< uint64_t > list( inData.size() / 8 );
outList.insert( list.begin(), list.end() );
}
};
std::vector< char > friends;
friends = res->getBlobVector( 2 );
func( friendsList.getMembers(), friends );
std::vector< char > friendInvites;
friendInvites = res->getBlobVector( 3 );
func( friendsList.getInvites(), friendInvites );
auto friendListPtr = boost::make_shared< Core::Social::FriendList >( friendsList );
m_groups[groupID] = friendListPtr;
return groupID;
}
#endif /* ! _SOCIALMGR_H */