diff --git a/src/items/item_manager.cpp b/src/items/item_manager.cpp index 80862f7f5..4fcf76c8e 100644 --- a/src/items/item_manager.cpp +++ b/src/items/item_manager.cpp @@ -32,7 +32,6 @@ #include "tracks/arena_graph.hpp" #include "tracks/arena_node.hpp" #include "tracks/track.hpp" -#include "utils/random_generator.hpp" #include "utils/string_utils.hpp" #include @@ -49,7 +48,7 @@ std::vector ItemManager::m_item_lowres_mesh; std::vector ItemManager::m_glow_color; bool ItemManager::m_disable_item_collection = false; ItemManager * ItemManager::m_item_manager = NULL; - +std::mt19937 ItemManager::m_random_engine; //----------------------------------------------------------------------------- /** Creates one instance of the item manager. */ @@ -577,11 +576,11 @@ bool ItemManager::randomItemsForArena(const AlignedArray& pos) invalid_location.push_back(node); } - RandomGenerator random; const unsigned int ALL_NODES = ag->getNumNodes(); const unsigned int MIN_DIST = int(sqrt(ALL_NODES)); const unsigned int TOTAL_ITEM = MIN_DIST / 2; + std::vector random_numbers; Log::info("[ItemManager]","Creating %d random items for arena", TOTAL_ITEM); for (unsigned int i = 0; i < TOTAL_ITEM; i++) { @@ -595,8 +594,9 @@ bool ItemManager::randomItemsForArena(const AlignedArray& pos) "Use default item location."); return false; } - - const int node = random.get(ALL_NODES); + uint32_t number = m_random_engine(); + Log::debug("[ItemManager]", "%u from random engine.", number); + const int node = number % ALL_NODES; // Check if tried std::vector::iterator it = std::find(invalid_location.begin(), @@ -622,6 +622,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray& pos) { chosen_node = node; invalid_location.push_back(node); + random_numbers.push_back(number); break; } else @@ -635,7 +636,8 @@ bool ItemManager::randomItemsForArena(const AlignedArray& pos) for (unsigned int i = 0; i < pos.size(); i++) used_location.erase(used_location.begin()); - assert (used_location.size() == TOTAL_ITEM); + assert(used_location.size() == TOTAL_ITEM); + assert(random_numbers.size() == TOTAL_ITEM); // Hard-coded ratio for now const int BONUS_BOX = 4; @@ -644,7 +646,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray& pos) for (unsigned int i = 0; i < TOTAL_ITEM; i++) { - const int j = random.get(10); + const unsigned j = random_numbers[i] % 10; ItemState::ItemType type = (j > BONUS_BOX ? ItemState::ITEM_BONUS_BOX : j > NITRO_BIG ? ItemState::ITEM_NITRO_BIG : j > NITRO_SMALL ? ItemState::ITEM_NITRO_SMALL : ItemState::ITEM_BANANA); diff --git a/src/items/item_manager.hpp b/src/items/item_manager.hpp index e5473e466..53924b5bc 100644 --- a/src/items/item_manager.hpp +++ b/src/items/item_manager.hpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -56,6 +57,7 @@ private: /** Disable item collection (for debugging purposes). */ static bool m_disable_item_collection; + static std::mt19937 m_random_engine; protected: /** The instance of ItemManager while a race is on. */ static ItemManager *m_item_manager; @@ -64,6 +66,11 @@ public: static void removeTextures(); static void create(); static void destroy(); + static void updateRandomSeed(uint32_t seed_number) + { + m_random_engine.seed(seed_number); + } // updateRandomSeed + // ------------------------------------------------------------------------ /** Disable item collection, useful to test client mispreditions or * client/server disagreements. */ @@ -115,7 +122,6 @@ protected: virtual ~ItemManager(); public: - virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz, const Vec3 &normal); virtual Item* dropNewItem (ItemState::ItemType type, diff --git a/src/network/game_setup.cpp b/src/network/game_setup.cpp index 0e68072d8..fbfa145e7 100644 --- a/src/network/game_setup.cpp +++ b/src/network/game_setup.cpp @@ -87,6 +87,8 @@ void GameSetup::loadWorld() if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER || race_manager->getMinorMode() == RaceManager::MINOR_MODE_3_STRIKES) { + bool prev_val = UserConfigParams::m_random_arena_item; + UserConfigParams::m_random_arena_item = m_reverse; race_manager->setReverseTrack(false); if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) { @@ -97,6 +99,7 @@ void GameSetup::loadWorld() } race_manager->startSingleRace(m_tracks.back(), -1, false/*from_overworld*/); + UserConfigParams::m_random_arena_item = prev_val; } else { diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index 997c9864c..06f49cc48 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -25,6 +25,7 @@ #include "guiengine/message_queue.hpp" #include "guiengine/screen_keyboard.hpp" #include "input/device_manager.hpp" +#include "items/item_manager.hpp" #include "karts/kart_properties_manager.hpp" #include "modes/linear_world.hpp" #include "network/crypto.hpp" @@ -241,6 +242,8 @@ void ClientLobby::addAllPlayers(Event* event) m_game_setup->addPlayer(player); players.push_back(player); } + uint32_t random_seed = data.getUInt32(); + ItemManager::updateRandomSeed(random_seed); configRemoteKart(players); loadWorld(); // Switch to assign mode in case a player hasn't chosen any karts @@ -427,7 +430,7 @@ void ClientLobby::displayPlayerVote(Event* event) { //I18N: Vote message in network game from a player vote_msg = _("Track: %s,\n" - "maximum time: %d,random item location: %s", + "maximum time: %d,\nrandom item location: %s", track_readable, lap, rev == 1 ? yes : no); } } diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 8c21487a8..bfa3242d3 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -19,6 +19,7 @@ #include "network/protocols/server_lobby.hpp" #include "config/user_config.hpp" +#include "items/item_manager.hpp" #include "karts/kart_properties_manager.hpp" #include "modes/linear_world.hpp" #include "network/crypto.hpp" @@ -409,6 +410,9 @@ void ServerLobby::asynchronousUpdate() } load_world->encodeString(player->getKartName()); } + uint32_t random_seed = (uint32_t)StkTime::getTimeSinceEpoch(); + ItemManager::updateRandomSeed(random_seed); + load_world->addUInt32(random_seed); configRemoteKart(players); // Reset for next state usage diff --git a/src/tracks/track.cpp b/src/tracks/track.cpp index a437169d9..82bf23c50 100644 --- a/src/tracks/track.cpp +++ b/src/tracks/track.cpp @@ -1111,13 +1111,6 @@ void Track::convertTrackToBullet(scene::ISceneNode *node) void Track::loadMinimap() { #ifndef SERVER_ONLY - //Check whether the hardware can do nonsquare or - // non power-of-two textures - video::IVideoDriver* const video_driver = irr_driver->getVideoDriver(); - bool nonpower = false; //video_driver->queryFeature(video::EVDF_TEXTURE_NPOT); - bool nonsquare = - video_driver->queryFeature(video::EVDF_TEXTURE_NSQUARE); - //Create the minimap resizing it as necessary. m_mini_map_size = World::getWorld()->getRaceGUI()->getMiniMapSize(); @@ -1808,7 +1801,11 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id) if (NetworkConfig::get()->isNetworking()) NetworkItemManager::create(); else + { + // Seed random engine locally + ItemManager::updateRandomSeed((uint32_t)StkTime::getTimeSinceEpoch()); ItemManager::create(); + } // Set the default start positions. Node that later the default // positions can still be overwritten.