diff --git a/src/world/Manager/DebugCommandMgr.cpp b/src/world/Manager/DebugCommandMgr.cpp index 61613421..115cd714 100644 --- a/src/world/Manager/DebugCommandMgr.cpp +++ b/src/world/Manager/DebugCommandMgr.cpp @@ -45,6 +45,7 @@ #include "WorldServer.h" #include "Session.h" +#include using namespace Sapphire::Network; using namespace Sapphire::Network::Packets; @@ -177,6 +178,15 @@ void DebugCommandMgr::set( char* data, Entity::Player& player, std::shared_ptr< if( ( ( subCommand == "pos" ) || ( subCommand == "posr" ) ) && ( params != "" ) ) { + auto& rngMgr = Common::Service< RNGMgr >::ref(); + auto state = rngMgr.getRandGenerator( 0, 10 ); + auto arr = state.nextCount< 10 >(); + + for( auto val : arr ) + { + Logger::info( std::to_string( val ) ); + } + int32_t posX; int32_t posY; int32_t posZ; diff --git a/src/world/Manager/RNGMgr.h b/src/world/Manager/RNGMgr.h index e7661624..57e9570c 100644 --- a/src/world/Manager/RNGMgr.h +++ b/src/world/Manager/RNGMgr.h @@ -8,6 +8,7 @@ #include #include #include +#include namespace Sapphire::World::Manager { @@ -19,24 +20,47 @@ namespace Sapphire::World::Manager { public: RandGenerator( std::shared_ptr< std::mt19937 > pEngine, T minRange = std::numeric_limits< T >::min(), T maxRange = std::numeric_limits< T >::max() ) - : m_engine( pEngine ), m_dist( minRange, maxRange ) + : m_engine( pEngine ), m_fpuDist( minRange, maxRange ), m_intDist( minRange, maxRange ) { } + // returns a single value for T type on set ranges, deducing real or integer distribution from given numeric type T next() { - return m_dist( *m_engine ); + if constexpr( std::is_integral< T >::value ) + return m_intDist( *m_engine ); + + return m_fpuDist( *m_engine ); } - private: - std::uniform_real_distribution< T > m_dist; + // returns an array of size nSize with values type T on set ranges, deducing real or integer distribution from given numeric type + template< std::size_t nSize > + const std::array< T, nSize > nextCount() + { + std::array< T, nSize > _valPush; + + for( auto i = 0; i < nSize; ++i ) + { + if constexpr( std::is_integral< T >::value ) + _valPush[ i ] = ( m_intDist( *m_engine ) ); + else + _valPush[ i ] = ( m_fpuDist( *m_engine ) ); + } + + return _valPush; + } + + protected: + std::uniform_real_distribution<> m_fpuDist; + std::uniform_int_distribution<> m_intDist; std::shared_ptr< std::mt19937 > m_engine; }; class RNGMgr { public: + // Constructs a manager to supply states for random integer and float distribution using a Mersenne Twister engine RNGMgr() { m_engine = std::make_shared< std::mt19937 >( *engineSeed< std::mt19937::state_size >() ); @@ -48,7 +72,7 @@ namespace Sapphire::World::Manager RNGMgr& operator=( const RNGMgr& pRNGMgr ) = delete; /*! - * @brief Creates a RNG with specified parameters for multiple uses + * @brief Creates a state 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 @@ -60,6 +84,17 @@ namespace Sapphire::World::Manager return RandGenerator< T >( m_engine, minRange, maxRange ); } + /*! + * @brief Creates a state with only typed data arithmetic range + * @tparam Numeric type to be used for the generator and range (::min(), ::max() of numeric type) + * @return Random number generator object + */ + template< typename T, typename = typename std::enable_if< std::is_arithmetic< T >::value, T >::type > + RandGenerator< T > getRandGenerator() + { + return RandGenerator< T >( m_engine ); + } + private: template< std::size_t STATE_SIZE > @@ -70,6 +105,11 @@ namespace Sapphire::World::Manager std::array< uint32_t, STATE_SIZE > seedArray; std::random_device rd; + // check if kernel can supply sufficiently non-deterministic output + + if( rd.entropy() == 0.f ) + Logger::error( "Kernel random device entropy reported zero - Random number generator may be poor quality" ); + std::generate_n( seedArray.data(), seedArray.size(), std::ref( rd ) ); auto pSeq = std::make_unique< std::seed_seq >( std::begin( seedArray ), std::end( seedArray ) ); diff --git a/src/world/WorldServer.cpp b/src/world/WorldServer.cpp index 1b06ac5c..5c49ebd3 100644 --- a/src/world/WorldServer.cpp +++ b/src/world/WorldServer.cpp @@ -163,6 +163,9 @@ void WorldServer::run( int32_t argc, char* argv[] ) } Common::Service< Db::DbWorkerPool< Db::ZoneDbConnection > >::set( pDb ); + auto pRNGMgr = std::make_shared< Manager::RNGMgr >(); + Common::Service< Manager::RNGMgr >::set( pRNGMgr ); + Logger::info( "Loading all players" ); if( !loadPlayers() ) { @@ -193,9 +196,6 @@ void WorldServer::run( int32_t argc, char* argv[] ) auto pNaviMgr = std::make_shared< Manager::NaviMgr >(); Common::Service< Manager::NaviMgr >::set( pNaviMgr ); - auto pRNGMgr = std::make_shared< Manager::RNGMgr >(); - Common::Service< Manager::RNGMgr >::set( pRNGMgr ); - Logger::info( "TerritoryMgr: Setting up zones" ); auto pTeriMgr = std::make_shared< Manager::TerritoryMgr >(); auto pHousingMgr = std::make_shared< Manager::HousingMgr >();