1
Fork 0
mirror of https://github.com/SapphireServer/Sapphire.git synced 2025-05-03 01:07:47 +00:00

Create and load member lists of fcs.

This commit is contained in:
Mordred 2023-02-08 15:22:26 +01:00
parent c99b2fa72a
commit 38b92fafa9
12 changed files with 212 additions and 57 deletions

View file

@ -0,0 +1,2 @@
ALTER TABLE `fcmember` CHANGE `FreeCompanyId` `FreeCompanyId` BIGINT(20) UNSIGNED NOT NULL;
ALTER TABLE `fcmember` CHANGE `FcMemberId` `FcMemberId` BIGINT(20) UNSIGNED NOT NULL;

View file

@ -381,4 +381,29 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements()
"DELETE FROM freecompany WHERE FreeCompanyId = ?;",
CONNECTION_BOTH );
prepareStatement( FC_MEMBERS_SEL_ALL,
"SELECT FreeCompanyId, FcMemberId, HierarchyType, LastLogout "
"FROM fcmember "
"ORDER BY FreeCompanyId ASC;",
CONNECTION_SYNC );
prepareStatement( FC_MEMBERS_SEL_FC,
"SELECT FcMemberId, HierarchyType, LastLogout "
"FROM fcmember "
"WHERE FreeCompanyId = ?;",
CONNECTION_SYNC );
prepareStatement( FC_MEMBERS_INS,
"INSERT INTO fcmember ( FreeCompanyId, FcMemberId, HierarchyType, LastLogout ) VALUES ( ?, ?, ?, ? );",
CONNECTION_BOTH );
prepareStatement( FC_MEMBERS_UP,
"UPDATE fcmember SET HierarchyType = ?, LastLogout = ? "
"WHERE FcMemberId = ?;",
CONNECTION_BOTH );
prepareStatement( FC_DEL,
"DELETE FROM fcmember WHERE FcMemberId = ?;",
CONNECTION_BOTH );
}

View file

@ -120,6 +120,12 @@ namespace Sapphire::Db
FC_UP,
FC_DEL,
FC_MEMBERS_SEL_ALL,
FC_MEMBERS_SEL_FC,
FC_MEMBERS_INS,
FC_MEMBERS_UP,
FC_MEMBERS_DEL,
MAX_STATEMENTS
};

View file

@ -182,7 +182,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
struct FFXIVIpcFreeCompanyResult : FFXIVIpcBasePacket< FreeCompanyResult >
{
uint64_t FreeCompanyID;
uint64_t TargetCharacterID;
uint64_t Arg;
uint32_t Type;
uint32_t Result;
uint8_t UpdateStatus;

View file

@ -102,6 +102,12 @@ class ComDefFreeCompany : public Sapphire::ScriptAPI::EventScript
eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 0 } );
pFcMgr.sendFreeCompanyStatus( player );
}
else if( sceneId == 6 && yieldId == 17 )
eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } );
else if( sceneId == 7 && yieldId == 17 )
eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } );
else if( sceneId == 8 && yieldId == 17 )
eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } );
}
@ -194,6 +200,7 @@ class ComDefFreeCompany : public Sapphire::ScriptAPI::EventScript
//////////////////////////////////////////////////////////////////////
// set tag
void Scene00007( Entity::Player& player )
{
eventMgr().playScene( player, getId(), 7, NONE, bindSceneReturn( &ComDefFreeCompany::Scene00007Return ) );
@ -205,6 +212,7 @@ class ComDefFreeCompany : public Sapphire::ScriptAPI::EventScript
//////////////////////////////////////////////////////////////////////
// fc rename
void Scene00008( Entity::Player& player )
{
eventMgr().playScene( player, getId(), 8, NONE, bindSceneReturn( &ComDefFreeCompany::Scene00008Return ) );

View file

@ -203,6 +203,17 @@ std::set< uint64_t >& Sapphire::FreeCompany::getMemberIdList()
return m_memberIds;
}
void Sapphire::FreeCompany::addInvite( uint64_t memberId )
{
}
void Sapphire::FreeCompany::addMember( uint64_t memberId, uint8_t hierarchyId, uint32_t lastLogout )
{
FcMember member{ memberId, hierarchyId, lastLogout };
m_memberDetails[ memberId ] = member;
m_memberIds.insert( memberId );
}

View file

@ -5,6 +5,7 @@
#include <string>
#include <array>
#include <optional>
#include <unordered_map>
namespace Sapphire
{
@ -57,8 +58,19 @@ namespace Sapphire
std::set< uint64_t > m_inviteIds;
/*! chat channel ID associated with fc */
uint64_t m_chatChannelId;
/*! List of players on petition list */
std::array< uint64_t, 3 > m_inviteList;
/*! pending invites, not yet accepted or declined */
std::set< uint64_t > m_pendingInviteIds;
struct FcMember
{
uint64_t characterId;
uint8_t hierarchyId;
uint32_t lastLogout;
};
/*! member details such as hierarchy mapping */
std::unordered_map< uint64_t, FcMember > m_memberDetails;
public:
FreeCompany( uint64_t id,
@ -126,7 +138,7 @@ namespace Sapphire
uint64_t getChatChannel() const;
void addMember( uint64_t memberId );
void addMember( uint64_t memberId, uint8_t hierarchyId, uint32_t lastLogout );
void removeMember( uint64_t memberId );

View file

@ -74,6 +74,31 @@ bool FreeCompanyMgr::loadFreeCompanies()
}
for( auto& [ fcId, fcPtr ] : m_fcIdMap )
{
auto fc = getFreeCompanyById( fcId );
if( !fc )
{
Logger::error( "FreeCompany {} not found for member initialisation!", fcId );
continue;
}
/* FcMemberId, HierarchyType, LastLogout */
auto queryMember = db.getPreparedStatement( Db::FC_MEMBERS_SEL_FC );
queryMember->setUInt64( 1, fcId );
auto resMember = db.query( queryMember );
while( resMember->next() )
{
uint64_t characterId = resMember->getUInt64( 1 );
uint8_t hierarchyId = resMember->getUInt8( 2 );
uint32_t lastLogout = resMember->getUInt( 3 );
fcPtr->addMember( characterId, hierarchyId, lastLogout );
m_charaIdToFcIdMap[ characterId ] = fcId;
}
}
return true;
}
@ -86,6 +111,7 @@ void FreeCompanyMgr::writeFreeCompany( uint64_t fcId )
if( !fc )
{
Logger::error( "FreeCompany {} not found for write!", fcId );
return;
}
auto query = db.getPreparedStatement( Db::FC_UP );
@ -123,7 +149,7 @@ void FreeCompanyMgr::writeFreeCompany( uint64_t fcId )
}
FreeCompanyPtr FreeCompanyMgr::getFcByName( const std::string& name )
FreeCompanyPtr FreeCompanyMgr::getFreeCompanyByName( const std::string& name )
{
auto it = m_fcNameMap.find( name );
if( it == m_fcNameMap.end() )
@ -161,7 +187,7 @@ FreeCompanyPtr FreeCompanyMgr::createFreeCompany( const std::string& name, const
chatChannelMgr.addToChannel( chatChannelId, player );
uint64_t masterId = player.getCharacterId();
Logger::debug( "MasterID# {}", masterId );
m_charaIdToFcIdMap[ masterId ] = freeCompanyId;
uint32_t createDate = Common::Util::getTimeSeconds();
@ -193,9 +219,18 @@ FreeCompanyPtr FreeCompanyMgr::createFreeCompany( const std::string& name, const
stmt->setUInt( 13, static_cast< uint8_t >( Common::FreeCompanyStatus::InviteStart ) );
stmt->setString( 14, std::string( "" ) );
stmt->setString( 15, std::string( "" ) );
db.directExecute( stmt );
/*! FreeCompanyId, FcMemberId, HierarchyType, LastLogout */
stmt = db.getPreparedStatement( Db::ZoneDbStatements::FC_MEMBERS_INS );
stmt->setUInt64( 1, freeCompanyId );
stmt->setUInt64( 2, masterId );
stmt->setUInt( 3, 0 );
stmt->setUInt( 4, createDate );
db.directExecute( stmt );
fcPtr->addMember( masterId, 0, createDate );
auto& server = Common::Service< World::WorldServer >::ref();
auto fcResult = makeFcResult( player, freeCompanyId,
@ -267,12 +302,27 @@ void FreeCompanyMgr::sendFcInviteList( Entity::Player& player )
inviteListPacket->data().MasterCharacter.CharacterID = masterCharacter->getCharacterId();
strcpy( inviteListPacket->data().MasterCharacter.CharacterName, masterCharacter->getName().c_str() );
inviteListPacket->data().MasterCharacter.SelectRegion = masterCharacter->getSearchSelectRegion();
inviteListPacket->data().MasterCharacter.OnlineStatus = masterCharacter->getOnlineStatusMask();
inviteListPacket->data().MasterCharacter.OnlineStatus = static_cast< uint64_t >( masterCharacter->getOnlineStatus() );
inviteListPacket->data().MasterCharacter.GrandCompanyRank[ 0 ] = masterCharacter->getGcRankArray()[ 0 ];
inviteListPacket->data().MasterCharacter.GrandCompanyRank[ 1 ] = masterCharacter->getGcRankArray()[ 1 ];
inviteListPacket->data().MasterCharacter.GrandCompanyRank[ 2 ] = masterCharacter->getGcRankArray()[ 2 ];
// todo - fill invite characters
uint8_t idx = 0;
for( auto& entry : fc->getMemberIdList() )
{
if( entry == 0 )
continue;
auto signee = server.getPlayer( entry );
if( !signee )
continue;
inviteListPacket->data().InviteCharacter[ idx ].CharacterID = signee->getCharacterId();
strcpy( inviteListPacket->data().InviteCharacter[ idx ].CharacterName, signee->getName().c_str() );
inviteListPacket->data().InviteCharacter[ idx ].SelectRegion = signee->getSearchSelectRegion();
inviteListPacket->data().InviteCharacter[ idx ].OnlineStatus = static_cast< uint64_t >( masterCharacter->getOnlineStatus() );
idx++;
}
server.queueForPlayer( player.getCharacterId(), inviteListPacket );
}
@ -312,8 +362,9 @@ void FreeCompanyMgr::onFcLogin( uint64_t characterId )
if( !fc )
return;
auto fcResult = makeFcResult( *player, fc->getId(),
2, FreeCompanyResultPacket::ResultType::FcLogin,
uint64_t onlinePlayers = 1;
auto fcResult = makeFcResult( *player, fc->getId(), onlinePlayers,
FreeCompanyResultPacket::ResultType::FcLogin,
0, FreeCompanyResultPacket::UpdateStatus::Execute,
fc->getName(), fc->getTag() );
@ -321,3 +372,8 @@ void FreeCompanyMgr::onFcLogin( uint64_t characterId )
// todo - send packet to rest of fc members
}
void FreeCompanyMgr::onSignPetition( Entity::Player& source, Entity::Player& target )
{
}

View file

@ -13,14 +13,14 @@ namespace Sapphire::World::Manager
class FreeCompanyMgr
{
private:
std::map< uint64_t, FreeCompanyPtr > m_fcIdMap;
std::map< std::string, FreeCompanyPtr > m_fcNameMap;
std::unordered_map< uint64_t, FreeCompanyPtr > m_fcIdMap;
std::unordered_map< std::string, FreeCompanyPtr > m_fcNameMap;
FreeCompanyPtr getFcByName( const std::string& name );
/*! map used for easy lookup of char id to fc id */
std::unordered_map< uint64_t, uint64_t > m_charaIdToFcIdMap;
public:
FreeCompanyMgr() = default;
// initialize all fcs from db to memory
@ -50,13 +50,14 @@ namespace Sapphire::World::Manager
// get fc associated with player
FreeCompanyPtr getPlayerFreeCompany( Entity::Player& player ) const;
FreeCompanyPtr getFreeCompanyById( uint64_t fcId );
FreeCompanyPtr getFreeCompanyByName( const std::string& name );
// void leaveLinkshell( uint64_t lsId, uint64_t characterId );
// void joinLinkshell( uint64_t lsId, uint64_t characterId );
void onFcLogin( uint64_t characterId );
void onSignPetition( Entity::Player& source, Entity::Player& target );
};

View file

@ -20,6 +20,7 @@
#include "Manager/FriendListMgr.h"
#include "Manager/PartyMgr.h"
#include "Manager/PlayerMgr.h"
#include "Manager/FreeCompanyMgr.h"
#include "Action/Action.h"
@ -34,8 +35,7 @@ using namespace Sapphire::Network::Packets::WorldPackets;
using namespace Sapphire::World::Manager;
void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::Packets::FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
void Sapphire::Network::GameConnection::inviteHandler( const FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{
const auto packet = ZoneChannelPacket< Client::FFXIVIpcInvite >( inPacket );
@ -45,9 +45,9 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
std::string name( packet.data().TargetName );
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto pSession = server.getSession( name );
auto pTargetPlayer = server.getPlayer( name );
if( !pSession )
if( !pTargetPlayer )
return;
switch( packet.data().AuthType )
@ -60,27 +60,22 @@ 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,
packet.data().AuthType, 1,
InviteUpdateType::NEW_INVITE );
pSession->getZoneConnection()->queueOutPacket( invitePacket );
auto invitePacket = makeInviteUpdatePacket( player, Common::Util::getTimeSeconds() + 30, packet.data().AuthType, 1, InviteUpdateType::NEW_INVITE );
server.queueForPlayer( pTargetPlayer->getCharacterId(), invitePacket );
break;
}
case HierarchyType::FRIENDLIST:
{
auto inviteResultPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteResult >( player.getId() );
auto inviteResultPacket = makeZonePacket< FFXIVIpcInviteResult >( player.getId() );
auto& data = inviteResultPacket->data();
data.AuthType = packet.data().AuthType;
strcpy( data.TargetName, packet.data().TargetName );
server.queueForPlayer( player.getCharacterId(), inviteResultPacket );
auto invitePacket = std::make_shared< InviteUpdatePacket >( player, 0,
packet.data().AuthType, 1,
InviteUpdateType::NEW_INVITE );
pSession->getZoneConnection()->queueOutPacket( invitePacket );
auto invitePacket = makeInviteUpdatePacket( player, 0, packet.data().AuthType, 1, InviteUpdateType::NEW_INVITE );
server.queueForPlayer( pTargetPlayer->getCharacterId(), invitePacket );
auto& flMgr = Common::Service< FriendListMgr >::ref();
// add support to adding offline players
@ -95,9 +90,29 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
case HierarchyType::AUTOPARTY:
break;
case HierarchyType::FCCREATE:
{
auto inviteResultPacket = makeZonePacket< FFXIVIpcInviteResult >( player.getId() );
auto& data = inviteResultPacket->data();
data.AuthType = packet.data().AuthType;
strcpy( data.TargetName, packet.data().TargetName );
server.queueForPlayer( player.getCharacterId(), inviteResultPacket );
auto invitePacket = makeInviteUpdatePacket( player, 1, packet.data().AuthType, 1, InviteUpdateType::NEW_INVITE );
server.queueForPlayer( pTargetPlayer->getCharacterId(), invitePacket );
break;
}
case HierarchyType::FREECOMPANY:
{
auto inviteResultPacket = makeZonePacket< FFXIVIpcInviteResult >( player.getId() );
auto& data = inviteResultPacket->data();
data.AuthType = packet.data().AuthType;
strcpy( data.TargetName, packet.data().TargetName );
server.queueForPlayer( player.getCharacterId(), inviteResultPacket );
auto invitePacket = makeInviteUpdatePacket( player, 1, packet.data().AuthType, 1, InviteUpdateType::NEW_INVITE );
server.queueForPlayer( pTargetPlayer->getCharacterId(), invitePacket );
break;
}
case HierarchyType::FCJOINREQUEST:
break;
case HierarchyType::PARTYCANCEL:
@ -105,19 +120,18 @@ void Sapphire::Network::GameConnection::inviteHandler( const Sapphire::Network::
}
}
void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKET_RAW& inPacket,
Entity::Player& player )
void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player )
{
const auto packet = ZoneChannelPacket< Client::FFXIVIpcInviteReply >( inPacket );
const auto& data = packet.data();
auto& server = Common::Service< Sapphire::World::WorldServer >::ref();
auto pSession = server.getSession( data.InviteCharacterID );
auto pPlayer = server.getPlayer( data.InviteCharacterID );
if( !pSession )
if( !pPlayer )
return;
auto inviteReplyPacket = makeZonePacket< WorldPackets::Server::FFXIVIpcInviteReplyResult >( player.getId() );
auto inviteReplyPacket = makeZonePacket< FFXIVIpcInviteReplyResult >( player.getId() );
auto& inviteReplyData = inviteReplyPacket->data();
inviteReplyData.Answer = data.Answer;
@ -125,51 +139,45 @@ void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKE
{
case HierarchyType::PCPARTY:
{
auto& partyMgr = Common::Service< Sapphire::World::Manager::PartyMgr >::ref();
auto& partyMgr = Common::Service< PartyMgr >::ref();
uint8_t result;
uint8_t result = InviteUpdateType::REJECT_INVITE;
if( data.Answer == InviteReplyType::ACCEPT )
{
partyMgr.onJoin( player.getId(), pSession->getPlayer()->getId() );
partyMgr.onJoin( player.getId(), pPlayer->getId() );
result = InviteUpdateType::ACCEPT_INVITE;
}
else
{
result = InviteUpdateType::REJECT_INVITE;
}
auto inviteUpPacket = std::make_shared< InviteUpdatePacket >( player, Common::Util::getTimeSeconds() + 30,
data.AuthType, 1, result );
pSession->getZoneConnection()->queueOutPacket( inviteUpPacket );
auto inviteUpPacket = makeInviteUpdatePacket( player, Common::Util::getTimeSeconds() + 30, data.AuthType, 1, result );
server.queueForPlayer( pPlayer->getCharacterId(), inviteUpPacket );
inviteReplyData.AuthType = data.AuthType;
strcpy( inviteReplyData.InviteCharacterName, pSession->getPlayer()->getName().c_str() );
strcpy( inviteReplyData.InviteCharacterName, pPlayer->getName().c_str() );
server.queueForPlayer( player.getCharacterId(), inviteReplyPacket );
break;
}
case HierarchyType::FRIENDLIST:
{
auto& flMgr = Common::Service< Sapphire::World::Manager::FriendListMgr >::ref();
auto& flMgr = Common::Service< FriendListMgr >::ref();
uint8_t result;
if( data.Answer == InviteReplyType::ACCEPT )
{
flMgr.onInviteAccept( player, *pSession->getPlayer() );
flMgr.onInviteAccept( player, *pPlayer );
result = InviteUpdateType::ACCEPT_INVITE;
}
else
{
flMgr.onInviteDecline( player, *pSession->getPlayer() );
flMgr.onInviteDecline( player, *pPlayer );
result = InviteUpdateType::REJECT_INVITE;
}
auto inviteUpPacket = std::make_shared< InviteUpdatePacket >( player, 0,
data.AuthType, 1, result );
pSession->getZoneConnection()->queueOutPacket( inviteUpPacket );
auto inviteUpPacket = makeInviteUpdatePacket( player, 0, data.AuthType, 1, result );
server.queueForPlayer( pPlayer->getCharacterId(), inviteUpPacket );
inviteReplyData.AuthType = data.AuthType;
strcpy( inviteReplyData.InviteCharacterName, pSession->getPlayer()->getName().c_str() );
strcpy( inviteReplyData.InviteCharacterName, pPlayer->getName().c_str() );
server.queueForPlayer( player.getCharacterId(), inviteReplyPacket );
break;
@ -177,7 +185,27 @@ void Sapphire::Network::GameConnection::inviteReplyHandler( const FFXIVARR_PACKE
case HierarchyType::AUTOPARTY:
break;
case HierarchyType::FCCREATE:
{
auto& fcMgr = Common::Service< FreeCompanyMgr >::ref();
uint8_t result;
if( data.Answer == InviteReplyType::ACCEPT )
{
fcMgr.onSignPetition( player, *pPlayer );
result = InviteUpdateType::ACCEPT_INVITE;
}
else
{
result = InviteUpdateType::REJECT_INVITE;
}
auto inviteUpPacket = makeInviteUpdatePacket( player, 0, data.AuthType, 1, result );
server.queueForPlayer( pPlayer->getCharacterId(), inviteUpPacket );
inviteReplyData.AuthType = data.AuthType;
strcpy( inviteReplyData.InviteCharacterName, pPlayer->getName().c_str() );
server.queueForPlayer( player.getCharacterId(), inviteReplyPacket );
break;
}
case HierarchyType::FREECOMPANY:
break;
case HierarchyType::FCJOINREQUEST:

View file

@ -75,16 +75,16 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
Member = 0xC,
};
FreeCompanyResultPacket( Entity::Player& player, uint64_t fcId, uint64_t targetId,
FreeCompanyResultPacket( Entity::Player& player, uint64_t fcId, uint64_t arg,
ResultType type, uint32_t result, UpdateStatus updateStatus, const std::string& fcName, const std::string& targetName ) :
ZoneChannelPacket< FFXIVIpcFreeCompanyResult >( player.getId(), player.getId() )
{
initialize( player, fcId, targetId, type, result, updateStatus, fcName, targetName );
initialize( player, fcId, arg, type, result, updateStatus, fcName, targetName );
};
private:
void initialize( Entity::Player& player, uint64_t fcId, uint64_t targetId,
void initialize( Entity::Player& player, uint64_t fcId, uint64_t arg,
ResultType type, uint32_t result, UpdateStatus updateStatus, const std::string& fcName, const std::string& targetName )
{
m_data.FreeCompanyID = fcId;
@ -92,7 +92,7 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
m_data.Type = static_cast< uint32_t >( type );
m_data.Result = result;
m_data.UpdateStatus = updateStatus;
m_data.TargetCharacterID = targetId;
m_data.Arg = arg;
strcpy( m_data.FreeCompanyName, fcName.c_str() );
strcpy( m_data.TargetName, targetName.c_str() );
};

View file

@ -27,4 +27,10 @@ namespace Sapphire::Network::Packets::WorldPackets::Server
strcpy( m_data.InviteName, player.getName().c_str() );
};
};
template< typename... Args >
std::shared_ptr< InviteUpdatePacket > makeInviteUpdatePacket( Args... args )
{
return std::make_shared< InviteUpdatePacket >( args... );
}
}