diff --git a/src/common/Database/ZoneDbConnection.cpp b/src/common/Database/ZoneDbConnection.cpp index fde532f1..ad303c97 100644 --- a/src/common/Database/ZoneDbConnection.cpp +++ b/src/common/Database/ZoneDbConnection.cpp @@ -326,7 +326,7 @@ void Sapphire::Db::ZoneDbConnection::doPrepareStatements() CONNECTION_SYNC ); prepareStatement( LINKSHELL_UP, - "UPDATE infolinkshell SET CharacterIdList = ?, LinkshellName = ?, LeaderIdList = ?, InviteIdList = ? WHERE LinkshellId = ?;", + "UPDATE infolinkshell SET CharacterIdList = ?, LinkshellName = ?, LeaderIdList = ?, InviteIdList = ?, MasterCharacterId = ? WHERE LinkshellId = ?;", CONNECTION_BOTH ); /*prepareStatement( LAND_INS, diff --git a/src/world/Linkshell/Linkshell.cpp b/src/world/Linkshell/Linkshell.cpp index 7c06e323..75675d75 100644 --- a/src/world/Linkshell/Linkshell.cpp +++ b/src/world/Linkshell/Linkshell.cpp @@ -98,5 +98,10 @@ void Sapphire::Linkshell::removeInvite( uint64_t memberId ) m_inviteIds.erase( memberId ); } +void Sapphire::Linkshell::setMasterId( uint64_t masterId ) +{ + m_masterCharacterId = masterId; +} + diff --git a/src/world/Linkshell/Linkshell.h b/src/world/Linkshell/Linkshell.h index 8d637a98..a286c330 100644 --- a/src/world/Linkshell/Linkshell.h +++ b/src/world/Linkshell/Linkshell.h @@ -40,6 +40,8 @@ namespace Sapphire uint64_t getMasterId() const; + void setMasterId( uint64_t masterId ); + const std::set< uint64_t >& getMemberIdList() const; std::set< uint64_t >& getMemberIdList(); diff --git a/src/world/Manager/LinkshellMgr.cpp b/src/world/Manager/LinkshellMgr.cpp index b293e061..bd0ad4b0 100644 --- a/src/world/Manager/LinkshellMgr.cpp +++ b/src/world/Manager/LinkshellMgr.cpp @@ -127,7 +127,8 @@ void LinkshellMgr::writeLinkshell( uint64_t lsId ) query->setString( 2, ls->getName() ); query->setBinary( 3, leaderBin ); query->setBinary( 4, inviteBin ); - query->setInt64( 5, lsId ); + query->setUInt64( 5, ls->getMasterId() ); + query->setInt64( 6, lsId ); db.execute( query ); } @@ -388,14 +389,14 @@ void LinkshellMgr::addLeader( Sapphire::Entity::Player &sourcePlayer, Sapphire:: writeLinkshell( lsPtr->getId() ); sendLinkshellList( newLeaderPlayer ); - auto linkshellResult = makeLinkshellResult( newLeaderPlayer, 0, 0, + auto linkshellResult = makeLinkshellResult( newLeaderPlayer, lsPtr->getId(), 0, WorldPackets::Client::LinkshellAddLeader, 0, LinkshellResultPacket::UpdateStatus::Target, lsPtr->getName(), sourcePlayer.getName() ); server.queueForPlayer( newLeaderPlayer.getCharacterId(), linkshellResult ); - auto linkshellResult1 = makeLinkshellResult( sourcePlayer, 0, 0, + auto linkshellResult1 = makeLinkshellResult( sourcePlayer, lsPtr->getId(), 0, WorldPackets::Client::LinkshellAddLeader, 0, LinkshellResultPacket::UpdateStatus::Execute, lsPtr->getName(), newLeaderPlayer.getName() ); @@ -416,7 +417,7 @@ void LinkshellMgr::declineLeader( Sapphire::Entity::Player &sourcePlayer, uint64 writeLinkshell( lsPtr->getId() ); sendLinkshellList( sourcePlayer ); - auto linkshellResult = makeLinkshellResult( sourcePlayer, 0, 0, + auto linkshellResult = makeLinkshellResult( sourcePlayer, lsPtr->getId(), 0, WorldPackets::Client::LinkshellDeclineLeader, 0, LinkshellResultPacket::UpdateStatus::Execute, lsPtr->getName(), sourcePlayer.getName() ); @@ -438,17 +439,46 @@ void LinkshellMgr::removeLeader( Sapphire::Entity::Player &sourcePlayer, Sapphir writeLinkshell( lsPtr->getId() ); sendLinkshellList( leaderPlayer ); - auto linkshellResult = makeLinkshellResult( leaderPlayer, 0, 0, + auto linkshellResult = makeLinkshellResult( leaderPlayer, lsPtr->getId(), 0, WorldPackets::Client::LinkshellRemoveLeader, 0, LinkshellResultPacket::UpdateStatus::Target, lsPtr->getName(), sourcePlayer.getName() ); server.queueForPlayer( leaderPlayer.getCharacterId(), linkshellResult ); - auto linkshellResult1 = makeLinkshellResult( sourcePlayer, 0, 0, + auto linkshellResult1 = makeLinkshellResult( sourcePlayer, lsPtr->getId(), 0, WorldPackets::Client::LinkshellRemoveLeader, 0, LinkshellResultPacket::UpdateStatus::Execute, lsPtr->getName(), leaderPlayer.getName() ); server.queueForPlayer( sourcePlayer.getCharacterId(), linkshellResult1 ); } + +void LinkshellMgr::changeMaster( Sapphire::Entity::Player &sourcePlayer, Sapphire::Entity::Player &nextMasterPlayer, uint64_t linkshellId ) +{ + auto& server = Common::Service< World::WorldServer >::ref(); + + auto lsPtr = getLinkshellById( linkshellId ); + + if( !lsPtr ) + return Logger::warn( "Failed to change master from linkshell - linkshell not found!" ); + + lsPtr->setMasterId( nextMasterPlayer.getCharacterId() ); + writeLinkshell( lsPtr->getId() ); + sendLinkshellList( nextMasterPlayer ); + sendLinkshellList( sourcePlayer ); + + auto linkshellResult = makeLinkshellResult( sourcePlayer, lsPtr->getId(), nextMasterPlayer.getCharacterId(), + WorldPackets::Client::LinkshellChangeMaster, 0, + LinkshellResultPacket::UpdateStatus::Target, + lsPtr->getName(), nextMasterPlayer.getName() ); + + server.queueForPlayer( nextMasterPlayer.getCharacterId(), linkshellResult ); + + auto linkshellResult1 = makeLinkshellResult( sourcePlayer, lsPtr->getId(), nextMasterPlayer.getCharacterId(), + WorldPackets::Client::LinkshellChangeMaster, 0, + LinkshellResultPacket::UpdateStatus::Execute, + lsPtr->getName(), nextMasterPlayer.getName() ); + + server.queueForPlayer( sourcePlayer.getCharacterId(), linkshellResult1 ); +} diff --git a/src/world/Manager/LinkshellMgr.h b/src/world/Manager/LinkshellMgr.h index 8184b28e..bf7a25e7 100644 --- a/src/world/Manager/LinkshellMgr.h +++ b/src/world/Manager/LinkshellMgr.h @@ -44,6 +44,7 @@ namespace Sapphire::World::Manager void addLeader( Entity::Player& sourcePlayer, Entity::Player& newLeaderPlayer, uint64_t linkshellId ); void removeLeader( Entity::Player& sourcePlayer, Entity::Player& leaderPlayer, uint64_t linkshellId ); void declineLeader( Entity::Player& sourcePlayer, uint64_t linkshellId ); + void changeMaster( Entity::Player& sourcePlayer, Entity::Player& nextMasterPlayer, uint64_t linkshellId ); void sendLinkshellList( Entity::Player& player ); diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 5c02f1ce..e4f9ca15 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -67,7 +67,9 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( GetLinkshellList, "GetLinkshellList", &GameConnection::linkshellListHandler ); setZoneHandler( LinkshellJoin, "LinkshellJoin", &GameConnection::linkshellJoinHandler ); setZoneHandler( LinkshellKick, "LinkshellKick", &GameConnection::linkshellKickHandler ); - + setZoneHandler( LinkshellLeave, "LinkshellLeave", &GameConnection::linkshellLeaveHandler ); + setZoneHandler( LinkshellChangeMaster, "LinkshellChangeMaster", &GameConnection::linkshellChangeMasterHandler ); + setZoneHandler( LinkshellJoinOfficial, "LinkshellJoinOfficial", &GameConnection::linkshellJoinOfficialHandler ); setZoneHandler( LinkshellAddLeader, "LinkshellAddLeader", &GameConnection::linkshellAddLeaderHandler ); setZoneHandler( LinkshellRemoveLeader, "LinkshellRemoveLeader", &GameConnection::linkshellRemoveLeaderHandler ); setZoneHandler( LinkshellDeclineLeader, "LinkshellDeclineLeader", &GameConnection::linkshellDeclineLeaderHandler ); @@ -149,8 +151,7 @@ Sapphire::Network::GameConnection::GameConnection( Sapphire::Network::HivePtr pH setZoneHandler( FriendlistRemove, "FriendlistRemove", &GameConnection::friendlistRemoveHandler ); setZoneHandler( SetFriendlistGroup, "SetFriendlistGroup", &GameConnection::setFriendlistGroupHandler ); - setZoneHandler( LinkshellLeave, "LinkshellLeave", &GameConnection::linkshellLeaveHandler ); - setZoneHandler( LinkshellJoinOfficial, "LinkshellJoinOfficial", &GameConnection::linkshellJoinOfficialHandler ); + } Sapphire::Network::GameConnection::~GameConnection() = default; diff --git a/src/world/Network/GameConnection.h b/src/world/Network/GameConnection.h index a8bfde62..428219d5 100644 --- a/src/world/Network/GameConnection.h +++ b/src/world/Network/GameConnection.h @@ -112,7 +112,9 @@ namespace Sapphire::Network DECLARE_HANDLER( linkshellListHandler ); DECLARE_HANDLER( linkshellKickHandler ); - + DECLARE_HANDLER( linkshellLeaveHandler ); + DECLARE_HANDLER( linkshellChangeMasterHandler ); + DECLARE_HANDLER( linkshellJoinOfficialHandler ); DECLARE_HANDLER( linkshellAddLeaderHandler ); DECLARE_HANDLER( linkshellRemoveLeaderHandler ); DECLARE_HANDLER( linkshellDeclineLeaderHandler ); @@ -225,8 +227,7 @@ namespace Sapphire::Network DECLARE_HANDLER( friendlistRemoveHandler ); DECLARE_HANDLER( setFriendlistGroupHandler ); - DECLARE_HANDLER( linkshellLeaveHandler ); - DECLARE_HANDLER( linkshellJoinOfficialHandler ); + }; } diff --git a/src/world/Network/Handlers/LinkshellHandlers.cpp b/src/world/Network/Handlers/LinkshellHandlers.cpp index 55c5992e..6aeffb9d 100644 --- a/src/world/Network/Handlers/LinkshellHandlers.cpp +++ b/src/world/Network/Handlers/LinkshellHandlers.cpp @@ -122,4 +122,22 @@ void Sapphire::Network::GameConnection::linkshellJoinOfficialHandler( const Pack auto& lsMgr = Common::Service< LinkshellMgr >::ref(); lsMgr.joinLinkshell( lsLeavePacket.data().LinkshellID, player.getCharacterId() ); +} + +void Sapphire::Network::GameConnection::linkshellChangeMasterHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) +{ + const auto lsChMasterPacket = ZoneChannelPacket< Client::FFXIVIpcLinkshellChangeMaster >( inPacket ); + auto& lsMgr = Common::Service< LinkshellMgr >::ref(); + auto& server = Common::Service< World::WorldServer >::ref(); + + auto charName = std::string( lsChMasterPacket.data().NextMasterCharacterName ); + auto nextMaster = server.getPlayer( charName ); + + if( !nextMaster ) + { + Logger::error( std::string( __FUNCTION__ ) + " requested player \"{}\" not found!", charName ); + return; + } + + lsMgr.changeMaster( player, *nextMaster, lsChMasterPacket.data().LinkshellID ); } \ No newline at end of file