Move voting to server lobby
This commit is contained in:
parent
d6936c5746
commit
a5c1dbb446
@ -18,8 +18,8 @@
|
||||
|
||||
#include "network/game_setup.hpp"
|
||||
|
||||
#include "config/player_manager.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "online/online_profile.hpp"
|
||||
@ -27,23 +27,14 @@
|
||||
#include "utils/log.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameSetup::GameSetup()
|
||||
{
|
||||
m_race_config = new RaceConfig();
|
||||
m_num_local_players = 0;
|
||||
m_local_master = 0;
|
||||
m_laps = 0;
|
||||
m_reverse = false;
|
||||
} // GameSetup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameSetup::~GameSetup()
|
||||
{
|
||||
// remove all players
|
||||
m_players.clear();
|
||||
delete m_race_config;
|
||||
} // ~GameSetup
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GameSetup::addPlayer(std::shared_ptr<NetworkPlayerProfile> profile)
|
||||
{
|
||||
@ -95,7 +86,16 @@ bool GameSetup::isLocalMaster(uint8_t player_id)
|
||||
} // isLocalMaster
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GameSetup::loadWorld()
|
||||
{
|
||||
assert(!m_track.empty());
|
||||
// Disable accidentally unlocking of a challenge
|
||||
PlayerManager::getCurrentPlayer()->setCurrentChallenge("");
|
||||
race_manager->setReverseTrack(m_reverse);
|
||||
race_manager->startSingleRace(m_track, m_laps, false/*from_overworld*/);
|
||||
} // loadWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void GameSetup::bindKartsToProfiles()
|
||||
{
|
||||
World::KartList karts = World::getWorld()->getKarts();
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include <vector>
|
||||
|
||||
class NetworkPlayerProfile;
|
||||
class RaceConfig;
|
||||
|
||||
// ============================================================================
|
||||
/*! \class GameSetup
|
||||
@ -46,9 +45,6 @@ private:
|
||||
/** Information about all connected players. */
|
||||
std::vector<std::weak_ptr<NetworkPlayerProfile> > m_players;
|
||||
|
||||
/** The race configuration. */
|
||||
RaceConfig* m_race_config;
|
||||
|
||||
/** Stores the number of local players. */
|
||||
int m_num_local_players;
|
||||
|
||||
@ -56,11 +52,17 @@ private:
|
||||
* kart selection screen. */
|
||||
uint8_t m_local_master;
|
||||
|
||||
std::string m_track;
|
||||
|
||||
unsigned m_laps;
|
||||
|
||||
bool m_reverse;
|
||||
|
||||
public:
|
||||
// ------------------------------------------------------------------------
|
||||
GameSetup();
|
||||
// ------------------------------------------------------------------------
|
||||
~GameSetup();
|
||||
~GameSetup() {}
|
||||
// ------------------------------------------------------------------------
|
||||
void addPlayer(std::shared_ptr<NetworkPlayerProfile> profile);
|
||||
// ------------------------------------------------------------------------
|
||||
@ -78,9 +80,6 @@ public:
|
||||
/** Returns the nunber of local players. */
|
||||
int getNumLocalPlayers() const { return m_num_local_players; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the configuration for this race. */
|
||||
RaceConfig* getRaceConfig() { return m_race_config; }
|
||||
// ------------------------------------------------------------------------
|
||||
/** \brief Get the players that are in the game
|
||||
* \return A vector containing pointers on the players profiles. */
|
||||
std::vector<std::weak_ptr<NetworkPlayerProfile> > getPlayers() const
|
||||
@ -98,6 +97,15 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the id of the local master. */
|
||||
int getLocalMasterID() const { return m_local_master; }
|
||||
// ------------------------------------------------------------------------
|
||||
void setRace(const std::string& track, unsigned laps, bool reverse)
|
||||
{
|
||||
m_track = track;
|
||||
m_laps = laps;
|
||||
m_reverse = reverse;
|
||||
}
|
||||
// ------------------------------------------------------------------------
|
||||
void loadWorld();
|
||||
};
|
||||
|
||||
#endif // GAME_SETUP_HPP
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "network/network_player_profile.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/latency_protocol.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "network/protocols/game_protocol.hpp"
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
#include "network/protocols/latency_protocol.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/rewind_manager.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
@ -74,6 +73,27 @@ void LobbyProtocol::loadWorld()
|
||||
race_manager->setNumPlayers(m_game_setup->getPlayerCount(),
|
||||
m_game_setup->getNumLocalPlayers());
|
||||
|
||||
// Make sure that if there is only a single local player this player can
|
||||
// use all input devices.
|
||||
StateManager::ActivePlayer *ap = race_manager->getNumLocalPlayers()>1
|
||||
? NULL
|
||||
: StateManager::get()->getActivePlayer(0);
|
||||
|
||||
input_manager->getDeviceManager()->setSinglePlayer(ap);
|
||||
|
||||
Log::info("LobbyProtocol", "Player configuration ready.");
|
||||
|
||||
// Load the actual world.
|
||||
m_game_setup->loadWorld();
|
||||
World::getWorld()->setNetworkWorld(true);
|
||||
GameProtocol::createInstance()->requestStart();
|
||||
std::make_shared<GameEventsProtocol>()->requestStart();
|
||||
|
||||
} // loadWorld
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void LobbyProtocol::configRemoteKart()
|
||||
{
|
||||
// Create the kart information for the race manager:
|
||||
// -------------------------------------------------
|
||||
/*std::vector<NetworkPlayerProfile*> players = m_game_setup->getPlayers();
|
||||
@ -114,24 +134,7 @@ void LobbyProtocol::loadWorld()
|
||||
// Inform the race manager about the data for this kart.
|
||||
race_manager->setPlayerKart(i, rki);
|
||||
} // for i in players*/
|
||||
|
||||
// Make sure that if there is only a single local player this player can
|
||||
// use all input devices.
|
||||
StateManager::ActivePlayer *ap = race_manager->getNumLocalPlayers()>1
|
||||
? NULL
|
||||
: StateManager::get()->getActivePlayer(0);
|
||||
|
||||
input_manager->getDeviceManager()->setSinglePlayer(ap);
|
||||
|
||||
Log::info("LobbyProtocol", "Player configuration ready.");
|
||||
|
||||
// Load the actual world.
|
||||
m_game_setup->getRaceConfig()->loadWorld();
|
||||
World::getWorld()->setNetworkWorld(true);
|
||||
GameProtocol::createInstance()->requestStart();
|
||||
std::make_shared<GameEventsProtocol>()->requestStart();
|
||||
|
||||
} // loadWorld
|
||||
} // configRemoteKart
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Terminates the LatencyProtocol.
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
class GameSetup;
|
||||
class NetworkPlayerProfile;
|
||||
|
||||
/*!
|
||||
* \class LobbyProtocol
|
||||
@ -74,6 +75,8 @@ protected:
|
||||
/** Stores data about the online game to play. */
|
||||
GameSetup* m_game_setup;
|
||||
|
||||
void configRemoteKart();
|
||||
|
||||
public:
|
||||
|
||||
/** Creates either a client or server lobby protocol as a singleton. */
|
||||
|
@ -28,7 +28,6 @@
|
||||
#include "network/protocols/connect_to_peer.hpp"
|
||||
#include "network/protocols/latency_protocol.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/race_config.hpp"
|
||||
#include "network/race_event_manager.hpp"
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/stk_peer.hpp"
|
||||
@ -124,6 +123,7 @@ void ServerLobby::setup()
|
||||
// the server are ready:
|
||||
m_server_has_loaded_world.store(false);
|
||||
m_peers_ready.clear();
|
||||
m_peers_votes.clear();
|
||||
m_server_delay = 0.0;
|
||||
Log::info("ServerLobby", "Reset server to initial state.");
|
||||
} // setup
|
||||
@ -995,22 +995,117 @@ void ServerLobby::playerVote(Event* event)
|
||||
event->getPeer()->getPlayerProfiles().empty())
|
||||
return;
|
||||
|
||||
NetworkString& data = event->data();
|
||||
NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
|
||||
other.addUInt8(LE_VOTE).encodeString(event->getPeer()
|
||||
->getPlayerProfiles()[0]->getName());
|
||||
other += data;
|
||||
// Check if first vote, if so start counter (10 seconds voting time)
|
||||
if (m_timeout == std::numeric_limits<float>::max())
|
||||
m_timeout = (float)StkTime::getRealTime() + 10.0f;
|
||||
float remaining_time = m_timeout - (float)StkTime::getRealTime();
|
||||
if (remaining_time < 0.0f)
|
||||
remaining_time = 0.0f;
|
||||
{
|
||||
// Start world
|
||||
handleVote();
|
||||
configRemoteKart();
|
||||
// Reset for next state usage
|
||||
for (auto p : m_peers_ready)
|
||||
{
|
||||
p.second = false;
|
||||
}
|
||||
|
||||
m_state = LOAD_WORLD;
|
||||
return;
|
||||
}
|
||||
|
||||
NetworkString& data = event->data();
|
||||
NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
|
||||
other.addUInt8(LE_VOTE).encodeString(event->getPeer()
|
||||
->getPlayerProfiles()[0]->getName());
|
||||
other += data;
|
||||
|
||||
std::string track_name;
|
||||
data.decodeString(&track_name);
|
||||
m_peers_votes.emplace(event->getPeerSP(), std::forward_as_tuple(track_name,
|
||||
data.getUInt8(), (bool)data.getUInt8()));
|
||||
other.addUInt8((uint8_t)remaining_time);
|
||||
sendMessageToPeersChangingToken(&other);
|
||||
|
||||
} // playerVote
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void ServerLobby::handleVote()
|
||||
{
|
||||
// Default settings if no votes at all
|
||||
RandomGenerator rg;
|
||||
std::set<std::string>::iterator it = m_available_kts.second.begin();
|
||||
std::advance(it, rg.get((int)m_available_kts.second.size()));
|
||||
std::string final_track = *it;
|
||||
unsigned final_laps = UserConfigParams::m_num_laps;
|
||||
bool final_reverse = (bool)(final_track.size() % 2);
|
||||
|
||||
std::map<std::string, unsigned> tracks;
|
||||
std::map<unsigned, unsigned> laps;
|
||||
std::map<bool, unsigned> reverses;
|
||||
for (auto p : m_peers_votes)
|
||||
{
|
||||
if (p.first.expired())
|
||||
continue;
|
||||
auto track_vote = tracks.find(std::get<0>(p.second));
|
||||
if (track_vote == tracks.end())
|
||||
tracks[std::get<0>(p.second)] = 1;
|
||||
else
|
||||
track_vote->second++;
|
||||
auto lap_vote = laps.find(std::get<1>(p.second));
|
||||
if (lap_vote == laps.end())
|
||||
laps[std::get<1>(p.second)] = 1;
|
||||
else
|
||||
lap_vote->second++;
|
||||
auto reverse_vote = reverses.find(std::get<2>(p.second));
|
||||
if (reverse_vote == reverses.end())
|
||||
reverses[std::get<2>(p.second)] = 1;
|
||||
else
|
||||
reverse_vote->second++;
|
||||
}
|
||||
|
||||
unsigned vote = 0;
|
||||
auto track_vote = tracks.begin();
|
||||
for (auto c_vote = tracks.begin(); c_vote != tracks.end(); c_vote++)
|
||||
{
|
||||
if (c_vote->second > vote)
|
||||
{
|
||||
vote = c_vote->second;
|
||||
track_vote = c_vote;
|
||||
}
|
||||
}
|
||||
if (track_vote != tracks.end())
|
||||
final_track = track_vote->first;
|
||||
|
||||
vote = 0;
|
||||
auto lap_vote = laps.begin();
|
||||
for (auto c_vote = laps.begin(); c_vote != laps.end(); c_vote++)
|
||||
{
|
||||
if (c_vote->second > vote)
|
||||
{
|
||||
vote = c_vote->second;
|
||||
lap_vote = c_vote;
|
||||
}
|
||||
}
|
||||
if (lap_vote != laps.end())
|
||||
final_laps = lap_vote->first;
|
||||
|
||||
vote = 0;
|
||||
auto reverse_vote = reverses.begin();
|
||||
for (auto c_vote = reverses.begin(); c_vote != reverses.end(); c_vote++)
|
||||
{
|
||||
if (c_vote->second > vote)
|
||||
{
|
||||
vote = c_vote->second;
|
||||
reverse_vote = c_vote;
|
||||
}
|
||||
}
|
||||
if (reverse_vote != reverses.end())
|
||||
final_reverse = reverse_vote->first;
|
||||
|
||||
m_game_setup->setRace(final_track, final_laps, final_reverse);
|
||||
} // handleVote
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
/** Called from the RaceManager of the server when the world is loaded. Marks
|
||||
* the server to be ready to start the race.
|
||||
|
@ -9,6 +9,7 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <set>
|
||||
#include <tuple>
|
||||
|
||||
class STKPeer;
|
||||
|
||||
@ -49,6 +50,10 @@ private:
|
||||
std::map<std::weak_ptr<STKPeer>, bool,
|
||||
std::owner_less<std::weak_ptr<STKPeer> > > m_peers_ready;
|
||||
|
||||
/** Vote from each peer. */
|
||||
std::map<std::weak_ptr<STKPeer>, std::tuple<std::string, uint8_t, bool>,
|
||||
std::owner_less<std::weak_ptr<STKPeer> > > m_peers_votes;
|
||||
|
||||
/** Keeps track of an artificial server delay (which makes sure that the
|
||||
* data from all clients has arrived when the server computes a certain
|
||||
* timestep.(. It stores the real time since epoch + delta (atm 0.1
|
||||
@ -88,6 +93,7 @@ private:
|
||||
void updatePlayerList();
|
||||
void updateServerOwner();
|
||||
bool checkPeersReady() const;
|
||||
void handleVote();
|
||||
|
||||
public:
|
||||
ServerLobby();
|
||||
|
@ -1,452 +0,0 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014-2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/race_config.hpp"
|
||||
|
||||
#include "config/user_config.hpp"
|
||||
#include "network/network_config.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
/** \brief Gets the element with the highest count in a std::map<S,int>.
|
||||
* \param histogram : A pointer to the histogram.
|
||||
* \return The key of type S that has the highest second value.
|
||||
*/
|
||||
template<typename S>
|
||||
S getHighestInHistogram(std::map<S,int>* histogram, S default_value)
|
||||
{
|
||||
if(histogram->empty())
|
||||
return default_value;
|
||||
|
||||
S best_item = histogram->begin()->first;
|
||||
uint8_t highest_count = histogram->begin()->second;
|
||||
for (typename std::map<S, int>::iterator it = histogram->begin();
|
||||
it != histogram->end(); it++)
|
||||
{
|
||||
if (it->second > highest_count)
|
||||
{
|
||||
highest_count = it->second;
|
||||
best_item = it->first;
|
||||
}
|
||||
}
|
||||
return best_item;
|
||||
} // getHighestInHistogram
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//--------------------------------- TrackVote --------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Constructor for a track vote.
|
||||
*/
|
||||
TrackVote::TrackVote()
|
||||
{
|
||||
has_voted_laps = false;
|
||||
has_voted_track = false;
|
||||
has_voted_reversed = false;
|
||||
} // TrackVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets that this vote is for the specified track.
|
||||
*/
|
||||
void TrackVote::voteTrack(const std::string &track)
|
||||
{
|
||||
track_info.track = track;
|
||||
has_voted_track = true;
|
||||
} // voteTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets if this vote is for normal or reversed driving.
|
||||
* \param reversed True if this vote is for reversed racing.
|
||||
*/
|
||||
void TrackVote::voteReversed(bool reversed)
|
||||
{
|
||||
track_info.reversed = reversed;
|
||||
has_voted_reversed = true;
|
||||
} // voteReversed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Votes for the number of laps.
|
||||
* \param laps Numger of laps.
|
||||
*/
|
||||
void TrackVote::voteLaps(uint8_t laps)
|
||||
{
|
||||
track_info.laps = laps;
|
||||
has_voted_laps = true;
|
||||
} // voteLaps
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//--------------------------------- RaceVote ---------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Constructor for a race vote.
|
||||
*/
|
||||
RaceVote::RaceVote()
|
||||
{
|
||||
m_has_voted_major = false;
|
||||
m_has_voted_minor = false;
|
||||
m_has_voted_races_count = false;
|
||||
m_major_mode = 0;
|
||||
m_minor_mode = 0;
|
||||
m_races_count = 0;
|
||||
m_tracks_vote.resize(1);
|
||||
} // RaceVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the selected major race vote.
|
||||
*/
|
||||
void RaceVote::voteMajor(uint32_t major)
|
||||
{
|
||||
m_has_voted_major = true;
|
||||
m_major_mode = major;
|
||||
} // voteMajor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets the vote for race count.
|
||||
*/
|
||||
void RaceVote::voteRaceCount(uint8_t count)
|
||||
{
|
||||
m_has_voted_races_count = true;
|
||||
m_races_count = count;
|
||||
} // voteRaceCount
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets vote for minor race mode.
|
||||
*/
|
||||
void RaceVote::voteMinor(uint32_t minor)
|
||||
{
|
||||
m_has_voted_minor = true;
|
||||
m_minor_mode = minor;
|
||||
} // voteMinor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets a track vote.
|
||||
* \param track Name of the track.
|
||||
*/
|
||||
void RaceVote::voteTrack(const std::string &track, uint8_t track_number)
|
||||
{
|
||||
m_tracks_vote[track_number].voteTrack(track);
|
||||
} // voteTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets a vote for reveresed racing.
|
||||
*/
|
||||
void RaceVote::voteReversed(bool reversed, uint8_t track_number)
|
||||
{
|
||||
m_tracks_vote[track_number].voteReversed(reversed);
|
||||
} // voteReversed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets a vote for number of laps.
|
||||
*/
|
||||
void RaceVote::voteLaps(uint8_t laps, uint8_t track_number)
|
||||
{
|
||||
m_tracks_vote[track_number].voteLaps(laps);
|
||||
} // voteLaps
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedMajor() const
|
||||
{
|
||||
return m_has_voted_major;
|
||||
} // hasVotedMajor
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedRacesCount() const
|
||||
{
|
||||
return m_has_voted_races_count;
|
||||
} // hasVotedRacesCount
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedMinor() const
|
||||
{
|
||||
return m_has_voted_minor;
|
||||
} // hasVotedMinor
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedTrack(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].has_voted_track;
|
||||
} // hasVotedTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedReversed(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].has_voted_reversed;
|
||||
} // hasVotedReversed
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::hasVotedLaps(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].has_voted_laps;
|
||||
} // hasVotedLaps
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getMajorVote() const
|
||||
{
|
||||
return m_major_mode;
|
||||
} // getMajorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getRacesCountVote() const
|
||||
{
|
||||
return m_races_count;
|
||||
} // getRacesCountVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getMinorVote() const
|
||||
{
|
||||
return m_minor_mode;
|
||||
} // getMinorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const std::string &RaceVote::getTrackVote(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].track_info.track;
|
||||
} // getTrackVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
bool RaceVote::getReversedVote(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].track_info.reversed;
|
||||
} // getReversedVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t RaceVote::getLapsVote(uint8_t track_number) const
|
||||
{
|
||||
return m_tracks_vote[track_number].track_info.laps;
|
||||
} // getLapsVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//--------------------------------- RaceConfig -------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
RaceConfig::RaceConfig()
|
||||
{
|
||||
m_max_players = NetworkConfig::get()->getMaxPlayers();
|
||||
} // RaceConfig
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceConfig::setPlayerMajorVote(uint8_t player_id, uint32_t major)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for major %d", player_id, major);
|
||||
m_votes[player_id].voteMajor(major);
|
||||
} // setPlayerMajorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceConfig::setPlayerRaceCountVote(uint8_t player_id, uint8_t count)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for %d races in GP",
|
||||
player_id, count);
|
||||
m_votes[player_id].voteRaceCount(count);
|
||||
} // setPlayerRaceCountVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceConfig::setPlayerMinorVote(uint8_t player_id, uint32_t minor)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for minor %d", player_id, minor);
|
||||
m_votes[player_id].voteMinor(minor);
|
||||
} // setPlayerMinorVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceConfig::setPlayerTrackVote(uint8_t player_id,
|
||||
const std::string &track, uint8_t track_nb)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted for track %s",
|
||||
player_id, track.c_str());
|
||||
m_votes[player_id].voteTrack(track, track_nb);
|
||||
} // setPlayerTrackVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceConfig::setPlayerReversedVote(uint8_t player_id, bool reversed,
|
||||
uint8_t track_nb)
|
||||
{
|
||||
if (reversed)
|
||||
Log::info("RaceConfig", "Player %d voted map %d to be reversed",
|
||||
player_id, track_nb);
|
||||
else
|
||||
Log::info("RaceConfig", "Player %d voted map %d NOT to be reversed",
|
||||
player_id, track_nb);
|
||||
m_votes[player_id].voteReversed(reversed, track_nb);
|
||||
} // setPlayerReversedVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void RaceConfig::setPlayerLapsVote(uint8_t player_id, uint8_t lap_count,
|
||||
uint8_t track_nb)
|
||||
{
|
||||
Log::info("RaceConfig", "Player %d voted map %d to have %d laps",
|
||||
player_id, track_nb, lap_count);
|
||||
m_votes[player_id].voteLaps(lap_count, track_nb);
|
||||
} // setPlayerLapsVote
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Computes the selected race mode.
|
||||
*/
|
||||
void RaceConfig::computeRaceMode()
|
||||
{
|
||||
// calculate the race type and number of tracks (in GP mode).
|
||||
std::map<int,int> major_histogram;
|
||||
std::map<int,int> races_count_histogram;
|
||||
std::map<int,int> minor_histogram;
|
||||
for (unsigned int i = 0; i < m_max_players; i++)
|
||||
{
|
||||
// increase the count of votes
|
||||
if (m_votes[i].hasVotedMajor())
|
||||
{
|
||||
try
|
||||
{
|
||||
major_histogram.at(m_votes[i].getMajorVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range&) // doesn't exist in the map
|
||||
{
|
||||
major_histogram[m_votes[i].getMajorVote()] = 1;
|
||||
}
|
||||
}
|
||||
else if (m_votes[i].hasVotedRacesCount())
|
||||
{
|
||||
try
|
||||
{
|
||||
races_count_histogram.at(m_votes[i].getRacesCountVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range&) // doesn't exist in the map
|
||||
{
|
||||
races_count_histogram[m_votes[i].getRacesCountVote()] = 1;
|
||||
}
|
||||
}
|
||||
else if (m_votes[i].hasVotedMinor())
|
||||
{
|
||||
try
|
||||
{
|
||||
minor_histogram.at(m_votes[i].getMinorVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range&) // doesn't exist in the map
|
||||
{
|
||||
minor_histogram[m_votes[i].getMinorVote()] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now we know :
|
||||
m_major_mode = getHighestInHistogram(&major_histogram,
|
||||
(int)RaceManager::MAJOR_MODE_SINGLE);
|
||||
m_minor_mode = getHighestInHistogram(&minor_histogram,
|
||||
(int)RaceManager::MINOR_MODE_NORMAL_RACE);
|
||||
|
||||
if (m_major_mode == RaceManager::MAJOR_MODE_GRAND_PRIX)
|
||||
{
|
||||
m_races_count = getHighestInHistogram(&races_count_histogram, 1);
|
||||
m_tracks.resize(m_races_count);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tracks.resize(1);
|
||||
m_races_count = 1;
|
||||
}
|
||||
|
||||
Log::info("RaceConfig", "Major mode will be %d with %d races. Minor is %d",
|
||||
m_major_mode, m_races_count, m_minor_mode);
|
||||
} // computeRaceMode
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
void RaceConfig::computeNextTrack()
|
||||
{
|
||||
for (unsigned int j = 0; j < m_races_count; j++)
|
||||
{
|
||||
// first create histograms of the votes
|
||||
std::map<std::string,int> tracks_histogram;
|
||||
std::map<bool,int> reversed_histogram;
|
||||
std::map<int,int> laps_histogram;
|
||||
for (unsigned int i = 0; i < m_max_players; i++)
|
||||
{
|
||||
// increase the count of votes
|
||||
if (m_votes[i].hasVotedTrack())
|
||||
{
|
||||
try // maps
|
||||
{
|
||||
tracks_histogram.at(m_votes[i].getTrackVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range&) // doesn't exist in the map
|
||||
{
|
||||
tracks_histogram[m_votes[i].getTrackVote()] = 1;
|
||||
}
|
||||
}
|
||||
if (m_votes[i].hasVotedReversed())
|
||||
{
|
||||
try // reversed
|
||||
{
|
||||
reversed_histogram.at(m_votes[i].getReversedVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range&) // doesn't exist in the map
|
||||
{
|
||||
reversed_histogram[m_votes[i].getReversedVote()] = 1;
|
||||
}
|
||||
}
|
||||
if (m_votes[i].hasVotedLaps())
|
||||
{
|
||||
try // laps
|
||||
{
|
||||
laps_histogram.at(m_votes[i].getLapsVote()) ++;
|
||||
}
|
||||
catch (const std::out_of_range&) // doesn't exist in the mapt
|
||||
{
|
||||
laps_histogram[m_votes[i].getLapsVote()] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// now find the highest votes
|
||||
m_tracks[j].track = getHighestInHistogram<std::string>(&tracks_histogram,
|
||||
UserConfigParams::m_last_track);
|
||||
m_tracks[j].reversed = getHighestInHistogram(&reversed_histogram, false);
|
||||
m_tracks[j].laps = getHighestInHistogram<int>(&laps_histogram,
|
||||
UserConfigParams::m_num_laps);
|
||||
if (m_tracks[j].reversed)
|
||||
Log::info("RaceConfig",
|
||||
"Race %d will be on %s with %d laps and reversed",
|
||||
j, m_tracks[j].track.c_str(), m_tracks[j].laps);
|
||||
else
|
||||
Log::info("RaceConfig", "Race %d will be on %s with %d laps",
|
||||
j, m_tracks[j].track.c_str(), m_tracks[j].laps);
|
||||
}
|
||||
} // computeNextTrack
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Computes the selected setting (based on the users' vote) and sets them
|
||||
* in the race manager. Then it loads the world.
|
||||
*/
|
||||
void RaceConfig::loadWorld()
|
||||
{
|
||||
computeRaceMode();
|
||||
computeNextTrack();
|
||||
race_manager->startSingleRace(m_tracks[0].track, m_tracks[0].laps,
|
||||
m_tracks[0].reversed);
|
||||
} // loadWorld
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
const TrackInfo* RaceConfig::getNextTrackInfo() const
|
||||
{
|
||||
return &m_tracks[0];
|
||||
} // getNextTrackInfo
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
int RaceConfig::getNumTrackVotes() const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (auto entry : m_votes)
|
||||
{
|
||||
if (entry.second.hasVotedTrack())
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
} // getNumTrackVotes
|
@ -1,136 +0,0 @@
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2014-2015 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef RACE_CONFIG_HPP
|
||||
#define RACE_CONFIG_HPP
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "utils/types.hpp"
|
||||
|
||||
/** Stores the name of a track, number of laps, and reverse driving.
|
||||
*/
|
||||
class TrackInfo
|
||||
{
|
||||
public:
|
||||
std::string track;
|
||||
bool reversed;
|
||||
uint8_t laps;
|
||||
TrackInfo() { laps = 0; reversed = false; }
|
||||
}; // TrackInfo
|
||||
|
||||
// ============================================================================
|
||||
/** Stores a vote about the name of a track, number of laps, and reverse
|
||||
* driving.
|
||||
*/
|
||||
class TrackVote
|
||||
{
|
||||
public:
|
||||
TrackVote();
|
||||
|
||||
void voteTrack(const std::string &track);
|
||||
void voteReversed(bool reversed);
|
||||
void voteLaps(uint8_t laps);
|
||||
|
||||
TrackInfo track_info;
|
||||
|
||||
bool has_voted_track;
|
||||
bool has_voted_reversed;
|
||||
bool has_voted_laps;
|
||||
}; // class TrackVote
|
||||
|
||||
// ============================================================================
|
||||
class RaceVote
|
||||
{
|
||||
public:
|
||||
RaceVote();
|
||||
|
||||
void voteMajor(uint32_t major);
|
||||
void voteRaceCount(uint8_t count);
|
||||
void voteMinor(uint32_t minor);
|
||||
void voteTrack(const std::string &track, uint8_t track_number = 0);
|
||||
void voteReversed(bool reversed, uint8_t track_number = 0);
|
||||
void voteLaps(uint8_t laps, uint8_t track_number = 0);
|
||||
|
||||
bool hasVotedMajor() const;
|
||||
bool hasVotedRacesCount() const;
|
||||
bool hasVotedMinor() const;
|
||||
bool hasVotedTrack(uint8_t track_number = 0) const;
|
||||
bool hasVotedReversed(uint8_t track_number = 0) const;
|
||||
bool hasVotedLaps(uint8_t track_number = 0) const;
|
||||
|
||||
uint8_t getMajorVote() const;
|
||||
uint8_t getRacesCountVote() const;
|
||||
uint8_t getMinorVote() const;
|
||||
const std::string &getTrackVote(uint8_t track_number = 0) const;
|
||||
bool getReversedVote(uint8_t track_number = 0) const;
|
||||
uint8_t getLapsVote(uint8_t track_number = 0) const;
|
||||
|
||||
private:
|
||||
uint32_t m_major_mode;
|
||||
uint32_t m_minor_mode;
|
||||
uint8_t m_races_count; //!< Stores the number of races that will be in a GP
|
||||
bool m_has_voted_major;
|
||||
bool m_has_voted_minor;
|
||||
bool m_has_voted_races_count;
|
||||
std::vector<TrackVote> m_tracks_vote;
|
||||
}; // RaceVote
|
||||
|
||||
// ============================================================================
|
||||
class RaceConfig
|
||||
{
|
||||
private:
|
||||
void computeRaceMode();
|
||||
void computeNextTrack();
|
||||
public:
|
||||
RaceConfig();
|
||||
|
||||
void setPlayerMajorVote(uint8_t player_id, uint32_t major);
|
||||
void setPlayerRaceCountVote(uint8_t player_id, uint8_t count);
|
||||
void setPlayerMinorVote(uint8_t player_id, uint32_t minor);
|
||||
void setPlayerTrackVote(uint8_t player_id, const std::string &track,
|
||||
uint8_t track_nb = 0);
|
||||
void setPlayerReversedVote(uint8_t player_id, bool reversed,
|
||||
uint8_t track_nb = 0);
|
||||
void setPlayerLapsVote(uint8_t player_id, uint8_t lap_count,
|
||||
uint8_t track_nb = 0);
|
||||
|
||||
void loadWorld();
|
||||
|
||||
const TrackInfo* getNextTrackInfo() const;
|
||||
bool getReverse() const;
|
||||
bool getLapCount() const;
|
||||
int getNumTrackVotes() const;
|
||||
|
||||
const RaceVote& getRaceVote(int global_player_id) { return m_votes[global_player_id]; }
|
||||
int getMaxPlayers() const { return m_max_players; }
|
||||
|
||||
protected:
|
||||
std::vector<TrackInfo> m_tracks;
|
||||
int m_minor_mode;
|
||||
int m_major_mode;
|
||||
unsigned int m_races_count;
|
||||
|
||||
/** Key: globalPlayerID */
|
||||
std::map<int, RaceVote> m_votes;
|
||||
|
||||
uint8_t m_max_players;
|
||||
}; // class RaceConfig
|
||||
|
||||
|
||||
#endif // RACE_CONFIG_HPP
|
Loading…
Reference in New Issue
Block a user