diff --git a/src/common/Network/PacketDef/Zone/ClientZoneDef.h b/src/common/Network/PacketDef/Zone/ClientZoneDef.h index ec21039b..1870685f 100644 --- a/src/common/Network/PacketDef/Zone/ClientZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ClientZoneDef.h @@ -713,4 +713,14 @@ struct FFXIVIpcPcPartyChangeLeader : FFXIVIpcBasePacket< PcPartyChangeLeader > char NextLeaderCharacterName[32]; }; +struct FFXIVIpcGetFcInviteList : FFXIVIpcBasePacket< GetFcInviteList > +{ + uint32_t Reserve; +}; + +struct FFXIVIpcGetFcHierarchy : FFXIVIpcBasePacket< GetFcHierarchy > +{ + uint8_t ListType; +}; + } diff --git a/src/common/Network/PacketDef/Zone/ServerZoneDef.h b/src/common/Network/PacketDef/Zone/ServerZoneDef.h index 7a3368ac..2965eef2 100644 --- a/src/common/Network/PacketDef/Zone/ServerZoneDef.h +++ b/src/common/Network/PacketDef/Zone/ServerZoneDef.h @@ -197,8 +197,8 @@ namespace Sapphire::Network::Packets::WorldPackets::Server uint64_t AuthorityList; uint64_t ChannelID; uint64_t CrestID; - uint64_t CharaFcState; - uint64_t CharaFcParam; + uint32_t CharaFcState; + uint32_t CharaFcParam; uint16_t Param; uint8_t FcStatus; uint8_t GrandCompanyID; diff --git a/src/scripts/common/ComDefFreeCompany.cpp b/src/scripts/common/ComDefFreeCompany.cpp index 8af1b23c..1b80bdc2 100644 --- a/src/scripts/common/ComDefFreeCompany.cpp +++ b/src/scripts/common/ComDefFreeCompany.cpp @@ -82,10 +82,24 @@ class ComDefFreeCompany : public Sapphire::ScriptAPI::EventScript } else if( sceneId == 5 && yieldId == 18 ) { + // resultstring contains name and tag delimited by '|' + std::size_t splitPos( resultString.find( '|' ) ); + std::string fcName( resultString.substr( 0, splitPos ) ); + std::string fcTag( resultString.substr( splitPos + 1 ) ); + auto& pFcMgr = Common::Service< Sapphire::World::Manager::FreeCompanyMgr >::ref(); - auto pFc = pFcMgr.createFreeCompany( resultString, resultString, player ); + auto& playerMgr = Common::Service< Sapphire::World::Manager::PlayerMgr >::ref(); + auto pFc = pFcMgr.createFreeCompany( fcName, fcTag, player ); + // if no fc is returned, the name has been taken already + if( !pFc ) + { + playerMgr.sendLogMessage( player, 3051 ); + eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 3051 } ); + return; + } pFcMgr.writeFreeCompany( pFc->getId() ); - eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ); + eventMgr().resumeScene( player, eventId, sceneId, yieldId, { 0 } ); + pFcMgr.sendFreeCompanyStatus( player ); } } diff --git a/src/world/Actor/PlayerQuest.cpp b/src/world/Actor/PlayerQuest.cpp index dd53f18a..a1d6f68a 100644 --- a/src/world/Actor/PlayerQuest.cpp +++ b/src/world/Actor/PlayerQuest.cpp @@ -2,8 +2,6 @@ #include #include -#include "Network/PacketWrappers/Notice2Packet.h" - #include "Manager/QuestMgr.h" #include "Player.h" diff --git a/src/world/FreeCompany/FreeCompany.cpp b/src/world/FreeCompany/FreeCompany.cpp index d39c5782..590ec3a0 100644 --- a/src/world/FreeCompany/FreeCompany.cpp +++ b/src/world/FreeCompany/FreeCompany.cpp @@ -188,6 +188,11 @@ const std::array< uint64_t, 15 >& Sapphire::FreeCompany::getActionStockArr() con return m_actionStock; } +uint64_t Sapphire::FreeCompany::getChatChannel() const +{ + return m_chatChannelId; +} + diff --git a/src/world/Manager/FreeCompanyMgr.cpp b/src/world/Manager/FreeCompanyMgr.cpp index 626d3f35..13206cdb 100644 --- a/src/world/Manager/FreeCompanyMgr.cpp +++ b/src/world/Manager/FreeCompanyMgr.cpp @@ -18,7 +18,7 @@ #include #include -//#include + #include #include "Session.h" @@ -59,7 +59,7 @@ bool FreeCompanyMgr::loadFreeCompanies() auto chatChannelId = chatChannelMgr.createChatChannel( Common::ChatChannelType::FreeCompanyChat ); - auto fcPtr = std::make_shared< FreeCompany >( fcId, name, tag, chatChannelId, masterId ); + auto fcPtr = std::make_shared< FreeCompany >( fcId, name, tag, masterId, chatChannelId ); m_fcIdMap[ fcId ] = fcPtr; m_fcNameMap[ name ] = fcPtr; @@ -164,9 +164,11 @@ FreeCompanyPtr FreeCompanyMgr::createFreeCompany( const std::string& name, const uint32_t createDate = Common::Util::getTimeSeconds(); - auto fcPtr = std::make_shared< FreeCompany >( freeCompanyId, name, tag, chatChannelId, masterId ); + auto fcPtr = std::make_shared< FreeCompany >( freeCompanyId, name, tag, masterId, chatChannelId ); fcPtr->setCreateDate( createDate ); fcPtr->setGrandCompany( player.getGc() ); + fcPtr->setFcStatus( Common::FreeCompanyStatus::InviteStart ); + fcPtr->setRank( 1 ); m_fcIdMap[ freeCompanyId ] = fcPtr; m_fcNameMap[ name ] = fcPtr; @@ -196,6 +198,30 @@ FreeCompanyPtr FreeCompanyMgr::createFreeCompany( const std::string& name, const return fcPtr; } +void FreeCompanyMgr::sendFreeCompanyStatus( Entity::Player& player ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + + auto fcStatusResult = makeZonePacket< FFXIVIpcGetFcStatusResult >( player.getId() ); + + auto playerFc = getPlayerFreeCompany( player ); + if( !playerFc ) + return; + + fcStatusResult->data().AuthorityList = 0; + fcStatusResult->data().ChannelID = playerFc->getChatChannel(); + fcStatusResult->data().Param = 2; // this appears to control which packets are requested afterwards + fcStatusResult->data().CharaFcParam = 0; + fcStatusResult->data().CrestID = playerFc->getCrest(); + fcStatusResult->data().FcRank = playerFc->getRank(); + fcStatusResult->data().FcStatus = static_cast< uint8_t >( playerFc->getFcStatus() ); + fcStatusResult->data().FreeCompanyID = playerFc->getId(); + fcStatusResult->data().GrandCompanyID = playerFc->getGrandCompany(); + + server.queueForPlayer( player.getCharacterId(), fcStatusResult ); + +} + void FreeCompanyMgr::finishFreeCompanyAction( const std::string& name, uint32_t result, Entity::Player& player, uint8_t action ) { auto& server = Common::Service< World::WorldServer >::ref(); @@ -204,11 +230,12 @@ void FreeCompanyMgr::finishFreeCompanyAction( const std::string& name, uint32_t FreeCompanyPtr FreeCompanyMgr::getPlayerFreeCompany( Entity::Player& player ) const { - for( const auto &[ key, value ] : m_fcIdMap ) { - + if( value->getMasterId() == player.getCharacterId() ) + { + return value; + } } - return nullptr; } diff --git a/src/world/Manager/QuestMgr.cpp b/src/world/Manager/QuestMgr.cpp index f8d62e69..d1afbcc5 100644 --- a/src/world/Manager/QuestMgr.cpp +++ b/src/world/Manager/QuestMgr.cpp @@ -8,7 +8,6 @@ #include #include "Network/GameConnection.h" -#include "Network/PacketWrappers/Notice2Packet.h" #include "QuestMgr.h" #include "AchievementMgr.h" diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index b92a73a2..2eb780b2 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -169,6 +169,8 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( GetBlacklist, "GetBlacklist", &GameConnection::getBlacklistHandler ); setZoneHandler( BlacklistAdd, "BlacklistAdd", &GameConnection::blacklistAddHandler ); setZoneHandler( BlacklistRemove, "BlacklistRemove", &GameConnection::blacklistRemoveHandler ); + + setZoneHandler( GetFcInviteList, "GetFcInviteList", &GameConnection::getFcInviteListHandler ); } Sapphire::Network::GameConnection::~GameConnection() = default; diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index 87916de7..6c5c1578 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -244,6 +244,8 @@ namespace Sapphire::Network DECLARE_HANDLER( getBlacklistHandler ); DECLARE_HANDLER( blacklistAddHandler ); DECLARE_HANDLER( blacklistRemoveHandler ); + + DECLARE_HANDLER( getFcInviteListHandler ); }; } diff --git a/src/world/Network/Handlers/FreeCompanyHandlers.cpp b/src/world/Network/Handlers/FreeCompanyHandlers.cpp new file mode 100644 index 00000000..1bcb0a0c --- /dev/null +++ b/src/world/Network/Handlers/FreeCompanyHandlers.cpp @@ -0,0 +1,50 @@ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "Network/GameConnection.h" + +#include "Session.h" +#include "Actor/Player.h" +#include "FreeCompany/FreeCompany.h" +#include "Manager/FreeCompanyMgr.h" +#include + +using namespace Sapphire::Common; +using namespace Sapphire::Network::Packets; +using namespace Sapphire::Network::Packets::WorldPackets::Server; +using namespace Sapphire::Network::Packets::WorldPackets; +using namespace Sapphire::World::Manager; + +void Sapphire::Network::GameConnection::getFcInviteListHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + auto& fcMgr = Common::Service< FreeCompanyMgr >::ref(); + + auto fc = fcMgr.getPlayerFreeCompany( player ); + if( !fc ) + return; + + auto inviteListPacket = makeZonePacket< FFXIVIpcGetFcInviteListResult >( player.getId() ); + inviteListPacket->data().GrandCompanyID = fc->getGrandCompany(); + inviteListPacket->data().FreeCompanyID = fc->getId(); + std::strcpy( inviteListPacket->data().FcTag, fc->getTag().c_str() ); + std::strcpy( inviteListPacket->data().FreeCompanyName, fc->getName().c_str() ); + inviteListPacket->data().MasterCharacter.GrandCompanyID = player.getGc(); + inviteListPacket->data().MasterCharacter.CharacterID = player.getCharacterId(); + strcpy( inviteListPacket->data().MasterCharacter.CharacterName, player.getName().c_str() ); + inviteListPacket->data().MasterCharacter.SelectRegion = player.getSearchSelectRegion(); + inviteListPacket->data().MasterCharacter.OnlineStatus = player.getOnlineStatusMask(); + inviteListPacket->data().MasterCharacter.GrandCompanyRank[ 0 ] = player.getGcRankArray()[ 0 ]; + inviteListPacket->data().MasterCharacter.GrandCompanyRank[ 1 ] = player.getGcRankArray()[ 1 ]; + inviteListPacket->data().MasterCharacter.GrandCompanyRank[ 2 ] = player.getGcRankArray()[ 2 ]; + + auto& server = Common::Service< World::WorldServer >::ref(); + server.queueForPlayer( player.getCharacterId(), inviteListPacket ); + +}