Add player rankings in achievements

This commit is contained in:
Benau 2018-05-20 01:15:39 +08:00
parent 06d0dafcbf
commit fdc299e073
6 changed files with 343 additions and 2 deletions

View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="2%" width="100%" height="96%" layout="vertical-row">
<header id="title" width="96%" height="fit" text_align="center"
word_wrap="true" I18N="In player rankings dialog"
text="Top 10 players"/>
<box x="2%" width="90%" height="60%" align="center" layout="vertical-row"
padding="6">
<list id="top-ten" x="0" y="0" width="100%" height="100%"/>
</box>
<label id="cur-rank" proportion="1" width="90%" align="center"
text_align="center" word_wrap="true" text=""/>
<buttonbar id="options" width="90%" height="10%" align="center">
<icon-button id="ok" width="16" height="16"
icon="gui/green_check.png" text="OK"
label_location="bottom"/>
<icon-button id="refresh" width="16" height="16"
icon="gui/restart.png"
text="Refresh" label_location="bottom"/>
</buttonbar>
<spacer width="20" height="2%" />
</div>
</stkgui>

View File

@ -18,5 +18,6 @@
<box proportion="1" width="100%" layout="vertical-row" padding="6">
<list id="achievements_list" x="0" y="0" width="100%" height="100%"/>
</box>
<button id="rankings" I18N="In the achievements screen" text="Player rankings"/>
</div>
</stkgui>

View File

@ -1,5 +1,5 @@
# Modify this file to change the last-modified date when you add/remove a file.
# This will then trigger a new cmake run automatically.
# This will then trigger a new cmake run automatically.
file(GLOB_RECURSE STK_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.hpp")
file(GLOB_RECURSE STK_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "src/*.cpp")
file(GLOB_RECURSE STK_SHADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "data/shaders/*")

View File

@ -0,0 +1,210 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 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 "states_screens/dialogs/player_rankings_dialog.hpp"
#include "config/player_manager.hpp"
#include "guiengine/dialog_queue.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "online/online_profile.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include <IGUIEnvironment.h>
using namespace GUIEngine;
using namespace irr;
using namespace irr::gui;
using namespace Online;
// ============================================================================
std::vector<std::tuple<int, core::stringw, float> >
PlayerRankingsDialog::m_rankings;
// ----------------------------------------------------------------------------
PlayerRankingsDialog::PlayerRankingsDialog(uint32_t online_id,
const core::stringw& name)
: ModalDialog(0.8f,0.9f), m_online_id(online_id),
m_name(name), m_self_destroy(false)
{
loadFromFile("online/player_rankings_dialog.stkgui");
m_top_ten = getWidget<ListWidget>("top-ten");
assert(m_top_ten != NULL);
if (m_rankings.empty())
updateTopTen();
else
addTopTen();
} // PlayerRankingsDialog
// -----------------------------------------------------------------------------
void PlayerRankingsDialog::beforeAddingWidgets()
{
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_ok_widget = getWidget<IconButtonWidget>("ok");
assert(m_ok_widget != NULL);
m_refresh_widget = getWidget<IconButtonWidget>("refresh");
assert(m_refresh_widget != NULL);
m_options_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
m_ranking_info = getWidget<LabelWidget>("cur-rank");
assert(m_ranking_info != NULL);
core::stringw fetching = _("Fetching ranking info for %s.", m_name);
m_ranking_info->setText(fetching, false);
updatePlayerRanking();
} // beforeAddingWidgets
// -----------------------------------------------------------------------------
void PlayerRankingsDialog::updatePlayerRanking()
{
class UpdatePlayerRankingRequest : public XMLRequest
{
// ------------------------------------------------------------------------
/** Callback for the request to send a friend invitation. Shows a
* confirmation message and takes care of updating all the cached
* information.
*/
virtual void callback()
{
PlayerRankingsDialog* prd = dynamic_cast<PlayerRankingsDialog*>
(getCurrent());
if (prd == NULL)
return;
core::stringw result = _("%s has no ranking yet.", prd->m_name);
if (isSuccess())
{
int rank = -1;
float score = 0.0;
getXMLData()->get("rank", &rank);
getXMLData()->get("scores", &score);
if (rank > 0)
{
result = _("%s has a rank of %d with score %d.",
prd->m_name, rank, (int)score);
}
}
prd->m_ranking_info->setText(result, false);
} // callback
public:
UpdatePlayerRankingRequest() : XMLRequest(true) {}
}; // UpdatePlayerRankingRequest
// ------------------------------------------------------------------------
UpdatePlayerRankingRequest* request = new UpdatePlayerRankingRequest();
PlayerManager::setUserDetails(request, "get-ranking");
request->addParameter("id", m_online_id);
request->queue();
} // updatePlayerRanking
// ----------------------------------------------------------------------------
void PlayerRankingsDialog::updateTopTen()
{
// ----------------------------------------------------------------
class UpdateTopTenRequest : public XMLRequest
{
/** Callback for the request to accept a friend invitation. Shows a
* confirmation message and takes care of updating all the cached
* information.
*/
virtual void callback()
{
if (isSuccess())
{
PlayerRankingsDialog* prd = dynamic_cast<PlayerRankingsDialog*>
(getCurrent());
if (prd == NULL)
return;
prd->m_rankings.clear();
const XMLNode* players = getXMLData()->getNode("players");
for (unsigned i = 0; i < players->getNumNodes(); i++)
{
int rank;
core::stringw user;
float score;
players->getNode(i)->get("rank", &rank);
players->getNode(i)->get("username", &user);
players->getNode(i)->get("scores", &score);
prd->m_rankings.emplace_back(rank, user, score);
}
prd->addTopTen();
}
} // callback
public:
UpdateTopTenRequest() : XMLRequest(true) {}
}; // UpdateTopTenRequest
// ------------------------------------------------------------------------
UpdateTopTenRequest *request = new UpdateTopTenRequest();
PlayerManager::setUserDetails(request, "top-players");
request->addParameter("ntop", 10);
request->queue();
} // updateTopTen
// -----------------------------------------------------------------------------
void PlayerRankingsDialog::addTopTen()
{
m_top_ten->clear();
for (auto& r : m_rankings)
{
std::vector<GUIEngine::ListWidget::ListCell> row;
row.push_back(GUIEngine::ListWidget::ListCell(
StringUtils::toWString(std::get<0>(r)), -1, 1, true));
row.push_back(GUIEngine::ListWidget::ListCell(std::get<1>(r), -1, 3,
true));
row.push_back(GUIEngine::ListWidget::ListCell(
StringUtils::toWString(std::get<2>(r)), -1, 1, true));
m_top_ten->addItem("rank", row);
}
} // addTopTen
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation
PlayerRankingsDialog::processEvent(const std::string& source)
{
if (source == m_options_widget->m_properties[PROP_ID])
{
const std::string& selection =
m_options_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == m_ok_widget->m_properties[PROP_ID])
{
m_self_destroy = true;
return GUIEngine::EVENT_BLOCK;
}
else if (selection == m_refresh_widget->m_properties[PROP_ID])
{
static double timer = StkTime::getRealTime();
// 1 minute per refresh
if (StkTime::getRealTime() < timer + 60.0)
return GUIEngine::EVENT_BLOCK;
timer = StkTime::getRealTime();
updatePlayerRanking();
updateTopTen();
return GUIEngine::EVENT_BLOCK;
}
}
return GUIEngine::EVENT_LET;
} // processEvent

View File

@ -0,0 +1,98 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2018 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 HEADER_PLAYER_RANKINGS_DIALOG_HPP
#define HEADER_PLAYER_RANKINGS_DIALOG_HPP
#include "guiengine/modaldialog.hpp"
#include "utils/types.hpp"
#include <irrString.h>
#include <tuple>
#include <vector>
namespace GUIEngine
{
class IconButtonWidget;
class LabelWidget;
class ListWidget;
class RibbonWidget;
}
/**
* \brief Dialog that handle user in network lobby
* \ingroup states_screens
*/
class PlayerRankingsDialog : public GUIEngine::ModalDialog
{
private:
const uint32_t m_online_id;
const core::stringw m_name;
bool m_self_destroy;
GUIEngine::RibbonWidget* m_options_widget;
GUIEngine::LabelWidget* m_ranking_info;
GUIEngine::ListWidget* m_top_ten;
GUIEngine::IconButtonWidget* m_refresh_widget;
GUIEngine::IconButtonWidget* m_ok_widget;
static std::vector<std::tuple</*rank*/int, /*user name*/core::stringw,
/*scores*/float> > m_rankings;
// ------------------------------------------------------------------------
void updatePlayerRanking();
// ------------------------------------------------------------------------
void updateTopTen();
// ------------------------------------------------------------------------
void addTopTen();
public:
PlayerRankingsDialog(uint32_t online_id, const core::stringw& name);
// ------------------------------------------------------------------------
~PlayerRankingsDialog() {}
// ------------------------------------------------------------------------
virtual void beforeAddingWidgets();
// ------------------------------------------------------------------------
void onEnterPressedInternal() { m_self_destroy = true; }
// ------------------------------------------------------------------------
GUIEngine::EventPropagation processEvent(const std::string& source);
// ------------------------------------------------------------------------
virtual bool onEscapePressed()
{
m_self_destroy = true;
return false;
}
// ------------------------------------------------------------------------
virtual void onUpdate(float dt)
{
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
ModalDialog::dismiss();
return;
}
}
};
#endif

View File

@ -26,8 +26,9 @@
#include "guiengine/widget.hpp"
#include "online/online_profile.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/player_rankings_dialog.hpp"
#include "states_screens/dialogs/user_info_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include <IGUIButton.h>
@ -151,6 +152,11 @@ void BaseOnlineProfileAchievements::eventCallback(Widget* widget,
new MessageDialog(AchievementsManager::get()
->getAchievementInfo(id)->getDescription());
}
if (name == "rankings")
{
new PlayerRankingsDialog(m_visiting_profile->getID(),
m_visiting_profile->getUserName());
}
} // eventCallback
// ----------------------------------------------------------------------------