diff --git a/application/application.cpp b/application/application.cpp index 49d493c2..1542e3d4 100644 --- a/application/application.cpp +++ b/application/application.cpp @@ -321,7 +321,7 @@ int eu07_application::init(int Argc, char *Argv[]) } if (!Global.random_seed) - Global.random_seed = clock_seed(); + Global.random_seed = true_random_seed(); Global.random_engine.seed(Global.random_seed); // configure the OS console according to Globals.ShowSystemConsole. @@ -1432,7 +1432,7 @@ int eu07_application::init_data() int eu07_application::init_modes() { - Global.local_random_engine.seed(clock_seed()); + Global.local_random_engine.seed(true_random_seed()); if ((!Global.network_servers.empty() || Global.network_client) && Global.SceneryFile.empty()) { diff --git a/utilities/utilities.cpp b/utilities/utilities.cpp index 1f5f0682..f5377619 100644 --- a/utilities/utilities.cpp +++ b/utilities/utilities.cpp @@ -138,10 +138,20 @@ int Random(int min, int max) return dist(Global.random_engine); } -std::uint32_t clock_seed() +std::uint64_t true_random_seed() { - static std::atomic nth{0}; - return static_cast(std::time({})) + nth.fetch_add(1, std::memory_order_relaxed); + try + { + std::random_device rd; + if (rd.entropy() > 0.0) + { + std::uint32_t high = rd(); + std::uint32_t low = rd(); + return (high << 32) | low; + } + } + catch (...) {} + return static_cast(std::chrono::high_resolution_clock::now().time_since_epoch().count()); } std::uint32_t seed_of(std::string const &Text) @@ -161,12 +171,11 @@ std::uint32_t seed_of(std::string const &Text) std::string generate_uuid_v4() { - static thread_local std::mt19937 generator{clock_seed()}; std::uniform_int_distribution dist(0, 255); std::array bytes; for (auto &b : bytes) - b = static_cast(dist(generator)); + b = static_cast(dist(Global.random_engine)); // UUID v4 (RFC 4122) bytes[6] = bytes[6] & 0x0F | 0x40; diff --git a/utilities/utilities.h b/utilities/utilities.h index d013fade..70cf1c07 100644 --- a/utilities/utilities.h +++ b/utilities/utilities.h @@ -63,9 +63,10 @@ inline long Round(double const f) double Random(double a, double b); int Random(int min, int max); -// Seed for the random engines: the clock, plus a counter so two engines seeded in -// the same second do not come out the same. -std::uint32_t clock_seed(); +/// @author lxvia +/// @brief Returns a random seed from the system's entropy source, if available. Otherwise, falls back to a clock-based seed. +/// @return A random seed as 64 bit unsigned integer +std::uint64_t true_random_seed(); // The seed a word stands for. A number is taken as it is written; anything else is // hashed the way Java's String.hashCode does it, so the same word gives the same diff --git a/utilities/uuid.hpp b/utilities/uuid.hpp index ff32f5d2..5eeb89f4 100644 --- a/utilities/uuid.hpp +++ b/utilities/uuid.hpp @@ -7,6 +7,7 @@ #include #include #include "utilities/utilities.h" +#include "utilities/Globals.h" class UID { public: @@ -14,10 +15,9 @@ public: static UID random() { - static thread_local std::mt19937_64 gen{clock_seed()}; UID u; - uint64_t a = gen(); - uint64_t b = gen(); + uint64_t a = Global.random_engine(); + uint64_t b = Global.random_engine(); for (int i = 0; i < 8; ++i) u.bytes[i] = uint8_t(a >> (i * 8) & 0xFF); for (int i = 0; i < 8; ++i) u.bytes[8 + i] = uint8_t(b >> (i * 8) & 0xFF);