server fetching and selection

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/uni@13193 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
unitraxx 2013-07-12 01:07:26 +00:00
parent 2bf2ed0002
commit 8dd9314eaf
8 changed files with 559 additions and 0 deletions

View File

@ -0,0 +1,17 @@
<stkgui>
<div x="0%" y="0%" width="100%" height="98%" layout="vertical-row" >
<div x="0" y="0" width="100%" layout="horizontal-row" height="8%">
<icon-button id="back" height="100%" icon="gui/back.png"/>
<header text_align="center" proportion="1" text="Server Selection" align="center"/>
<icon-button id="reload" height="90%" icon="gui/restart.png"/>
</div>
<box proportion="1" width="98%" align="center" layout="vertical-row" padding="6">
<list id="server_list" x="0" y="0" width="100%" height="100%"/>
</box>
</div>
</stkgui>

View File

@ -147,6 +147,7 @@ src/network/race_state.cpp
src/online/current_online_user.cpp
src/online/http_connector.cpp
src/online/online_user.cpp
src/online/server.cpp
src/physics/btKart.cpp
src/physics/btKartRaycast.cpp
src/physics/btUprightConstraint.cpp
@ -205,6 +206,7 @@ src/states_screens/race_gui.cpp
src/states_screens/race_gui_overworld.cpp
src/states_screens/race_result_gui.cpp
src/states_screens/race_setup_screen.cpp
src/states_screens/server_selection.cpp
src/states_screens/soccer_setup_screen.cpp
src/states_screens/state_manager.cpp
src/states_screens/story_mode_lobby.cpp
@ -412,6 +414,7 @@ src/network/world_loaded_message.hpp
src/online/current_online_user.hpp
src/online/http_connector.hpp
src/online/online_user.hpp
src/online/server.hpp
src/physics/btKart.hpp
src/physics/btKartRaycast.hpp
src/physics/btUprightConstraint.hpp
@ -473,6 +476,7 @@ src/states_screens/race_gui.hpp
src/states_screens/race_gui_overworld.hpp
src/states_screens/race_result_gui.hpp
src/states_screens/race_setup_screen.hpp
src/states_screens/server_selection.hpp
src/states_screens/soccer_setup_screen.hpp
src/states_screens/state_manager.hpp
src/states_screens/story_mode_lobby.hpp

View File

@ -176,6 +176,33 @@ bool CurrentOnlineUser::signOut(){
return !m_is_signed_in;
}
// ============================================================================
PtrVector<Server> * CurrentOnlineUser::getServerList(){
assert(m_is_signed_in == true);
HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
connector->setParameter("action",std::string("get_server_list"));
connector->setParameter("token",m_token);
connector->setParameter("userid",m_id);
const XMLNode * result = connector->getXMLFromPage();
std::string rec_success = "";
if(result->get("success", &rec_success))
{
if (rec_success =="yes")
{
const XMLNode * servers_xml = result->getNode("servers");
PtrVector<Server> * servers = new PtrVector<Server>;
for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++)
{
servers->push_back(new Server(*servers_xml->getNode(i)));
}
return servers;
}
}
return NULL;
}
// ============================================================================
irr::core::stringw CurrentOnlineUser::getUserName() const

View File

@ -22,6 +22,8 @@
#include "online/online_user.hpp"
#include <string>
#include <irrString.h>
#include "utils/ptr_vector.hpp"
#include "online/server.hpp"
// ============================================================================
@ -62,6 +64,8 @@ class CurrentOnlineUser : public OnlineUser
int max_players,
irr::core::stringw &info);
PtrVector<Server> * getServerList();
/** Returns the username if signed in. */
irr::core::stringw getUserName() const;
bool isSignedIn(){ return m_is_signed_in; }

84
src/online/server.cpp Normal file
View File

@ -0,0 +1,84 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe
//
// 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.
/**
\page online Online
*/
#include "online/server.hpp"
#include "io/xml_node.hpp"
#include "utils/constants.hpp"
#include "utils/string_utils.hpp"
Server::SortOrder Server::m_sort_order=Server::SO_NAME;
Server::Server(const XMLNode & xml)
{
assert(xml.getName() == "server");
m_name = "";
m_server_id = 0;
m_description = "";
m_current_players = 0;
m_max_players = 0;
xml.get("name", &m_lower_case_name);
m_name = StringUtils::decodeFromHtmlEntities(m_lower_case_name);
m_lower_case_name = StringUtils::toLowerCase(m_lower_case_name);
std::string description;
xml.get("description", &description);
m_description = StringUtils::decodeFromHtmlEntities(description);
// resolve XML entities
//m_description = StringUtils::replace(m_description, "&#10;", "\n");
//m_description = StringUtils::replace(m_description, "&#13;", ""); // ignore \r
xml.get("id", &m_server_id);
xml.get("max_players", &m_max_players);
xml.get("current_players", &m_current_players);
}; // Server(const XML&)
// ----------------------------------------------------------------------------
/**
* \brief Filter the add-on with a list of words.
* \param words A list of words separated by ' '.
* \return true if the add-on contains one of the words, otherwise false.
*/
bool Server::filterByWords(const core::stringw words) const
{
if (words == NULL || words.empty())
return true;
std::vector<core::stringw> list = StringUtils::split(words, ' ', false);
for (unsigned int i = 0; i < list.size(); i++)
{
list[i].make_lower();
if ((core::stringw(m_name).make_lower()).find(list[i].c_str()) != -1)
{
return true;
}
if ((core::stringw(m_description)).make_lower().find(list[i].c_str()) != -1)
{
return true;
}
}
return false;
} // filterByWords

135
src/online/server.hpp Normal file
View File

@ -0,0 +1,135 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe
//
// 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_SERVER_HPP
#define HEADER_SERVER_HPP
/**
* \defgroup onlinegroup Online
* Represents a server that is joinable
*/
#include <string>
#include <irrString.h>
#include "io/xml_node.hpp"
class XMLNode;
/**
* \ingroup online
*/
class Server
{
public:
/** Set the sort order used in the comparison function. */
enum SortOrder { SO_SCORE = 1, // Sorted on satisfaction score
SO_NAME = 2, // Sorted alphabetically by name
SO_PLAYERS = 4
};
protected:
/** The name to be displayed. */
irr::core::stringw m_name;
std::string m_lower_case_name; //Used for comparison
irr::core::stringw m_description;
int m_server_id;
int m_max_players;
int m_current_players;
float m_satisfaction_score;
/** The sort order to be used in the comparison. */
static SortOrder m_sort_order;
Server() {};
public:
/** Initialises the object from an XML node. */
Server(const XMLNode & xml);
// ------------------------------------------------------------------------
/** Sets the sort order used in the comparison function. It is static, so
* that each instance can access the sort order. */
static void setSortOrder(SortOrder so) { m_sort_order = so; }
// ------------------------------------------------------------------------
/** Returns the name of the server. */
const irr::core::stringw& getName() const { return m_name; }
const std::string & getLowerCaseName() const { return m_lower_case_name; }
// ------------------------------------------------------------------------
/** Returns the name of the server. */
const irr::core::stringw& getDescription() const { return m_description; }
// ------------------------------------------------------------------------
const float getScore() const { return m_satisfaction_score; }
// ------------------------------------------------------------------------
/** Returns the ID of this server. */
const int getServerId() const { return m_server_id; }
const int getMaxPlayers() const { return m_max_players; }
const int getCurrentPlayers() const { return m_current_players; }
// ------------------------------------------------------------------------
bool filterByWords(const irr::core::stringw words) const;
// ------------------------------------------------------------------------
/** Compares two servers according to the sort order currently defined.
* \param a The addon to compare this addon to.
*/
bool operator<(const Server &server) const
{
switch(m_sort_order)
{
case SO_SCORE:
return m_satisfaction_score < server.getScore();
break;
case SO_NAME:
// m_id is the lower case name
return m_name < server.getName();
break;
} // switch
return true;
} // operator<
// ------------------------------------------------------------------------
/** Compares two addons according to the sort order currently defined.
* Comparison is done for sorting in descending order.
* \param a The addon to compare this addon to.
*/
bool operator>(const Server &server) const
{
switch(m_sort_order)
{
/*case SO_SCORE:
return m_satisfaction_score > server.getScore();
break;*/
case SO_NAME:
return m_lower_case_name > server.getLowerCaseName();
break;
case SO_PLAYERS:
return m_current_players > server.getCurrentPlayers();
break;
} // switch
return true;
} // operator>
}; // Server
#endif

View File

@ -0,0 +1,194 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2010 Lucas Baudin, Joerg Henrichs
//
// 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/server_selection.hpp"
#include <iostream>
#include <assert.h>
#include "guiengine/modaldialog.hpp"
#include "guiengine/widget.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include "online/current_online_user.hpp"
DEFINE_SCREEN_SINGLETON( ServerSelection );
// ----------------------------------------------------------------------------
ServerSelection::ServerSelection() : Screen("server_selection.stkgui")
{
m_selected_index = -1;
m_reload_timer = 0.0f;
} // ServerSelection
// ----------------------------------------------------------------------------
void ServerSelection::loadedFromFile()
{
m_back_widget = getWidget<GUIEngine::IconButtonWidget>("back");
m_reload_widget = getWidget<GUIEngine::IconButtonWidget>("reload");
m_server_list_widget = getWidget<GUIEngine::ListWidget>("server_list");
assert(m_server_list_widget != NULL);
m_server_list_widget->setColumnListener(this);
m_servers = CurrentOnlineUser::get()->getServerList();
} // loadedFromFile
// ----------------------------------------------------------------------------
void ServerSelection::beforeAddingWidget()
{
m_server_list_widget->clearColumns();
m_server_list_widget->addColumn( _("Name"), 4 );
m_server_list_widget->addColumn( _("Players"), 1 );
m_server_list_widget->addColumn( _("Max"), 1 );
}
// ----------------------------------------------------------------------------
void ServerSelection::init()
{
Screen::init();
m_reloading = false;
m_sort_desc = true;
m_reload_widget->setActivated();
// Set the default sort order
Server::setSortOrder(Server::SO_NAME);
loadList();
} // init
// ----------------------------------------------------------------------------
void ServerSelection::unloaded()
{
}
// ----------------------------------------------------------------------------
void ServerSelection::tearDown()
{
}
// ----------------------------------------------------------------------------
/** Loads the list of all servers. The gui element will be
* updated.
* \param type Must be 'kart' or 'track'.
*/
void ServerSelection::loadList()
{
// First create a list of sorted entries
m_servers->insertionSort(/*start=*/0, m_sort_desc);
m_server_list_widget->clear();
for(int i=0; i<m_servers->size(); i++)
{
core::stringw table_entry;
table_entry.append((*m_servers)[i].getName());
table_entry.append("\t");
table_entry.append((*m_servers)[i].getCurrentPlayers());
table_entry.append("\t");
table_entry.append((*m_servers)[i].getMaxPlayers());
m_server_list_widget->addItem("server", table_entry);
}
} // loadList
// ----------------------------------------------------------------------------
void ServerSelection::onColumnClicked(int column_id)
{
switch(column_id)
{
case 0: Server::setSortOrder(Server::SO_NAME); break;
case 1: Server::setSortOrder(Server::SO_PLAYERS); break;
case 2: Server::setSortOrder(Server::SO_PLAYERS); break;
default: assert(0); break;
} // switch
/** \brief Toggle the sort order after column click **/
m_sort_desc = !m_sort_desc;
loadList();
} // onColumnClicked
// ----------------------------------------------------------------------------
void ServerSelection::eventCallback( GUIEngine::Widget* widget,
const std::string& name,
const int playerID)
{
if (name == "back")
{
StateManager::get()->escapePressed();
}
else if (name == "reload")
{
if (!m_reloading)
{
m_reloading = true;
m_server_list_widget->clear();
m_server_list_widget->addItem("spacer", L"");
m_server_list_widget->addItem("loading", _("Please wait while the list is being updated."));
}
}
else if (name == m_server_list_widget->m_properties[GUIEngine::PROP_ID])
{
m_selected_index = m_server_list_widget->getSelectionID();
//new ServerInfoDialog(0.8f, 0.8f, id);
}
} // eventCallback
// ----------------------------------------------------------------------------
/** Selects the last selected item on the list (which is the item that
* is just being installed) again. This function is used from the
* addons_loading screen: when it is closed, it will reset the
* select item so that people can keep on installing from that
* point on.
*/
void ServerSelection::setLastSelected()
{
if(m_selected_index>-1)
{
m_server_list_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
m_server_list_widget->setSelectionID(m_selected_index);
}
} // setLastSelected
// ----------------------------------------------------------------------------
void ServerSelection::onUpdate(float dt, irr::video::IVideoDriver*)
{
m_reload_timer += dt;
if (m_reloading)
{
m_reloading = false;
if(m_reload_timer > 5000.0f)
{
m_servers = CurrentOnlineUser::get()->getServerList();
m_reload_timer = 0.0f;
}
loadList();
}
} // onUpdate

View File

@ -0,0 +1,94 @@
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 Glenn De Jonghe
//
// 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_SERVER_SELECTION_HPP
#define HEADER_SERVER_SELECTION_HPP
#include "guiengine/screen.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "utils/ptr_vector.hpp"
#include "online/server.hpp"
namespace GUIEngine { class Widget; }
/**
* \brief ServerSelection
* \ingroup states_screens
*/
class ServerSelection : public GUIEngine::Screen,
public GUIEngine::ScreenSingleton<ServerSelection>,
public GUIEngine::IListWidgetHeaderListener
{
friend class GUIEngine::ScreenSingleton<ServerSelection>;
private:
ServerSelection();
GUIEngine::IconButtonWidget * m_back_widget;
GUIEngine::IconButtonWidget * m_reload_widget;
GUIEngine::LabelWidget * m_update_status;
GUIEngine::ListWidget * m_server_list_widget;
/** Currently selected type. */
std::string m_type;
/** The currently selected index, used to re-select this item after
* addons_loading is being displayed. */
int m_selected_index;
bool m_reloading;
/** \brief To check (and set) if sort order is descending **/
bool m_sort_desc;
float m_reload_timer;
PtrVector<Server> * m_servers;
public:
/** Load the addons into the main list.*/
void loadList();
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() OVERRIDE;
virtual void unloaded() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
const int playerID) OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void beforeAddingWidget() OVERRIDE;
virtual void onColumnClicked(int columnId);
virtual void init() OVERRIDE;
virtual void tearDown() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void onUpdate(float dt, irr::video::IVideoDriver*) OVERRIDE;
void setLastSelected();
};
#endif