Show votes in vote overview screen. This is NOT fully working,

and contains debug output.
This commit is contained in:
hiker 2018-12-01 09:32:21 +11:00
parent e20d6a437a
commit d6d879d2ed
8 changed files with 321 additions and 104 deletions

View File

@ -9,23 +9,55 @@
<div id="rect-box" width="100%" height="80%" padding="15" layout="vertical-row">
<div proportion="1" width="100%" layout="horizontal-row" padding="1">
<box id="rect-box0" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-0" width="100%" height="10%"/>
<icon-button id="track-0" width="100%" height="40%"/>
<label id="numlaps-0" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-0" width="5%" height="10%"/>
</box>
<box id="rect-box1" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-1" width="100%" height="10%"/>
<icon-button id="track-1" width="100%" height="40%"/>
<label id="numlaps-1" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-1" width="5%" height="10%"/>
</box>
<box id="rect-box2" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-2" width="100%" height="10%"/>
<icon-button id="track-2" width="100%" height="40%"/>
<label id="numlaps-2" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-2" width="5%" height="10%"/>
</box>
<box id="rect-box3" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-3" width="100%" height="10%"/>
<icon-button id="track-3" width="100%" height="40%"/>
<label id="numlaps-3" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-3" width="5%" height="10%"/>
</box>
</div>
<div proportion="1" width="100%" layout="horizontal-row" padding="1">
<box id="rect-box4" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-4" width="100%" height="10%"/>
<icon-button id="track-4" width="100%" height="40%"/>
<label id="numlaps-4" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-4" width="5%" height="10%"/>
</box>
<box id="rect-box5" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-5" width="100%" height="10%"/>
<icon-button id="track-5" width="100%" height="40%"/>
<label id="numlaps-5" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-5" width="5%" height="10%"/>
</box>
<box id="rect-box6" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-6" width="100%" height="10%"/>
<icon-button id="track-6" width="100%" height="40%"/>
<label id="numlaps-6" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-6" width="5%" height="10%"/>
</box>
<box id="rect-box7" width="24%" height="100%" padding="15" layout="vertical-row">
<label id="name-7" width="100%" height="10%"/>
<icon-button id="track-7" width="100%" height="40%"/>
<label id="numlaps-7" proportion="1" width="100%" height="10%" text=""></label>
<label id="reverse-7" width="5%" height="10%"/>
</box>
</div>
<progressbar id="timer" height="4%" width="100%"></progressbar>

View File

@ -456,11 +456,16 @@ void ClientLobby::receivePlayerVote(Event* event)
uint32_t host_id = data.getUInt32();
player_name += ": ";
PeerVote vote(data);
m_peers_votes[event->getPeer()->getHostId()] = vote;
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);
Track* track = track_manager->getTrack(vote.m_track_name);
if (!track)
Log::fatal("ClientLobby", "Missing track %s", vote.m_track_name.c_str());
VoteOverview *overview = VoteOverview::getInstance();
overview->addVote(host_id2);
} // receivePlayerVote
//-----------------------------------------------------------------------------
@ -850,6 +855,8 @@ void ClientLobby::startSelection(Event* event)
screen->push();
}
VoteOverview *overview = VoteOverview::getInstance();
overview->resetVote();
m_state.store(SELECTING_ASSETS);
Log::info("ClientLobby", "Selection starts now");
} // startSelection

View File

@ -34,6 +34,16 @@
std::weak_ptr<LobbyProtocol> LobbyProtocol::m_lobby;
void LobbyProtocol::addVote(int host_id, const PeerVote &vote)
{
Log::verbose("LP", "host %d vote track %s reverse %d",
host_id, vote.m_track_name.c_str(), vote.m_reverse);
m_peers_votes[host_id] = vote;
} // addVote
LobbyProtocol::LobbyProtocol(CallbackObject* callback_object)
: Protocol(PROTOCOL_LOBBY_ROOM, callback_object)
{

View File

@ -85,24 +85,34 @@ public:
/** The maximum voting time. */
uint64_t m_max_voting_time;
protected:
public:
/** A simple structure to store a vote from a client:
* track name, number of laps and reverse or not. */
class PeerVote
{
public:
std::string m_track_name;
uint8_t m_num_laps;
bool m_reverse;
core::stringw m_player_name;
std::string m_track_name;
uint8_t m_num_laps;
bool m_reverse;
// ------------------------------------------------------
PeerVote() : m_track_name(""), m_num_laps(1),
m_reverse(false)
PeerVote() : m_player_name(""), m_track_name(""),
m_num_laps(1), m_reverse(false)
{}
// ------------------------------------------------------
PeerVote(const core::stringw &name,
const std::string track,
int laps, bool reverse) : m_player_name(name),
m_track_name(track),
m_num_laps(laps),
m_reverse(reverse)
{}
// ------------------------------------------------------
/** Initialised this object from a data in a network string. */
PeerVote(NetworkString &ns)
{
ns.decodeStringW(&m_player_name);
ns.decodeString(&m_track_name);
m_num_laps = ns.getUInt8();
m_reverse = ns.getUInt8();
@ -112,12 +122,14 @@ protected:
/** Encodes this vote object into a network string. */
void encode(NetworkString *ns)
{
ns->encodeString(m_track_name)
ns->encodeString(m_player_name)
.encodeString(m_track_name)
.addUInt8(m_num_laps)
.addUInt8(m_reverse);
} // encode
}; // class PeerVote
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;
@ -181,8 +193,29 @@ public:
/** Returns the maximum floating time in seconds. */
float getMaxVotingTime() { return m_max_voting_time / 1000.0f; }
// ------------------------------------------------------------------------
/** Returns the game setup data structure. */
GameSetup* getGameSetup() const { return m_game_setup; }
// ------------------------------------------------------------------------
/** Returns the number of votes received so far. */
int getNumberOfVotes() const { return 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
// -----------------------------------------------------------------------
/** 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);
}
}; // class LobbyProtocol
#endif // LOBBY_PROTOCOL_HPP

View File

@ -1850,6 +1850,8 @@ 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);
if (race_manager->modeHasLaps())
{
@ -1875,7 +1877,7 @@ void ServerLobby::handlePlayerVote(Event* event)
}
// Store vote:
m_peers_votes[event->getPeer()->getHostId()] = vote;
addVote(event->getPeer()->getHostId(), vote);
// Now inform all clients about the vote
NetworkString other = NetworkString(PROTOCOL_LOBBY_ROOM);
@ -1941,6 +1943,9 @@ bool ServerLobby::handleAllVotes(PeerVote *winner)
*winner = vote->second;
// DEBUG ONLY TO SHOW VOTING RESULT
return false;
return m_peers_votes.size() == cur_players;
} // handleAllVotes

View File

@ -338,7 +338,19 @@ void TracksScreen::init()
//I18N: In track screen
getWidget<LabelWidget>("reverse-text")->setText(_("Drive in reverse"), false);
m_reversed->setVisible(true);
m_reversed->setState(m_reverse_checked);
auto lp = LobbyProtocol::get<LobbyProtocol>();
const LobbyProtocol::PeerVote *vote =
lp ->getVote(STKHost::get()->getMyHostId());
if(vote)
{
m_reverse_checked = vote->m_reverse;
m_selected_track = track_manager->getTrack(vote->m_track_name);
}
else
{
m_reversed->setState(m_reverse_checked);
}
}
}
if (NetworkConfig::get()->isAutoConnect() && m_network_tracks)
@ -445,6 +457,8 @@ void TracksScreen::voteForPlayer()
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->getMinorMode() != RaceManager::MINOR_MODE_BATTLE &&
race_manager->getMinorMode() != RaceManager::MINOR_MODE_SOCCER)
{
@ -469,9 +483,15 @@ void TracksScreen::voteForPlayer()
}
else
{
vote.encodeString(m_selected_track->getIdent())
.addUInt8(m_laps->getValue())
.addUInt8(m_reversed->getState() ? 1 : 0);
LobbyProtocol::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
lp->addVote(STKHost::get()->getMyHostId(), pvote);
}
STKHost::get()->sendToServer(&vote, true);
} // voteForPlayer

View File

@ -27,16 +27,19 @@
#include "guiengine/widgets/check_box_widget.hpp"
#include "guiengine/widgets/dynamic_ribbon_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/progress_bar_widget.hpp"
#include "guiengine/widgets/spinner_widget.hpp"
#include "io/file_manager.hpp"
#include "network/game_setup.hpp"
#include "network/protocols/client_lobby.hpp"
#include "network/protocols/lobby_protocol.hpp"
#include "network/network_config.hpp"
#include "network/stk_host.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/track_info_screen.hpp"
//##include "states_screens/track_info_screen.hpp"
#include "states_screens/online/tracks_screen.hpp"
#include "tracks/track.hpp"
#include "tracks/track_manager.hpp"
#include "utils/translation.hpp"
@ -47,78 +50,12 @@ using namespace GUIEngine;
using namespace irr::core;
using namespace irr::video;
static const char ALL_TRACK_GROUPS_ID[] = "all";
// -----------------------------------------------------------------------------
/** Called on any event, e.g. user input.
*/
void VoteOverview::eventCallback(Widget* widget, const std::string& name,
const int playerID)
VoteOverview::VoteOverview() : Screen("online/vote_overview.stkgui")
{
if (name == "tracks")
{
DynamicRibbonWidget* w2 = dynamic_cast<DynamicRibbonWidget*>(widget);
if(!w2) return;
std::string selection = w2->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (UserConfigParams::logGUI())
{
Log::info("VoteOverview", "Clicked on track '%s'.",
selection.c_str());
}
UserConfigParams::m_last_track = selection;
if (selection == "locked" && race_manager->getNumLocalPlayers() == 1)
{
unlock_manager->playLockSound();
return;
}
else if (selection == RibbonWidget::NO_ITEM_ID)
{
return;
}
if (selection == "random_track")
{
if (m_random_track_list.empty()) return;
selection = m_random_track_list.front();
m_random_track_list.pop_front();
m_random_track_list.push_back(selection);
} // selection=="random_track"
} // name=="tracks"
else if (name == "back")
{
StateManager::get()->escapePressed();
}
} // eventCallback
// -----------------------------------------------------------------------------
bool VoteOverview::onEscapePressed()
{
if (m_quit_server)
{
// Remove this screen
StateManager::get()->popMenu();
STKHost::get()->shutdown();
}
else
{
auto cl = LobbyProtocol::get<ClientLobby>();
if (cl)
cl->clearPlayers();
}
// remove the screen
return true;
} // onEscapePressed
// -----------------------------------------------------------------------------
void VoteOverview::tearDown()
{
m_quit_server = false;
} // tearDown
m_quit_server = false;
m_bottom_box_height = -1;
} // VoteOverview
// -----------------------------------------------------------------------------
void VoteOverview::loadedFromFile()
@ -146,10 +83,7 @@ void VoteOverview::beforeAddingWidget()
RaceManager::MinorRaceModeType minor_mode = race_manager->getMinorMode();
bool is_soccer = minor_mode == RaceManager::MINOR_MODE_SOCCER;
bool is_arena = is_soccer || minor_mode == RaceManager::MINOR_MODE_BATTLE;
//DynamicRibbonWidget* tracks_widget = getWidget<DynamicRibbonWidget>("tracks");
//tracks_widget->setItemCountHint( (int)track_manager->getNumberOfTracks()+1 );
} // beforeAddingWidget
@ -168,14 +102,193 @@ void VoteOverview::init()
back_button->setImage("gui/icons/back.png");
}
for (unsigned int i = 0; i < 8; i++)
{
std::string s = StringUtils::insertValues("track-%d", i);
IconButtonWidget *track_widget = getWidget<IconButtonWidget>(s.c_str());
track_widget->setVisible(false);
}
for(auto host_id: m_index_to_hostid)
showVote(host_id);
} // init
// -----------------------------------------------------------------------------
void VoteOverview::tearDown()
{
m_quit_server = false;
} // tearDown
// -----------------------------------------------------------------------------
/** Selects in which part of the grid the new host is being shown and stores
* this information in the m_index_to_hostid mapping. If the host_id is
* already mapped, this is ignored (this can happen in case one host changes
* its vote.
* \param host_id Index of the host that is voting.
*/
void VoteOverview::addVote(int host_id)
{
auto it = std::find(m_index_to_hostid.begin(), m_index_to_hostid.end(),
host_id);
Log::verbose("VO", "hostid %d new %d",
host_id, it==m_index_to_hostid.end());
// Add a new index if this is the first vote for the host/
if (it == m_index_to_hostid.end())
{
m_index_to_hostid.push_back(host_id);
}
if(GUIEngine::getCurrentScreen() == this)
showVote(host_id);
} // addVote
// ----------------------------------------------------------------------------
/** Populates the one box in the voting screen with the vote from the
* corresponding host. A mapping of host_id to index MUST exist for this
* host.
* \param host_id Host id from hich a new vote was received.
*/
void VoteOverview::showVote(int host_id)
{
auto it = std::find(m_index_to_hostid.begin(), m_index_to_hostid.end(),
host_id);
assert(it!=m_index_to_hostid.end());
int index = *it;
auto lp = LobbyProtocol::get<LobbyProtocol>();
const LobbyProtocol::PeerVote *vote = lp->getVote(host_id);
assert(vote);
std::string s = StringUtils::insertValues("name-%d", index);
LabelWidget *name_widget = getWidget<LabelWidget>(s.c_str());
name_widget->setText(_("Name: %s", vote->m_player_name), true);
s = StringUtils::insertValues("track-%d", index);
IconButtonWidget *track_widget = getWidget<IconButtonWidget>(s.c_str());
Track *track = track_manager->getTrack(vote->m_track_name);
track_widget->setVisible(true);
track_widget->setImage(track->getScreenshotFile());
s = StringUtils::insertValues("numlaps-%d", index);
LabelWidget *laps_widget = getWidget<LabelWidget>(s.c_str());
laps_widget->setText(_("Laps: %d", vote->m_num_laps), true);
s = StringUtils::insertValues("reverse-%d", index);
LabelWidget *reverse_widget = getWidget<LabelWidget>(s.c_str());
reverse_widget->setText(_("Reverse: %s", vote->m_reverse ? _("yes")
: _("no")), true);
} // addVote
// -----------------------------------------------------------------------------
void VoteOverview::onUpdate(float dt)
{
// Show the remaining time:
auto lp = LobbyProtocol::get<LobbyProtocol>();
float new_value = lp->getRemainingVotingTime() / lp->getMaxVotingTime();
if (new_value < 0) new_value = 0;
m_timer->moveValue(int(new_value * 100));
if(m_index_to_hostid.size()==0) return;
static float xx = 0.0f;
xx += dt;
int index = int(xx) % m_index_to_hostid.size();
std::string box_name = StringUtils::insertValues("rect-box%d", index);
Widget *box = getWidget(box_name.c_str());
box->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
std::string s = StringUtils::insertValues("name-%d", index);
LabelWidget *name_widget = getWidget<LabelWidget>(s.c_str());
name_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
name_widget->setErrorColor();
s = StringUtils::insertValues("name-%d", 1-index);
name_widget = getWidget<LabelWidget>(s.c_str());
name_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
name_widget->setDefaultColor();
#ifdef XX
std::string s = StringUtils::insertValues("box-%d", index);
LabelWidget *name_widget = getWidget<>(s.c_str());
//assert(box);
std::string num_laps = StringUtils::insertValues("numlaps-%d", i);
LabelWidget *laps_widget = getWidget<LabelWidget>(num_laps.c_str());
core::stringw laps = _("Laps: %d", vote->m_num_laps);
laps_widget->setText(laps, true);
std::string track_widget_name = StringUtils::insertValues("track-%d", i);
IconButtonWidget *track_widget =
getWidget<IconButtonWidget>(track_widget_name.c_str());
Track *track = track_manager->getTrack(vote->m_track_name);
track_widget->setImage(track->getScreenshotFile());
}
calculateLayout();
#endif
} // onUpdate
// -----------------------------------------------------------------------------
/** Called on any event, e.g. user input.
*/
void VoteOverview::eventCallback(Widget* widget, const std::string& name,
const int playerID)
{
if (name == "tracks")
{
DynamicRibbonWidget* w2 = dynamic_cast<DynamicRibbonWidget*>(widget);
if (!w2) return;
std::string selection = w2->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (UserConfigParams::logGUI())
{
Log::info("VoteOverview", "Clicked on track '%s'.",
selection.c_str());
}
UserConfigParams::m_last_track = selection;
if (selection == "locked" && race_manager->getNumLocalPlayers() == 1)
{
unlock_manager->playLockSound();
return;
}
else if (selection == RibbonWidget::NO_ITEM_ID)
{
return;
}
} // name=="tracks"
else if (name == "back")
{
StateManager::get()->escapePressed();
}
} // eventCallback
// -----------------------------------------------------------------------------
bool VoteOverview::onEscapePressed()
{
if (m_quit_server)
{
// Remove this screen
StateManager::get()->popMenu();
STKHost::get()->shutdown();
}
else
{
auto ts = TracksScreen::getInstance();
if (ts)
ts->setNetworkTracks();
}
// remove the screen
return true;
} // onEscapePressed

View File

@ -20,10 +20,9 @@
#include "guiengine/screen.hpp"
#include "utils/synchronised.hpp"
#include <deque>
#include <limits>
#include <map>
#include <string>
#include <vector>
namespace GUIEngine
{
@ -47,20 +46,15 @@ private:
* (going backwards). */
GUIEngine::ProgressBarWidget *m_timer;
bool m_reverse_checked, m_quit_server;
int m_bottom_box_height;
std::map<std::string, core::stringw> m_vote_messages;
/** This stores which vote (hostid) is shown at which index in
* the result gui. */
std::vector<int> m_index_to_hostid;
std::deque<std::string> m_random_track_list;
bool m_quit_server;
VoteOverview() : Screen("online/vote_overview.stkgui")
{
m_reverse_checked = false;
m_quit_server = false;
m_bottom_box_height = -1;
}
VoteOverview();
public:
@ -86,18 +80,21 @@ public:
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void onUpdate(float dt) OVERRIDE;
void addVote(int host_id);
void showVote(int host_id);
// ------------------------------------------------------------------------
void setQuitServer() { m_quit_server = true; }
// ------------------------------------------------------------------------
void resetVote()
{
m_vote_messages.clear();
m_index_to_hostid.clear();
}
// ------------------------------------------------------------------------
void addVoteMessage(const std::string& user,
const irr::core::stringw& message)
{
m_vote_messages[user] = message;
}
};