diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 88ab338d..5fbdd6c4 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -7,6 +7,7 @@ file(GLOB UTILS_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/Crypt/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Database/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Exd/*.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/Event/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Logging/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Network/*.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/Network/PacketDef/*.cpp" diff --git a/src/common/Event/Event.h b/src/common/Event/Event.h new file mode 100644 index 00000000..5342b65a --- /dev/null +++ b/src/common/Event/Event.h @@ -0,0 +1,14 @@ +#pragma once +#include + +namespace Sapphire::Common::EventSystem +{ + class Event + { + public: + virtual~ Event() = default; + + using DescriptorType = const char*; + virtual DescriptorType type() const = 0; + }; +} \ No newline at end of file diff --git a/src/common/Event/EventDispatcher.cpp b/src/common/Event/EventDispatcher.cpp new file mode 100644 index 00000000..5015d875 --- /dev/null +++ b/src/common/Event/EventDispatcher.cpp @@ -0,0 +1,21 @@ +#include "EventDispatcher.h" + +using namespace Sapphire::Common::EventSystem; + +void EventDispatcher::subscribe( const Event::DescriptorType& descriptor, SlotType&& slot ) +{ + m_observers[ descriptor ].push_back( slot ); +} + +void EventDispatcher::emit( const Event& event ) const +{ + auto type = event.type(); + + if( m_observers.find( type ) == m_observers.end() ) + return; + + auto&& observers = m_observers.at( type ); + + for( auto&& observer : observers ) + observer( event ); +} \ No newline at end of file diff --git a/src/common/Event/EventDispatcher.h b/src/common/Event/EventDispatcher.h new file mode 100644 index 00000000..b750d00a --- /dev/null +++ b/src/common/Event/EventDispatcher.h @@ -0,0 +1,24 @@ +#pragma once +#include +#include "Event.h" +#include + +namespace Sapphire::Common::EventSystem +{ + + class EventDispatcher + { + public: + using SlotType = std::function< void( const Event& ) >; + + void subscribe( const Event::DescriptorType& descriptor, SlotType&& slot ); + + void emit( const Event& event ) const; + + private: + std::unordered_map< Event::DescriptorType, std::vector< SlotType > > m_observers; + + }; + +} + diff --git a/src/common/Event/Observer.h b/src/common/Event/Observer.h new file mode 100644 index 00000000..576cbcc4 --- /dev/null +++ b/src/common/Event/Observer.h @@ -0,0 +1,11 @@ +#pragma once +#include "Event.h" + +namespace Sapphire::Common::EventSystem +{ + class EventObserver + { + public: + virtual void handleEvent( const Event& e ) = 0; + }; +} diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index c3ea4e20..6c972ad0 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -477,20 +477,16 @@ Player::Discovery& Player::getDiscoveryBitmask() return m_discovery; } -void Player::discover( int16_t map_id, int16_t sub_id ) +void Player::discover( int16_t mapId, int16_t subId ) { - // map.exd field 12 -> index in one of the two discovery sections, if field 15 is false, need to use 2nd section - // section 1 starts at 0 - 2 bytes each - // section to starts at 320 - 4 bytes long - auto& exdData = Common::Service< Data::ExdData >::ref(); int32_t offset; - auto info = exdData.getRow< Excel::Map >( map_id ); + auto info = exdData.getRow< Excel::Map >( mapId ); if( !info ) { - PlayerMgr::sendDebug( *this, "discover(): Could not obtain map data for map_id == {0}", map_id ); + PlayerMgr::sendDebug( *this, "discover(): Could not obtain map data for map_id == {0}", mapId ); return; } @@ -499,15 +495,15 @@ void Player::discover( int16_t map_id, int16_t sub_id ) else offset = 320 + 4 * info->data().DiscoveryIndex; - int32_t index = offset + sub_id / 8; - uint8_t bitIndex = sub_id % 8; + uint16_t index; + uint8_t bitIndex; + uint8_t value; - uint8_t value = 1 << bitIndex; + Util::valueToFlagByteIndexValue( subId, value, index ); - m_discovery[ index ] |= value; + m_discovery[ index + offset ] |= value; uint16_t level = getLevel(); - uint32_t exp = ( exdData.getRow< Excel::ParamGrow >( level )->data().NextExp * 5 / 100 ); gainExp( exp ); @@ -517,8 +513,7 @@ void Player::discover( int16_t map_id, int16_t sub_id ) uint32_t discoveredAreas; if( info->data().IsUint16Discovery ) { - discoveredAreas = ( m_discovery[ offset + 1 ] << 8 ) | - m_discovery[ offset ]; + discoveredAreas = ( m_discovery[ offset + 1 ] << 8 ) | m_discovery[ offset ]; } else { diff --git a/src/world/Actor/Player.h b/src/world/Actor/Player.h index 74977910..ac4156d5 100644 --- a/src/world/Actor/Player.h +++ b/src/world/Actor/Player.h @@ -438,7 +438,7 @@ namespace Sapphire::Entity uint8_t getHomepoint() const; /*! discover subarea subid fo map map_id, also send udpate packet */ - void discover( int16_t map_id, int16_t sub_id ); + void discover( int16_t mapId, int16_t subId ); /*! return a reference to the discovery bitmask array */ Discovery& getDiscoveryBitmask(); diff --git a/src/world/Event/EventDefinitions/EventDefinitions.h b/src/world/Event/EventDefinitions/EventDefinitions.h new file mode 100644 index 00000000..614d5793 --- /dev/null +++ b/src/world/Event/EventDefinitions/EventDefinitions.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +namespace Sapphire::Common::EventSystem +{ + + class LoginEvent : public Event + { + public: + static constexpr DescriptorType descriptor = "LoginEvent"; + virtual DescriptorType type() const { return descriptor; } + + LoginEvent( uint64_t charId ) : characterId( charId ) {}; + virtual ~LoginEvent() = default; + + + uint64_t characterId; + }; + +} \ No newline at end of file diff --git a/src/world/Manager/FreeCompanyMgr.cpp b/src/world/Manager/FreeCompanyMgr.cpp index 78b92f8e..df732426 100644 --- a/src/world/Manager/FreeCompanyMgr.cpp +++ b/src/world/Manager/FreeCompanyMgr.cpp @@ -22,12 +22,23 @@ #include #include "Session.h" +#include using namespace Sapphire; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::World::Manager; +void FreeCompanyMgr::handleEvent( const Common::EventSystem::Event& e ) +{ + if( e.type() == Common::EventSystem::LoginEvent::descriptor ) + { + const Common::EventSystem::LoginEvent& loginEvent = static_cast< const Common::EventSystem::LoginEvent& >( e ); + onFcLogin( loginEvent.characterId ); + } + +} + bool FreeCompanyMgr::loadFreeCompanies() { auto& chatChannelMgr = Common::Service< Manager::ChatChannelMgr >::ref(); diff --git a/src/world/Manager/FreeCompanyMgr.h b/src/world/Manager/FreeCompanyMgr.h index 0ab7dd16..58410b8b 100644 --- a/src/world/Manager/FreeCompanyMgr.h +++ b/src/world/Manager/FreeCompanyMgr.h @@ -5,13 +5,12 @@ #include #include "ForwardsZone.h" #include "FreeCompany/FreeCompany.h" +#include namespace Sapphire::World::Manager { - - - class FreeCompanyMgr + class FreeCompanyMgr : public Common::EventSystem::EventObserver { private: std::unordered_map< uint64_t, FreeCompanyPtr > m_fcIdMap; @@ -27,6 +26,8 @@ namespace Sapphire::World::Manager FreeCompanyMgr() = default; + void handleEvent( const Common::EventSystem::Event& e ); + // initialize all fcs from db to memory bool loadFreeCompanies(); void writeFreeCompany( uint64_t fcId ); diff --git a/src/world/Manager/PlayerMgr.cpp b/src/world/Manager/PlayerMgr.cpp index 61e1a010..c8b7e33a 100644 --- a/src/world/Manager/PlayerMgr.cpp +++ b/src/world/Manager/PlayerMgr.cpp @@ -41,12 +41,24 @@ #include +#include + using namespace Sapphire; using namespace Sapphire::World::Manager; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::WorldPackets::Server; using namespace Sapphire::Network::ActorControl; +void PlayerMgr::handleEvent( const Common::EventSystem::Event& e ) +{ + if( e.type() == Common::EventSystem::LoginEvent::descriptor ) + { + const Common::EventSystem::LoginEvent& loginEvent = static_cast< const Common::EventSystem::LoginEvent& >( e ); + auto player = server().getPlayer( loginEvent.characterId ); + onLogin( *player ); + } + +} void PlayerMgr::onOnlineStatusChanged( Entity::Player& player, bool updateProfile ) { diff --git a/src/world/Manager/PlayerMgr.h b/src/world/Manager/PlayerMgr.h index 54f4286c..d97c9bc9 100644 --- a/src/world/Manager/PlayerMgr.h +++ b/src/world/Manager/PlayerMgr.h @@ -3,14 +3,17 @@ #include "ForwardsZone.h" #include #include "MgrUtil.h" +#include namespace Sapphire::World::Manager { - class PlayerMgr + class PlayerMgr : public Common::EventSystem::EventObserver { public: PlayerMgr() = default; + void handleEvent( const Common::EventSystem::Event& e ); + void onOnlineStatusChanged( Sapphire::Entity::Player& player, bool updateProfile = true ); void onEquipDisplayFlagsChanged( Sapphire::Entity::Player& player ); diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index b2cc81f0..b0765d4c 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -64,6 +64,9 @@ #include "WorldServer.h" #include "Forwards.h" +#include +#include + using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::WorldPackets::Server; @@ -370,7 +373,7 @@ void Sapphire::Network::GameConnection::syncHandler( const Packets::FFXIVARR_PAC void Sapphire::Network::GameConnection::setLanguageHandler( const Packets::FFXIVARR_PACKET_RAW& inPacket, Entity::Player& player ) { auto& playerMgr = Common::Service< World::Manager::PlayerMgr >::ref(); - + auto& eventDispatcher = Common::Service< Common::EventSystem::EventDispatcher >::ref(); auto& teriMgr = Common::Service< TerritoryMgr >::ref(); auto pCurrentZone = teriMgr.getTerritoryByGuId( player.getTerritoryId() ); @@ -382,8 +385,9 @@ void Sapphire::Network::GameConnection::setLanguageHandler( const Packets::FFXIV // if this is a login event if( player.isLogin() ) { + eventDispatcher.emit( EventSystem::LoginEvent( player.getCharacterId() ) ); // fire the onLogin Event - playerMgr.onLogin( player ); + //playerMgr.onLogin( player ); } // spawn the player for himself diff --git a/src/world/WorldServer.cpp b/src/world/WorldServer.cpp index 96107540..de44e126 100644 --- a/src/world/WorldServer.cpp +++ b/src/world/WorldServer.cpp @@ -54,6 +54,9 @@ #include "Manager/FreeCompanyMgr.h" #include "Manager/MapMgr.h" +#include +#include + #include "ContentFinder/ContentFinder.h" #include "Territory/InstanceObjectCache.h" @@ -181,8 +184,11 @@ void WorldServer::run( int32_t argc, char* argv[] ) auto pChatChannelMgr = std::make_shared< Manager::ChatChannelMgr >(); Common::Service< Manager::ChatChannelMgr >::set( pChatChannelMgr ); - auto pLsMgr = std::make_shared< Manager::LinkshellMgr >(); + auto dispatcher = std::make_shared< Common::EventSystem::EventDispatcher >(); + Logger::info( "EventDispatcher: Setup of event dispatcher" ); + Common::Service< Common::EventSystem::EventDispatcher >::set( dispatcher ); + auto pLsMgr = std::make_shared< Manager::LinkshellMgr >(); Logger::info( "LinkshellMgr: Caching linkshells" ); if( !pLsMgr->loadLinkshells() ) { @@ -306,6 +312,8 @@ void WorldServer::run( int32_t argc, char* argv[] ) Common::Service< ContentFinder >::set( contentFinder ); Common::Service< Manager::TaskMgr >::set( taskMgr ); + dispatcher->subscribe( Common::EventSystem::LoginEvent::descriptor, std::bind( &Manager::PlayerMgr::handleEvent, pPlayerMgr, std::placeholders::_1 ) ); + Logger::info( "World server running on {0}:{1}", m_ip, m_port );