mirror of
https://github.com/SapphireServer/Sapphire.git
synced 2025-04-28 15:17:46 +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:
parent
be2320aa98
commit
3e73da6463
18 changed files with 413 additions and 67 deletions
2
sql/migrations/20211201205038_FixFriendlistKey.sql
Normal file
2
sql/migrations/20211201205038_FixFriendlistKey.sql
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
ALTER TABLE `charainfofriendlist`
|
||||||
|
CHANGE COLUMN `CharacterId` `CharacterId` BIGINT NOT NULL DEFAULT 0 FIRST;
|
|
@ -268,6 +268,16 @@ void PlayerMinimal::saveAsNew()
|
||||||
stmtSearchInfo->setUInt64( 1, m_characterId );
|
stmtSearchInfo->setUInt64( 1, m_characterId );
|
||||||
g_charaDb.directExecute( stmtSearchInfo );
|
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
|
/// SET UP INVENTORIES
|
||||||
createInvDbContainer( InventoryType::Bag0 );
|
createInvDbContainer( InventoryType::Bag0 );
|
||||||
|
|
|
@ -24,7 +24,7 @@ namespace Sapphire::Common
|
||||||
const uint16_t MAX_PLAYER_LEVEL = 80;
|
const uint16_t MAX_PLAYER_LEVEL = 80;
|
||||||
const uint8_t CURRENT_EXPANSION_ID = 3;
|
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 CLASSJOB_SLOTS = 20;
|
||||||
|
|
||||||
const uint8_t TOWN_COUNT = 6;
|
const uint8_t TOWN_COUNT = 6;
|
||||||
|
@ -971,7 +971,7 @@ namespace Sapphire::Common
|
||||||
InvincibilityIgnoreDamage,
|
InvincibilityIgnoreDamage,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum InviteType : int32_t
|
enum HierarchyType : uint8_t
|
||||||
{
|
{
|
||||||
NONE_2 = 0x0,
|
NONE_2 = 0x0,
|
||||||
PCPARTY = 0x1,
|
PCPARTY = 0x1,
|
||||||
|
@ -984,6 +984,14 @@ namespace Sapphire::Common
|
||||||
MAX_1 = 0xFF,
|
MAX_1 = 0xFF,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum HierarchyStatus : uint8_t
|
||||||
|
{
|
||||||
|
Invalid = 0,
|
||||||
|
Added = 0x10,
|
||||||
|
SentRequest = 0x20,
|
||||||
|
ReceivedRequest = 0x30
|
||||||
|
};
|
||||||
|
|
||||||
enum LinkshellHierarchy : int32_t
|
enum LinkshellHierarchy : int32_t
|
||||||
{
|
{
|
||||||
NONE_1 = 0x0,
|
NONE_1 = 0x0,
|
||||||
|
@ -994,13 +1002,17 @@ namespace Sapphire::Common
|
||||||
MAX_0 = 0x7,
|
MAX_0 = 0x7,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union HierarchyData
|
||||||
enum GroupEntryStatus : uint8_t
|
|
||||||
{
|
{
|
||||||
Invalid = 0,
|
uint64_t u64;
|
||||||
Added = 0x10,
|
|
||||||
SentRequest = 0x20,
|
struct HierarchyPackedData {
|
||||||
ReceivedRequest = 0x30
|
uint32_t dateAdded;
|
||||||
|
uint8_t status;
|
||||||
|
uint8_t type;
|
||||||
|
uint8_t group;
|
||||||
|
uint8_t unk;
|
||||||
|
} data;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* 61719 */
|
/* 61719 */
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace Sapphire::Network::Packets
|
||||||
PcSearch = 0xEB,
|
PcSearch = 0xEB,
|
||||||
GetFcJoinRequestComment = 0xEC,
|
GetFcJoinRequestComment = 0xEC,
|
||||||
InviteCancel = 0xED,
|
InviteCancel = 0xED,
|
||||||
|
SetFriendlistGroup = 0xEE,
|
||||||
LinkshellJoin = 0xF0,
|
LinkshellJoin = 0xF0,
|
||||||
LinkshellJoinOfficial = 0xF1,
|
LinkshellJoinOfficial = 0xF1,
|
||||||
LinkshellLeave = 0xF2,
|
LinkshellLeave = 0xF2,
|
||||||
|
|
|
@ -579,6 +579,18 @@ struct FFXIVIpcGetCommonlistDetail : FFXIVIpcBasePacket< GetCommonlistDetail >
|
||||||
uint8_t ListType;
|
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 >
|
struct FFXIVIpcPcSearch : FFXIVIpcBasePacket< PcSearch >
|
||||||
{
|
{
|
||||||
uint64_t ClassID;
|
uint64_t ClassID;
|
||||||
|
|
|
@ -58,12 +58,17 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
/**
|
/**
|
||||||
* Structural representation of the packet sent by the server
|
* Structural representation of the packet sent by the server
|
||||||
* with a list of players ( party list | friend list | search results )
|
* with a list of players ( party list | friend list | search results )
|
||||||
|
* 3.0 Update: 64bit TerritoryID -> 32bit Timestamp, 32bit TerritoryID
|
||||||
*/
|
*/
|
||||||
struct PlayerEntry
|
struct PlayerEntry
|
||||||
{
|
{
|
||||||
uint64_t CharacterID;
|
uint64_t CharacterID;
|
||||||
uint64_t TerritoryID;
|
uint32_t Timestamp;
|
||||||
uint32_t HierarchyID;
|
uint32_t TerritoryID;
|
||||||
|
uint8_t HierarchyStatus;
|
||||||
|
uint8_t HierarchyType;
|
||||||
|
uint8_t HierarchyGroup;
|
||||||
|
uint8_t HierarchyUnk;
|
||||||
uint16_t TerritoryType;
|
uint16_t TerritoryType;
|
||||||
uint8_t GrandCompanyID;
|
uint8_t GrandCompanyID;
|
||||||
uint8_t Region;
|
uint8_t Region;
|
||||||
|
@ -144,6 +149,14 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
|
||||||
char InviteName[32];
|
char InviteName[32];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FFXIVIpcFriendlistRemoveResult : FFXIVIpcBasePacket< FriendlistRemoveResult >
|
||||||
|
{
|
||||||
|
uint64_t RemovedCharacterID;
|
||||||
|
uint32_t Result;
|
||||||
|
uint8_t Identity;
|
||||||
|
char RemovedCharacterName[32];
|
||||||
|
};
|
||||||
|
|
||||||
struct FFXIVIpcGetFcStatusResult : FFXIVIpcBasePacket< GetFcStatusResult >
|
struct FFXIVIpcGetFcStatusResult : FFXIVIpcBasePacket< GetFcStatusResult >
|
||||||
{
|
{
|
||||||
uint64_t FreeCompanyID;
|
uint64_t FreeCompanyID;
|
||||||
|
|
|
@ -2138,6 +2138,15 @@ void Sapphire::Entity::Player::setPartyId( uint64_t partyId )
|
||||||
m_partyId = 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 )
|
void Sapphire::Entity::Player::setLastPcSearchResult( std::vector< uint32_t > result )
|
||||||
{
|
{
|
||||||
m_lastPcSearch = std::move( result );
|
m_lastPcSearch = std::move( result );
|
||||||
|
|
|
@ -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 );
|
Common::HuntingLogEntry& getHuntingLogEntry( uint8_t index );
|
||||||
|
|
||||||
void sendHuntingLog();
|
void sendHuntingLog();
|
||||||
|
@ -808,6 +811,9 @@ namespace Sapphire::Entity
|
||||||
uint64_t getPartyId() const;
|
uint64_t getPartyId() const;
|
||||||
void setPartyId( uint64_t partyId );
|
void setPartyId( uint64_t partyId );
|
||||||
|
|
||||||
|
FriendListIDVec& getFriendListID();
|
||||||
|
FriendListDataVec& getFriendListData();
|
||||||
|
|
||||||
uint64_t m_lastMoveTime{};
|
uint64_t m_lastMoveTime{};
|
||||||
uint8_t m_lastMoveflag{};
|
uint8_t m_lastMoveflag{};
|
||||||
bool m_falling;
|
bool m_falling;
|
||||||
|
@ -963,8 +969,8 @@ namespace Sapphire::Entity
|
||||||
|
|
||||||
std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries{};
|
std::array< Common::HuntingLogEntry, 12 > m_huntingLogEntries{};
|
||||||
|
|
||||||
std::array< uint64_t, 200 > m_friendList{};
|
FriendListIDVec m_friendList{};
|
||||||
std::array< uint64_t, 200 > m_friendInviteList{};
|
FriendListDataVec m_friendInviteList{};
|
||||||
|
|
||||||
uint64_t m_partyId;
|
uint64_t m_partyId;
|
||||||
std::vector< uint32_t > m_lastPcSearch;
|
std::vector< uint32_t > m_lastPcSearch;
|
||||||
|
|
|
@ -462,12 +462,12 @@ void Sapphire::Entity::Player::updateDbFriendList()
|
||||||
auto stmt = db.getPreparedStatement( Db::CHARA_FRIENDLIST_UP );
|
auto stmt = db.getPreparedStatement( Db::CHARA_FRIENDLIST_UP );
|
||||||
|
|
||||||
std::vector< uint8_t > friendIds( 1600 );
|
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( 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( 1, friendIds );
|
||||||
stmt->setBinary( 2, InviteIds );
|
stmt->setBinary( 2, inviteIds );
|
||||||
stmt->setUInt64( 3, m_characterId );
|
stmt->setUInt64( 3, m_characterId );
|
||||||
db.execute( stmt );
|
db.execute( stmt );
|
||||||
}
|
}
|
||||||
|
|
153
src/world/Manager/FriendListMgr.cpp
Normal file
153
src/world/Manager/FriendListMgr.cpp
Normal 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 );
|
||||||
|
}
|
25
src/world/Manager/FriendListMgr.h
Normal file
25
src/world/Manager/FriendListMgr.h
Normal 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 );
|
||||||
|
};
|
||||||
|
}
|
|
@ -141,6 +141,8 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH
|
||||||
setZoneHandler( PcPartyKick, "PcPartyKick", &GameConnection::pcPartyKickHandler );
|
setZoneHandler( PcPartyKick, "PcPartyKick", &GameConnection::pcPartyKickHandler );
|
||||||
setZoneHandler( PcPartyChangeLeader, "PcPartyChangeLeader", &GameConnection::pcPartyChangeLeaderHandler );
|
setZoneHandler( PcPartyChangeLeader, "PcPartyChangeLeader", &GameConnection::pcPartyChangeLeaderHandler );
|
||||||
|
|
||||||
|
setZoneHandler( FriendlistRemove, "FriendlistRemove", &GameConnection::friendlistRemoveHandler );
|
||||||
|
setZoneHandler( SetFriendlistGroup, "SetFriendlistGroup", &GameConnection::setFriendlistGroupHandler );
|
||||||
}
|
}
|
||||||
|
|
||||||
Sapphire::Network::GameConnection::~GameConnection() = default;
|
Sapphire::Network::GameConnection::~GameConnection() = default;
|
||||||
|
|
|
@ -217,6 +217,8 @@ namespace Sapphire::Network
|
||||||
DECLARE_HANDLER( pcPartyKickHandler );
|
DECLARE_HANDLER( pcPartyKickHandler );
|
||||||
DECLARE_HANDLER( pcPartyChangeLeaderHandler );
|
DECLARE_HANDLER( pcPartyChangeLeaderHandler );
|
||||||
|
|
||||||
|
DECLARE_HANDLER( friendlistRemoveHandler );
|
||||||
|
DECLARE_HANDLER( setFriendlistGroupHandler );
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,10 +58,9 @@ void Sapphire::Network::GameConnection::getCommonlistDetailHandler( const Packet
|
||||||
|
|
||||||
// serialize class data to packet
|
// serialize class data to packet
|
||||||
|
|
||||||
// todo: fix 28 (common::classjob count does not match packet size)
|
|
||||||
auto classDataArr = pPlayer->getClassArray();
|
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 ].id = static_cast< uint16_t >( i );
|
||||||
resultPacket->data().ClassData[ i ].level = classDataArr[ 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
|
// TODO: possibly move lambda func to util
|
||||||
auto& server = Common::Service< World::WorldServer >::ref();
|
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;
|
std::vector< PlayerEntry > entries;
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
|
||||||
}
|
}
|
||||||
|
|
||||||
auto id = idVec[ i ];
|
auto id = idVec[ i ];
|
||||||
|
|
||||||
auto pPlayer = server.getPlayer( id );
|
auto pPlayer = server.getPlayer( id );
|
||||||
|
|
||||||
if( !pPlayer )
|
if( !pPlayer )
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -101,8 +101,14 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
|
||||||
|
|
||||||
if( isConnected )
|
if( isConnected )
|
||||||
{
|
{
|
||||||
entry.TerritoryType = pPlayer->getCurrentTerritory()->getTerritoryTypeId();
|
// todo: fix odd teri nullptr on login for friendlist etc
|
||||||
entry.TerritoryID = pPlayer->getCurrentTerritory()->getTerritoryTypeId();
|
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.CurrentClassID = static_cast< uint8_t >( pPlayer->getClass() );
|
||||||
entry.SelectClassID = static_cast< uint8_t >( pPlayer->getSearchSelectClass() );
|
entry.SelectClassID = static_cast< uint8_t >( pPlayer->getSearchSelectClass() );
|
||||||
|
|
||||||
|
@ -122,10 +128,20 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
|
||||||
entry.CharacterID = pPlayer->getCharacterId();
|
entry.CharacterID = pPlayer->getCharacterId();
|
||||||
strcpy( entry.CharacterName, pPlayer->getName().c_str() );
|
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 );
|
entries.emplace_back( entry );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return entries;
|
return entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -156,7 +172,7 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
|
||||||
auto pParty = partyMgr.getParty( player.getPartyId() );
|
auto pParty = partyMgr.getParty( player.getPartyId() );
|
||||||
assert( pParty );
|
assert( pParty );
|
||||||
|
|
||||||
page = generateEntries( pParty->MemberId, offset );
|
page = generateEntries( pParty->MemberId, offset, {} );
|
||||||
|
|
||||||
// ensure first entry is the player requesting packet
|
// ensure first entry is the player requesting packet
|
||||||
for( int i = 0; i < 8; ++i )
|
for( int i = 0; i < 8; ++i )
|
||||||
|
@ -172,32 +188,17 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::vector< uint32_t > soloParty = { player.getId() };
|
std::vector< uint32_t > soloParty = { player.getId() };
|
||||||
page = generateEntries( soloParty, offset );
|
page = generateEntries( soloParty, offset, {} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( data.ListType == 0x0b )
|
else if( data.ListType == 0x0b )
|
||||||
{ // friend list
|
{ // friend list
|
||||||
/* listPacket->data().entries[ 0 ].TerritoryType = player.getCurrentTerritory()->getTerritoryTypeId();
|
auto& friendList = player.getFriendListID();
|
||||||
listPacket->data().entries[ 0 ].TerritoryID = player.getCurrentTerritory()->getTerritoryTypeId();
|
auto& friendListData = player.getFriendListData();
|
||||||
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;
|
|
||||||
|
|
||||||
strcpy( listPacket->data().entries[ 0 ].CharacterName, player.getName().c_str() );
|
std::vector< Common::HierarchyData > hierarchyData( friendListData.begin(), friendListData.end() );
|
||||||
|
|
||||||
// GC icon
|
page = generateEntries( friendList, offset, hierarchyData );
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
else if( data.ListType == 0x0c )
|
else if( data.ListType == 0x0c )
|
||||||
{ // linkshell
|
{ // linkshell
|
||||||
|
@ -213,13 +214,13 @@ void Sapphire::Network::GameConnection::getCommonlistHandler( const Packets::FFX
|
||||||
std::vector< uint64_t > memberVec;
|
std::vector< uint64_t > memberVec;
|
||||||
std::copy( memberSet.begin(), memberSet.end(), std::back_inserter( memberVec ) );
|
std::copy( memberSet.begin(), memberSet.end(), std::back_inserter( memberVec ) );
|
||||||
|
|
||||||
page = generateEntries( memberVec, offset );
|
page = generateEntries( memberVec, offset, {} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if( data.ListType == 0x0e )
|
else if( data.ListType == 0x0e )
|
||||||
{ // player search result
|
{ // player search result
|
||||||
auto queryPlayers = player.getLastPcSearchResult();
|
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
|
// if we didn't manually terminate pagination (party, etc), check if we need to do so
|
||||||
|
|
63
src/world/Network/Handlers/FriendListHandlers.cpp
Normal file
63
src/world/Network/Handlers/FriendListHandlers.cpp
Normal 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 );
|
||||||
|
}
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
#include "Network/PacketWrappers/PlayerSetupPacket.h"
|
||||||
#include "Network/PacketWrappers/InviteUpdatePacket.h"
|
#include "Network/PacketWrappers/InviteUpdatePacket.h"
|
||||||
|
|
||||||
|
#include "Manager/FriendListMgr.h"
|
||||||
#include "Manager/PartyMgr.h"
|
#include "Manager/PartyMgr.h"
|
||||||
#include "Manager/PlayerMgr.h"
|
#include "Manager/PlayerMgr.h"
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
|
||||||
|
|
||||||
switch( packet.data().AuthType )
|
switch( packet.data().AuthType )
|
||||||
{
|
{
|
||||||
case InviteType::PCPARTY:
|
case HierarchyType::PCPARTY:
|
||||||
{
|
{
|
||||||
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
|
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
|
||||||
auto& data = inviteResultPacket->data();
|
auto& data = inviteResultPacket->data();
|
||||||
|
@ -71,7 +72,7 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case InviteType::FRIENDLIST:
|
case HierarchyType::FRIENDLIST:
|
||||||
{
|
{
|
||||||
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
|
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
|
||||||
auto& data = inviteResultPacket->data();
|
auto& data = inviteResultPacket->data();
|
||||||
|
@ -79,22 +80,31 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
|
||||||
strcpy( data.TargetName, packet.data().TargetName );
|
strcpy( data.TargetName, packet.data().TargetName );
|
||||||
server.queueForPlayer( player.getCharacterId(), inviteResultPacket );
|
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,
|
packet.data().AuthType, 1,
|
||||||
InviteUpdateType::NEW_INVITE );
|
InviteUpdateType::NEW_INVITE );
|
||||||
pSession->getZoneConnection()->queueOutPacket( invitePacket );
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case Common::InviteType::AUTOPARTY:
|
case HierarchyType::AUTOPARTY:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::FCCREATE:
|
case HierarchyType::FCCREATE:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::FREECOMPANY:
|
case HierarchyType::FREECOMPANY:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::FCJOINREQUEST:
|
case HierarchyType::FCJOINREQUEST:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::PARTYCANCEL:
|
case HierarchyType::PARTYCANCEL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,19 +118,19 @@ void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKE
|
||||||
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
|
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
|
||||||
auto pSession = server.getSession( data.InviteCharacterID );
|
auto pSession = server.getSession( data.InviteCharacterID );
|
||||||
|
|
||||||
auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref();
|
|
||||||
|
|
||||||
if( !pSession )
|
if( !pSession )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
auto inviteReplyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteReplyResult >( player.getId() );
|
||||||
|
auto& inviteReplyData = inviteReplyPacket->data();
|
||||||
|
inviteReplyData.Answer = data.Answer;
|
||||||
|
|
||||||
switch( data.AuthType )
|
switch( data.AuthType )
|
||||||
{
|
{
|
||||||
case Common::InviteType::PCPARTY:
|
case HierarchyType::PCPARTY:
|
||||||
{
|
{
|
||||||
auto inviteReplyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteReplyResult >( player.getId() );
|
auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref();
|
||||||
auto& inviteReplyData = inviteReplyPacket->data();
|
|
||||||
|
|
||||||
inviteReplyData.Answer = data.Answer;
|
|
||||||
uint8_t result;
|
uint8_t result;
|
||||||
if( data.Answer == InviteReplyType::ACCEPT )
|
if( data.Answer == InviteReplyType::ACCEPT )
|
||||||
{
|
{
|
||||||
|
@ -142,17 +152,41 @@ void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKE
|
||||||
|
|
||||||
break;
|
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;
|
break;
|
||||||
case Common::InviteType::AUTOPARTY:
|
}
|
||||||
|
case HierarchyType::AUTOPARTY:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::FCCREATE:
|
case HierarchyType::FCCREATE:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::FREECOMPANY:
|
case HierarchyType::FREECOMPANY:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::FCJOINREQUEST:
|
case HierarchyType::FCJOINREQUEST:
|
||||||
break;
|
break;
|
||||||
case Common::InviteType::PARTYCANCEL:
|
case HierarchyType::PARTYCANCEL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,6 @@
|
||||||
|
|
||||||
#include "Manager/PartyMgr.h"
|
#include "Manager/PartyMgr.h"
|
||||||
|
|
||||||
#include "Territory/InstanceContent.h"
|
|
||||||
|
|
||||||
#include "Network/GameConnection.h"
|
#include "Network/GameConnection.h"
|
||||||
|
|
||||||
#include "Session.h"
|
#include "Session.h"
|
||||||
|
|
|
@ -42,6 +42,7 @@
|
||||||
#include "Manager/ChatChannelMgr.h"
|
#include "Manager/ChatChannelMgr.h"
|
||||||
#include "Manager/QuestMgr.h"
|
#include "Manager/QuestMgr.h"
|
||||||
#include "Manager/PartyMgr.h"
|
#include "Manager/PartyMgr.h"
|
||||||
|
#include "Manager/FriendListMgr.h"
|
||||||
|
|
||||||
#include "ContentFinder/ContentFinder.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 pRNGMgr = std::make_shared< Manager::RNGMgr >();
|
||||||
auto pQuestMgr = std::make_shared< Manager::QuestMgr >();
|
auto pQuestMgr = std::make_shared< Manager::QuestMgr >();
|
||||||
auto pPartyMgr = std::make_shared< Manager::PartyMgr >();
|
auto pPartyMgr = std::make_shared< Manager::PartyMgr >();
|
||||||
|
auto pFriendMgr = std::make_shared< Manager::FriendListMgr >();
|
||||||
auto contentFinder = std::make_shared< ContentFinder >();
|
auto contentFinder = std::make_shared< ContentFinder >();
|
||||||
|
|
||||||
Common::Service< DebugCommandMgr >::set( pDebugCom );
|
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::RNGMgr >::set( pRNGMgr );
|
||||||
Common::Service< Manager::QuestMgr >::set( pQuestMgr );
|
Common::Service< Manager::QuestMgr >::set( pQuestMgr );
|
||||||
Common::Service< Manager::PartyMgr >::set( pPartyMgr );
|
Common::Service< Manager::PartyMgr >::set( pPartyMgr );
|
||||||
|
Common::Service< Manager::FriendListMgr >::set( pFriendMgr );
|
||||||
Common::Service< ContentFinder >::set( contentFinder );
|
Common::Service< ContentFinder >::set( contentFinder );
|
||||||
|
|
||||||
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();
|
auto& exdData = Common::Service< Sapphire::Data::ExdData >::ref();
|
||||||
|
|
Loading…
Add table
Reference in a new issue