Fix #3589
This commit is contained in:
parent
073708c97e
commit
dba713f72e
@ -526,6 +526,7 @@ void Powerup::hitBonusBox(const ItemState &item_state)
|
||||
// (1) The item id
|
||||
// (2) The time
|
||||
// (3) The position of the kart
|
||||
// (4) An extra random 64bit integer
|
||||
// Using (1) means that not all boxes at a certain time for a kart
|
||||
// will give the same box. Using (2) means that the item will
|
||||
// change over time - even if the next item is displayed, it
|
||||
@ -533,7 +534,8 @@ void Powerup::hitBonusBox(const ItemState &item_state)
|
||||
// of the time component it will also be difficult to get the
|
||||
// item at the right time. Using (3) adds another cheat-prevention
|
||||
// layer: even if a cheater is waiting for the right sequence
|
||||
// of items, if he is overtaken the sequence will change.
|
||||
// of items, if he is overtaken the sequence will change, using (4)
|
||||
// to avoid same item sequence when starting
|
||||
//
|
||||
// In order to increase the probability of correct client prediction
|
||||
// in networking (where there might be 1 or 2 frames difference
|
||||
@ -544,7 +546,8 @@ void Powerup::hitBonusBox(const ItemState &item_state)
|
||||
// number to spread the random values across the (typically 200)
|
||||
// weights used in the PowerupManager - same for the position.
|
||||
uint64_t random_number = item_state.getItemId() * 31 +
|
||||
world->getTicksSinceStart() / 10 + position * 23;
|
||||
world->getTicksSinceStart() / 10 + position * 23 +
|
||||
powerup_manager->getRandomSeed();
|
||||
|
||||
// Use this random number as a seed of a PRNG (based on the one in
|
||||
// bullet's btSequentialImpulseConstraintSolver) to avoid getting
|
||||
|
@ -43,6 +43,7 @@ PowerupManager* powerup_manager=0;
|
||||
/** The constructor initialises everything to zero. */
|
||||
PowerupManager::PowerupManager()
|
||||
{
|
||||
m_random_seed.store(0);
|
||||
for(int i=0; i<POWERUP_MAX; i++)
|
||||
{
|
||||
m_all_meshes[i] = NULL;
|
||||
|
@ -19,11 +19,13 @@
|
||||
#ifndef HEADER_POWERUPMANAGER_HPP
|
||||
#define HEADER_POWERUPMANAGER_HPP
|
||||
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/leak_check.hpp"
|
||||
#include "utils/no_copy.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include "btBulletDynamicsCommon.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -151,6 +153,11 @@ private:
|
||||
WeightsData m_current_item_weights;
|
||||
|
||||
PowerupType getPowerupType(const std::string &name) const;
|
||||
|
||||
/** Seed for random powerup, for local game it will use a random number,
|
||||
* for network games it will use the start time from server. */
|
||||
std::atomic<uint64_t> m_random_seed;
|
||||
|
||||
public:
|
||||
static void unitTesting();
|
||||
|
||||
@ -171,6 +178,11 @@ public:
|
||||
/** Returns the mesh for a certain powerup.
|
||||
* \param type Mesh type for which the model is returned. */
|
||||
irr::scene::IMesh *getMesh(int type) const {return m_all_meshes[type];}
|
||||
// ------------------------------------------------------------------------
|
||||
uint64_t getRandomSeed() const { return m_random_seed.load(); }
|
||||
// ------------------------------------------------------------------------
|
||||
void setRandomSeed(uint64_t seed) { m_random_seed.store(seed); }
|
||||
|
||||
}; // class PowerupManager
|
||||
|
||||
extern PowerupManager* powerup_manager;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "guiengine/screen_keyboard.hpp"
|
||||
#include "input/device_manager.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
#include "network/crypto.hpp"
|
||||
@ -816,6 +817,7 @@ void ClientLobby::startGame(Event* event)
|
||||
{
|
||||
World::getWorld()->setPhase(WorldStatus::SERVER_READY_PHASE);
|
||||
uint64_t start_time = event->data().getUInt64();
|
||||
powerup_manager->setRandomSeed(start_time);
|
||||
joinStartGameThread();
|
||||
m_start_game_thread = std::thread([start_time, this]()
|
||||
{
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/controller/player_controller.hpp"
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
@ -2369,6 +2370,7 @@ void ServerLobby::configPeersStartTime()
|
||||
// Start up time will be after 2500ms, so even if this packet is sent late
|
||||
// (due to packet loss), the start time will still ahead of current time
|
||||
uint64_t start_time = STKHost::get()->getNetworkTimer() + (uint64_t)2500;
|
||||
powerup_manager->setRandomSeed(start_time);
|
||||
NetworkString* ns = getNetworkString(10);
|
||||
ns->addUInt8(LE_START_RACE).addUInt64(start_time);
|
||||
sendMessageToPeers(ns, /*reliable*/true);
|
||||
|
@ -53,6 +53,7 @@
|
||||
#include "items/item.hpp"
|
||||
#include "items/item_manager.hpp"
|
||||
#include "items/network_item_manager.hpp"
|
||||
#include "items/powerup_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
#include "modes/linear_world.hpp"
|
||||
@ -1855,8 +1856,10 @@ void Track::loadTrackModel(bool reverse_track, unsigned int mode_id)
|
||||
else
|
||||
{
|
||||
// Seed random engine locally
|
||||
ItemManager::updateRandomSeed((uint32_t)StkTime::getTimeSinceEpoch());
|
||||
uint32_t seed = (uint32_t)StkTime::getTimeSinceEpoch();
|
||||
ItemManager::updateRandomSeed(seed);
|
||||
ItemManager::create();
|
||||
powerup_manager->setRandomSeed(seed);
|
||||
}
|
||||
|
||||
// Set the default start positions. Node that later the default
|
||||
|
Loading…
Reference in New Issue
Block a user