From d6d879d2ed66cf67be6dfc28fc74d7397550b78d Mon Sep 17 00:00:00 2001 From: hiker Date: Sat, 1 Dec 2018 09:32:21 +1100 Subject: [PATCH] Show votes in vote overview screen. This is NOT fully working, and contains debug output. --- data/gui/screens/online/vote_overview.stkgui | 32 +++ src/network/protocols/client_lobby.cpp | 9 +- src/network/protocols/lobby_protocol.cpp | 10 + src/network/protocols/lobby_protocol.hpp | 49 +++- src/network/protocols/server_lobby.cpp | 7 +- src/states_screens/online/tracks_screen.cpp | 28 +- src/states_screens/online/vote_overview.cpp | 263 +++++++++++++------ src/states_screens/online/vote_overview.hpp | 27 +- 8 files changed, 321 insertions(+), 104 deletions(-) diff --git a/data/gui/screens/online/vote_overview.stkgui b/data/gui/screens/online/vote_overview.stkgui index 888aa0f9c..2a272e4df 100644 --- a/data/gui/screens/online/vote_overview.stkgui +++ b/data/gui/screens/online/vote_overview.stkgui @@ -9,23 +9,55 @@
+ + + +
+ + + +
diff --git a/src/network/protocols/client_lobby.cpp b/src/network/protocols/client_lobby.cpp index a37f7cefc..8173c45f2 100644 --- a/src/network/protocols/client_lobby.cpp +++ b/src/network/protocols/client_lobby.cpp @@ -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 diff --git a/src/network/protocols/lobby_protocol.cpp b/src/network/protocols/lobby_protocol.cpp index 0c234f0e1..5cfb8edd8 100644 --- a/src/network/protocols/lobby_protocol.cpp +++ b/src/network/protocols/lobby_protocol.cpp @@ -34,6 +34,16 @@ std::weak_ptr 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) { diff --git a/src/network/protocols/lobby_protocol.hpp b/src/network/protocols/lobby_protocol.hpp index 2ebbc9a9c..0f126be6d 100644 --- a/src/network/protocols/lobby_protocol.hpp +++ b/src/network/protocols/lobby_protocol.hpp @@ -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 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 diff --git a/src/network/protocols/server_lobby.cpp b/src/network/protocols/server_lobby.cpp index 892f4e769..c1975441e 100644 --- a/src/network/protocols/server_lobby.cpp +++ b/src/network/protocols/server_lobby.cpp @@ -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 diff --git a/src/states_screens/online/tracks_screen.cpp b/src/states_screens/online/tracks_screen.cpp index 7f49f56f3..4dc147831 100644 --- a/src/states_screens/online/tracks_screen.cpp +++ b/src/states_screens/online/tracks_screen.cpp @@ -338,7 +338,19 @@ void TracksScreen::init() //I18N: In track screen getWidget("reverse-text")->setText(_("Drive in reverse"), false); m_reversed->setVisible(true); - m_reversed->setState(m_reverse_checked); + + auto lp = LobbyProtocol::get(); + 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(); + + // The vote will be sent to + lp->addVote(STKHost::get()->getMyHostId(), pvote); } STKHost::get()->sendToServer(&vote, true); } // voteForPlayer diff --git a/src/states_screens/online/vote_overview.cpp b/src/states_screens/online/vote_overview.cpp index 0b2aa8f56..48693d787 100644 --- a/src/states_screens/online/vote_overview.cpp +++ b/src/states_screens/online/vote_overview.cpp @@ -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(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(); - 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("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(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(); + const LobbyProtocol::PeerVote *vote = lp->getVote(host_id); + assert(vote); + + std::string s = StringUtils::insertValues("name-%d", index); + LabelWidget *name_widget = getWidget(s.c_str()); + name_widget->setText(_("Name: %s", vote->m_player_name), true); + + s = StringUtils::insertValues("track-%d", index); + IconButtonWidget *track_widget = getWidget(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(s.c_str()); + laps_widget->setText(_("Laps: %d", vote->m_num_laps), true); + + s = StringUtils::insertValues("reverse-%d", index); + LabelWidget *reverse_widget = getWidget(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(); 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(s.c_str()); + name_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER); + name_widget->setErrorColor(); + + s = StringUtils::insertValues("name-%d", 1-index); + name_widget = getWidget(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(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(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(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 + diff --git a/src/states_screens/online/vote_overview.hpp b/src/states_screens/online/vote_overview.hpp index a0133e148..a9e0645b1 100644 --- a/src/states_screens/online/vote_overview.hpp +++ b/src/states_screens/online/vote_overview.hpp @@ -20,10 +20,9 @@ #include "guiengine/screen.hpp" #include "utils/synchronised.hpp" -#include -#include -#include + #include +#include 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 m_vote_messages; + /** This stores which vote (hostid) is shown at which index in + * the result gui. */ + std::vector m_index_to_hostid; - std::deque 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; } };