Clean up tracks screen and lobbies

This commit is contained in:
Benau 2018-12-17 15:23:19 +08:00
parent a98baf847f
commit a3a36e33a6
8 changed files with 150 additions and 125 deletions

View File

@ -24,6 +24,7 @@
#include "modes/capture_the_flag.hpp"
#include "network/network_config.hpp"
#include "network/network_player_profile.hpp"
#include "network/peer_vote.hpp"
#include "network/protocols/game_events_protocol.hpp"
#include "network/protocols/server_lobby.hpp"
#include "network/server_config.hpp"
@ -300,3 +301,11 @@ std::pair<int, int> GameSetup::getPlayerTeamInfo() const
}
return std::make_pair(red_count, blue_count);
} // getPlayerTeamInfo
// ----------------------------------------------------------------------------
void GameSetup::setRace(const PeerVote &vote)
{
m_tracks.push_back(vote.m_track_name);
m_laps = vote.m_num_laps;
m_reverse = vote.m_reverse;
} // setRace

View File

@ -24,8 +24,6 @@
#include "network/remote_kart_info.hpp"
#include "network/peer_vote.hpp"
#include <atomic>
#include <cassert>
#include <memory>
@ -36,6 +34,7 @@
class NetworkPlayerProfile;
class NetworkString;
class PeerVote;
// ============================================================================
/*! \class GameSetup
@ -110,12 +109,7 @@ public:
/** Returns the number of connected players. */
unsigned getPlayerCount() { return m_connected_players_count.load(); }
// ------------------------------------------------------------------------
void setRace(const PeerVote &vote)
{
m_tracks.push_back(vote.m_track_name);
m_laps = vote.m_num_laps;
m_reverse = vote.m_reverse;
} // setRace
void setRace(const PeerVote &vote);
// ------------------------------------------------------------------------
void reset()
{

View File

@ -35,6 +35,7 @@
#include "network/network_config.hpp"
#include "network/network_player_profile.hpp"
#include "network/network_timer_synchronizer.hpp"
#include "network/peer_vote.hpp"
#include "network/protocols/connect_to_server.hpp"
#include "network/protocols/game_protocol.hpp"
#include "network/protocols/game_events_protocol.hpp"
@ -437,26 +438,20 @@ void ClientLobby::receivePlayerVote(Event* event)
if (!checkDataSize(event, 4)) return;
// Get the player name who voted
NetworkString& data = event->data();
uint32_t host_id2 = data.getUInt32();
std::shared_ptr<STKPeer> peer = STKHost::get()->findPeerByHostId(host_id2);
std::string player_name;
data.decodeString(&player_name);
uint32_t host_id = data.getUInt32();
player_name += ": ";
PeerVote vote(data);
Log::verbose("CL", "vote from server: host %d track %s reverse %d",
host_id, vote.m_track_name.c_str(), vote.m_reverse);
addVote(host_id, vote);
Log::debug("ClientLobby",
"Vote from server: host %d, track %s, laps %d, reverse %d.",
host_id, vote.m_track_name.c_str(), vote.m_num_laps, vote.m_reverse);
Track* track = track_manager->getTrack(vote.m_track_name);
if (!track)
Log::fatal("ClientLobby", "Missing track %s", vote.m_track_name.c_str());
TracksScreen *ts = TracksScreen::getInstance();
ts->addVote(host_id2);
{
Log::fatal("ClientLobby", "Missing track %s",
vote.m_track_name.c_str());
}
addVote(host_id, vote);
TracksScreen::getInstance()->updatePlayerVotes();
} // receivePlayerVote
//-----------------------------------------------------------------------------
@ -477,18 +472,18 @@ void ClientLobby::disconnectedPlayer(Event* event)
NetworkString &data = event->data();
SFXManager::get()->quickSound("appear");
unsigned disconnected_player_count = data.getUInt8();
uint32_t host_id = data.getUInt32();
m_peers_votes.erase(host_id);
for (unsigned i = 0; i < disconnected_player_count; i++)
{
std::string name;
data.decodeString(&name);
core::stringw player_name = StringUtils::utf8ToWide(name);
core::stringw msg = _("%s disconnected.", player_name);
uint32_t host_id = data.getUInt32();
// Use the friend icon to avoid an error-like message
MessageQueue::add(MessageQueue::MT_FRIEND, msg);
TracksScreen::getInstance()->removeVote(host_id);
}
TracksScreen::getInstance()->updatePlayerVotes();
} // disconnectedPlayer
//-----------------------------------------------------------------------------

View File

@ -25,6 +25,7 @@
#include "network/game_setup.hpp"
#include "network/network_config.hpp"
#include "network/network_player_profile.hpp"
#include "network/peer_vote.hpp"
#include "network/protocols/game_protocol.hpp"
#include "network/protocols/game_events_protocol.hpp"
#include "network/race_event_manager.hpp"
@ -141,6 +142,8 @@ void LobbyProtocol::configRemoteKart(
*/
void LobbyProtocol::setup()
{
resetVotingTime();
m_peers_votes.clear();
m_game_setup->reset();
} // setupNewGame
@ -158,6 +161,8 @@ void LobbyProtocol::startVotingPeriod(float max_time)
/** Returns the remaining voting time in seconds. */
float LobbyProtocol::getRemainingVotingTime()
{
if (m_end_voting_period.load() == 0)
return 0.0f;
uint64_t t = m_end_voting_period.load()- StkTime::getRealTimeMs();
return t/1000.0f;
} // getRemainingVotingTime
@ -166,6 +171,26 @@ float LobbyProtocol::getRemainingVotingTime()
/** Returns if the voting period is over. */
bool LobbyProtocol::isVotingOver()
{
return m_end_voting_period.load() < StkTime::getRealTimeMs();
return m_end_voting_period.load() != 0 &&
m_end_voting_period.load() < StkTime::getRealTimeMs();
} // isVotingOver
//-----------------------------------------------------------------------------
/** Adds a vote.
* \param host_id Host id of this vote.
* \param vote The vote to add. */
void LobbyProtocol::addVote(uint32_t host_id, const PeerVote &vote)
{
m_peers_votes[host_id] = vote;
} // addVote
//-----------------------------------------------------------------------------
/** Returns the voting data for one host. Returns NULL if the vote from
* the given host id has not yet arrived (or if it is an invalid host id).
*/
const PeerVote* LobbyProtocol::getVote(uint32_t host_id) const
{
auto it = m_peers_votes.find(host_id);
if (it == m_peers_votes.end()) return NULL;
return &(it->second);
} // getVote

View File

@ -21,11 +21,9 @@
#include "network/protocol.hpp"
#include "network/network_string.hpp"
#include "network/peer_vote.hpp"
class GameSetup;
class NetworkPlayerProfile;
class PeerVote;
#include <atomic>
#include <cassert>
@ -82,18 +80,17 @@ public:
RR_INVALID_PLAYER = 5
};
protected:
/** Vote from each peer. The host id is used as a key. Note that
* host ids can be non-consecutive, so we cannot use std::vector. */
std::map<uint32_t, PeerVote> m_peers_votes;
/** Timer user for voting periods in both lobbies. */
std::atomic<uint64_t> m_end_voting_period;
/** The maximum voting time. */
uint64_t m_max_voting_time;
protected:
/** Vote from each peer. The host id is used as a key. Note that
* host ids can be non-consecutive, so we cannot use std::vector. */
std::map<int, PeerVote> m_peers_votes;
std::thread m_start_game_thread;
static std::weak_ptr<LobbyProtocol> m_lobby;
@ -166,23 +163,15 @@ public:
/** Returns the number of votes received so far. */
int getNumberOfVotes() const { return (int)m_peers_votes.size(); }
// -----------------------------------------------------------------------
/** Adds a vote.
* \param host_id Host id of this vote.
* \param vote The vote to add. */
void addVote(int host_id, const PeerVote &vote)
{
m_peers_votes[host_id] = vote;
} // addVote
void addVote(uint32_t host_id, const PeerVote &vote);
// -----------------------------------------------------------------------
/** Returns the voting data for one host. Returns NULL if the vote from
* the given host id has not yet arrived (or if it is an invalid host id).
*/
const PeerVote* getVote(int host_id)
{
auto it = m_peers_votes.find(host_id);
if (it == m_peers_votes.end()) return NULL;
return &(it->second);
}
const PeerVote* getVote(uint32_t host_id) const;
// -----------------------------------------------------------------------
void resetVotingTime() { m_end_voting_period.store(0); }
// -----------------------------------------------------------------------
/** Returns all voting data.*/
const std::map<uint32_t, PeerVote>& getAllVotes() const
{ return m_peers_votes; }
// -----------------------------------------------------------------------
std::pair<uint32_t, uint32_t> getGameStartedProgress() const
{

View File

@ -31,6 +31,7 @@
#include "network/game_setup.hpp"
#include "network/network_config.hpp"
#include "network/network_player_profile.hpp"
#include "network/peer_vote.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/connect_to_peer.hpp"
#include "network/protocols/game_protocol.hpp"
@ -265,7 +266,6 @@ void ServerLobby::setup()
// Initialise the data structures to detect if all clients and
// the server are ready:
resetPeersReady();
m_peers_votes.clear();
m_timeout.store(std::numeric_limits<int64_t>::max());
m_waiting_for_reset = false;
m_server_started_at = m_server_delay = 0;
@ -1416,11 +1416,12 @@ void ServerLobby::clientDisconnected(Event* event)
event->getPeer()->isWaitingForGame();
msg->setSynchronous(true);
msg->addUInt8(LE_PLAYER_DISCONNECTED);
msg->addUInt8((uint8_t)players_on_peer.size());
msg->addUInt8((uint8_t)players_on_peer.size())
.addUInt32(event->getPeer()->getHostId());
for (auto p : players_on_peer)
{
std::string name = StringUtils::wideToUtf8(p->getName());
msg->encodeString(name).addUInt32(event->getPeer()->getHostId());
msg->encodeString(name);
Log::info("ServerLobby", "%s disconnected", name.c_str());
}
@ -1928,7 +1929,8 @@ void ServerLobby::kartSelectionRequested(Event* event)
} // kartSelectionRequested
//-----------------------------------------------------------------------------
/*! \brief Called when a player votes for track(s).
/*! \brief Called when a player votes for track(s), it will auto correct client
* data if it sends some invalid data.
* \param event : Event providing the information.
*/
void ServerLobby::handlePlayerVote(Event* event)
@ -1949,62 +1951,64 @@ void ServerLobby::handlePlayerVote(Event* event)
NetworkString& data = event->data();
PeerVote vote(data);
Log::verbose("SL", "vote from server: host %d track %s reverse %d",
event->getPeer()->getHostId(), vote.m_track_name.c_str(), vote.m_reverse);
Log::debug("ServerLobby",
"Vote from client: host %d, track %s, laps %d, reverse %d.",
event->getPeer()->getHostId(), vote.m_track_name.c_str(),
vote.m_num_laps, vote.m_reverse);
Track* t = track_manager->getTrack(vote.m_track_name);
if (!t)
{
vote.m_track_name = *m_available_kts.second.begin();
t = track_manager->getTrack(vote.m_track_name);
assert(t);
}
if (race_manager->modeHasLaps())
{
if (ServerConfig::m_auto_game_time_ratio > 0.0f)
{
Track* t = track_manager->getTrack(vote.m_track_name);
if (t)
{
vote.m_num_laps =
(uint8_t)(fmaxf(1.0f,
(float)t->getDefaultNumberOfLaps()
*ServerConfig::m_auto_game_time_ratio ) );
}
else
{
// Prevent someone send invalid vote
vote.m_track_name = *m_available_kts.second.begin();
vote.m_num_laps = (uint8_t)3;
}
vote.m_num_laps =
(uint8_t)(fmaxf(1.0f, (float)t->getDefaultNumberOfLaps() *
ServerConfig::m_auto_game_time_ratio));
}
else if (vote.m_num_laps == 0)
else if (vote.m_num_laps == 0 || vote.m_num_laps > 20)
vote.m_num_laps = (uint8_t)3;
}
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_SOCCER &&
ServerConfig::m_auto_game_time_ratio > 0.0f )
else if (race_manager->isSoccerMode())
{
if (m_game_setup->isSoccerGoalTarget())
{
vote.m_num_laps = (uint8_t)(ServerConfig::m_auto_game_time_ratio *
UserConfigParams::m_num_goals);
if (ServerConfig::m_auto_game_time_ratio > 0.0f)
{
vote.m_num_laps = (uint8_t)(ServerConfig::m_auto_game_time_ratio *
UserConfigParams::m_num_goals);
}
else if (vote.m_num_laps > 10)
vote.m_num_laps = (uint8_t)5;
}
else
{
vote.m_num_laps = (uint8_t)(ServerConfig::m_auto_game_time_ratio *
UserConfigParams::m_soccer_time_limit);
if (ServerConfig::m_auto_game_time_ratio > 0.0f)
{
vote.m_num_laps = (uint8_t)(ServerConfig::m_auto_game_time_ratio *
UserConfigParams::m_soccer_time_limit);
}
else if (vote.m_num_laps > 15)
vote.m_num_laps = (uint8_t)7;
}
}
// Store vote:
vote.m_player_name = event->getPeer()->getPlayerProfiles()[0]->getName();
addVote(event->getPeer()->getHostId(), vote);
// Now inform all clients about the vote
NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
std::string name =
StringUtils::wideToUtf8(event->getPeer()
->getPlayerProfiles()[0]->getName());
other.setSynchronous(true);
other.addUInt8(LE_VOTE);
other.addUInt32(event->getPeer()->getHostId()) .encodeString(name)
.addUInt32(event->getPeer()->getHostId());
other.addUInt32(event->getPeer()->getHostId());
vote.encode(&other);
sendMessageToPeers(&other);
} // handlePlayerVote
@ -2034,7 +2038,7 @@ bool ServerLobby::handleAllVotes(PeerVote *winner_vote)
for (auto peer : peers)
{
if (peer->hasPlayerProfiles() && !peer->isWaitingForGame())
cur_players ++;
cur_players++;
}
if (cur_players == 0 || m_peers_votes.size() < cur_players)
{

View File

@ -32,6 +32,7 @@
#include "guiengine/widgets/spinner_widget.hpp"
#include "io/file_manager.hpp"
#include "network/game_setup.hpp"
#include "network/peer_vote.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/network_config.hpp"
#include "network/stk_host.hpp"
@ -158,6 +159,7 @@ void TracksScreen::beforeAddingWidget()
{
Screen::init();
m_selected_track = NULL;
m_timer = getWidget<GUIEngine::ProgressBarWidget>("timer");
m_timer->showLabel(false);
@ -260,6 +262,14 @@ void TracksScreen::init()
// goals / time limit and random item location
auto cl = LobbyProtocol::get<ClientLobby>();
assert(cl);
const PeerVote* vote = cl->getVote(STKHost::get()->getMyHostId());
if (vote)
{
DynamicRibbonWidget* w2 = getWidget<DynamicRibbonWidget>("tracks");
m_selected_track = track_manager->getTrack(vote->m_track_name);
w2->setBadge(vote->m_track_name, OK_BADGE);
}
if (UserConfigParams::m_num_laps == 0 ||
UserConfigParams::m_num_laps > 20)
UserConfigParams::m_num_laps = 1;
@ -272,6 +282,8 @@ void TracksScreen::init()
getWidget<LabelWidget>("reverse-text")->setText(_("Random item location"), false);
m_reversed->setVisible(true);
m_reversed->setState(UserConfigParams::m_random_arena_item);
if (vote)
m_reversed->setState(vote->m_reverse);
}
else if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_CAPTURE_THE_FLAG)
{
@ -292,8 +304,6 @@ void TracksScreen::init()
{
m_laps->setVisible(true);
getWidget("lap-text")->setVisible(true);
auto cl = LobbyProtocol::get<ClientLobby>();
assert(cl);
if (cl->getGameSetup()->isSoccerGoalTarget())
{
//I18N: In track screen
@ -310,12 +320,16 @@ void TracksScreen::init()
m_laps->setMin(1);
m_laps->setMax(15);
}
if (vote)
m_laps->setValue(vote->m_num_laps);
}
getWidget("reverse-text")->setVisible(true);
//I18N: In track screen
getWidget<LabelWidget>("reverse-text")->setText(_("Random item location"), false);
m_reversed->setVisible(true);
m_reversed->setState(UserConfigParams::m_random_arena_item);
if (vote)
m_reversed->setState(vote->m_reverse);
}
else
{
@ -335,26 +349,16 @@ void TracksScreen::init()
m_laps->setMin(1);
m_laps->setMax(20);
m_laps->setValue(UserConfigParams::m_num_laps);
if (vote)
m_laps->setValue(vote->m_num_laps);
}
getWidget("reverse-text")->setVisible(true);
//I18N: In track screen
getWidget<LabelWidget>("reverse-text")
->setText(_("Drive in reverse"), false);
m_reversed->setVisible(true);
auto lp = LobbyProtocol::get<LobbyProtocol>();
const PeerVote *vote = lp ->getVote(STKHost::get()->getMyHostId());
DynamicRibbonWidget* w2 = getWidget<DynamicRibbonWidget>("tracks");
if(vote)
{
m_reverse_checked = vote->m_reverse;
m_selected_track = track_manager->getTrack(vote->m_track_name);
w2->setBadge(vote->m_track_name, OK_BADGE);
}
else
{
m_reversed->setState(m_reverse_checked);
}
if (vote)
m_reversed->setState(vote->m_reverse);
}
}
if (NetworkConfig::get()->isAutoConnect() && m_network_tracks)
@ -365,6 +369,7 @@ void TracksScreen::init()
vote.encodeString(m_random_track_list[0]).addUInt8(1).addUInt8(0);
STKHost::get()->sendToServer(&vote, true);
}
updatePlayerVotes();
} // init
// -----------------------------------------------------------------------------
@ -458,30 +463,22 @@ void TracksScreen::voteForPlayer()
{
assert(STKHost::existHost());
// If submit is clicked without a vote, select a random track.
if(!m_selected_track)
{
std::string track_name = m_random_track_list.front();
m_selected_track = track_manager->getTrack(track_name);
m_random_track_list.pop_front();
m_random_track_list.push_back(track_name);
}
assert(m_laps);
assert(m_reversed);
// Remember reverse globally for each stk instance if not arena
const core::stringw &player_name =
PlayerManager::getCurrentPlayer()->getName();
if (!race_manager->isBattleMode() &&
race_manager->getMinorMode() != RaceManager::MINOR_MODE_SOCCER)
{
UserConfigParams::m_num_laps = m_laps->getValue();
m_reverse_checked = m_reversed->getState();
}
else
UserConfigParams::m_random_arena_item = m_reversed->getState();
NetworkString vote(PROTOCOL_LOBBY_ROOM);
vote.addUInt8(LobbyProtocol::LE_VOTE);
const core::stringw &player_name =
PlayerManager::getCurrentPlayer()->getName();
vote.encodeString(player_name);
if (race_manager->getMinorMode() == RaceManager::MINOR_MODE_FREE_FOR_ALL)
{
vote.encodeString(m_selected_track->getIdent())
@ -495,12 +492,15 @@ void TracksScreen::voteForPlayer()
}
else
{
PeerVote pvote(player_name, m_selected_track->getIdent(),
m_laps->getValue(), m_reversed->getState() );
pvote.encode(&vote);
auto lp = LobbyProtocol::get<LobbyProtocol>();
// The vote will be sent to
vote.encodeString(m_selected_track->getIdent())
.addUInt8(m_laps->getValue())
.addUInt8(m_reversed->getState() ? 1 : 0);
}
if (auto lp = LobbyProtocol::get<LobbyProtocol>())
{
vote.reset();
vote.skip(2);
PeerVote pvote(vote);
lp->addVote(STKHost::get()->getMyHostId(), pvote);
}
STKHost::get()->sendToServer(&vote, true);
@ -687,3 +687,11 @@ void TracksScreen::setResult(const PeerVote &winner_vote)
} // wim_winning_index == -1
} // setResult
// -----------------------------------------------------------------------------
/* Update player votes whenever vote is recieved from any players or
* player disconnected, or when this screen is pushed.
*/
void TracksScreen::updatePlayerVotes()
{
} // updatePlayerVotes

View File

@ -59,7 +59,7 @@ private:
/** Maximum number of votes, as sent by the server. */
unsigned int m_max_num_votes;
bool m_network_tracks, m_reverse_checked, m_quit_server;
bool m_network_tracks, m_quit_server;
int m_bottom_box_height;
@ -80,7 +80,6 @@ private:
TracksScreen() : Screen("tracks.stkgui")
{
m_network_tracks = false;
m_reverse_checked = false;
m_quit_server = false;
m_bottom_box_height = -1;
}
@ -129,8 +128,10 @@ public:
{
m_index_to_hostid.clear();
}
// ------------------------------------------------------------------------
void setVoteTimeout(float timeout);
// ------------------------------------------------------------------------
void updatePlayerVotes();
};
#endif