Synchronized random arena item in network game

This commit is contained in:
Benau 2018-07-14 08:11:35 +08:00
parent 9fbfe0588f
commit c72db7099d
6 changed files with 31 additions and 16 deletions

View File

@ -32,7 +32,6 @@
#include "tracks/arena_graph.hpp" #include "tracks/arena_graph.hpp"
#include "tracks/arena_node.hpp" #include "tracks/arena_node.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "utils/random_generator.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
#include <IMesh.h> #include <IMesh.h>
@ -49,7 +48,7 @@ std::vector<scene::IMesh *> ItemManager::m_item_lowres_mesh;
std::vector<video::SColorf> ItemManager::m_glow_color; std::vector<video::SColorf> ItemManager::m_glow_color;
bool ItemManager::m_disable_item_collection = false; bool ItemManager::m_disable_item_collection = false;
ItemManager * ItemManager::m_item_manager = NULL; ItemManager * ItemManager::m_item_manager = NULL;
std::mt19937 ItemManager::m_random_engine;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Creates one instance of the item manager. */ /** Creates one instance of the item manager. */
@ -577,11 +576,11 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
invalid_location.push_back(node); invalid_location.push_back(node);
} }
RandomGenerator random;
const unsigned int ALL_NODES = ag->getNumNodes(); const unsigned int ALL_NODES = ag->getNumNodes();
const unsigned int MIN_DIST = int(sqrt(ALL_NODES)); const unsigned int MIN_DIST = int(sqrt(ALL_NODES));
const unsigned int TOTAL_ITEM = MIN_DIST / 2; const unsigned int TOTAL_ITEM = MIN_DIST / 2;
std::vector<uint32_t> random_numbers;
Log::info("[ItemManager]","Creating %d random items for arena", TOTAL_ITEM); Log::info("[ItemManager]","Creating %d random items for arena", TOTAL_ITEM);
for (unsigned int i = 0; i < TOTAL_ITEM; i++) for (unsigned int i = 0; i < TOTAL_ITEM; i++)
{ {
@ -595,8 +594,9 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
"Use default item location."); "Use default item location.");
return false; return false;
} }
uint32_t number = m_random_engine();
const int node = random.get(ALL_NODES); Log::debug("[ItemManager]", "%u from random engine.", number);
const int node = number % ALL_NODES;
// Check if tried // Check if tried
std::vector<int>::iterator it = std::find(invalid_location.begin(), std::vector<int>::iterator it = std::find(invalid_location.begin(),
@ -622,6 +622,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
{ {
chosen_node = node; chosen_node = node;
invalid_location.push_back(node); invalid_location.push_back(node);
random_numbers.push_back(number);
break; break;
} }
else else
@ -636,6 +637,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
used_location.erase(used_location.begin()); 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 // Hard-coded ratio for now
const int BONUS_BOX = 4; const int BONUS_BOX = 4;
@ -644,7 +646,7 @@ bool ItemManager::randomItemsForArena(const AlignedArray<btTransform>& pos)
for (unsigned int i = 0; i < TOTAL_ITEM; i++) 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 : ItemState::ItemType type = (j > BONUS_BOX ? ItemState::ITEM_BONUS_BOX :
j > NITRO_BIG ? ItemState::ITEM_NITRO_BIG : j > NITRO_BIG ? ItemState::ITEM_NITRO_BIG :
j > NITRO_SMALL ? ItemState::ITEM_NITRO_SMALL : ItemState::ITEM_BANANA); j > NITRO_SMALL ? ItemState::ITEM_NITRO_SMALL : ItemState::ITEM_BANANA);

View File

@ -31,6 +31,7 @@
#include <assert.h> #include <assert.h>
#include <map> #include <map>
#include <memory> #include <memory>
#include <random>
#include <string> #include <string>
#include <vector> #include <vector>
@ -56,6 +57,7 @@ private:
/** Disable item collection (for debugging purposes). */ /** Disable item collection (for debugging purposes). */
static bool m_disable_item_collection; static bool m_disable_item_collection;
static std::mt19937 m_random_engine;
protected: protected:
/** The instance of ItemManager while a race is on. */ /** The instance of ItemManager while a race is on. */
static ItemManager *m_item_manager; static ItemManager *m_item_manager;
@ -64,6 +66,11 @@ public:
static void removeTextures(); static void removeTextures();
static void create(); static void create();
static void destroy(); 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 /** Disable item collection, useful to test client mispreditions or
* client/server disagreements. */ * client/server disagreements. */
@ -115,7 +122,6 @@ protected:
virtual ~ItemManager(); virtual ~ItemManager();
public: public:
virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz, virtual Item* placeItem (ItemState::ItemType type, const Vec3& xyz,
const Vec3 &normal); const Vec3 &normal);
virtual Item* dropNewItem (ItemState::ItemType type, virtual Item* dropNewItem (ItemState::ItemType type,

View File

@ -87,6 +87,8 @@ void GameSetup::loadWorld()
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER || if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER ||
race_manager->getMinorMode() == RaceManager::MINOR_MODE_3_STRIKES) 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); race_manager->setReverseTrack(false);
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER) if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER)
{ {
@ -97,6 +99,7 @@ void GameSetup::loadWorld()
} }
race_manager->startSingleRace(m_tracks.back(), -1, race_manager->startSingleRace(m_tracks.back(), -1,
false/*from_overworld*/); false/*from_overworld*/);
UserConfigParams::m_random_arena_item = prev_val;
} }
else else
{ {

View File

@ -25,6 +25,7 @@
#include "guiengine/message_queue.hpp" #include "guiengine/message_queue.hpp"
#include "guiengine/screen_keyboard.hpp" #include "guiengine/screen_keyboard.hpp"
#include "input/device_manager.hpp" #include "input/device_manager.hpp"
#include "items/item_manager.hpp"
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
#include "modes/linear_world.hpp" #include "modes/linear_world.hpp"
#include "network/crypto.hpp" #include "network/crypto.hpp"
@ -241,6 +242,8 @@ void ClientLobby::addAllPlayers(Event* event)
m_game_setup->addPlayer(player); m_game_setup->addPlayer(player);
players.push_back(player); players.push_back(player);
} }
uint32_t random_seed = data.getUInt32();
ItemManager::updateRandomSeed(random_seed);
configRemoteKart(players); configRemoteKart(players);
loadWorld(); loadWorld();
// Switch to assign mode in case a player hasn't chosen any karts // 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 //I18N: Vote message in network game from a player
vote_msg = _("Track: %s,\n" 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); track_readable, lap, rev == 1 ? yes : no);
} }
} }

View File

@ -19,6 +19,7 @@
#include "network/protocols/server_lobby.hpp" #include "network/protocols/server_lobby.hpp"
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "items/item_manager.hpp"
#include "karts/kart_properties_manager.hpp" #include "karts/kart_properties_manager.hpp"
#include "modes/linear_world.hpp" #include "modes/linear_world.hpp"
#include "network/crypto.hpp" #include "network/crypto.hpp"
@ -409,6 +410,9 @@ void ServerLobby::asynchronousUpdate()
} }
load_world->encodeString(player->getKartName()); load_world->encodeString(player->getKartName());
} }
uint32_t random_seed = (uint32_t)StkTime::getTimeSinceEpoch();
ItemManager::updateRandomSeed(random_seed);
load_world->addUInt32(random_seed);
configRemoteKart(players); configRemoteKart(players);
// Reset for next state usage // Reset for next state usage

View File

@ -1111,13 +1111,6 @@ void Track::convertTrackToBullet(scene::ISceneNode *node)
void Track::loadMinimap() void Track::loadMinimap()
{ {
#ifndef SERVER_ONLY #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. //Create the minimap resizing it as necessary.
m_mini_map_size = World::getWorld()->getRaceGUI()->getMiniMapSize(); 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()) if (NetworkConfig::get()->isNetworking())
NetworkItemManager::create(); NetworkItemManager::create();
else else
{
// Seed random engine locally
ItemManager::updateRandomSeed((uint32_t)StkTime::getTimeSinceEpoch());
ItemManager::create(); ItemManager::create();
}
// Set the default start positions. Node that later the default // Set the default start positions. Node that later the default
// positions can still be overwritten. // positions can still be overwritten.