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:
parent
b36402119e
commit
5069bdd3e0
15 changed files with 385 additions and 164 deletions
|
@ -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
|
||||
}
|
||||
|
|
|
@ -75,6 +75,8 @@ enum CharaDbStatements : uint32_t
|
|||
|
||||
CHARA_ITEMGLOBAL_INS,
|
||||
|
||||
CHARA_SOCIAL_FRIENDS_INS,
|
||||
|
||||
MAX_STATEMENTS
|
||||
};
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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' );" ) );
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 )
|
||||
{
|
||||
|
|
|
@ -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" );
|
||||
}
|
||||
|
|
|
@ -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() )
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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 };
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)>
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Add table
Reference in a new issue