1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-04-28 07:07:45 +00:00

add initial friendlist impl; fix teri crash on login if commonlist is called; fix sql type and initial data on player creation;

This commit is contained in:
Alice Ogeda 2021-12-01 21:30:12 -03:00
parent be2320aa98
commit 3e73da6463
18 changed files with 413 additions and 67 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE `charainfofriendlist`
CHANGE COLUMN `CharacterId` `CharacterId` BIGINT NOT NULL DEFAULT 0 FIRST;

View file

@ -268,6 +268,16 @@ void PlayerMinimal::saveAsNew()
stmtSearchInfo->setUInt64( 1, m_characterId );
g_charaDb.directExecute( stmtSearchInfo );
// Friend list related
auto stmtFriendList = g_charaDb.getPreparedStatement( Db::ZoneDbStatements::CHARA_FRIENDLIST_INS );
std::vector< uint8_t > friendIds( 1600, 0 );
std::vector< uint8_t > inviteIds( 1600, 0 );
stmtFriendList->setUInt64( 1, m_characterId );
stmtFriendList->setBinary( 2, friendIds );
stmtFriendList->setBinary( 3, inviteIds );
g_charaDb.directExecute( stmtFriendList );
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// SET UP INVENTORIES
createInvDbContainer( InventoryType::Bag0 );

View file

@ -24,7 +24,7 @@ namespace Sapphire::Common
const uint16_t MAX_PLAYER_LEVEL = 80;
const uint8_t CURRENT_EXPANSION_ID = 3;
const uint8_t CLASSJOB_TOTAL = 38;
const uint8_t CLASSJOB_TOTAL = 33;
const uint8_t CLASSJOB_SLOTS = 20;
const uint8_t TOWN_COUNT = 6;
@ -971,7 +971,7 @@ namespace Sapphire::Common
InvincibilityIgnoreDamage,
};
enum InviteType : int32_t
enum HierarchyType : uint8_t
{
NONE_2 = 0x0,
PCPARTY = 0x1,
@ -984,6 +984,14 @@ namespace Sapphire::Common
MAX_1 = 0xFF,
};
enum HierarchyStatus : uint8_t
{
Invalid = 0,
Added = 0x10,
SentRequest = 0x20,
ReceivedRequest = 0x30
};
enum LinkshellHierarchy : int32_t
{
NONE_1 = 0x0,
@ -994,13 +1002,17 @@ namespace Sapphire::Common
MAX_0 = 0x7,
};
enum GroupEntryStatus : uint8_t
union HierarchyData
{
Invalid = 0,
Added = 0x10,
SentRequest = 0x20,
ReceivedRequest = 0x30
uint64_t u64;
struct HierarchyPackedData {
uint32_t dateAdded;
uint8_t status;
uint8_t type;
uint8_t group;
uint8_t unk;
} data;
};
/* 61719 */

View file

@ -83,6 +83,7 @@ namespace Sapphire::Network::Packets
PcSearch = 0xEB,
GetFcJoinRequestComment = 0xEC,
InviteCancel = 0xED,
SetFriendlistGroup = 0xEE,
LinkshellJoin = 0xF0,
LinkshellJoinOfficial = 0xF1,
LinkshellLeave = 0xF2,

View file

@ -579,6 +579,18 @@ struct FFXIVIpcGetCommonlistDetail : FFXIVIpcBasePacket< GetCommonlistDetail >
uint8_t ListType;
};
struct FFXIVIpcFriendlistRemove : FFXIVIpcBasePacket< FriendlistRemove >
{
uint64_t TargetCharacterID;
char TargetCharacterName[32];
};
struct FFXIVIpcSetFriendlistGroup : FFXIVIpcBasePacket< SetFriendlistGroup >
{
uint64_t TargetCharacterID;
uint8_t group;
};
struct FFXIVIpcPcSearch : FFXIVIpcBasePacket< PcSearch >
{
uint64_t ClassID;

View file

@ -58,12 +58,17 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
/**
* Structural representation of the packet sent by the server
* with a list of players ( party list | friend list | search results )
* 3.0 Update: 64bit TerritoryID -> 32bit Timestamp, 32bit TerritoryID
*/
struct PlayerEntry
{
uint64_t CharacterID;
uint64_t TerritoryID;
uint32_t HierarchyID;
uint32_t Timestamp;
uint32_t TerritoryID;
uint8_t HierarchyStatus;
uint8_t HierarchyType;
uint8_t HierarchyGroup;
uint8_t HierarchyUnk;
uint16_t TerritoryType;
uint8_t GrandCompanyID;
uint8_t Region;
@ -144,6 +149,14 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
char InviteName[32];
};
struct FFXIVIpcFriendlistRemoveResult : FFXIVIpcBasePacket< FriendlistRemoveResult >
{
uint64_t RemovedCharacterID;
uint32_t Result;
uint8_t Identity;
char RemovedCharacterName[32];
};
struct FFXIVIpcGetFcStatusResult : FFXIVIpcBasePacket< GetFcStatusResult >
{
uint64_t FreeCompanyID;

View file

@ -2138,6 +2138,15 @@ void Sapphire::Entity::Player::setPartyId( uint64_t partyId )
m_partyId = partyId;
}
Sapphire::Entity::Player::FriendListIDVec& Sapphire::Entity::Player::getFriendListID()
{
return m_friendList;
}
Sapphire::Entity::Player::FriendListDataVec& Sapphire::Entity::Player::getFriendListData()
{
return m_friendInviteList;
}
void Sapphire::Entity::Player::setLastPcSearchResult( std::vector< uint32_t > result )
{
m_lastPcSearch = std::move( result );

View file

@ -799,6 +799,9 @@ namespace Sapphire::Entity
//////////////////////////////////////////////////////////////////////////////////////////////////////
using FriendListIDVec = std::array< uint64_t, 200 >;
using FriendListDataVec = std::array< Common::HierarchyData, 200 >;
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );
void sendHuntingLog();
@ -808,6 +811,9 @@ namespace Sapphire::Entity
uint64_t getPartyId() const;
void setPartyId( uint64_t partyId );
FriendListIDVec& getFriendListID();
FriendListDataVec& getFriendListData();
uint64_t m_lastMoveTime{};
uint8_t m_lastMoveflag{};
bool m_falling;
@ -963,8 +969,8 @@ namespace Sapphire::Entity
std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries{};
std::array< uint64_t, 200 > m_friendList{};
std::array< uint64_t, 200 > m_friendInviteList{};
FriendListIDVec m_friendList{};
FriendListDataVec m_friendInviteList{};
uint64_t m_partyId;
std::vector< uint32_t > m_lastPcSearch;

View file

@ -462,12 +462,12 @@ void Sapphire::Entity::Player::updateDbFriendList()
auto stmt = db.getPreparedStatement( Db::CHARA_FRIENDLIST_UP );
std::vector< uint8_t > friendIds( 1600 );
std::vector< uint8_t > InviteIds( 1600 );
std::vector< uint8_t > inviteIds( 1600 );
memcpy( friendIds.data(), m_friendList.data(), 1600 );
memcpy( InviteIds.data(), m_friendInviteList.data(), 1600 );
memcpy( inviteIds.data(), m_friendInviteList.data(), 1600 );
stmt->setBinary( 1, friendIds );
stmt->setBinary( 2, InviteIds );
stmt->setBinary( 2, inviteIds );
stmt->setUInt64( 3, m_characterId );
db.execute( stmt );
}

View file

@ -0,0 +1,153 @@
#include <algorithm>
#include <iterator>
#include <Logging/Logger.h>
#include <Service.h>
#include <Util/Util.h>
#include "Actor/Player.h"
#include "FriendListMgr.h"
bool Sapphire::World::Manager::FriendListMgr::onInviteCreate( Entity::Player& source, Entity::Player& target )
{
auto& sourceFL = source.getFriendListID();
auto& targetFL = target.getFriendListID();
// check if player already has been invited or friends
if( getEntryIndex( source, target.getCharacterId() ) != -1 )
{
// already invited/friends
return false;
}
// check if there are slots available to allocate and get idx
auto sourceIdx = getEntryIndex( source, 0 );
auto targetIdx = getEntryIndex( target, 0 );
if( sourceIdx == -1 || targetIdx == -1 )
{
// todo: complain about having too many friends
return false;
}
auto& sourceFLData = source.getFriendListData();
auto& targetFLData = target.getFriendListData();
// add ID and data to arrays of both players
sourceFL[sourceIdx] = target.getCharacterId();
targetFL[targetIdx] = source.getCharacterId();
Common::HierarchyData hierarchy;
hierarchy.data.dateAdded = Common::Util::getTimeSeconds();
hierarchy.data.group = 0;
hierarchy.data.status = Common::HierarchyStatus::SentRequest; // set type for invite sender
hierarchy.data.type = Common::HierarchyType::FRIENDLIST;
sourceFLData[sourceIdx] = hierarchy;
// set type for invite receiver
hierarchy.data.status = Common::HierarchyStatus::ReceivedRequest;
targetFLData[targetIdx] = hierarchy;
// force db update for friendlist
source.updateDbFriendList();
target.updateDbFriendList();
return true;
}
bool Sapphire::World::Manager::FriendListMgr::onInviteAccept( Entity::Player& source, Entity::Player& target )
{
// accept friend invite
auto sourceIdx = getEntryIndex( source, target.getCharacterId() );
auto targetIdx = getEntryIndex( target, source.getCharacterId() );
if( sourceIdx == -1 || targetIdx == -1 )
{
// currently not friends
return false;
}
auto& sourceFLData = source.getFriendListData();
auto& targetFLData = target.getFriendListData();
sourceFLData[sourceIdx].data.status = Common::HierarchyStatus::Added;
sourceFLData[sourceIdx].data.type = Common::HierarchyType::NONE_2;
targetFLData[targetIdx].data.status = Common::HierarchyStatus::Added;
targetFLData[targetIdx].data.type = Common::HierarchyType::NONE_2;
source.updateDbFriendList();
target.updateDbFriendList();
return true;
}
bool Sapphire::World::Manager::FriendListMgr::onInviteDecline( Entity::Player& source, Entity::Player& target )
{
// decline friend invite
auto sourceIdx = getEntryIndex( source, target.getCharacterId() );
auto targetIdx = getEntryIndex( target, source.getCharacterId() );
if( sourceIdx == -1 || targetIdx == -1 )
{
// currently not friends
return false;
}
auto& sourceFL = source.getFriendListID();
auto& targetFL = target.getFriendListID();
auto& sourceFLData = source.getFriendListData();
auto& targetFLData = target.getFriendListData();
sourceFL[sourceIdx] = 0;
targetFL[targetIdx] = 0;
sourceFLData[sourceIdx].u64 = 0;
targetFLData[targetIdx].u64 = 0;
source.updateDbFriendList();
target.updateDbFriendList();
return true;
}
bool Sapphire::World::Manager::FriendListMgr::onRemoveFriend( Entity::Player& source, Entity::Player& target )
{
// remove friend
// this not retail accurate - retail only removes source friendlist, but that also makes it more complicated for readding friend
// this will simply remove the entry from both players
return onInviteDecline( source, target );
}
bool Sapphire::World::Manager::FriendListMgr::onAssignGroup( Entity::Player& source, Entity::Player& target, uint8_t group )
{
// assign group to friend entry (to source only)
auto sourceIdx = getEntryIndex( source, target.getCharacterId() );
if( sourceIdx == -1 )
{
// currently not friends
return false;
}
auto& sourceFLData = source.getFriendListData();
sourceFLData[sourceIdx].data.group = group;
source.updateDbFriendList();
return true;
}
ptrdiff_t Sapphire::World::Manager::FriendListMgr::getEntryIndex( Entity::Player& source, uint64_t characterId )
{
auto& sourceFL = source.getFriendListID();
auto sourceInvIt = std::find( std::begin( sourceFL ), std::end( sourceFL ), characterId );
// not found
if( sourceInvIt == sourceFL.end() )
return -1;
return sourceInvIt - std::begin( sourceFL );
}

View file

@ -0,0 +1,25 @@
#pragma once
#include <memory>
#include <vector>
#include "ForwardsZone.h"
namespace Sapphire::World::Manager
{
class FriendListMgr
{
public:
FriendListMgr() = default;
bool onInviteCreate( Entity::Player& source, Entity::Player& target );
bool onInviteAccept( Entity::Player& source, Entity::Player& target );
bool onInviteDecline( Entity::Player& source, Entity::Player& target );
bool onRemoveFriend( Entity::Player& source, Entity::Player& target );
bool onAssignGroup( Entity::Player& source, Entity::Player& target, uint8_t group );
private:
ptrdiff_t getEntryIndex( Entity::Player& source, uint64_t characterId );
};
}

View file

@ -141,6 +141,8 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
setZoneHandler( PcPartyKick, "PcPartyKick", &GameConnection::pcPartyKickHandler );
setZoneHandler( PcPartyChangeLeader, "PcPartyChangeLeader", &GameConnection::pcPartyChangeLeaderHandler );
setZoneHandler( FriendlistRemove, "FriendlistRemove", &GameConnection::friendlistRemoveHandler );
setZoneHandler( SetFriendlistGroup, "SetFriendlistGroup", &GameConnection::setFriendlistGroupHandler );
}
Sapphire::Network::GameConnection::~GameConnection() = default;

View file

@ -217,6 +217,8 @@ namespace Sapphire::Network
DECLARE_HANDLER( pcPartyKickHandler );
DECLARE_HANDLER( pcPartyChangeLeaderHandler );
DECLARE_HANDLER( friendlistRemoveHandler );
DECLARE_HANDLER( setFriendlistGroupHandler );
};
}

View file

@ -58,10 +58,9 @@ void Sapphire::Network::GameConnection::getCommonlistDetailHandler( const Packet
// serialize class data to packet
// todo: fix 28 (common::classjob count does not match packet size)
auto classDataArr = pPlayer->getClassArray();
for( size_t i = 0; i < 28; ++i )
for( size_t i = 0; i < Common::CLASSJOB_TOTAL; ++i )
{
resultPacket->data().ClassData[ i ].id = static_cast< uint16_t >( i );
resultPacket->data().ClassData[ i ].level = classDataArr[ i ];
@ -76,7 +75,8 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
// TODO: possibly move lambda func to util
auto& server = Common::Service< World::WorldServer >::ref();
auto generateEntries = [&]( const auto& idVec, size_t offset ) -> std::vector< PlayerEntry >
// this func paginates any commonlist entry, associating them with online player data and hierarchy ID (optional)
auto generateEntries = [&]( const auto& idVec, size_t offset, const std::vector< Common::HierarchyData >& hierarchyVec ) -> std::vector< PlayerEntry >
{
std::vector< PlayerEntry > entries;
@ -90,8 +90,8 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
}
auto id = idVec[ i ];
auto pPlayer = server.getPlayer( id );
if( !pPlayer )
continue;
@ -101,8 +101,14 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
if( isConnected )
{
entry.TerritoryType = pPlayer->getCurrentTerritory()->getTerritoryTypeId();
entry.TerritoryID = pPlayer->getCurrentTerritory()->getTerritoryTypeId();
// todo: fix odd teri nullptr on login for friendlist etc
auto pTeri = pPlayer->getCurrentTerritory();
if( pTeri )
{
entry.TerritoryType = pPlayer->getCurrentTerritory()->getTerritoryTypeId();
entry.TerritoryID = pPlayer->getCurrentTerritory()->getTerritoryTypeId();
}
entry.CurrentClassID = static_cast< uint8_t >( pPlayer->getClass() );
entry.SelectClassID = static_cast< uint8_t >( pPlayer->getSearchSelectClass() );
@ -122,10 +128,20 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
entry.CharacterID = pPlayer->getCharacterId();
strcpy( entry.CharacterName, pPlayer->getName().c_str() );
if( hierarchyVec.size() > 0 )
{
auto hierarchy = hierarchyVec[ i ];
entry.Timestamp = hierarchy.data.dateAdded;
entry.HierarchyStatus = hierarchy.data.status;
entry.HierarchyType = hierarchy.data.type;
entry.HierarchyGroup = hierarchy.data.group;
entry.HierarchyUnk = hierarchy.data.unk;
}
entries.emplace_back( entry );
}
return entries;
};
@ -156,7 +172,7 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
auto pParty = partyMgr.getParty( player.getPartyId() );
assert( pParty );
page = generateEntries( pParty->MemberId, offset );
page = generateEntries( pParty->MemberId, offset, {} );
// ensure first entry is the player requesting packet
for( int i = 0; i < 8; ++i )
@ -172,32 +188,17 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
else
{
std::vector< uint32_t > soloParty = { player.getId() };
page = generateEntries( soloParty, offset );
page = generateEntries( soloParty, offset, {} );
}
}
else if( data.ListType == 0x0b )
{ // friend list
/* listPacket->data().entries[ 0 ].TerritoryType = player.getCurrentTerritory()->getTerritoryTypeId();
listPacket->data().entries[ 0 ].TerritoryID = player.getCurrentTerritory()->getTerritoryTypeId();
listPacket->data().entries[ 0 ].CurrentClassID = static_cast< uint8_t >( player.getClass() );
listPacket->data().entries[ 0 ].SelectClassID = static_cast< uint8_t >( player.getClass() );
listPacket->data().entries[ 0 ].CharacterID = player.getContentId();
listPacket->data().entries[ 0 ].CurrentLevel = player.getLevel();
listPacket->data().entries[ 0 ].SelectLevel = player.getLevel();
listPacket->data().entries[ 0 ].Identity = 1;
auto& friendList = player.getFriendListID();
auto& friendListData = player.getFriendListData();
strcpy( listPacket->data().entries[ 0 ].CharacterName, player.getName().c_str() );
std::vector< Common::HierarchyData > hierarchyData( friendListData.begin(), friendListData.end() );
// GC icon
listPacket->data().entries[ 0 ].GrandCompanyID = 2;
// client language J = 0, E = 1, D = 2, F = 3
listPacket->data().entries[ 0 ].Region = 1;
// user language settings flag J = 1, E = 2, D = 4, F = 8
listPacket->data().entries[ 0 ].SelectRegion = 1 + 2;
listPacket->data().entries[ 0 ].OnlineStatus = player.getOnlineStatusMask();
listPacket->data().entries[ 0 ].HierarchyID = 0x20;*/
offset = 0;
isLast = true;
page = generateEntries( friendList, offset, hierarchyData );
}
else if( data.ListType == 0x0c )
{ // linkshell
@ -213,13 +214,13 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
std::vector< uint64_t > memberVec;
std::copy( memberSet.begin(), memberSet.end(), std::back_inserter( memberVec ) );
page = generateEntries( memberVec, offset );
page = generateEntries( memberVec, offset, {} );
}
}
else if( data.ListType == 0x0e )
{ // player search result
auto queryPlayers = player.getLastPcSearchResult();
page = generateEntries( queryPlayers, offset );
page = generateEntries( queryPlayers, offset, {} );
}
// if we didn't manually terminate pagination (party, etc), check if we need to do so

View file

@ -0,0 +1,63 @@
#include <Common.h>
#include <Network/CommonNetwork.h>
#include <Network/GamePacket.h>
#include <Network/PacketContainer.h>
#include <Exd/ExdData.h>
#include <Service.h>
#include <Network/PacketDef/Zone/ClientZoneDef.h>
#include <Network/PacketDef/Zone/ServerZoneDef.h>
#include "Manager/FriendListMgr.h"
#include "Network/GameConnection.h"
#include "Actor/Player.h"
#include "WorldServer.h"
using namespace Sapphire::Common;
using namespace Sapphire::Network::Packets;
using namespace Sapphire::Network::Packets::WorldPackets;
using namespace Sapphire::World::Manager;
void Sapphire::Network::GameConnection::friendlistRemoveHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
{
const auto packet = ZoneChannelPacket< Client::FFXIVIpcFriendlistRemove >( inPacket );
const auto& data = packet.data();
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto& flMgr = Common::Service< Sapphire::World::Manager::FriendListMgr >::ref();
auto target = server.getPlayer( data.TargetCharacterID );
if( !target )
return;
flMgr.onRemoveFriend( player, *target );
auto replyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcFriendlistRemoveResult >( player.getId() );
auto& replyData = replyPacket->data();
replyData.RemovedCharacterID = target->getCharacterId();
replyData.Identity = target->getGender();
replyData.Result = 0;
strcpy( replyData.RemovedCharacterName, target->getName().c_str() );
server.queueForPlayer( player.getCharacterId(), replyPacket );
}
void Sapphire::Network::GameConnection::setFriendlistGroupHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
{
const auto packet = ZoneChannelPacket< Client::FFXIVIpcSetFriendlistGroup >( inPacket );
const auto& data = packet.data();
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto& flMgr = Common::Service< Sapphire::World::Manager::FriendListMgr >::ref();
auto target = server.getPlayer( data.TargetCharacterID );
if( !target )
return;
flMgr.onAssignGroup( player, *target, data.group );
}

View file

@ -20,6 +20,7 @@
#include "Network/PacketWrappers/PlayerSetupPacket.h"
#include "Network/PacketWrappers/InviteUpdatePacket.h"
#include "Manager/FriendListMgr.h"
#include "Manager/PartyMgr.h"
#include "Manager/PlayerMgr.h"
@ -55,7 +56,7 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
switch( packet.data().AuthType )
{
case InviteType::PCPARTY:
case HierarchyType::PCPARTY:
{
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
auto& data = inviteResultPacket->data();
@ -71,7 +72,7 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
break;
}
case InviteType::FRIENDLIST:
case HierarchyType::FRIENDLIST:
{
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
auto& data = inviteResultPacket->data();
@ -79,22 +80,31 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
strcpy( data.TargetName, packet.data().TargetName );
server.queueForPlayer( player.getCharacterId(), inviteResultPacket );
auto invitePacket = std::make_shared< InviteUpdatePacket >( player, Common::Util::getTimeSeconds() + 30,
auto invitePacket = std::make_shared< InviteUpdatePacket >( player, 0,
packet.data().AuthType, 1,
InviteUpdateType::NEW_INVITE );
pSession->getZoneConnection()->queueOutPacket( invitePacket );
auto& flMgr = Common::Service< FriendListMgr >::ref();
// add support to adding offline players
auto target = server.getPlayer( data.TargetName );
if( !target )
return;
flMgr.onInviteCreate( player, *target );
break;
}
case Common::InviteType::AUTOPARTY:
case HierarchyType::AUTOPARTY:
break;
case Common::InviteType::FCCREATE:
case HierarchyType::FCCREATE:
break;
case Common::InviteType::FREECOMPANY:
case HierarchyType::FREECOMPANY:
break;
case Common::InviteType::FCJOINREQUEST:
case HierarchyType::FCJOINREQUEST:
break;
case Common::InviteType::PARTYCANCEL:
case HierarchyType::PARTYCANCEL:
break;
}
}
@ -108,19 +118,19 @@ void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKE
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto pSession = server.getSession( data.InviteCharacterID );
auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref();
if( !pSession )
return;
auto inviteReplyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteReplyResult >( player.getId() );
auto& inviteReplyData = inviteReplyPacket->data();
inviteReplyData.Answer = data.Answer;
switch( data.AuthType )
{
case Common::InviteType::PCPARTY:
case HierarchyType::PCPARTY:
{
auto inviteReplyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteReplyResult >( player.getId() );
auto& inviteReplyData = inviteReplyPacket->data();
auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref();
inviteReplyData.Answer = data.Answer;
uint8_t result;
if( data.Answer == InviteReplyType::ACCEPT )
{
@ -142,17 +152,41 @@ void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKE
break;
}
case Common::InviteType::FRIENDLIST:
case HierarchyType::FRIENDLIST:
{
auto& flMgr = Common::Service< Sapphire::World::Manager::FriendListMgr >::ref();
uint8_t result;
if( data.Answer == InviteReplyType::ACCEPT )
{
flMgr.onInviteAccept( player, *pSession->getPlayer() );
result = InviteUpdateType::ACCEPT_INVITE;
}
else
{
flMgr.onInviteDecline( player, *pSession->getPlayer() );
result = InviteUpdateType::REJECT_INVITE;
}
auto inviteUpPacket = std::make_shared< InviteUpdatePacket >( player, 0,
data.AuthType, 1, result );
pSession->getZoneConnection()->queueOutPacket( inviteUpPacket );
inviteReplyData.AuthType = data.AuthType;
strcpy( inviteReplyData.InviteCharacterName, pSession->getPlayer()->getName().c_str() );
server.queueForPlayer( player.getCharacterId(), inviteReplyPacket );
break;
case Common::InviteType::AUTOPARTY:
}
case HierarchyType::AUTOPARTY:
break;
case Common::InviteType::FCCREATE:
case HierarchyType::FCCREATE:
break;
case Common::InviteType::FREECOMPANY:
case HierarchyType::FREECOMPANY:
break;
case Common::InviteType::FCJOINREQUEST:
case HierarchyType::FCJOINREQUEST:
break;
case Common::InviteType::PARTYCANCEL:
case HierarchyType::PARTYCANCEL:
break;
}
}

View file

@ -9,8 +9,6 @@
#include "Manager/PartyMgr.h"
#include "Territory/InstanceContent.h"
#include "Network/GameConnection.h"
#include "Session.h"

View file

@ -42,6 +42,7 @@
#include "Manager/ChatChannelMgr.h"
#include "Manager/QuestMgr.h"
#include "Manager/PartyMgr.h"
#include "Manager/FriendListMgr.h"
#include "ContentFinder/ContentFinder.h"
@ -238,6 +239,7 @@ void Sapphire::World::WorldServer::run( int32_t argc, char* argv[] )
auto pRNGMgr = std::make_shared< Manager::RNGMgr >();
auto pQuestMgr = std::make_shared< Manager::QuestMgr >();
auto pPartyMgr = std::make_shared< Manager::PartyMgr >();
auto pFriendMgr = std::make_shared< Manager::FriendListMgr >();
auto contentFinder = std::make_shared< ContentFinder >();
Common::Service< DebugCommandMgr >::set( pDebugCom );
@ -249,6 +251,7 @@ void Sapphire::World::WorldServer::run( int32_t argc, char* argv[] )
Common::Service< Manager::RNGMgr >::set( pRNGMgr );
Common::Service< Manager::QuestMgr >::set( pQuestMgr );
Common::Service< Manager::PartyMgr >::set( pPartyMgr );
Common::Service< Manager::FriendListMgr >::set( pFriendMgr );
Common::Service< ContentFinder >::set( contentFinder );
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();