From 544538012d67362c259f58005ad8858c39897839 Mon Sep 17 00:00:00 2001 From: Maru Date: Sat, 19 Jan 2019 21:20:23 -0200 Subject: [PATCH] RNGManager PoC, fix overuse of static cast --- src/common/Network/GamePacketNew.h | 2 +- src/common/Util/Util.cpp | 6 +- src/common/Util/Util.h | 7 +- src/world/Actor/Player.cpp | 2 +- src/world/Manager/MarketMgr.cpp | 3 +- src/world/Manager/RNGMgr.cpp | 10 ++ src/world/Manager/RNGMgr.h | 94 +++++++++++++++++++ src/world/Network/GameConnection.cpp | 3 +- src/world/Network/Handlers/PacketHandlers.cpp | 7 +- src/world/ServerMgr.cpp | 5 +- src/world/Session.cpp | 2 +- src/world/Session.h | 4 +- .../Housing/HousingInteriorTerritory.cpp | 2 +- src/world/Territory/Land.cpp | 4 +- src/world/Territory/Zone.cpp | 14 +-- 15 files changed, 139 insertions(+), 26 deletions(-) create mode 100644 src/world/Manager/RNGMgr.cpp create mode 100644 src/world/Manager/RNGMgr.h diff --git a/src/common/Network/GamePacketNew.h b/src/common/Network/GamePacketNew.h index 0bb8a078..c32b8478 100644 --- a/src/common/Network/GamePacketNew.h +++ b/src/common/Network/GamePacketNew.h @@ -258,7 +258,7 @@ namespace Sapphire::Network::Packets // The IPC type itself. m_ipcHdr.type = static_cast< ServerZoneIpcType >( m_data._ServerIpcType ); - m_ipcHdr.timestamp = static_cast< uint32_t >( Util::getTimeSeconds() ); + m_ipcHdr.timestamp = Util::getTimeSeconds(); m_segHdr.size = sizeof( T ) + sizeof( FFXIVARR_IPC_HEADER ) + sizeof( FFXIVARR_PACKET_SEGMENT_HEADER ); }; diff --git a/src/common/Util/Util.cpp b/src/common/Util/Util.cpp index 78db7be7..f443ddf8 100644 --- a/src/common/Util/Util.cpp +++ b/src/common/Util/Util.cpp @@ -119,10 +119,10 @@ uint64_t Sapphire::Util::getTimeMs() return epoch.count(); } -int64_t Sapphire::Util::getTimeSeconds() +uint32_t Sapphire::Util::getTimeSeconds() { - std::chrono::seconds epoch = std::chrono::seconds( std::time( nullptr ) ); - return epoch.count(); + auto currClock = std::chrono::system_clock::now(); + return std::chrono::time_point_cast< std::chrono::seconds >( currClock ).time_since_epoch().count(); } uint64_t Sapphire::Util::getEorzeanTimeStamp() diff --git a/src/common/Util/Util.h b/src/common/Util/Util.h index ab810cef..faea94c6 100644 --- a/src/common/Util/Util.h +++ b/src/common/Util/Util.h @@ -21,7 +21,12 @@ namespace Sapphire::Util uint64_t getTimeMs(); - int64_t getTimeSeconds(); + /*! + * @brief Get a POSIX epoch representation of the current time + * @return 32-bit unsigned integer + */ + + uint32_t getTimeSeconds(); uint64_t getEorzeanTimeStamp(); diff --git a/src/world/Actor/Player.cpp b/src/world/Actor/Player.cpp index 991975e9..2c6fb8c4 100644 --- a/src/world/Actor/Player.cpp +++ b/src/world/Actor/Player.cpp @@ -1533,7 +1533,7 @@ uint32_t Sapphire::Entity::Player::getCFPenaltyMinutes() const void Sapphire::Entity::Player::setCFPenaltyMinutes( uint32_t minutes ) { auto currentTimestamp = Sapphire::Util::getTimeSeconds(); - setCFPenaltyTimestamp( static_cast< uint32_t >( currentTimestamp + minutes * 60 ) ); + setCFPenaltyTimestamp( currentTimestamp + minutes * 60 ); } uint8_t Sapphire::Entity::Player::getOpeningSequence() const diff --git a/src/world/Manager/MarketMgr.cpp b/src/world/Manager/MarketMgr.cpp index d18d28e1..5022471a 100644 --- a/src/world/Manager/MarketMgr.cpp +++ b/src/world/Manager/MarketMgr.cpp @@ -83,12 +83,11 @@ void Sapphire::World::Manager::MarketMgr::requestItemListingInfo( Sapphire::Enti listing.itemCatalogId = catalogId; listing.quantity = i + 1; - listing.purchaseTime = time( nullptr ); + listing.purchaseTime = Sapphire::Util::getTimeSeconds(); listing.salePrice = 69420420; listing.isHq = 1; listing.onMannequin = 1; - strcpy( listing.buyerName, name.c_str() ); } diff --git a/src/world/Manager/RNGMgr.cpp b/src/world/Manager/RNGMgr.cpp new file mode 100644 index 00000000..69c21185 --- /dev/null +++ b/src/world/Manager/RNGMgr.cpp @@ -0,0 +1,10 @@ +#include "RNGMgr.h" +#include + +Sapphire::World::Manager::RNGMgr::RNGMgr( FrameworkPtr pFw ) : + BaseManager( pFw ), + m_engine( *engineSeed< std::mt19937::state_size >() ) +{ + +} + diff --git a/src/world/Manager/RNGMgr.h b/src/world/Manager/RNGMgr.h new file mode 100644 index 00000000..a91325f2 --- /dev/null +++ b/src/world/Manager/RNGMgr.h @@ -0,0 +1,94 @@ +#ifndef SAPPHIRE_RNGMGR_H +#define SAPPHIRE_RNGMGR_H + +#include "Forwards.h" +#include "BaseManager.h" + +#include +#include +#include +#include +#include +#include + +namespace Sapphire::World::Manager +{ + /*! + * @brief Generator object that is used on multiple state situations + */ + template< typename T, typename = typename std::enable_if< std::is_arithmetic< T >::value, T >::type > + class RandGenerator + { + public: + RandGenerator( T minRange = std::numeric_limits< T >::min(), T maxRange = std::numeric_limits< T >::max() ) + : m_engine( *engineSeed< std::mt19937::state_size >() ), m_dist( minRange, maxRange ) + { + + } + + T next() + { + return m_dist( m_engine ); + } + private: + template< std::size_t STATE_SIZE > + std::unique_ptr< std::seed_seq > engineSeed() + { + std::array< uint32_t, STATE_SIZE > seedArray; + std::random_device rd; + + std::generate_n( seedArray.data(), seedArray.size(), std::ref( rd ) ); + auto pSeq = std::make_unique< std::seed_seq >( std::begin( seedArray ), std::end( seedArray ) ); + + return pSeq; + } + + std::uniform_real_distribution< T > m_dist; + std::mt19937 m_engine; + }; + + class RNGMgr : public BaseManager + { + + public: + + + RNGMgr( FrameworkPtr pFw ); + virtual ~RNGMgr() = default; + + RNGMgr( const RNGMgr& pRNGMgr ) = delete; + RNGMgr& operator=( const RNGMgr& pRNGMgr ) = delete; + + /*! + * @brief Creates a RNG with specified parameters for multiple uses + * @tparam Numeric type to be used for the generator + * @param Minimum value possible for the random value + * @param Maximum value possible for the random value + * @return Random number generator object + */ + template< typename T, typename = typename std::enable_if< std::is_arithmetic< T >::value, T >::type > + RandGenerator< T > getRandGenerator( T minRange, T maxRange ) + { + return RandGenerator< T >( minRange, maxRange ); + } + + private: + + template< std::size_t STATE_SIZE > + std::unique_ptr< std::seed_seq > engineSeed() + { + std::array< uint32_t, STATE_SIZE > seedArray; + std::random_device rd; + + std::generate_n( seedArray.data(), seedArray.size(), std::ref( rd ) ); + auto pSeq = std::make_unique< std::seed_seq >( std::begin( seedArray ), std::end( seedArray ) ); + + return pSeq; + } + + std::mt19937 m_engine; + }; + +} + +#endif // SAPPHIRE_RNGMGR_H diff --git a/src/world/Network/GameConnection.cpp b/src/world/Network/GameConnection.cpp index 13523dcd..006ee48b 100644 --- a/src/world/Network/GameConnection.cpp +++ b/src/world/Network/GameConnection.cpp @@ -385,6 +385,7 @@ void Sapphire::Network::GameConnection::handlePackets( const Sapphire::Network:: const std::vector< Sapphire::Network::Packets::FFXIVARR_PACKET_RAW >& packetData ) { auto pServerZone = m_pFw->get< World::ServerMgr >(); + // if a session is set, update the last time it recieved a game packet if( m_pSession ) m_pSession->updateLastDataTime(); @@ -427,7 +428,7 @@ void Sapphire::Network::GameConnection::handlePackets( const Sapphire::Network:: auto pe = std::make_shared< FFXIVRawPacket >( 0x07, 0x18, 0, 0 ); *( unsigned int* ) ( &pe->data()[ 0 ] ) = 0xE0037603; - *( unsigned int* ) ( &pe->data()[ 4 ] ) = static_cast< uint32_t >( time( nullptr ) ); + *( unsigned int* ) ( &pe->data()[ 4 ] ) = Sapphire::Util::getTimeSeconds(); sendSinglePacket( pe ); // main connection, assinging it to the session diff --git a/src/world/Network/Handlers/PacketHandlers.cpp b/src/world/Network/Handlers/PacketHandlers.cpp index fecf8ed9..956b1d9e 100644 --- a/src/world/Network/Handlers/PacketHandlers.cpp +++ b/src/world/Network/Handlers/PacketHandlers.cpp @@ -14,10 +14,8 @@ #include "Network/GameConnection.h" -#include "Manager/TerritoryMgr.h" #include "Territory/Zone.h" #include "Territory/HousingZone.h" -#include "Manager/HousingMgr.h" #include "Territory/Land.h" #include "Territory/ZonePosition.h" #include "Territory/House.h" @@ -37,6 +35,9 @@ #include "Manager/DebugCommandMgr.h" #include "Manager/EventMgr.h" #include "Manager/MarketMgr.h" +#include "Manager/TerritoryMgr.h" +#include "Manager/HousingMgr.h" +#include "Manager/RNGMgr.h" #include "Action/Action.h" #include "Action/ActionTeleport.h" @@ -440,7 +441,7 @@ void Sapphire::Network::GameConnection::pingHandler( FrameworkPtr pFw, queueOutPacket( std::make_shared< Server::PingPacket >( player, packet.data().timestamp ) ); - player.setLastPing( static_cast< uint32_t >( time( nullptr ) ) ); + player.setLastPing( Sapphire::Util::getTimeSeconds() ); } diff --git a/src/world/ServerMgr.cpp b/src/world/ServerMgr.cpp index 0212af09..3de61f73 100644 --- a/src/world/ServerMgr.cpp +++ b/src/world/ServerMgr.cpp @@ -40,6 +40,7 @@ #include "Manager/EventMgr.h" #include "Manager/ItemMgr.h" #include "Manager/MarketMgr.h" +#include "Manager/RNGMgr.h" using namespace Sapphire::World::Manager; @@ -205,6 +206,7 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) auto pInventoryMgr = std::make_shared< Manager::InventoryMgr >( framework() ); auto pEventMgr = std::make_shared< Manager::EventMgr >( framework() ); auto pItemMgr = std::make_shared< Manager::ItemMgr >( framework() ); + auto pRNGMgr = std::make_shared< Manager::RNGMgr >( framework() ); framework()->set< DebugCommandMgr >( pDebugCom ); framework()->set< Manager::PlayerMgr >( pPlayerMgr ); @@ -212,6 +214,7 @@ void Sapphire::World::ServerMgr::run( int32_t argc, char* argv[] ) framework()->set< Manager::InventoryMgr >( pInventoryMgr ); framework()->set< Manager::EventMgr >( pEventMgr ); framework()->set< Manager::ItemMgr >( pItemMgr ); + framework()->set< Manager::RNGMgr >( pRNGMgr ); Logger::info( "World server running on {0}:{1}", m_ip, m_port ); @@ -256,7 +259,7 @@ void Sapphire::World::ServerMgr::mainLoop() auto currTime = Util::getTimeSeconds(); - pTeriMgr->updateTerritoryInstances( static_cast< uint32_t >( currTime ) ); + pTeriMgr->updateTerritoryInstances( currTime ); pScriptMgr->update(); diff --git a/src/world/Session.cpp b/src/world/Session.cpp index 682fdb45..6f49d45f 100644 --- a/src/world/Session.cpp +++ b/src/world/Session.cpp @@ -206,7 +206,7 @@ void Sapphire::World::Session::update() // SESSION LOGIC m_pPlayer->update( Util::getTimeMs() ); - if( ( static_cast< uint32_t >( Util::getTimeSeconds() ) - static_cast< uint32_t >( getLastSqlTime() ) ) > 10 ) + if( Util::getTimeSeconds() - static_cast< uint32_t >( getLastSqlTime() ) > 10 ) { updateLastSqlTime(); m_pPlayer->updateSql(); diff --git a/src/world/Session.h b/src/world/Session.h index d51122be..97d51241 100644 --- a/src/world/Session.h +++ b/src/world/Session.h @@ -56,9 +56,9 @@ namespace Sapphire::World Entity::PlayerPtr m_pPlayer; - int64_t m_lastDataTime; + uint32_t m_lastDataTime; - int64_t m_lastSqlTime; + uint32_t m_lastSqlTime; bool m_isValid; bool m_isReplaying; diff --git a/src/world/Territory/Housing/HousingInteriorTerritory.cpp b/src/world/Territory/Housing/HousingInteriorTerritory.cpp index 1121e268..4d0b436e 100644 --- a/src/world/Territory/Housing/HousingInteriorTerritory.cpp +++ b/src/world/Territory/Housing/HousingInteriorTerritory.cpp @@ -39,7 +39,7 @@ Sapphire::World::Territory::Housing::HousingInteriorTerritory::HousingInteriorTe Zone( territoryTypeId, guId, internalName, contentName, pFw ), m_landIdent( ident ) { - m_lastActivityTime = static_cast< uint32_t >( Util::getTimeSeconds() ); + m_lastActivityTime = Util::getTimeSeconds(); } Housing::HousingInteriorTerritory::~HousingInteriorTerritory() = default; diff --git a/src/world/Territory/Land.cpp b/src/world/Territory/Land.cpp index 15411d24..a0cf5cbc 100644 --- a/src/world/Territory/Land.cpp +++ b/src/world/Territory/Land.cpp @@ -30,7 +30,7 @@ Sapphire::Land::Land( uint16_t territoryTypeId, uint8_t wardNum, uint8_t landId, Sapphire::Data::HousingLandSetPtr info, FrameworkPtr pFw ) : m_currentPrice( 0 ), m_minPrice( 0 ), - m_nextDrop( static_cast< uint32_t >( Util::getTimeSeconds() ) + 21600 ), + m_nextDrop( Util::getTimeSeconds() + 21600 ), m_ownerId( 0 ), m_landSetId( landSetId ), m_landInfo( info ), @@ -185,7 +185,7 @@ uint64_t Sapphire::Land::getOwnerId() uint32_t Sapphire::Land::getDevaluationTime() { - return m_nextDrop - static_cast< uint32_t >( Util::getTimeSeconds() ); + return m_nextDrop - Util::getTimeSeconds(); } void Sapphire::Land::setCurrentPrice( uint32_t currentPrice ) diff --git a/src/world/Territory/Zone.cpp b/src/world/Territory/Zone.cpp index 3ad04d39..136f5f5e 100644 --- a/src/world/Territory/Zone.cpp +++ b/src/world/Territory/Zone.cpp @@ -39,6 +39,8 @@ #include "Zone.h" #include "Framework.h" +#include + using namespace Sapphire::Common; using namespace Sapphire::Network::Packets; using namespace Sapphire::Network::Packets::Server; @@ -159,7 +161,7 @@ void Sapphire::Zone::loadCellCache() Weather Sapphire::Zone::getNextWeather() { - uint32_t unixTime = static_cast< uint32_t >( Util::getTimeSeconds() ); + uint32_t unixTime = Util::getTimeSeconds(); // Get Eorzea hour for weather start uint32_t bell = unixTime / 175; // Do the magic 'cause for calculations 16:00 is 0, 00:00 is 8 and 08:00 is 16 @@ -381,9 +383,8 @@ void Sapphire::Zone::updateBNpcs( int64_t tickCount ) { if( ( tickCount - m_lastMobUpdate ) > 250 ) { - m_lastMobUpdate = tickCount; - uint32_t currTime = static_cast< uint32_t >( time( nullptr ) ); + uint32_t currTime = Sapphire::Util::getTimeSeconds(); /*for( auto it3 = m_BattleNpcDeadMap.begin(); it3 != m_BattleNpcDeadMap.end(); ++it3 ) { @@ -812,9 +813,8 @@ bool Sapphire::Zone::loadSpawnGroups() void Sapphire::Zone::updateSpawnPoints() { - std::random_device rd; - std::mt19937 mt( rd() ); - std::uniform_real_distribution< float > dist( 0.0, PI * 2 ); + auto pRNGMgr = m_pFw->get< World::Manager::RNGMgr >(); + auto rng = pRNGMgr->getRandGenerator< float >( 0.f, PI * 2 ); for( auto& group : m_spawnGroups ) { @@ -837,7 +837,7 @@ void Sapphire::Zone::updateSpawnPoints() point->getPosX(), point->getPosY(), point->getPosZ(), - dist( mt ), + rng.next(), group.getLevel(), group.getMaxHp(), shared_from_this(), m_pFw ); point->setLinkedBNpc( pBNpc );