merging uni's branch

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13337 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hilnius 2013-07-24 15:43:54 +00:00
commit c5c6c6195f
80 changed files with 4533 additions and 930 deletions

View File

@ -42,6 +42,8 @@ endif()
# Build the irrlicht library
add_subdirectory("${PROJECT_SOURCE_DIR}/lib/irrlicht")
include_directories("${PROJECT_SOURCE_DIR}/lib/irrlicht/include")
include_directories("${PROJECT_SOURCE_DIR}/lib/irrlicht/source/Irrlicht")
# Set include paths

View File

@ -0,0 +1,36 @@
<stkgui>
<div x="0" y="0" width="100%" height="100%" layout="vertical-row" >
<header text_align="center" width="80%" align="center" I18N="In the create server screen" text="Server Creation"/>
<spacer height="15" width="10"/>
<box proportion="4" width="90%" layout="vertical-row" align="center">
<div width="90%" align="center" layout="vertical-row" y="2%" height="96%">
<div width="100%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the create server screen" text="Name of the server"/>
<textbox proportion="1" id="name" I18N="In the create server screen"/>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the create server screen" text="Max. number of players"/>
<gauge id="max_players" proportion="1" min_value="2" max_value="12"/>
</div>
</div>
<label id="info" proportion="1" width="100%" align="center" text_align="center" word_wrap="true" text=""/>
<buttonbar id="options" x="0" y="0" width="25%" height="12%" align="center">
<icon-button id="create" width="64" height="64" icon="gui/green_check.png"
I18N="Main menu button" text="Create" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Main menu button" text="Cancel" label_location="bottom"/>
</buttonbar>
</div>
</box>
<spacer height="15" width="10"/>
</div>
</stkgui>

View File

@ -6,8 +6,10 @@
<div proportion="1" x="2%" width="96%" layout="vertical-row">
<div width="100%" proportion="2" layout="horizontal-row">
<box id="info" proportion="2" height="100%" layout="vertical-row">
<label I18N="In networking lobby" word_wrap="true" text="Description about room"
align="center" text-align="center"/>
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the networking lobby" text="Server name :"/>
<label proportion="2" text_align="left" id="server_name" text=""/>
</div>
</box>
<spacer width="20" height="20"/>
<box proportion="1" height="100%" layout="vertical-row">
@ -36,12 +38,8 @@
<spacer width="10" height="10" />
<buttonbar id="menu_bottomrow" x="0" y="0" width="20%" height="100%" align="center">
<icon-button id="sign_in" width="64" height="64" icon="gui/main_about.png" extend_label="50"
I18N="Main menu button" text="Sign In" label_location="hover"/>
<icon-button id="register" width="64" height="64" icon="gui/tutorial.png" extend_label="75"
I18N="Main menu button" text="Register" label_location="hover"/>
<icon-button id="sign_out" width="64" height="64" icon="gui/main_quit.png" extend_label="70"
I18N="Main menu button" text="Sign Out" label_location="hover"/>
<icon-button id="exit" width="64" height="64" icon="gui/main_quit.png" extend_label="50"
I18N="Main menu button" text="Exit" label_location="hover"/>
</buttonbar>
</bottombar>

View File

@ -7,32 +7,47 @@
<spacer height="20" width="50">
<label id="info" proportion="2" width="90%" align="center" text_align="left" word_wrap="true" text=""/>
<label id="message" proportion="2" width="90%" align="center" text_align="left" word_wrap="true" text=""/>
<spacer height="40" width="50">
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the login dialog" text="Username"/>
<textbox proportion="2" id="username" I18N="In the login dialog"/>
<div proportion="2" height="100%" layout="horizontal-row">
<spacer height="1" width="2%">
<textbox proportion="2" id="username" I18N="In the login dialog"/>
</div>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the login dialog" text="Password"/>
<textbox proportion="2" id="password" I18N="In the login dialog"/>
<div proportion="2" height="100%" layout="horizontal-row">
<spacer height="1" width="2%">
<textbox proportion="2" id="password" I18N="In the login dialog"/>
</div>
</div>
<spacer height="20" width="20">
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the login dialog" text="Stay signed in"/>
<div proportion="2" height="100%" layout="horizontal-row">
<checkbox width="fit" height="fit" id="remember" I18N="In the login dialog"/>
</div>
</div>
</div>
<spacer height="20" width="50">
<spacer height="20" width="50">
<label id="message" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" text=""/>
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" text=""/>
<spacer height="20" width="50">
<buttonbar id="options" width="90%" proportion="1" align="center">
<icon-button id="sign_in" width="64" height="64" icon="gui/main_options.png"
<icon-button id="sign_in" width="64" height="64" icon="gui/green_check.png"
I18N="Login dialog" text="Sign In" label_location="bottom"/>
<icon-button id="recovery" width="64" height="64" icon="gui/main_help.png"
I18N="Login dialog" text="Recovery" label_location="bottom"/>
@ -41,7 +56,7 @@
<icon-button id="as_guest" width="64" height="64" icon="gui/main_about.png"
I18N="Login dialog" text="As guest" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Login dialog" text="Cancel" label_location="bottom"/>
I18N="Login dialog" text="Close" label_location="bottom"/>
</buttonbar>

View File

@ -31,7 +31,7 @@
<spacer width="10" height="10" />
<buttonbar id="menu_bottomrow" x="0" y="0" width="20%" height="100%" align="center">
<buttonbar id="menu_bottomrow" x="0" y="0" width="12%" height="100%" align="center">
<icon-button id="sign_in" width="64" height="64" icon="gui/main_about.png" extend_label="50"
I18N="Main menu button" text="Sign In" label_location="hover"/>
<icon-button id="register" width="64" height="64" icon="gui/tutorial.png" extend_label="75"

View File

@ -15,11 +15,12 @@
<spacer height="20" width="50">
<div id="options" width="fit" proportion="1" align="center" layout="horizontal-row">
<button id="next" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Activate"/>
<spacer height="50" width="50">
<button id="cancel" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Close"/>
</div>
<buttonbar id="options" width="25%" proportion="1" align="center">
<icon-button id="next" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Next" label_location="none"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Registration dialog" text="Cancel" label_location="none"/>
</buttonbar>
</div>

View File

@ -49,12 +49,12 @@
<spacer height="20" width="50">
<div id="options" width="fit" proportion="1" align="center" layout="horizontal-row">
<button id="next" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Next"/>
<spacer height="50" width="50">
<button id="cancel" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Cancel"/>
</div>
<buttonbar id="options" width="25%" proportion="1" align="center">
<icon-button id="next" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Next" label_location="none"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Registration dialog" text="Cancel" label_location="none"/>
</buttonbar>
</div>

View File

@ -7,7 +7,7 @@
<spacer height="20" width="50">
<label id="terms" proportion="6" width="90%" align="center" text_align="center" word_wrap="true"
<label id="terms" proportion="5" width="90%" align="center" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text="The terms will come here. In a fancy scroll box."/>
<div align="center" width="fit" height="fit" layout="horizontal-row" >
@ -17,14 +17,20 @@
</div>
<spacer height="20" width="50">
<div id="options" width="fit" proportion="1" align="center" layout="horizontal-row">
<button id="previous" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Previous"/>
<spacer height="50" width="50">
<button id="next" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Submit"/>
<spacer height="50" width="50">
<button id="cancel" height="fit" align="center" width="fit" I18N="In the registration dialog" text="Cancel"/>
</div>
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true"
I18N="In the registration dialog' dialog" text=""/>
<spacer height="20" width="50">
<buttonbar id="options" width="45%" proportion="1" align="center">
<icon-button id="previous" width="64" height="64" icon="gui/back.png"
I18N="Registration dialog" text="Previous" label_location="bottom"/>
<icon-button id="next" width="64" height="64" icon="gui/green_check.png"
I18N="Registration dialog" text="Submit" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Registration dialog" text="Cancel" label_location="bottom"/>
</buttonbar>
</div>

View File

@ -0,0 +1,33 @@
<stkgui>
<div x="2%" y="5%" width="96%" height="85%" layout="vertical-row" >
<header id="title" width="96%" height="fit" text_align="center" word_wrap="true"
I18N="In the server info dialog' dialog" text="Server Info"/>
<spacer height="20" width="50">
<div width="80%" align="center" layout="vertical-row" height="fit" >
<div width="100%" height="fit" layout="horizontal-row" >
<label proportion="1" text_align="left" I18N="In the server info dialog" text="Name"/>
<label id="name" proportion="2" text_align="left" text=""/>
</div>
</div>
<spacer height="20" width="50">
<label id="info" proportion="1" width="90%" align="center" text_align="center" word_wrap="true" text=""/>
<spacer height="20" width="50">
<buttonbar id="options" width="90%" height="20%" align="center">
<icon-button id="join" width="64" height="64" icon="gui/green_check.png"
I18N="Login dialog" text="Join" label_location="bottom"/>
<icon-button id="cancel" width="64" height="64" icon="gui/main_quit.png"
I18N="Login dialog" text="Cancel" label_location="bottom"/>
</buttonbar>
</div>
</stkgui>

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

@ -63,6 +63,7 @@ src/guiengine/widget.cpp
src/guiengine/widgets/bubble_widget.cpp
src/guiengine/widgets/button_widget.cpp
src/guiengine/widgets/CGUIEditBox.cpp
src/guiengine/widgets/CGUISTKListBox.cpp
src/guiengine/widgets/check_box_widget.cpp
src/guiengine/widgets/dynamic_ribbon_widget.cpp
src/guiengine/widgets/icon_button_widget.cpp
@ -169,9 +170,13 @@ src/network/server_network_manager.cpp
src/network/stk_host.cpp
src/network/stk_peer.cpp
src/network/types.cpp
src/online/current_online_user.cpp
src/online/http_connector.cpp
src/online/online_user.cpp
src/online/current_user.cpp
src/online/http_manager.cpp
src/online/messages.cpp
src/online/request.cpp
src/online/server.cpp
src/online/servers_manager.cpp
src/online/user.cpp
src/physics/btKart.cpp
src/physics/btKartRaycast.cpp
src/physics/btUprightConstraint.cpp
@ -190,6 +195,7 @@ src/replay/replay_play.cpp
src/replay/replay_recorder.cpp
src/states_screens/addons_screen.cpp
src/states_screens/arenas_screen.cpp
src/states_screens/create_server_screen.cpp
src/states_screens/credits.cpp
src/states_screens/cutscene_gui.cpp
src/states_screens/dialogs/add_device_dialog.cpp
@ -205,6 +211,7 @@ src/states_screens/dialogs/press_a_key_dialog.cpp
src/states_screens/dialogs/race_paused_dialog.cpp
src/states_screens/dialogs/registration_dialog.cpp
src/states_screens/dialogs/select_challenge.cpp
src/states_screens/dialogs/server_info_dialog.cpp
src/states_screens/dialogs/track_info_dialog.cpp
src/states_screens/dialogs/tutorial_message_dialog.cpp
src/states_screens/feature_unlocked.cpp
@ -230,6 +237,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
@ -430,9 +438,9 @@ src/network/protocols/client_lobby_room_protocol.hpp
src/network/protocols/connect_to_peer.hpp
src/network/protocols/connect_to_server.hpp
src/network/protocols/controller_events_protocol.hpp
src/network/protocols/game_events_protocol.hpp
src/network/protocols/get_peer_address.hpp
src/network/protocols/get_public_address.hpp
src/network/protocols/game_events_protocol.hpp
src/network/protocols/hide_public_address.hpp
src/network/protocols/kart_update_protocol.hpp
src/network/protocols/lobby_room_protocol.hpp
@ -451,9 +459,13 @@ src/network/singleton.hpp
src/network/stk_host.hpp
src/network/stk_peer.hpp
src/network/types.hpp
src/online/current_online_user.hpp
src/online/http_connector.hpp
src/online/online_user.hpp
src/online/current_user.hpp
src/online/http_manager.hpp
src/online/messages.hpp
src/online/request.hpp
src/online/server.hpp
src/online/servers_manager.hpp
src/online/user.hpp
src/physics/btKart.hpp
src/physics/btKartRaycast.hpp
src/physics/btUprightConstraint.hpp
@ -475,6 +487,7 @@ src/replay/replay_play.hpp
src/replay/replay_recorder.hpp
src/states_screens/addons_screen.hpp
src/states_screens/arenas_screen.hpp
src/states_screens/create_server_screen.hpp
src/states_screens/credits.hpp
src/states_screens/cutscene_gui.hpp
src/states_screens/dialogs/add_device_dialog.hpp
@ -490,6 +503,7 @@ src/states_screens/dialogs/press_a_key_dialog.hpp
src/states_screens/dialogs/race_paused_dialog.hpp
src/states_screens/dialogs/registration_dialog.hpp
src/states_screens/dialogs/select_challenge.hpp
src/states_screens/dialogs/server_info_dialog.hpp
src/states_screens/dialogs/track_info_dialog.hpp
src/states_screens/dialogs/tutorial_message_dialog.hpp
src/states_screens/feature_unlocked.hpp
@ -515,6 +529,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

@ -605,16 +605,48 @@ namespace UserConfigParams
PARAM_DEFAULT( WStringUserConfigParam(L"", "default_player",
"Which player to use by default (if empty, will prompt)") );
// ---- Online multiplayer related
// ---- Internet related
PARAM_PREFIX IntUserConfigParam m_internet_status
PARAM_DEFAULT( IntUserConfigParam(0, "enable_internet",
"Status of internet: 0 user "
"wasn't asked, 1: allowed, 2: "
"not allowed") );
// ---- Online gameplay related
PARAM_PREFIX GroupUserConfigParam m_online_group
PARAM_DEFAULT( GroupUserConfigParam("OnlinePlay",
"Everything related to online play.") );
PARAM_PREFIX StringUserConfigParam m_server_multiplayer
PARAM_DEFAULT( StringUserConfigParam("http://api.stkaddons.net/",
"server_multiplayer",
"The server used for online multiplayer."));
PARAM_DEFAULT( StringUserConfigParam( "http://api.stkaddons.net/",
"server_multiplayer",
&m_online_group,
"The server used for online multiplayer."));
PARAM_PREFIX BoolUserConfigParam m_saved_session
PARAM_DEFAULT( BoolUserConfigParam( false,
"saved_session",
&m_online_group,
"Is there a saved session?") );
PARAM_PREFIX IntUserConfigParam m_saved_user
PARAM_DEFAULT( IntUserConfigParam( 0,
"saved_user",
&m_online_group,
"User ID of the saved session.") );
PARAM_PREFIX StringUserConfigParam m_saved_token
PARAM_DEFAULT( StringUserConfigParam( "",
"saved_token",
&m_online_group,
"Token of the saved session.") );
// ---- Addon server related entries
PARAM_PREFIX GroupUserConfigParam m_addon_group
PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews",
PARAM_DEFAULT( GroupUserConfigParam("AddonAndNews",
"Addon and news related settings") );
PARAM_PREFIX StringUserConfigParam m_server_addons
@ -645,13 +677,6 @@ namespace UserConfigParams
"Don't show important message "
"with this or a lower id again") );
PARAM_PREFIX IntUserConfigParam m_internet_status
PARAM_DEFAULT( IntUserConfigParam(0, "enable_internet",
&m_addon_group,
"Status of internet: 0 user "
"wasn't asked, 1: allowed, 2: "
"not allowed") );
PARAM_PREFIX TimeUserConfigParam m_addons_last_updated
PARAM_DEFAULT( TimeUserConfigParam(0, "addon_last_updated",
&m_addon_group,

View File

@ -105,7 +105,7 @@ namespace GUIEngine
static bool isADialogActive();
/** Override to change what happens on escape pressed */
virtual void escapePressed() { dismiss(); }
virtual bool onEscapePressed() { return true; }
/** Override to be notified of updates */
virtual void onUpdate(float dt) { }

View File

@ -32,7 +32,6 @@ ScalableFont::ScalableFont(IGUIEnvironment *env, const io::path& filename)
m_fallback_kerning_width = 0;
m_fallback_font_scale = 1.0f;
m_scale = 1.0f;
m_tab_stop = 0.5f;
m_is_hollow_copy = false;
m_black_border = false;
m_shadow = false;
@ -500,15 +499,12 @@ void ScalableFont::draw(const core::stringw& text,
core::position2d<s32> offset = position.UpperLeftCorner;
core::dimension2d<s32> text_dimension;
// When we use the "tab" hack, disable right-alignment, it messes up everything
bool has_tab = (text.findFirst(L'\t') != -1);
if ((m_rtl && !has_tab) || hcenter || vcenter || clip)
if (m_rtl || hcenter || vcenter || clip)
{
text_dimension = getDimension(text.c_str());
if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) / 2;
else if (m_rtl && !has_tab) offset.X += (position.getWidth() - text_dimension.Width);
if (hcenter) offset.X += (position.getWidth() - text_dimension.Width) / 2;
else if (m_rtl) offset.X += (position.getWidth() - text_dimension.Width);
if (vcenter) offset.Y += (position.getHeight() - text_dimension.Height) / 2;
if (clip)
@ -519,14 +515,6 @@ void ScalableFont::draw(const core::stringw& text,
}
}
if (m_rtl && has_tab)
{
const int where = text.findFirst(L'\t');
core::stringw substr = text.subString(0, where-1);
text_dimension = getDimension(substr.c_str()) + getDimension(L"XX");
offset.X += (int)(position.getWidth()*m_tab_stop-text_dimension.Width);
}
// ---- collect character locations
const unsigned int text_size = text.size();
core::array<s32> indices(text_size);
@ -537,14 +525,6 @@ void ScalableFont::draw(const core::stringw& text,
{
wchar_t c = text[i];
//hack: one tab character is supported, it moves the cursor to the tab stop
if (c == L'\t')
{
offset.X = (int)(position.UpperLeftCorner.X +
position.getWidth()*m_tab_stop);
continue;
}
if (c == L'\r' || // Windows breaks
c == L'\n' ) // Unix breaks
{

View File

@ -61,9 +61,6 @@ class ScalableFont : public IGUIFontBitmap
bool m_is_hollow_copy;
bool m_rtl;
/** Position in range [0..1] of the single tab stop we support */
float m_tab_stop;
public:
LEAK_CHECK()
@ -145,9 +142,6 @@ public:
void updateRTL();
/** \param pos position of the tab stop, in range [0..1] */
void setTabStop(float pos) { m_tab_stop = pos; }
private:
struct SFontArea

View File

@ -327,6 +327,15 @@ bool Widget::isVisible() const
// -----------------------------------------------------------------------------
bool Widget::isActivated() const
{
if (isVisible())
return !m_deactivated;
return false;
}
// -----------------------------------------------------------------------------
void Widget::setVisible(bool visible)
{
if (m_element != NULL)

View File

@ -326,6 +326,8 @@ namespace GUIEngine
/** Returns if the element is visible. */
bool isVisible() const;
bool isActivated() const;
/**
* Call to resize/move the widget. Not all widgets can resize gracefully.
*/

View File

@ -0,0 +1,757 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// 2013 Glenn De Jonghe
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#include "guiengine/widgets/CGUISTKListBox.h"
#include "IGUISkin.h"
#include "IGUIEnvironment.h"
#include "IVideoDriver.h"
#include "IGUIFont.h"
#include "IGUISpriteBank.h"
#include "CGUIScrollBar.h"
//#include "os.h"
#include "utils/time.hpp"
namespace irr
{
namespace gui
{
//! constructor
CGUISTKListBox::CGUISTKListBox(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip,
bool drawBack, bool moveOverSelect)
: IGUIElement(EGUIET_LIST_BOX, environment, parent, id, rectangle), Selected(-1),
ItemHeight(0),ItemHeightOverride(0),
TotalItemHeight(0), ItemsIconWidth(0), Font(0), IconBank(0),
ScrollBar(0), selectTime(0), LastKeyTime(0), Selecting(false), DrawBack(drawBack),
MoveOverSelect(moveOverSelect), AutoScroll(true), HighlightWhenNotFocused(true)
{
#ifdef _DEBUG
setDebugName("CGUISTKListBox");
#endif
IGUISkin* skin = Environment->getSkin();
const s32 s = skin->getSize(EGDS_SCROLLBAR_SIZE);
ScrollBar = new CGUIScrollBar(false, Environment, this, -1,
core::rect<s32>(RelativeRect.getWidth() - s, 0, RelativeRect.getWidth(), RelativeRect.getHeight()),
!clip);
ScrollBar->setSubElement(true);
ScrollBar->setTabStop(false);
ScrollBar->setAlignment(EGUIA_LOWERRIGHT, EGUIA_LOWERRIGHT, EGUIA_UPPERLEFT, EGUIA_LOWERRIGHT);
ScrollBar->setVisible(false);
ScrollBar->setPos(0);
setNotClipped(!clip);
// this element can be tabbed to
setTabStop(true);
setTabOrder(-1);
updateAbsolutePosition();
}
//! destructor
CGUISTKListBox::~CGUISTKListBox()
{
if (ScrollBar)
ScrollBar->drop();
if (Font)
Font->drop();
if (IconBank)
IconBank->drop();
}
//! returns amount of list items
u32 CGUISTKListBox::getItemCount() const
{
return Items.size();
}
const wchar_t* CGUISTKListBox::getCellText(u32 row_num, u32 col_num) const
{
if ( row_num >= Items.size() )
return 0;
if ( col_num >= Items[row_num].m_contents.size() )
return 0;
return Items[row_num].m_contents[col_num].m_text.c_str();
}
CGUISTKListBox::ListItem CGUISTKListBox::getItem(u32 id) const
{
return Items[id];
}
//! Returns the icon of an item
s32 CGUISTKListBox::getIcon(u32 row_num, u32 col_num) const
{
if ( row_num >= Items.size() )
return -1;
if ( col_num >= Items[row_num].m_contents.size() )
return -1;
return Items[row_num].m_contents[col_num].m_icon;
}
void CGUISTKListBox::removeItem(u32 id)
{
if (id >= Items.size())
return;
if ((u32)Selected==id)
{
Selected = -1;
}
else if ((u32)Selected > id)
{
Selected -= 1;
selectTime = Time::getTimeSinceEpoch();
}
Items.erase(id);
recalculateItemHeight();
}
s32 CGUISTKListBox::getItemAt(s32 xpos, s32 ypos) const
{
if ( xpos < AbsoluteRect.UpperLeftCorner.X || xpos >= AbsoluteRect.LowerRightCorner.X
|| ypos < AbsoluteRect.UpperLeftCorner.Y || ypos >= AbsoluteRect.LowerRightCorner.Y
)
return -1;
if ( ItemHeight == 0 )
return -1;
s32 item = ((ypos - AbsoluteRect.UpperLeftCorner.Y - 1) + ScrollBar->getPos()) / ItemHeight;
if ( item < 0 || item >= (s32)Items.size())
return -1;
return item;
}
//! clears the list
void CGUISTKListBox::clear()
{
Items.clear();
ItemsIconWidth = 0;
Selected = -1;
if (ScrollBar)
ScrollBar->setPos(0);
recalculateItemHeight();
}
void CGUISTKListBox::recalculateItemHeight()
{
IGUISkin* skin = Environment->getSkin();
if (Font != skin->getFont())
{
if (Font)
Font->drop();
Font = skin->getFont();
if ( 0 == ItemHeightOverride )
ItemHeight = 0;
if (Font)
{
if ( 0 == ItemHeightOverride )
ItemHeight = Font->getDimension(L"A").Height + 4;
Font->grab();
}
}
TotalItemHeight = ItemHeight * Items.size();
ScrollBar->setMax( core::max_(0, TotalItemHeight - AbsoluteRect.getHeight()) );
s32 minItemHeight = ItemHeight > 0 ? ItemHeight : 1;
ScrollBar->setSmallStep ( minItemHeight );
ScrollBar->setLargeStep ( 2*minItemHeight );
if ( TotalItemHeight <= AbsoluteRect.getHeight() )
ScrollBar->setVisible(false);
else
ScrollBar->setVisible(true);
}
//! returns id of selected item. returns -1 if no item is selected.
s32 CGUISTKListBox::getSelected() const
{
return Selected;
}
//! sets the selected item. Set this to -1 if no item should be selected
void CGUISTKListBox::setSelected(s32 id)
{
if ((u32)id>=Items.size())
Selected = -1;
else
Selected = id;
selectTime = Time::getTimeSinceEpoch();
recalculateScrollPos();
}
s32 CGUISTKListBox::getRowByCellText(const wchar_t * text)
{
s32 row_index = -1;
s32 col_index = -1;
if (text)
{
for ( row_index = 0; row_index < (s32) Items.size(); ++row_index )
{
for ( col_index = 0; col_index < (s32) Items[row_index].m_contents.size(); ++col_index )
{
if ( Items[row_index].m_contents[col_index].m_text == text ) return row_index;
}
}
}
return -1;
}
//! sets the selected item. Set this to -1 if no item should be selected
void CGUISTKListBox::setSelectedByCellText(const wchar_t * text)
{
setSelected(getRowByCellText(text));
}
s32 CGUISTKListBox::getRowByInternalName(const std::string & text) const
{
s32 row_index = -1;
if (text != "")
{
for ( row_index = 0; row_index < (s32) Items.size(); ++row_index )
{
if (Items[row_index].m_internal_name == text) return row_index;
}
}
return -1;
}
//! called if an event happened.
bool CGUISTKListBox::OnEvent(const SEvent& event)
{
if (isEnabled())
{
switch(event.EventType)
{
case EET_KEY_INPUT_EVENT:
if (event.KeyInput.PressedDown &&
(event.KeyInput.Key == KEY_DOWN ||
event.KeyInput.Key == KEY_UP ||
event.KeyInput.Key == KEY_HOME ||
event.KeyInput.Key == KEY_END ||
event.KeyInput.Key == KEY_NEXT ||
event.KeyInput.Key == KEY_PRIOR ) )
{
s32 oldSelected = Selected;
switch (event.KeyInput.Key)
{
case KEY_DOWN:
Selected += 1;
break;
case KEY_UP:
Selected -= 1;
break;
case KEY_HOME:
Selected = 0;
break;
case KEY_END:
Selected = (s32)Items.size()-1;
break;
case KEY_NEXT:
Selected += AbsoluteRect.getHeight() / ItemHeight;
break;
case KEY_PRIOR:
Selected -= AbsoluteRect.getHeight() / ItemHeight;
break;
default:
break;
}
if (Selected >= (s32)Items.size())
Selected = Items.size() - 1;
else
if (Selected<0)
Selected = 0;
recalculateScrollPos();
// post the news
if (oldSelected != Selected && Parent && !Selecting && !MoveOverSelect)
{
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_LISTBOX_CHANGED;
Parent->OnEvent(e);
}
return true;
}
else
if (!event.KeyInput.PressedDown && ( event.KeyInput.Key == KEY_RETURN || event.KeyInput.Key == KEY_SPACE ) )
{
if (Parent)
{
SEvent e;
e.EventType = EET_GUI_EVENT;
e.GUIEvent.Caller = this;
e.GUIEvent.Element = 0;
e.GUIEvent.EventType = EGET_LISTBOX_SELECTED_AGAIN;
Parent->OnEvent(e);
}
return true;
}
break;
case EET_GUI_EVENT:
switch(event.GUIEvent.EventType)
{
case gui::EGET_SCROLL_BAR_CHANGED:
if (event.GUIEvent.Caller == ScrollBar)
return true;
break;
case gui::EGET_ELEMENT_FOCUS_LOST:
{
if (event.GUIEvent.Caller == this)
Selecting = false;
break;
}
default:
break;
}
break;
case EET_MOUSE_INPUT_EVENT:
{
core::position2d<s32> p(event.MouseInput.X, event.MouseInput.Y);
switch(event.MouseInput.Event)
{
case EMIE_MOUSE_WHEEL:
ScrollBar->setPos(ScrollBar->getPos() + (event.MouseInput.Wheel < 0 ? -1 : 1)*-ItemHeight/2);
return true;
case EMIE_LMOUSE_PRESSED_DOWN:
{
Selecting = true;
return true;
}
case EMIE_LMOUSE_LEFT_UP:
{
Selecting = false;
if (isPointInside(p))
selectNew(event.MouseInput.Y);
return true;
}
case EMIE_MOUSE_MOVED:
if (Selecting || MoveOverSelect)
{
if (isPointInside(p))
{
selectNew(event.MouseInput.Y, true);
return true;
}
}
default:
break;
}
}
break;
case EET_LOG_TEXT_EVENT:
case EET_USER_EVENT:
case EET_JOYSTICK_INPUT_EVENT:
case EGUIET_FORCE_32_BIT:
break;
}
}
return IGUIElement::OnEvent(event);
}
void CGUISTKListBox::selectNew(s32 ypos, bool onlyHover)
{
u32 now = Time::getTimeSinceEpoch();
s32 oldSelected = Selected;
Selected = getItemAt(AbsoluteRect.UpperLeftCorner.X, ypos);
if (Selected<0 && !Items.empty())
Selected = 0;
recalculateScrollPos();
gui::EGUI_EVENT_TYPE eventType = (Selected == oldSelected && now < selectTime + 500) ? EGET_LISTBOX_SELECTED_AGAIN : EGET_LISTBOX_CHANGED;
selectTime = now;
// post the news
if (Parent && !onlyHover)
{
SEvent event;
event.EventType = EET_GUI_EVENT;
event.GUIEvent.Caller = this;
event.GUIEvent.Element = 0;
event.GUIEvent.EventType = eventType;
Parent->OnEvent(event);
}
}
//! Update the position and size of the listbox, and update the scrollbar
void CGUISTKListBox::updateAbsolutePosition()
{
IGUIElement::updateAbsolutePosition();
recalculateItemHeight();
}
//! draws the element and its children
void CGUISTKListBox::draw()
{
if (!IsVisible)
return;
recalculateItemHeight(); // if the font changed
IGUISkin* skin = Environment->getSkin();
core::rect<s32>* clipRect = 0;
// draw background
core::rect<s32> frameRect(AbsoluteRect);
// draw items
core::rect<s32> clientClip(AbsoluteRect);
clientClip.UpperLeftCorner.Y += 1;
clientClip.UpperLeftCorner.X += 1;
if (ScrollBar->isVisible())
clientClip.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE);
clientClip.LowerRightCorner.Y -= 1;
clientClip.clipAgainst(AbsoluteClippingRect);
skin->draw3DSunkenPane(this, skin->getColor(EGDC_3D_HIGH_LIGHT), true,
DrawBack, frameRect, &clientClip);
if (clipRect)
clientClip.clipAgainst(*clipRect);
frameRect = AbsoluteRect;
frameRect.UpperLeftCorner.X += 1;
if (ScrollBar->isVisible())
frameRect.LowerRightCorner.X = AbsoluteRect.LowerRightCorner.X - skin->getSize(EGDS_SCROLLBAR_SIZE);
frameRect.LowerRightCorner.Y = AbsoluteRect.UpperLeftCorner.Y + ItemHeight;
frameRect.UpperLeftCorner.Y -= ScrollBar->getPos();
frameRect.LowerRightCorner.Y -= ScrollBar->getPos();
bool hl = (HighlightWhenNotFocused || Environment->hasFocus(this) || Environment->hasFocus(ScrollBar));
for (s32 i=0; i<(s32)Items.size(); ++i)
{
if (frameRect.LowerRightCorner.Y >= AbsoluteRect.UpperLeftCorner.Y &&
frameRect.UpperLeftCorner.Y <= AbsoluteRect.LowerRightCorner.Y)
{
if (i == Selected && hl)
skin->draw2DRectangle(this, skin->getColor(EGDC_HIGH_LIGHT), frameRect, &clientClip);
core::rect<s32> textRect = frameRect;
if (Font)
{
int total_proportion = 0;
for(int x = 0; x < Items[i].m_contents.size(); ++x)
{
total_proportion += Items[i].m_contents[x].m_proportion;
}
int part_size = (int)(textRect.getWidth() / float(total_proportion));
for(int x = 0; x < Items[i].m_contents.size(); ++x)
{
textRect.LowerRightCorner.X = textRect.UpperLeftCorner.X +
(Items[i].m_contents[x].m_proportion * part_size);
textRect.UpperLeftCorner.X += 3;
if (IconBank && (Items[i].m_contents[x].m_icon > -1))
{
core::position2di iconPos = textRect.UpperLeftCorner;
iconPos.Y += textRect.getHeight() / 2;
iconPos.X += ItemsIconWidth/2;
if ( i==Selected && hl )
{
IconBank->draw2DSprite(
(u32)Items[i].m_contents[x].m_icon,
iconPos, &clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) ?
getItemOverrideColor(i, EGUI_LBC_ICON_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_ICON_HIGHLIGHT),
selectTime, Time::getTimeSinceEpoch(), false, true);
}
else
{
IconBank->draw2DSprite(
(u32)Items[i].m_contents[x].m_icon,
iconPos,
&clientClip,
hasItemOverrideColor(i, EGUI_LBC_ICON) ? getItemOverrideColor(i, EGUI_LBC_ICON) : getItemDefaultColor(EGUI_LBC_ICON),
0 , (i==Selected) ? Time::getTimeSinceEpoch() : 0, false, true);
}
textRect.UpperLeftCorner.X += ItemsIconWidth;
}
textRect.UpperLeftCorner.X += 3;
if ( i==Selected && hl )
{
Font->draw(
Items[i].m_contents[x].m_text.c_str(),
textRect,
hasItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) ?
getItemOverrideColor(i, EGUI_LBC_TEXT_HIGHLIGHT) : getItemDefaultColor(EGUI_LBC_TEXT_HIGHLIGHT),
Items[i].m_contents[x].m_center, true, &clientClip);
}
else
{
Font->draw(
Items[i].m_contents[x].m_text.c_str(),
textRect,
hasItemOverrideColor(i, EGUI_LBC_TEXT) ? getItemOverrideColor(i, EGUI_LBC_TEXT) : getItemDefaultColor(EGUI_LBC_TEXT),
Items[i].m_contents[x].m_center, true, &clientClip);
}
//Position back to inital pos
textRect.UpperLeftCorner.X -= ItemsIconWidth+6;
//Calculate new beginning
textRect.UpperLeftCorner.X += Items[i].m_contents[x].m_proportion * part_size;
}
}
}
frameRect.UpperLeftCorner.Y += ItemHeight;
frameRect.LowerRightCorner.Y += ItemHeight;
}
IGUIElement::draw();
}
//! adds an list item with an icon
u32 CGUISTKListBox::addItem(const ListItem & item)
{
Items.push_back(item);
recalculateItemHeight();
recalculateIconWidth();
return Items.size() - 1;
}
void CGUISTKListBox::setSpriteBank(IGUISpriteBank* bank)
{
if ( bank == IconBank )
return;
if (IconBank)
IconBank->drop();
IconBank = bank;
if (IconBank)
IconBank->grab();
}
void CGUISTKListBox::recalculateScrollPos()
{
if (!AutoScroll)
return;
const s32 selPos = (Selected == -1 ? TotalItemHeight : Selected * ItemHeight) - ScrollBar->getPos();
if (selPos < 0)
{
ScrollBar->setPos(ScrollBar->getPos() + selPos);
}
else
if (selPos > AbsoluteRect.getHeight() - ItemHeight)
{
ScrollBar->setPos(ScrollBar->getPos() + selPos - AbsoluteRect.getHeight() + ItemHeight);
}
}
void CGUISTKListBox::setAutoScrollEnabled(bool scroll)
{
AutoScroll = scroll;
}
bool CGUISTKListBox::isAutoScrollEnabled() const
{
_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
return AutoScroll;
}
void CGUISTKListBox::recalculateIconWidth()
{
for(int x = 0; x < (int)Items.getLast().m_contents.size(); ++x)
{
s32 icon = Items.getLast().m_contents[x].m_icon;
if (IconBank && icon > -1 &&
IconBank->getSprites().size() > (u32)icon &&
IconBank->getSprites()[(u32)icon].Frames.size())
{
u32 rno = IconBank->getSprites()[(u32)icon].Frames[0].rectNumber;
if (IconBank->getPositions().size() > rno)
{
const s32 w = IconBank->getPositions()[rno].getWidth();
if (w > ItemsIconWidth)
ItemsIconWidth = w;
}
}
}
}
void CGUISTKListBox::setCell(u32 row_num, u32 col_num, const wchar_t* text, s32 icon)
{
if ( row_num >= Items.size() )
return;
if ( col_num >= Items[row_num].m_contents.size() )
return;
Items[row_num].m_contents[col_num].m_text = text;
Items[row_num].m_contents[col_num].m_icon = icon;
recalculateItemHeight();
recalculateIconWidth();
}
void CGUISTKListBox::swapItems(u32 index1, u32 index2)
{
if ( index1 >= Items.size() || index2 >= Items.size() )
return;
ListItem dummmy = Items[index1];
Items[index1] = Items[index2];
Items[index2] = dummmy;
}
void CGUISTKListBox::setItemOverrideColor(u32 index, video::SColor color)
{
for ( u32 c=0; c < EGUI_LBC_COUNT; ++c )
{
Items[index].OverrideColors[c].Use = true;
Items[index].OverrideColors[c].Color = color;
}
}
void CGUISTKListBox::setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color)
{
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
return;
Items[index].OverrideColors[colorType].Use = true;
Items[index].OverrideColors[colorType].Color = color;
}
void CGUISTKListBox::clearItemOverrideColor(u32 index)
{
for (u32 c=0; c < (u32)EGUI_LBC_COUNT; ++c )
{
Items[index].OverrideColors[c].Use = false;
}
}
void CGUISTKListBox::clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType)
{
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
return;
Items[index].OverrideColors[colorType].Use = false;
}
bool CGUISTKListBox::hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const
{
if ( index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
return false;
return Items[index].OverrideColors[colorType].Use;
}
video::SColor CGUISTKListBox::getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const
{
if ( (u32)index >= Items.size() || colorType < 0 || colorType >= EGUI_LBC_COUNT )
return video::SColor();
return Items[index].OverrideColors[colorType].Color;
}
video::SColor CGUISTKListBox::getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const
{
IGUISkin* skin = Environment->getSkin();
if ( !skin )
return video::SColor();
switch ( colorType )
{
case EGUI_LBC_TEXT:
return skin->getColor(EGDC_BUTTON_TEXT);
case EGUI_LBC_TEXT_HIGHLIGHT:
return skin->getColor(EGDC_HIGH_LIGHT_TEXT);
case EGUI_LBC_ICON:
return skin->getColor(EGDC_ICON);
case EGUI_LBC_ICON_HIGHLIGHT:
return skin->getColor(EGDC_ICON_HIGH_LIGHT);
default:
return video::SColor();
}
}
//! set global itemHeight
void CGUISTKListBox::setItemHeight( s32 height )
{
ItemHeight = height;
ItemHeightOverride = 1;
}
//! Sets whether to draw the background
void CGUISTKListBox::setDrawBackground(bool draw)
{
DrawBack = draw;
}
} // end namespace gui
} // end namespace irr

View File

@ -0,0 +1,198 @@
// Copyright (C) 2002-2012 Nikolaus Gebhardt
// 2013 Glenn De Jonghe
// This file is part of the "Irrlicht Engine".
// For conditions of distribution and use, see copyright notice in irrlicht.h
#ifndef HEADER_CGUISTKListBox_HPP
#define HEADER_CGUISTKListBox_HPP
#include "IrrCompileConfig.h"
#include "IGUIListBox.h"
#include "IGUIElement.h"
#include "irrArray.h"
#include <string>
namespace irr
{
namespace gui
{
class IGUIFont;
class IGUIScrollBar;
class CGUISTKListBox : public IGUIElement
{
public:
struct ListItem
{
struct ListCell
{
irr::core::stringw m_text;
int m_proportion;
s32 m_icon;
bool m_center;
ListCell(irr::core::stringw text, s32 icon = -1, int proportion = 1, bool center = false)
{
m_text = text;
m_proportion = proportion;
m_icon = icon;
m_center = center;
}
};
core::array< ListCell > m_contents;
// Actually only used in list_widget -- still refactoring FIXME
std::string m_internal_name;
int m_current_id;
// A multicolor extension
struct ListItemOverrideColor
{
ListItemOverrideColor() : Use(false) {}
bool Use;
video::SColor Color;
};
ListItemOverrideColor OverrideColors[EGUI_LBC_COUNT];
};
//! constructor
CGUISTKListBox(IGUIEnvironment* environment, IGUIElement* parent,
s32 id, core::rect<s32> rectangle, bool clip=true,
bool drawBack=false, bool moveOverSelect=false);
//! destructor
virtual ~CGUISTKListBox();
//! returns amount of list items
virtual u32 getItemCount() const;
virtual const wchar_t* getCellText(u32 row_num, u32 col_num) const;
virtual ListItem getItem(u32 id) const;
//! clears the list
virtual void clear();
//! returns id of selected item. returns -1 if no item is selected.
virtual s32 getSelected() const;
//! sets the selected item. Set this to -1 if no item should be selected
virtual void setSelected(s32 id);
virtual s32 getRowByCellText(const wchar_t * text);
//! sets the selected item. Set this to -1 if no item should be selected
virtual void setSelectedByCellText(const wchar_t * text);
virtual s32 getRowByInternalName(const std::string & text) const;
//! called if an event happened.
virtual bool OnEvent(const SEvent& event);
//! draws the element and its children
virtual void draw();
//! adds an list item with an icon
//! \param text Text of list entry
//! \param icon Sprite index of the Icon within the current sprite bank. Set it to -1 if you want no icon
//! \return
//! returns the id of the new created item
//virtual u32 addItem(const wchar_t* text, s32 icon);
virtual u32 addItem(const ListItem & item);
//! Returns the icon of an item
virtual s32 getIcon(u32 row_num, u32 col_num) const;
//! removes an item from the list
virtual void removeItem(u32 id);
//! get the the id of the item at the given absolute coordinates
virtual s32 getItemAt(s32 xpos, s32 ypos) const;
//! Sets the sprite bank which should be used to draw list icons. This font is set to the sprite bank of
//! the built-in-font by default. A sprite can be displayed in front of every list item.
//! An icon is an index within the icon sprite bank. Several default icons are available in the
//! skin through getIcon
virtual void setSpriteBank(IGUISpriteBank* bank);
//! set whether the listbox should scroll to newly selected items
virtual void setAutoScrollEnabled(bool scroll);
//! returns true if automatic scrolling is enabled, false if not.
virtual bool isAutoScrollEnabled() const;
//! Update the position and size of the listbox, and update the scrollbar
virtual void updateAbsolutePosition();
//! set all item colors at given index to color
virtual void setItemOverrideColor(u32 index, video::SColor color);
//! set all item colors of specified type at given index to color
virtual void setItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType, video::SColor color);
//! clear all item colors at index
virtual void clearItemOverrideColor(u32 index);
//! clear item color at index for given colortype
virtual void clearItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType);
//! has the item at index its color overwritten?
virtual bool hasItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const;
//! return the overwrite color at given item index.
virtual video::SColor getItemOverrideColor(u32 index, EGUI_LISTBOX_COLOR colorType) const;
//! return the default color which is used for the given colorType
virtual video::SColor getItemDefaultColor(EGUI_LISTBOX_COLOR colorType) const;
//! set the item at the given index
virtual void setCell(u32 row_num, u32 col_num, const wchar_t* text, s32 icon);
//! Swap the items at the given indices
virtual void swapItems(u32 index1, u32 index2);
//! set global itemHeight
virtual void setItemHeight( s32 height );
//! Sets whether to draw the background
virtual void setDrawBackground(bool draw);
private:
void recalculateItemHeight();
void selectNew(s32 ypos, bool onlyHover=false);
void recalculateScrollPos();
// extracted that function to avoid copy&paste code
void recalculateIconWidth();
core::array< ListItem > Items;
s32 Selected;
s32 ItemHeight;
s32 ItemHeightOverride;
s32 TotalItemHeight;
s32 ItemsIconWidth;
gui::IGUIFont* Font;
gui::IGUISpriteBank* IconBank;
gui::IGUIScrollBar* ScrollBar;
u32 selectTime;
u32 LastKeyTime;
core::stringw KeyBuffer;
bool Selecting;
bool DrawBack;
bool MoveOverSelect;
bool AutoScroll;
bool HighlightWhenNotFocused;
};
} // end namespace gui
} // end namespace irr
#endif

View File

@ -39,15 +39,17 @@ using namespace irr;
LabelWidget::LabelWidget(bool title, bool bright) : Widget(WTYPE_LABEL)
{
m_title_font = title;
m_has_color = false;
m_scroll_speed = 0;
m_scroll_offset = 0;
m_bright = bright;
if (bright)
if (m_bright)
{
m_has_color = true;
m_color = Skin::getColor("brighttext::neutral");
}
else
m_has_color = false;
} // LabelWidget
// ----------------------------------------------------------------------------
@ -126,11 +128,11 @@ void LabelWidget::add()
void LabelWidget::setText(const wchar_t *text, bool expandIfNeeded)
{
assert(m_element != NULL);
m_scroll_offset = 0;
if (expandIfNeeded)
{
assert(m_element != NULL);
const int fwidth = (m_title_font ? GUIEngine::getTitleFont() : GUIEngine::getFont())->getDimension(text).Width;
core::rect<s32> rect = m_element->getRelativePosition();
@ -173,7 +175,6 @@ bool LabelWidget::scrolledOff() const
{
// This method may only be called after this widget has been add()ed
assert(m_element != NULL);
return m_scroll_offset <= -m_element->getAbsolutePosition().getWidth();
}
@ -189,9 +190,34 @@ void LabelWidget::setScrollSpeed(float speed)
void LabelWidget::setColor(const irr::video::SColor& color)
{
assert(m_element != NULL);
m_color = color;
m_has_color = true;
if (m_element != NULL)
((IGUIStaticText*)m_element)->setOverrideColor(m_color);
((IGUIStaticText*)m_element)->setOverrideColor(m_color);
}
// ----------------------------------------------------------------------------
void LabelWidget::setErrorColor()
{
setColor(irr::video::SColor(255, 255, 0, 0));
}
// ----------------------------------------------------------------------------
void LabelWidget::setDefaultColor()
{
if (m_bright)
{
setColor(Skin::getColor("brighttext::neutral"));
}
else
{
if(m_has_color)
{
assert(m_element != NULL);
m_has_color = false;
((IGUIStaticText*)m_element)->enableOverrideColor(false);
}
}
}
// ----------------------------------------------------------------------------

View File

@ -34,6 +34,7 @@ namespace GUIEngine
*/
class LabelWidget : public Widget
{
bool m_bright;
bool m_has_color;
irr::video::SColor m_color;
@ -58,10 +59,12 @@ namespace GUIEngine
/** \brief Callback from base class Widget */
virtual void add();
/** Sets the color of the widget.
/** Sets the color of the widget.
* \param color The color to use for this widget. */
void setColor(const irr::video::SColor& color);
void setErrorColor();
void setDefaultColor();
/** \brief Callback from base class Widget */
virtual void update(float dt);
@ -83,11 +86,11 @@ namespace GUIEngine
virtual void setText(const wchar_t *text, bool expandAsNeeded);
/** Overloaded function which takes a stringw. */
virtual void setText(const irr::core::stringw &s, bool expandAsNeeded)
virtual void setText(const irr::core::stringw &s, bool expandAsNeeded)
{
setText(s.c_str(), expandAsNeeded);
}
// --------------------------------------------------------------------
/** Sets horizontal scroll speed. */

View File

@ -15,14 +15,16 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "guiengine/widgets/list_widget.hpp"
#include "guiengine/CGUISpriteBank.h"
#include "guiengine/engine.hpp"
#include "guiengine/widgets/list_widget.hpp"
#include "io/file_manager.hpp"
#include <IGUIElement.h>
#include <IGUISkin.h>
#include <IGUIEnvironment.h>
#include <IGUIListBox.h>
#include "IGUIFontBitmap.h"
#include <sstream>
@ -50,7 +52,7 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
if (m_use_icons)
{
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
list->setSpriteBank(m_icons);
@ -80,8 +82,8 @@ void ListWidget::setIcons(STKModifiedSpriteBank* icons, int size)
}
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
void ListWidget::add()
{
const int header_height = GUIEngine::getFontHeight() + 15;
@ -89,11 +91,32 @@ void ListWidget::add()
rect<s32> widget_size = (m_header.size() > 0 ? rect<s32>(m_x, m_y + header_height, m_x + m_w, m_y + m_h) :
rect<s32>(m_x, m_y, m_x + m_w, m_y + m_h) );
IGUIListBox* list = GUIEngine::getGUIEnv()->addListBox (widget_size, m_parent, getNewID());
list->setAutoScrollEnabled(false);
IGUISkin * current_skin = GUIEngine::getGUIEnv()->getSkin();
IGUIFont * current_font = GUIEngine::getGUIEnv()->getBuiltInFont();
CGUISTKListBox * list_box = new CGUISTKListBox(
GUIEngine::getGUIEnv(),
m_parent ? m_parent : GUIEngine::getGUIEnv()->getRootGUIElement(),
getNewID(),
widget_size,
true,
true,
false);
m_element = list;
m_element->setTabOrder( list->getID() );
if (current_skin && current_skin->getSpriteBank())
{
list_box->setSpriteBank(current_skin->getSpriteBank());
}
else if (current_font && current_font->getType() == EGFT_BITMAP)
{
list_box->setSpriteBank( ((IGUIFontBitmap*)current_font)->getSpriteBank());
}
list_box->drop();
list_box->setAutoScrollEnabled(false);
m_element = list_box;
m_element->setTabOrder( list_box->getID() );
if (m_header.size() > 0)
{
@ -149,91 +172,129 @@ void ListWidget::clear()
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
list->clear();
m_items.clear();
}
// -----------------------------------------------------------------------------
void ListWidget::addItem(const std::string& internalName,
const irr::core::stringw& name, const int icon)
void ListWidget::addItem( const std::string& internal_name,
const irr::core::stringw &name,
const int icon,
bool center)
{
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
ListCell cell(name, icon, 1, center);
ListItem newItem;
newItem.m_internal_name = internal_name;
newItem.m_contents.push_back(cell);
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
u32 itemID = list->addItem( newItem );
if (m_use_icons)
{
list->setItemOverrideColor( itemID, gui::EGUI_LBC_ICON, video::SColor(255,255,255,255) );
list->setItemOverrideColor( itemID, gui::EGUI_LBC_ICON_HIGHLIGHT, video::SColor(255,255,255,255) );
}
newItem.m_current_id = itemID;
}
// -----------------------------------------------------------------------------
void ListWidget::addItem(const std::string& internal_name,
PtrVector<ListCell> * contents)
{
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
ListItem newItem;
newItem.m_label = name;
newItem.m_internal_name = internalName;
newItem.m_internal_name = internal_name;
for(int i = 0; i < (int)contents->size(); i++)
{
newItem.m_contents.push_back(*contents->get(i));
}
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
if (m_use_icons && icon != -1)
u32 itemID = list->addItem( newItem );
if (m_use_icons)
{
u32 itemID = list->addItem( name.c_str(), icon );
list->setItemOverrideColor( itemID, gui::EGUI_LBC_ICON, video::SColor(255,255,255,255) );
list->setItemOverrideColor( itemID, gui::EGUI_LBC_ICON_HIGHLIGHT, video::SColor(255,255,255,255) );
newItem.m_current_id = itemID;
}
else
{
newItem.m_current_id = list->addItem( name.c_str() );
}
m_items.push_back(newItem);
newItem.m_current_id = itemID;
}
// -----------------------------------------------------------------------------
void ListWidget::renameItem(const int itemID, const irr::core::stringw newName, const int icon)
void ListWidget::renameCell(const int row_index, const int col_index, const irr::core::stringw newName, const int icon)
{
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
m_items[itemID].m_label = newName;
list->setItem(itemID, newName.c_str(), icon);
list->setCell(row_index, col_index, newName.c_str(), icon);
list->setItemOverrideColor( itemID, EGUI_LBC_TEXT , video::SColor(255,0,0,0) );
list->setItemOverrideColor( itemID, EGUI_LBC_TEXT_HIGHLIGHT, video::SColor(255,255,255,255) );
list->setItemOverrideColor( row_index, EGUI_LBC_TEXT , video::SColor(255,0,0,0) );
list->setItemOverrideColor( row_index, EGUI_LBC_TEXT_HIGHLIGHT, video::SColor(255,255,255,255) );
}
// -----------------------------------------------------------------------------
void ListWidget::renameItem(const int row_index, const irr::core::stringw newName, const int icon)
{
renameCell(row_index, 0, newName, icon);
}
// -----------------------------------------------------------------------------
void ListWidget::renameItem(const std::string & internal_name, const irr::core::stringw newName, const int icon)
{
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
renameCell(list->getRowByInternalName(internal_name), 0, newName, icon);
}
// -----------------------------------------------------------------------------
std::string ListWidget::getSelectionInternalName()
{
if (getSelectionID() == -1) return "";
return m_items[ getSelectionID() ].m_internal_name;
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
if (getSelectionID() == -1 || (getSelectionID() >= (int)list->getItemCount()))
return "";
return list->getItem(getSelectionID()).m_internal_name;
}
// -----------------------------------------------------------------------------
irr::core::stringw ListWidget::getSelectionLabel() const
irr::core::stringw ListWidget::getSelectionLabel(const int cell) const
{
const IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
const CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
return list->getListItem( list->getSelected() );
return list->getCellText( list->getSelected(), cell);
}
// -----------------------------------------------------------------------------
void ListWidget::selectItemWithLabel(const irr::core::stringw& name)
{
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
return list->setSelected( name.c_str() );
return list->setSelectedByCellText( name.c_str() );
}
// -----------------------------------------------------------------------------
void ListWidget::unfocused(const int playerID, Widget* new_focus)
{
IGUIListBox* list = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
// remove selection when leaving list
if (list != NULL) list->setSelected(-1);
@ -246,7 +307,7 @@ int ListWidget::getSelectionID() const
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
return getIrrlichtElement<IGUIListBox>()->getSelected();
return getIrrlichtElement<CGUISTKListBox>()->getSelected();
}
// -----------------------------------------------------------------------------
@ -256,7 +317,7 @@ void ListWidget::setSelectionID(const int index)
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
IGUIListBox* irritem = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* irritem = getIrrlichtElement<CGUISTKListBox>();
// auto-scroll to item when selecting something, don't auto-scroll when selecting nothing
if (index != -1)
@ -279,8 +340,7 @@ int ListWidget::getItemCount() const
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
const int count = getIrrlichtElement<IGUIListBox>()->getItemCount();
assert((int)m_items.size() == count);
const int count = getIrrlichtElement<CGUISTKListBox>()->getItemCount();
return count;
}
@ -290,7 +350,6 @@ int ListWidget::getItemCount() const
void ListWidget::elementRemoved()
{
Widget::elementRemoved();
m_items.clear();
for (int n=0; n<m_header_elements.size(); n++)
{
@ -303,26 +362,12 @@ void ListWidget::elementRemoved()
// -----------------------------------------------------------------------------
int ListWidget::getItemID(const std::string internalName) const
{
const int count = m_items.size();
for (int i=0; i<count; i++)
{
if (m_items[i].m_internal_name == internalName) return i;
}
return -1;
}
// -----------------------------------------------------------------------------
void ListWidget::markItemRed(const int id, bool red)
{
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
IGUIListBox* irritem = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* irritem = getIrrlichtElement<CGUISTKListBox>();
if (red)
{
@ -343,7 +388,7 @@ void ListWidget::markItemBlue(const int id, bool blue)
// May only be called AFTER this widget has been add()ed
assert(m_element != NULL);
IGUIListBox* irritem = getIrrlichtElement<IGUIListBox>();
CGUISTKListBox* irritem = getIrrlichtElement<CGUISTKListBox>();
if (blue)
{
@ -389,3 +434,11 @@ EventPropagation ListWidget::transmitEvent(Widget* w,
return EVENT_LET;
}
// -----------------------------------------------------------------------------
int ListWidget::getItemID(const std::string internalName) const
{
const CGUISTKListBox* list = getIrrlichtElement<CGUISTKListBox>();
assert(list != NULL);
return list->getRowByInternalName(internalName);
}

View File

@ -22,10 +22,13 @@
#include <irrString.h>
#include "guiengine/widgets/CGUISTKListBox.h"
#include "guiengine/widget.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "utils/leak_check.hpp"
#include "utils/ptr_vector.hpp"
#include "IGUIElement.h"
namespace irr { namespace gui { class STKModifiedSpriteBank; } }
@ -47,7 +50,6 @@ namespace GUIEngine
class ListWidget : public Widget
{
friend class Skin;
/** \brief whether this list has icons */
bool m_use_icons;
@ -55,14 +57,6 @@ namespace GUIEngine
/** \brief if m_use_icons is true, this will contain the icon bank */
irr::gui::STKModifiedSpriteBank* m_icons;
struct ListItem
{
std::string m_internal_name;
irr::core::stringw m_label;
int m_current_id;
};
std::vector< ListItem > m_items;
PtrVector< ButtonWidget > m_header_elements;
ButtonWidget* m_selected_column;
@ -86,8 +80,10 @@ namespace GUIEngine
std::vector< Column > m_header;
IListWidgetHeaderListener* m_listener;
public:
typedef irr::gui::CGUISTKListBox::ListItem ListItem;
typedef ListItem::ListCell ListCell;
LEAK_CHECK()
@ -124,8 +120,13 @@ namespace GUIEngine
* \param icon ID of the icon within the icon bank. Only used if an icon bank was passed.
* \pre may only be called after the widget has been added to the screen with add()
*/
void addItem(const std::string& internal_name,
const irr::core::stringw &name, const int icon=-1);
void addItem( const std::string& internal_name,
const irr::core::stringw &name,
const int icon=-1,
bool center = false);
void addItem( const std::string& internal_name,
PtrVector<ListCell> * contents);
/**
* \brief erases all items in the list
@ -151,7 +152,7 @@ namespace GUIEngine
*/
std::string getSelectionInternalName();
irr::core::stringw getSelectionLabel() const;
irr::core::stringw getSelectionLabel(const int cell = 0) const;
void selectItemWithLabel(const irr::core::stringw& name);
@ -171,18 +172,24 @@ namespace GUIEngine
* \brief rename an item and/or change its icon based on its ID
* \pre may only be called after the widget has been added to the screen with add()
*/
void renameItem(const int itemID, const irr::core::stringw newName, const int icon=-1);
void renameCell(const int row_num, const int col_num, const irr::core::stringw newName, const int icon=-1);
/**
* renames first cell only
*/
void renameItem(const int row_num, const irr::core::stringw newName, const int icon=-1);
void renameItem(const std::string & internal_name, const irr::core::stringw newName, const int icon=-1);
/**
* \brief rename an item and/or change its icon based on its internal name
* \pre may only be called after the widget has been added to the screen with add()
*/
void renameItem(const std::string internalName, const irr::core::stringw newName,
void renameCell(const std::string internalName, const int col_num, const irr::core::stringw newName,
const int icon=-1)
{
const int id = getItemID(internalName);
assert(id != -1);
renameItem( id, newName, icon );
renameCell( id, col_num, newName, icon );
}
/**

View File

@ -173,7 +173,8 @@
#include "network/server_network_manager.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/server_lobby_room_protocol.hpp"
#include "online/current_online_user.hpp"
#include "online/current_user.hpp"
#include "online/http_manager.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/highscore_manager.hpp"
#include "race/history.hpp"
@ -1107,8 +1108,16 @@ int handleCmdLine(int argc, char **argv)
if (try_login)
{
/*
irr::core::stringw s;
CurrentOnlineUser::get()->signIn(login, password, s);
Online::CurrentUser::SignInRequest* request =
Online::CurrentUser::acquire()->requestSignIn(login, password, false);
request->setManageMemory(true);
if (request->isSuccess())
{
Log::info("Main", "Logged in from command line.");
}*/
}
return 1;
@ -1230,6 +1239,8 @@ void cleanSuperTuxKart()
if(INetworkHttp::get())
INetworkHttp::get()->stopNetworkThread();
if(Online::HTTPManager::isRunning())
Online::HTTPManager::get()->stopNetworkThread();
//delete in reverse order of what they were created in.
//delete in reverse order of what they were created in.
//see InitTuxkart()

View File

@ -22,7 +22,7 @@
#ifndef GAME_SETUP_HPP
#define GAME_SETUP_HPP
#include "online/online_user.hpp"
#include "online/user.hpp"
#include <vector>
#include <string>
@ -35,10 +35,10 @@ class NetworkPlayerProfile
public:
NetworkPlayerProfile() { race_id = 0; user_profile = NULL; }
~NetworkPlayerProfile() {}
uint8_t race_id; //!< The id of the player for the race
std::string kart_name; //!< The selected kart.
OnlineUser* user_profile; //!< Pointer to the lobby profile
Online::User* user_profile; //!< Pointer to the lobby profile
};
/*! \class GameSetup
@ -60,7 +60,7 @@ class GameSetup
int getPlayerCount() { return m_players.size(); }
const NetworkPlayerProfile* getProfile(uint32_t id); //!< Get a profile by database id
const NetworkPlayerProfile* getProfile(uint8_t id); //!< Get the profile by the lobby id
bool isKartAvailable(std::string kart_name);
bool isKartAllowed(std::string kart_name) {return true; }

View File

@ -20,7 +20,7 @@
#include "network/network_manager.hpp"
#include "network/protocols/start_game_protocol.hpp"
#include "online/current_online_user.hpp"
#include "online/current_user.hpp"
#include "utils/log.hpp"
ClientLobbyRoomProtocol::ClientLobbyRoomProtocol(const TransportAddress& server_address)
@ -105,7 +105,7 @@ void ClientLobbyRoomProtocol::update()
{
NetworkString ns;
// 1 (connection request), 4 (size of id), global id
ns.ai8(1).ai8(4).ai32(CurrentOnlineUser::get()->getUserID());
ns.ai8(1).ai8(4).ai32(Online::CurrentUser::acquire()->getUserID());
m_listener->sendMessage(this, ns);
m_state = REQUESTING_CONNECTION;
} break;
@ -145,7 +145,7 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
uint32_t global_id = event->data.gui32(1);
uint8_t race_id = event->data.gui8(6);
if (global_id == CurrentOnlineUser::get()->getUserID())
if (global_id == Online::CurrentUser::acquire()->getUserID())
{
Log::error("ClientLobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal).");
}
@ -155,7 +155,7 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
profile->kart_name = "";
profile->race_id = race_id;
profile->user_profile = new OnlineUser(global_id);
profile->user_profile = new Online::User(global_id);
m_setup->addPlayer(profile);
}
else
@ -216,7 +216,7 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
STKPeer* peer = *(event->peer);
uint32_t global_id = event->data.gui32(8);
if (global_id == CurrentOnlineUser::get()->getUserID())
if (global_id == Online::CurrentUser::acquire()->getUserID())
{
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
@ -224,7 +224,7 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
profile->kart_name = "";
profile->race_id = event->data.gui8(1);
profile->user_profile = CurrentOnlineUser::get();
profile->user_profile = Online::CurrentUser::acquire();
m_setup->addPlayer(profile);
// connection token
uint32_t token = event->data.gui32(3);
@ -243,7 +243,7 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
Log::error("ClientLobbyRoomProtocol", "Bad format in players list.");
uint8_t race_id = event->data[1];
uint32_t global_id = event->data.gui32(3);
OnlineUser* new_user = new OnlineUser(global_id);
Online::User* new_user = new Online::User(global_id);
NetworkPlayerProfile* profile2 = new NetworkPlayerProfile();
profile2->race_id = race_id;
profile2->user_profile = new_user;

View File

@ -25,7 +25,7 @@
#include "network/protocols/hide_public_address.hpp"
#include "network/protocols/request_connection.hpp"
#include "network/protocols/ping_protocol.hpp"
#include "online/current_online_user.hpp"
#include "online/current_user.hpp"
#include "utils/time.hpp"
#include "utils/log.hpp"

View File

@ -27,7 +27,7 @@
#include "network/protocols/ping_protocol.hpp"
#include "network/protocols/quick_join_protocol.hpp"
#include "network/protocols/client_lobby_room_protocol.hpp"
#include "online/current_online_user.hpp"
#include "online/current_user.hpp"
#include "utils/time.hpp"
#include "utils/log.hpp"

View File

@ -20,8 +20,8 @@
#include "network/protocol_manager.hpp"
#include "network/http_functions.hpp"
#include "online/http_connector.hpp"
#include "online/current_online_user.hpp"
#include "online/http_manager.hpp"
#include "online/current_user.hpp"
#include "config/user_config.hpp"
#include "utils/log.hpp"
@ -42,20 +42,26 @@ void GetPeerAddress::notifyEvent(Event* event)
void GetPeerAddress::setup()
{
m_state = NONE;
m_request = NULL;
}
void GetPeerAddress::asynchronousUpdate()
{
if (m_state == NONE)
{
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("peer_id",m_peer_id);
m_request->setParameter("action","get");
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("peer_id",m_peer_id);
connector.setParameter("action","get");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
}
else if (m_state == REQUEST_PENDING && m_request->isDone())
{
const XMLNode * result = m_request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
@ -81,6 +87,8 @@ void GetPeerAddress::asynchronousUpdate()
else if (m_state == DONE)
{
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
}
}

View File

@ -20,6 +20,7 @@
#define GET_PEER_ADDRESS_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
class GetPeerAddress : public Protocol
{
@ -35,10 +36,11 @@ class GetPeerAddress : public Protocol
void setPeerID(uint32_t m_peer_id);
protected:
uint32_t m_peer_id;
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -19,8 +19,8 @@
#include "network/protocols/hide_public_address.hpp"
#include "network/protocol_manager.hpp"
#include "online/http_connector.hpp"
#include "online/current_online_user.hpp"
#include "online/http_manager.hpp"
#include "online/current_user.hpp"
#include "config/user_config.hpp"
#include "utils/log.hpp"
@ -45,12 +45,18 @@ void HidePublicAddress::asynchronousUpdate()
{
if (m_state == NONE)
{
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("action","unset");
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("action","unset");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
}
else if (m_state == REQUEST_PENDING && m_request->isDone())
{
const XMLNode * result = m_request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
@ -73,6 +79,8 @@ void HidePublicAddress::asynchronousUpdate()
else if (m_state == DONE)
{
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
}
}

View File

@ -20,6 +20,7 @@
#define HIDE_PUBLIC_ADDRESS_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
#include <string>
class HidePublicAddress : public Protocol
@ -34,10 +35,11 @@ class HidePublicAddress : public Protocol
virtual void asynchronousUpdate();
protected:
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -19,8 +19,8 @@
#include "quick_join_protocol.hpp"
#include "network/network_manager.hpp"
#include "online/current_online_user.hpp"
#include "online/http_connector.hpp"
#include "online/current_user.hpp"
#include "online/http_manager.hpp"
#include "config/user_config.hpp"
#include "utils/log.hpp"
@ -47,12 +47,18 @@ void QuickJoinProtocol::asynchronousUpdate()
if (m_state == NONE)
{
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("action","quick-join");
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("action","quick-join");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
}
else if (m_state == REQUEST_PENDING && m_request->isDone())
{
const XMLNode * result = m_request->getResult();
std::string rec_success;
TransportAddress* res = static_cast<TransportAddress*>(m_callback_object);
@ -79,6 +85,8 @@ void QuickJoinProtocol::asynchronousUpdate()
else if (m_state == DONE)
{
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
}
}

View File

@ -2,7 +2,7 @@
#define QUICK_JOIN_PROTOCOL_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
class QuickJoinProtocol : public Protocol
{
@ -17,9 +17,11 @@ class QuickJoinProtocol : public Protocol
protected:
uint32_t* m_server_id;
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -19,8 +19,8 @@
#include "network/protocols/request_connection.hpp"
#include "network/protocol_manager.hpp"
#include "online/http_connector.hpp"
#include "online/current_online_user.hpp"
#include "online/http_manager.hpp"
#include "online/current_user.hpp"
#include "config/user_config.hpp"
RequestConnection::RequestConnection(uint32_t server_id) : Protocol(NULL, PROTOCOL_SILENT)
@ -47,13 +47,22 @@ void RequestConnection::asynchronousUpdate()
{
case NONE:
{
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("server_id",m_server_id);
connector.setParameter("action","request-connection");
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("server_id",m_server_id);
m_request->setParameter("action","request-connection");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
break;
}
case REQUEST_PENDING:
{
if (!m_request->isDone())
return;
const XMLNode * result = m_request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
@ -77,6 +86,8 @@ void RequestConnection::asynchronousUpdate()
}
case DONE:
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
break;
case EXITING:

View File

@ -2,6 +2,7 @@
#define REQUEST_CONNECTION_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
class RequestConnection : public Protocol
{
@ -16,10 +17,11 @@ class RequestConnection : public Protocol
protected:
uint32_t m_server_id;
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -25,8 +25,8 @@
#include "network/protocols/start_server.hpp"
#include "network/protocols/start_game_protocol.hpp"
#include "online/current_online_user.hpp"
#include "online/http_connector.hpp"
#include "online/current_user.hpp"
#include "online/http_manager.hpp"
#include "config/user_config.hpp"
#include "utils/log.hpp"
#include "utils/time.hpp"
@ -113,14 +113,18 @@ void ServerLobbyRoomProtocol::update()
{
last_poll_time = Time::getRealTime();
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("address",addr.ip);
connector.setParameter("port",addr.port);
connector.setParameter("action","poll-connection-requests");
Online::XMLRequest* request = new Online::XMLRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
request->setParameter("token",Online::CurrentUser::acquire()->getToken());
request->setParameter("address",addr.ip);
request->setParameter("port",addr.port);
request->setParameter("action","poll-connection-requests");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->synchronousRequest(request);
assert(request->isDone());
const XMLNode * result = request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
{
@ -144,6 +148,7 @@ void ServerLobbyRoomProtocol::update()
{
Log::error("ServerLobbyRoomProtocol", "Cannot retrieve the list.");
}
delete request;
}
// now
@ -257,7 +262,7 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
profile->race_id = m_next_id;
profile->kart_name = "";
profile->user_profile = new OnlineUser(player_id);
profile->user_profile = new Online::User(player_id);
m_setup->addPlayer(profile);
peer->setPlayerProfile(profile);
Log::verbose("ServerLobbyRoomProtocol", "New player.");

View File

@ -19,8 +19,8 @@
#include "network/protocols/show_public_address.hpp"
#include "network/network_manager.hpp"
#include "online/http_connector.hpp"
#include "online/current_online_user.hpp"
#include "online/http_manager.hpp"
#include "online/current_user.hpp"
#include "config/user_config.hpp"
#include "utils/log.hpp"
@ -46,14 +46,20 @@ void ShowPublicAddress::asynchronousUpdate()
if (m_state == NONE)
{
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("address",addr.ip);
connector.setParameter("port",addr.port);
connector.setParameter("action","set");
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("address",addr.ip);
m_request->setParameter("port",addr.port);
m_request->setParameter("action","set");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
}
else if (m_state == REQUEST_PENDING && m_request->isDone())
{
const XMLNode * result = m_request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
@ -76,6 +82,8 @@ void ShowPublicAddress::asynchronousUpdate()
else if (m_state == DONE)
{
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
}
}

View File

@ -20,6 +20,7 @@
#define SHOW_PUBLIC_ADDRESS_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
#include <string>
class ShowPublicAddress : public Protocol
@ -34,10 +35,11 @@ class ShowPublicAddress : public Protocol
virtual void asynchronousUpdate();
protected:
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -14,7 +14,7 @@
#include "challenges/unlock_manager.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/kart_selection.hpp"
#include "online/current_online_user.hpp"
#include "online/current_user.hpp"
StartGameProtocol::StartGameProtocol(GameSetup* game_setup) :
Protocol(NULL, PROTOCOL_START_GAME)
@ -103,7 +103,7 @@ void StartGameProtocol::update()
// have to add self first
for (unsigned int i = 0; i < players.size(); i++)
{
bool is_me = (players[i]->user_profile == CurrentOnlineUser::get());
bool is_me = (players[i]->user_profile == Online::CurrentUser::acquire());
if (is_me)
{
NetworkPlayerProfile* profile = players[i];
@ -127,7 +127,7 @@ void StartGameProtocol::update()
}
for (unsigned int i = 0; i < players.size(); i++)
{
bool is_me = (players[i]->user_profile == CurrentOnlineUser::get());
bool is_me = (players[i]->user_profile == Online::CurrentUser::acquire());
NetworkPlayerProfile* profile = players[i];
RemoteKartInfo rki(profile->race_id, profile->kart_name,
profile->user_profile->getUserName(), profile->race_id, !is_me);

View File

@ -19,8 +19,8 @@
#include "network/protocols/start_server.hpp"
#include "network/network_manager.hpp"
#include "online/current_online_user.hpp"
#include "online/http_connector.hpp"
#include "online/current_user.hpp"
#include "online/http_manager.hpp"
#include "config/user_config.hpp"
StartServer::StartServer() : Protocol(NULL, PROTOCOL_SILENT)
@ -45,15 +45,21 @@ void StartServer::asynchronousUpdate()
if (m_state == NONE)
{
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("address",addr.ip);
connector.setParameter("port",addr.port);
connector.setParameter("max_players",UserConfigParams::m_server_max_players);
connector.setParameter("action","start-server");
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("address",addr.ip);
m_request->setParameter("port",addr.port);
m_request->setParameter("max_players",UserConfigParams::m_server_max_players);
m_request->setParameter("action","start-server");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
}
else if (m_state == REQUEST_PENDING && m_request->isDone())
{
const XMLNode * result = m_request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
@ -76,6 +82,8 @@ void StartServer::asynchronousUpdate()
else if (m_state == DONE)
{
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
}
}

View File

@ -2,6 +2,7 @@
#define START_SERVER_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
/*!
* This protocol tells to the database that the server is up and running,
@ -19,9 +20,11 @@ class StartServer : public Protocol
virtual void asynchronousUpdate();
protected:
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -19,8 +19,8 @@
#include "network/protocols/stop_server.hpp"
#include "network/network_manager.hpp"
#include "online/current_online_user.hpp"
#include "online/http_connector.hpp"
#include "online/current_user.hpp"
#include "online/http_manager.hpp"
#include "config/user_config.hpp"
StopServer::StopServer() : Protocol(NULL, PROTOCOL_SILENT)
@ -45,14 +45,20 @@ void StopServer::asynchronousUpdate()
if (m_state == NONE)
{
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector connector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector.setParameter("id",CurrentOnlineUser::get()->getUserID());
connector.setParameter("token",CurrentOnlineUser::get()->getToken());
connector.setParameter("address",addr.ip);
connector.setParameter("port",addr.port);
connector.setParameter("action","stop-server");
m_request = new Online::XMLRequest();
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
m_request->setParameter("id",Online::CurrentUser::acquire()->getUserID());
m_request->setParameter("token",Online::CurrentUser::acquire()->getToken());
m_request->setParameter("address",addr.ip);
m_request->setParameter("port",addr.port);
m_request->setParameter("action","stop-server");
const XMLNode * result = connector.getXMLFromPage();
Online::HTTPManager::get()->addRequest(m_request);
m_state = REQUEST_PENDING;
}
else if (m_state == REQUEST_PENDING && m_request->isDone())
{
const XMLNode * result = m_request->getResult();
std::string rec_success;
if(result->get("success", &rec_success))
@ -75,6 +81,8 @@ void StopServer::asynchronousUpdate()
else if (m_state == DONE)
{
m_state = EXITING;
delete m_request;
m_request = NULL;
m_listener->requestTerminate(this);
}
}

View File

@ -2,7 +2,7 @@
#define STOP_SERVER_HPP
#include "network/protocol.hpp"
#include "online/request.hpp"
/*! \brief Removes the server info from the database
*/
@ -19,9 +19,11 @@ class StopServer : public Protocol
virtual void asynchronousUpdate();
protected:
Online::XMLRequest* m_request;
enum STATE
{
NONE,
REQUEST_PENDING,
DONE,
EXITING
};

View File

@ -1,153 +0,0 @@
//
// 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.
#include "online/current_online_user.hpp"
#include "config/user_config.hpp"
#include "online/http_connector.hpp"
#include "utils/translation.hpp"
#include <assert.h>
#include <sstream>
#include <stdlib.h>
static CurrentOnlineUser* user_singleton = NULL;
CurrentOnlineUser* CurrentOnlineUser::get()
{
if (user_singleton == NULL)
user_singleton = new CurrentOnlineUser();
return user_singleton;
} // get
void CurrentOnlineUser::deallocate()
{
delete user_singleton;
user_singleton = NULL;
} // deallocate
// ============================================================================
CurrentOnlineUser::CurrentOnlineUser(){
m_is_signed_in = false;
m_is_guest = false;
m_id = 0;
m_name = "";
m_token = "";
}
// ============================================================================
// Register
bool CurrentOnlineUser::signUp( const irr::core::stringw &username,
const irr::core::stringw &password,
const irr::core::stringw &password_ver,
const irr::core::stringw &email,
bool terms,
irr::core::stringw &info)
{
assert(m_is_signed_in == false);
HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
connector->setParameter("action",std::string("register"));
connector->setParameter("username",username);
connector->setParameter("password",password);
const XMLNode * result = connector->getXMLFromPage();
std::string rec_success;
bool success = false;
if(result->get("success", &rec_success))
{
success = (rec_success == "yes");
assert(result->get("info", &info));
}
else
{
info = _("Unable to connect to the server. Check your internet connection or try again later.");
}
return success;
}
// ============================================================================
bool CurrentOnlineUser::signIn( const irr::core::stringw &username,
const irr::core::stringw &password,
irr::core::stringw &info)
{
assert(m_is_signed_in == false);
HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
connector->setParameter("action",std::string("connect"));
connector->setParameter("username",username);
connector->setParameter("password",password);
const XMLNode * result = connector->getXMLFromPage();
std::string rec_success = "";
if(result->get("success", &rec_success))
{
if (rec_success =="yes")
{
int token_fetched = result->get("token", &m_token);
int username_fetched = result->get("username", &m_name);
int userid_fetched = result->get("userid", &m_id);
assert(token_fetched && username_fetched && userid_fetched);
m_is_signed_in = true;
m_is_guest = false;
}
result->get("info", &info);
}
else
{
info = _("Unable to connect to the server. Check your internet connection or try again later.");
}
return m_is_signed_in;
}
// ============================================================================
bool CurrentOnlineUser::signOut(){
assert(m_is_signed_in == true);
HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
connector->setParameter("action",std::string("disconnect"));
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")
{
m_token = "";
m_name = "";
m_id = 0;
m_is_signed_in = false;
m_is_guest = false;
}
}
return !m_is_signed_in;
}
// ============================================================================
irr::core::stringw CurrentOnlineUser::getUserName() const
{
if(m_is_signed_in)
return m_name;
else
return _("Currently not signed in");
}

View File

@ -1,72 +0,0 @@
//
// 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_CURRENT_ONLINE_USER_HPP
#define HEADER_CURRENT_ONLINE_USER_HPP
#include "online/online_user.hpp"
#include <irrString.h>
#include <string>
// ============================================================================
/**
* \brief Class that represents an online registered user
* \ingroup online
*/
class CurrentOnlineUser : public OnlineUser
{
private:
protected:
std::string m_token;
bool m_is_signed_in;
bool m_is_guest;
CurrentOnlineUser();
public:
// singleton
static CurrentOnlineUser* get();
static void deallocate();
// Login
bool signIn( const irr::core::stringw &username,
const irr::core::stringw &password,
irr::core::stringw &info);
// Register
bool signUp( const irr::core::stringw &username,
const irr::core::stringw &password,
const irr::core::stringw &password_ver,
const irr::core::stringw &email,
bool terms,
irr::core::stringw &info);
// Logout - Best to be followed by CurrentOnlineUser::deallocate
bool signOut();
/** Returns the username if signed in. */
irr::core::stringw getUserName() const;
std::string getToken() const { return m_token; }
bool isSignedIn() { return m_is_signed_in; }
bool isGuest() { return m_is_guest; }
}; // class CurrentOnlineUser
#endif
/*EOF*/

250
src/online/current_user.cpp Normal file
View File

@ -0,0 +1,250 @@
//
// 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.
#include "online/current_user.hpp"
#include <sstream>
#include <stdlib.h>
#include <assert.h>
#include "config/user_config.hpp"
#include "utils/translation.hpp"
#include "utils/log.hpp"
#include "online/servers_manager.hpp"
namespace Online{
static Synchronised<CurrentUser*> user_singleton(NULL);
CurrentUser* CurrentUser::acquire()
{
user_singleton.lock();
CurrentUser * user = user_singleton.getData();
if (user == NULL)
{
user_singleton.unlock();
user = new CurrentUser();
user_singleton.setAtomic(user);
user_singleton.lock();
}
return user;
}
void CurrentUser::release()
{
user_singleton.unlock();
}
void CurrentUser::deallocate()
{
user_singleton.lock();
CurrentUser* user = user_singleton.getData();
delete user;
user = NULL;
user_singleton.unlock();
} // deallocate
// ============================================================================
CurrentUser::CurrentUser(){
m_state = US_SIGNED_OUT;
m_id = 0;
m_name = "";
m_token = "";
m_save_session = false;
}
// ============================================================================
XMLRequest * CurrentUser::requestSignUp( const irr::core::stringw &username,
const irr::core::stringw &password,
const irr::core::stringw &password_confirm,
const irr::core::stringw &email,
bool terms)
{
assert(m_state == US_SIGNED_OUT || m_state == US_GUEST);
XMLRequest * request = new XMLRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action", std::string("register"));
request->setParameter("username", username);
request->setParameter("password", password);
request->setParameter("password_confirm", password_confirm);
request->setParameter("email", email);
request->setParameter("terms", std::string("on"));
HTTPManager::get()->addRequest(request);
return request;
}
// ============================================================================
CurrentUser::SignInRequest * CurrentUser::requestSavedSession()
{
SignInRequest * request = NULL;
if(m_state != US_SIGNED_IN && UserConfigParams::m_saved_session)
{
request = new SignInRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action",std::string("saved-session"));
request->setParameter("userid", UserConfigParams::m_saved_user);
request->setParameter("token", UserConfigParams::m_saved_token.c_str());
HTTPManager::get()->addRequest(request);
m_state = US_SIGNING_IN;
}
return request;
}
CurrentUser::SignInRequest * CurrentUser::requestSignIn( const irr::core::stringw &username,
const irr::core::stringw &password,
bool save_session, bool request_now)
{
assert(m_state == US_SIGNED_OUT);
m_save_session = save_session;
SignInRequest * request = new SignInRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action",std::string("connect"));
request->setParameter("username",username);
request->setParameter("password",password);
if (request_now)
{
HTTPManager::get()->addRequest(request);
m_state = US_SIGNING_IN;
}
return request;
}
void CurrentUser::signIn(const SignInRequest * input)
{
if (input->isSuccess())
{
int token_fetched = input->getResult()->get("token", &m_token);
int username_fetched = input->getResult()->get("username", &m_name);
int userid_fetched = input->getResult()->get("userid", &m_id);
assert(token_fetched && username_fetched && userid_fetched);
m_state = US_SIGNED_IN;
if(m_save_session)
{
UserConfigParams::m_saved_user = m_id;
UserConfigParams::m_saved_token = m_token;
UserConfigParams::m_saved_session = true;
m_save_session = false;
}
}
else
m_state = US_SIGNED_OUT;
}
void CurrentUser::SignInRequest::callback()
{
CurrentUser::acquire()->signIn(this);
CurrentUser::release();
}
// ============================================================================
CurrentUser::ServerCreationRequest * CurrentUser::requestServerCreation(const irr::core::stringw &name, int max_players)
{
assert(m_state == US_SIGNED_IN);
ServerCreationRequest * request = new ServerCreationRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action", std::string("create_server"));
request->setParameter("token", m_token);
request->setParameter("userid", m_id);
request->setParameter("name", name);
request->setParameter("max_players", max_players);
HTTPManager::get()->addRequest(request);
return request;
}
void CurrentUser::ServerCreationRequest::callback()
{
if(isSuccess())
{
Server * server = new Server(*getResult()->getNode("server"));
ServersManager::acquire()->addServer(server);
ServersManager::release();
m_created_server_id.setAtomic(server->getServerId());
}
}
// ============================================================================
CurrentUser::SignOutRequest * CurrentUser::requestSignOut(){
assert(m_state == US_SIGNED_IN || m_state == US_GUEST);
SignOutRequest * request = new SignOutRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action",std::string("disconnect"));
request->setParameter("token",m_token);
request->setParameter("userid",m_id);
HTTPManager::get()->addRequest(request);
m_state = US_SIGNING_OUT;
return request;
}
void CurrentUser::signOut(const SignOutRequest * input)
{
if(!input->isSuccess())
{
Log::warn("CurrentUser::signOut", "%s", _("There were some connection issues while signing out. Report a bug if this caused issues."));
}
m_token = "";
m_name = "";
m_id = 0;
m_state = US_SIGNED_OUT;
UserConfigParams::m_saved_user = 0;
UserConfigParams::m_saved_token = "";
UserConfigParams::m_saved_session = false;
}
void CurrentUser::SignOutRequest::callback()
{
CurrentUser::acquire()->signOut(this);
CurrentUser::release();
}
// ============================================================================
CurrentUser::ServerJoinRequest * CurrentUser::requestServerJoin(uint32_t server_id){
assert(m_state == US_SIGNED_IN || m_state == US_GUEST);
ServerJoinRequest * request = new ServerJoinRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
request->setParameter("action",std::string("request-connection"));
request->setParameter("token", m_token);
request->setParameter("id", m_id);
request->setParameter("server_id", server_id);
HTTPManager::get()->addRequest(request);
return request;
}
void CurrentUser::ServerJoinRequest::callback()
{
if(isSuccess())
{
uint32_t server_id;
getResult()->get("serverid", &server_id);
ServersManager::acquire()->setJoinedServer(server_id);
ServersManager::release();
}
//FIXME needs changes for actual valid joining
}
// ============================================================================
irr::core::stringw CurrentUser::getUserName() const
{
if((m_state == US_SIGNED_IN ) || (m_state == US_GUEST))
return m_name;
else
return _("Currently not signed in");
}
} // namespace Online

136
src/online/current_user.hpp Normal file
View File

@ -0,0 +1,136 @@
//
// 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_CURRENT_ONLINE_USER_HPP
#define HEADER_CURRENT_ONLINE_USER_HPP
#include "online/user.hpp"
#include <string>
#include <irrString.h>
#include "utils/types.hpp"
#include "online/server.hpp"
#include "http_manager.hpp"
namespace Online{
// ============================================================================
/**
* \brief Class that represents an online registered user
* \ingroup online
*/
class CurrentUser : public User
{
public:
enum UserState
{
US_SIGNED_OUT,
US_SIGNED_IN,
US_GUEST,
US_SIGNING_IN,
US_SIGNING_OUT
};
enum RequestType
{
RT_SIGN_IN = 1,
RT_SIGN_OUT,
RT_SIGN_UP,
RT_SERVER_JOIN,
RT_SERVER_CREATION
};
class SignInRequest : public XMLRequest
{
virtual void callback ();
public:
SignInRequest() : XMLRequest(RT_SIGN_IN) {}
};
class SignOutRequest : public XMLRequest
{
virtual void callback ();
public:
SignOutRequest() : XMLRequest(RT_SIGN_OUT) {}
};
class ServerCreationRequest : public XMLRequest {
virtual void callback ();
Synchronised<uint32_t> m_created_server_id;
public:
ServerCreationRequest() : XMLRequest(RT_SERVER_CREATION) {}
uint32_t getCreatedServerID() {return m_created_server_id.getAtomic();}
};
class ServerJoinRequest : public XMLRequest {
virtual void callback ();
public:
ServerJoinRequest() : XMLRequest(RT_SERVER_JOIN) {}
};
private:
std::string m_token;
bool m_save_session;
UserState m_state;
CurrentUser();
void signIn (const SignInRequest * input);
void signOut (const SignOutRequest * input);
void createServer (const ServerCreationRequest * input);
public:
//Singleton
static CurrentUser* acquire();
static void release();
static void deallocate();
SignInRequest * requestSavedSession();
SignInRequest * requestSignIn( const irr::core::stringw &username,
const irr::core::stringw &password,
bool save_session,
bool request_now = true);
SignOutRequest * requestSignOut();
ServerCreationRequest * requestServerCreation( const irr::core::stringw &name, int max_players);
ServerJoinRequest * requestServerJoin( uint32_t server_id);
// Register
XMLRequest * requestSignUp( const irr::core::stringw &username,
const irr::core::stringw &password,
const irr::core::stringw &password_ver,
const irr::core::stringw &email,
bool terms);
/** Returns the username if signed in. */
irr::core::stringw getUserName() const;
bool isSignedIn() const { return m_state == US_SIGNED_IN; }
bool isGuest() const { return m_state == US_GUEST; }
bool isSigningIn() const { return m_state == US_SIGNING_IN; }
UserState getUserState() { return m_state; }
std::string getToken() const { return m_token; }
}; // class CurrentUser
} // namespace Online
#endif
/*EOF*/

View File

@ -1,88 +0,0 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 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 "http_connector.hpp"
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include "io/file_manager.hpp"
HTTPConnector::HTTPConnector(const std::string &url){
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
if(!curl)
Log::error("online/http_functions", "Error while loading cURL library.");
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
if (url.substr(0, 5)!="http:")
{
Log::error("online/http_functions", "Invalid URL.");
}
}
// ============================================================================
HTTPConnector::~HTTPConnector(){
curl_easy_cleanup(curl);
curl_global_cleanup();
}
// ============================================================================
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
XMLNode * HTTPConnector::getXMLFromPage()
{
return file_manager->createXMLTreeFromString(getPage());
}
std::string HTTPConnector::getPage()
{
Parameters::iterator iter;
std::string postString = "";
for (iter = m_parameters.begin(); iter != m_parameters.end(); ++iter)
{
if(iter != m_parameters.begin())
postString.append("&");
char * escaped = curl_easy_escape(this->curl , iter->first.c_str(), iter->first.size());
postString.append(escaped);
curl_free(escaped);
postString.append("=");
escaped = curl_easy_escape(this->curl , iter->second.c_str(), iter->second.size());
postString.append(escaped);
curl_free(escaped);
}
curl_easy_setopt(this->curl, CURLOPT_POSTFIELDS, postString.c_str());
std::string readBuffer;
curl_easy_setopt(this->curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(this->curl, CURLOPT_FILE, &readBuffer);
res = curl_easy_perform(this->curl);
if(res != CURLE_OK)
Log::error("online/http_functions", "curl_easy_perform() failed: \"%s\"", curl_easy_strerror(res));
else
Log::verbose("online/http_functions", "Received : \"%s\"", readBuffer.c_str());
m_parameters.clear();
return readBuffer;
}

View File

@ -1,70 +0,0 @@
//
// SuperTuxKart - a fun racing game with go-kart
// Copyright (C) 2013 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 HTTP_CONNECTOR_HPP
#define HTTP_CONNECTOR_HPP
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
#include <irrString.h>
#ifdef WIN32
# include <WinSock2.h>
#endif
#include <curl/curl.h>
#include <string>
/**
* \brief Class to connect with a server over HTTP
* \ingroup online
*/
class HTTPConnector
{
protected:
CURL *curl;
CURLcode res;
typedef std::map<std::string, std::string> Parameters;
Parameters m_parameters;
public:
HTTPConnector(const std::string &url);
~HTTPConnector();
//Execute
std::string getPage();
XMLNode * getXMLFromPage();
//Setting parameters to be send with the next request
void setParameter(const std::string & name, const std::string &value){
m_parameters[name] = value;
};
void setParameter(const std::string & name, const irr::core::stringw &value){
m_parameters[name] = irr::core::stringc(value.c_str()).c_str();
}
template <typename T>
void setParameter(const std::string & name, const T& value){
m_parameters[name] = StringUtils::toString(value);
}
}; //class HTTPConnector
#endif // HTTP_CONNECTOR_HPP
/*EOF*/

222
src/online/http_manager.cpp Normal file
View File

@ -0,0 +1,222 @@
//
// 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.
#include "online/http_manager.hpp"
#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <errno.h>
#if defined(WIN32) && !defined(__CYGWIN__)
# include <windows.h>
# define isnan _isnan
#else
# include <sys/time.h>
# include <math.h>
#endif
#if defined(WIN32) && !defined(__CYGWIN__)
// Use Sleep, which takes time in msecs. It must be defined after the
// includes, since otherwise irrlicht's sleep function is changed.
# define sleep(s) Sleep(1000*(s))
#else
# include <unistd.h>
#endif
namespace Online{
static HTTPManager * http_singleton = NULL;
HTTPManager* HTTPManager::get()
{
if (http_singleton == NULL)
{
http_singleton = new HTTPManager();
http_singleton->startNetworkThread();
}
return http_singleton;
} // get
void HTTPManager::deallocate()
{
delete http_singleton;
http_singleton = NULL;
} // deallocate
bool HTTPManager::isRunning()
{
return http_singleton != NULL;
}
HTTPManager::HTTPManager(){
curl_global_init(CURL_GLOBAL_DEFAULT);
pthread_cond_init(&m_cond_request, NULL);
m_abort.setAtomic(false);
}
// ============================================================================
HTTPManager::~HTTPManager(){
curl_global_cleanup();
}
// ---------------------------------------------------------------------------
/** Start the actual network thread. This can not be done as part of
* the constructor, since the assignment to the global network_http
* variable has not been assigned at that stage, and the thread might
* use network_http - a very subtle race condition. So the thread can
* only be started after the assignment (in main) has been done.
*/
void HTTPManager::startNetworkThread()
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
// Should be the default, but just in case:
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
//pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
m_thread_id.setAtomic(new pthread_t());
int error = pthread_create(m_thread_id.getData(), &attr,
&HTTPManager::mainLoop, this);
if(error)
{
m_thread_id.lock();
delete m_thread_id.getData();
m_thread_id.unlock();
m_thread_id.setAtomic(0);
Log::error("HTTP Manager", "Could not create thread, error=%d.\n", errno);
}
pthread_attr_destroy(&attr);
} // startNetworkThread
// ---------------------------------------------------------------------------
/** This function inserts a high priority request to quit into the request
* queue of the network thead, and also aborts any ongoing download.
* Separating this allows more time for the thread to finish cleanly,
* before it gets cancelled in the destructor.
*/
void HTTPManager::stopNetworkThread()
{
// If a download should be active (which means it was cancelled by the
// user, in which case it will still be ongoing in the background)
// we can't get the mutex, and would have to wait for a timeout,
// and we couldn't finish STK. This way we request an abort of
// a download, which mean we can get the mutex and ask the service
// thread here to cancel properly.
cancelAllDownloads();
addRequest(new Request(true, 9999, Request::RT_QUIT));
} // stopNetworkThread
// ----------------------------------------------------------------------------
/** Signals to the progress function to request any ongoing download to be
* cancelled. This function can also be called if there is actually no
* download atm. The function progressDownload checks m_abort and will
* return a non-zero value which causes libcurl to abort. */
void HTTPManager::cancelAllDownloads()
{
m_abort.setAtomic(true);
} // cancelAllDownloads
// ----------------------------------------------------------------------------
/** Inserts a request into the queue of all requests. The request will be
* sorted by priority.
* \param request The pointer to the new request to insert.
*/
void HTTPManager::addRequest(Request *request)
{
assert(request->isAllowedToAdd());
m_request_queue.lock();
m_request_queue.getData().push(request);
// Wake up the network http thread
pthread_cond_signal(&m_cond_request);
m_request_queue.unlock();
} // addRequest
// ----------------------------------------------------------------------------
/** Immediately performs a request synchronously
* \param request The pointer to the new request to insert.
*/
void HTTPManager::synchronousRequest(Request *request)
{
assert(request->isAllowedToAdd());
request->execute();
} // synchronousRequest
// ---------------------------------------------------------------------------
/** The actual main loop, which is started as a separate thread from the
* constructor. After testing for a new server, fetching news, the list
* of packages to download, it will wait for commands to be issued.
* \param obj: A pointer to this object, passed on by pthread_create
*/
void *HTTPManager::mainLoop(void *obj)
{
HTTPManager *me = (HTTPManager*) obj;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
me->m_current_request = NULL;
me->m_request_queue.lock();
while( me->m_request_queue.getData().empty() || me->m_request_queue.getData().top()->getType() != Request::RT_QUIT)
{
bool empty = me->m_request_queue.getData().empty();
// Wait in cond_wait for a request to arrive. The 'while' is necessary
// since "spurious wakeups from the pthread_cond_wait ... may occur"
// (pthread_cond_wait man page)!
while(empty)
{
pthread_cond_wait(&me->m_cond_request, me->m_request_queue.getMutex());
empty = me->m_request_queue.getData().empty();
}
me->m_current_request = me->m_request_queue.getData().top();
me->m_request_queue.getData().pop();
me->m_request_queue.unlock();
me->m_current_request->execute();
if(me->m_current_request->manageMemory())
{
delete me->m_current_request;
me->m_current_request = NULL;
}
me->m_request_queue.lock();
} // while
// At this stage we have the lock for m_request_queue
while(!me->m_request_queue.getData().empty())
{
Online::Request * request = me->m_request_queue.getData().top();
me->m_request_queue.getData().pop();
// Manage memory can be ignored here, all requests
// need to be freed.
delete request;
}
me->m_request_queue.unlock();
pthread_exit(NULL);
return 0;
} // mainLoop
} // namespace Online

View File

@ -0,0 +1,98 @@
//
// 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 HTTP_MANAGER_HPP
#define HTTP_MANAGER_HPP
#include <string>
#include <curl/curl.h>
#include <irrString.h>
#include <queue>
#include <pthread.h>
#ifdef WIN32
# include <winsock2.h>
#endif
#include "io/xml_node.hpp"
#include "utils/string_utils.hpp"
#include "utils/synchronised.hpp"
#include "online/request.hpp"
namespace Online{
/**
* \brief Class to connect with a server over HTTP
* \ingroup online
*/
class HTTPManager
{
protected:
/** Ment for networking threads */
/** The current requested being worked on. */
Online::Request * m_current_request;
/** A conditional variable to wake up the main loop. */
pthread_cond_t m_cond_request;
/** Signal an abort in case that a download is still happening. */
Synchronised<bool> m_abort;
/** Thread id of the thread running in this object. */
Synchronised<pthread_t *> m_thread_id;
/** The list of pointers to all requests that still need to be handled. */
Synchronised< std::priority_queue <
Online::Request*,
std::vector<Online::Request*>,
Online::Request::Compare
>
> m_request_queue;
static void *mainLoop(void *obj);
void startNetworkThread();
HTTPManager(); //const std::string &url
~HTTPManager();
public:
// singleton
static HTTPManager* get();
static void deallocate();
static bool isRunning();
//Execute
std::string getPage(Online::Request * request);
XMLNode * getXMLFromPage(Online::Request * request);
void synchronousRequest(Online::Request *request);
void addRequest(Online::Request *request);
void cancelAllDownloads();
void stopNetworkThread();
bool getAbort(){ return m_abort.getAtomic(); };
}; //class HTTPManager
} // namespace Online
#endif // HTTP_MANAGER_HPP
/*EOF*/

78
src/online/messages.cpp Normal file
View File

@ -0,0 +1,78 @@
//
// 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.
#include "online/messages.hpp"
#include "utils/translation.hpp"
#include "utils/time.hpp"
namespace Online
{
namespace Messages
{
irr::core::stringw signingIn()
{
return irr::core::stringw(_("Signing in")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw signingOut()
{
return irr::core::stringw(_("Signing out")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw signingUp()
{
return irr::core::stringw(_("Validating registration info")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw signedInAs(const irr::core::stringw & name)
{
return irr::core::stringw(_("Signed in as : ")) + name + ".";
}
// ------------------------------------------------------------------------
irr::core::stringw joiningServer()
{
return irr::core::stringw(_("Joining server")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw creatingServer()
{
return irr::core::stringw(_("Creating server")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw fetchingServers()
{
return irr::core::stringw(_("Fetching servers")) + loadingDots();
}
// ------------------------------------------------------------------------
irr::core::stringw loadingDots(bool spaces, float interval, int max_dots)
{
int nr_dots = int(floor(Time::getRealTime() * (1 / interval))) % (max_dots+1);
return irr::core::stringw((std::string(nr_dots,'.') + std::string(max_dots-nr_dots,' ')).c_str());
}
} // namespace messages
} // namespace Online
/* EOF */

41
src/online/messages.hpp Normal file
View File

@ -0,0 +1,41 @@
//
// 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_ONLINE_MESSAGES_HPP
#define HEADER_ONLINE_MESSAGES_HPP
#include <string>
#include <irrString.h>
namespace Online
{
namespace Messages
{
irr::core::stringw loadingDots (bool spaces = true, float interval = 0.5f, int max_dots = 3);
irr::core::stringw signingIn ();
irr::core::stringw signingOut ();
irr::core::stringw signingUp ();
irr::core::stringw joiningServer ();
irr::core::stringw creatingServer ();
irr::core::stringw fetchingServers ();
irr::core::stringw signedInAs (const irr::core::stringw & name);
} // namespace Messages
}// namespace Online
#endif
/* EOF */

234
src/online/request.cpp Normal file
View File

@ -0,0 +1,234 @@
// 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.
#include "online/request.hpp"
#include <curl/curl.h>
#include <assert.h>
#include <online/http_manager.hpp>
#include <utils/translation.hpp>
namespace Online{
class HTTPManager;
// =========================================================================================
Request::Request(int type, bool manage_memory, int priority)
: m_type(type), m_manage_memory(manage_memory), m_priority(priority)
{
m_cancel.setAtomic(false);
m_done.setAtomic(false);
} // Request
Request::~Request()
{
}
void Request::execute()
{
beforeOperation();
operation();
afterOperation();
}
void Request::afterOperation()
{
m_done.setAtomic(true);
}
// =========================================================================================
HTTPRequest::HTTPRequest(int type, bool manage_memory, int priority)
: Request(priority, manage_memory, type)
{
//Negative numbers are reserved for special requests ment for the HTTP Manager
assert(type >= 0);
m_url.setAtomic("");
m_parameters = new Parameters;
m_progress.setAtomic(0);
}
HTTPRequest::~HTTPRequest()
{
delete m_parameters;
}
bool HTTPRequest::isAllowedToAdd()
{
bool ok = true;
m_url.lock();
if (m_url.getData().size() > 5 && ( m_url.getData().substr(0, 5) != "http:"))
ok = false;
m_url.unlock();
return ok;
}
void HTTPRequest::afterOperation()
{
callback();
Request::afterOperation();
}
std::string HTTPRequest::downloadPage()
{
CURL * curl_session;
curl_session = curl_easy_init();
if(!curl_session)
{
Log::error("online/http_functions", "Error while initialising libCurl session");
return "";
}
curl_easy_setopt(curl_session, CURLOPT_URL, m_url.getAtomic().c_str());
Parameters::iterator iter;
std::string postString = "";
for (iter = m_parameters->begin(); iter != m_parameters->end(); ++iter)
{
if(iter != m_parameters->begin())
postString.append("&");
char * escaped = curl_easy_escape(curl_session , iter->first.c_str(), iter->first.size());
postString.append(escaped);
curl_free(escaped);
postString.append("=");
escaped = curl_easy_escape(curl_session , iter->second.c_str(), iter->second.size());
postString.append(escaped);
curl_free(escaped);
}
curl_easy_setopt(curl_session, CURLOPT_POSTFIELDS, postString.c_str());
std::string readBuffer;
curl_easy_setopt(curl_session, CURLOPT_WRITEFUNCTION, &HTTPRequest::WriteCallback);
curl_easy_setopt(curl_session, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(curl_session, CURLOPT_PROGRESSDATA, this);
curl_easy_setopt(curl_session, CURLOPT_PROGRESSFUNCTION, &HTTPRequest::progressDownload);
curl_easy_setopt(curl_session, CURLOPT_FILE, &readBuffer);
// Timeout
// Reduce the connection phase timeout (it's 300 by default).
// Add a low speed limit to have a sort of timeout in the
// download phase. Being under 10 B/s during a certain time will
// probably only happen when no access to the net is available.
// The timeout is set to 20s, it should be enough to not produce
// false positive error.
curl_easy_setopt(curl_session, CURLOPT_CONNECTTIMEOUT, 20);
curl_easy_setopt(curl_session, CURLOPT_LOW_SPEED_LIMIT, 10);
curl_easy_setopt(curl_session, CURLOPT_LOW_SPEED_TIME, 20);
CURLcode res = curl_easy_perform(curl_session);
if(res == CURLE_OK)
{
Log::info("online/http_functions", "Received : %s", readBuffer.c_str());
setProgress(1.0f);
}
else
{
Log::error("HTTPRequest::downloadPage", "curl_easy_perform() failed: %s", curl_easy_strerror(res));
setProgress(-1.0f);
}
curl_easy_cleanup(curl_session);
return readBuffer;
}
size_t HTTPRequest::WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
// ----------------------------------------------------------------------------
/** Callback function from curl: inform about progress.
* \param clientp
* \param download_total Total size of data to download.
* \param download_now How much has been downloaded so far.
* \param upload_total Total amount of upload.
* \param upload_now How muc has been uploaded so far.
*/
int HTTPRequest::progressDownload(void *clientp,
double download_total, double download_now,
double upload_total, double upload_now)
{
HTTPRequest *request = (HTTPRequest *)clientp;
HTTPManager* http_manager = HTTPManager::get();
// Check if we are asked to abort the download. If so, signal this
// back to libcurl by returning a non-zero status.
if(http_manager->getAbort() || request->isCancelled() )
{
// Indicates to abort the current download, which means that this
// thread will go back to the mainloop and handle the next request.
return 1;
}
float f;
if(download_now < download_total)
{
f = (float)download_now / (float)download_total;
// In case of floating point rouding errors make sure that
// 1.0 is only reached when downloadFileInternal is finished
if (f>=1.0f) f=0.99f;
}
else
{
// Don't set progress to 1.0f; this is done in loadFileInternal
// after checking curls return code!
f= download_total==0 ? 0 : 0.99f;
}
request->setProgress(f);
return 0;
} // progressDownload
// =========================================================================================
XMLRequest::XMLRequest(int type, bool manage_memory, int priority)
: HTTPRequest(priority, manage_memory, type)
{
m_info.setAtomic("");
m_success.setAtomic(false);
m_result = NULL;
}
XMLRequest::~XMLRequest()
{
delete m_result;
}
void XMLRequest::operation()
{
m_result = file_manager->createXMLTreeFromString(downloadPage());
}
void XMLRequest::afterOperation()
{
const XMLNode * xml = this->getResult();
bool success = false;
irr::core::stringw info;
std::string rec_success;
if(xml->get("success", &rec_success))
{
if (rec_success =="yes")
success = true;
xml->get("info", &info);
}
else
info = _("Unable to connect to the server. Check your internet connection or try again later.");
m_info.setAtomic(info);
m_success.setAtomic(success);
HTTPRequest::afterOperation();
}
} // namespace Online

208
src/online/request.hpp Normal file
View File

@ -0,0 +1,208 @@
// 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_ONLINE_REQUEST_HPP
#define HEADER_ONLINE_REQUEST_HPP
#include <string>
#include "utils/cpp2011.h"
#include "utils/string_utils.hpp"
#include "utils/synchronised.hpp"
#include "io/file_manager.hpp"
namespace Online{
/**
* Stores a request for the HTTP Manager. They will be sorted by priorities.
* \ingroup online
*/
class Request
{
private:
/** Can be used as identifier for the user.
* Has 0 as default value.
* Only requests ment to control the HTTP Manager should use negative values, for all other uses positive values are obliged
* */
const int m_type;
/** True if the memory for this Request should be managed by
* http connector (i.e. this object is freed once the request
* is handled). Otherwise the memory is not freed, so it must
* be freed by the calling function. */
const bool m_manage_memory;
/** The priority of this request. The higher the value the more
important this request is. */
const int m_priority;
protected:
/** Cancel this request if it is active. */
Synchronised<bool> m_cancel;
/** Set to though if the reply of the request is in and callbacks are executed */
Synchronised<bool> m_done;
virtual void beforeOperation() {}
virtual void operation() {};
virtual void afterOperation();
public:
/** Negative numbers are reserved for requests that are special for the HTTP Manager*/
enum RequestType
{
RT_QUIT = -1
};
Request(int type, bool manage_memory, int priority);
virtual ~Request();
void execute();
int getType() const { return m_type; }
// ------------------------------------------------------------------------
/** Returns if the memory for this object should be managed by
* by network_http (i.e. freed once the request is handled). */
bool manageMemory() const { return m_manage_memory; }
// ------------------------------------------------------------------------
/** Returns the priority of this request. */
int getPriority() const { return m_priority; }
// ------------------------------------------------------------------------
/** Signals that this request should be canceled. */
void cancel() { m_cancel.setAtomic(true); }
// ------------------------------------------------------------------------
/** Returns if this request is to be canceled. */
bool isCancelled() const { return m_cancel.getAtomic(); }
// ------------------------------------------------------------------------
/** Returns if this request is done. */
bool isDone() const { return m_done.getAtomic(); }
// ------------------------------------------------------------------------
/** Virtual method to check if a request has initialized all needed members to a valid value. */
virtual bool isAllowedToAdd() const { return true; }
/** This class is used by the priority queue to sort requests by priority.
*/
class Compare
{
public:
/** Compares two requests, returns if the first request has a lower
* priority than the second one. */
bool operator() (const Request *a, const Request *b) const
{
return a->getPriority() < b->getPriority();
}
}; // Compare
}; // Request
// ========================================================================
class HTTPRequest : public Request
{
protected :
typedef std::map<std::string, std::string> Parameters;
/** The progress indicator. 0 untill it is started and the first
* packet is downloaded. At the end either -1 (error) or 1
* (everything ok) at the end. */
Synchronised<float> m_progress;
Synchronised<std::string> m_url;
Parameters * m_parameters;
virtual void afterOperation() OVERRIDE;
/** Executed when a request has finished. */
virtual void callback() {}
/**
* Performs a POST request to the website with URL m_url using the parameters given in m_parameters.
* Returns the page as a string.
**/
std::string downloadPage();
static int progressDownload( void *clientp,
double dltotal,
double dlnow,
double ultotal,
double ulnow);
static size_t WriteCallback( void *contents,
size_t size,
size_t nmemb,
void *userp);
public :
HTTPRequest(int type = 0, bool manage_memory = false, int priority = 1);
virtual ~HTTPRequest();
void setParameter(const std::string & name, const std::string &value){
(*m_parameters)[name] = value;
};
void setParameter(const std::string & name, const irr::core::stringw &value){
(*m_parameters)[name] = irr::core::stringc(value.c_str()).c_str();
}
template <typename T>
void setParameter(const std::string & name, const T& value){
(*m_parameters)[name] = StringUtils::toString(value);
}
/** Returns the current progress. */
float getProgress() const { return m_progress.getAtomic(); }
/** Sets the current progress. */
void setProgress(float f) { m_progress.setAtomic(f); }
const std::string getURL() {
m_url.lock();
const std::string url = m_url.getData();
m_url.unlock();
return url;
}
void setURL(const std::string & url) { m_url.setAtomic(url);}
virtual bool isAllowedToAdd() OVERRIDE;
};
class XMLRequest : public HTTPRequest
{
protected :
XMLNode * m_result;
Synchronised<irr::core::stringw> m_info;
Synchronised<bool> m_success;
virtual void operation() OVERRIDE;
virtual void afterOperation() OVERRIDE;
public :
XMLRequest(int type = 0, bool manage_memory = false, int priority = 1);
virtual ~XMLRequest();
virtual XMLNode * getResult() const { return m_result; }
const irr::core::stringw getInfo() {
m_info.lock();
const irr::core::stringw info = m_info.getData();
m_info.unlock();
return info;
}
bool isSuccess() const { return m_success.getAtomic(); }
};
} //namespace Online
#endif

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

@ -0,0 +1,75 @@
// 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"
namespace Online{
Server::SortOrder Server::m_sort_order=Server::SO_NAME; //FIXME change to some other default
Server::Server(const XMLNode & xml)
{
assert(xml.getName() == "server");
m_name = "";
m_satisfaction_score = 0;
m_server_id = 0;
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);
xml.get("id", &m_server_id);
xml.get("hostid", &m_host_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;
}
}
return false;
} // filterByWords
} // namespace Online

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

@ -0,0 +1,136 @@
//
// 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"
#include "utils/types.hpp"
class XMLNode;
namespace Online{
/**
* \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
uint32_t m_server_id;
uint32_t m_host_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; }
// ------------------------------------------------------------------------
const float getScore() const { return m_satisfaction_score; }
// ------------------------------------------------------------------------
/** Returns the ID of this server. */
const uint32_t 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;
case SO_PLAYERS:
return m_current_players < server.getCurrentPlayers();
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
} // namespace Online
#endif

View File

@ -0,0 +1,165 @@
//
// 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.
#include "online/servers_manager.hpp"
#include <string>
#include <irrString.h>
#include <assert.h>
#include "config/user_config.hpp"
#include "utils/translation.hpp"
#include "utils/time.hpp"
#define SERVER_REFRESH_INTERVAL 5.0f
namespace Online{
static Synchronised<ServersManager*> manager_singleton(NULL);
ServersManager* ServersManager::acquire()
{
manager_singleton.lock();
ServersManager * manager = manager_singleton.getData();
if (manager == NULL)
{
manager_singleton.unlock();
manager = new ServersManager();
manager_singleton.setAtomic(manager);
manager_singleton.lock();
}
return manager;
}
void ServersManager::release()
{
manager_singleton.unlock();
}
void ServersManager::deallocate()
{
manager_singleton.lock();
ServersManager* manager = manager_singleton.getData();
delete manager;
manager = NULL;
manager_singleton.unlock();
} // deallocate
// ============================================================================
ServersManager::ServersManager(){
m_info_message = "";
m_last_load_time = 0.0f;
m_joined_server = NULL;
}
ServersManager::~ServersManager(){
cleanUpServers();
delete m_joined_server;
}
// ============================================================================
void ServersManager::cleanUpServers()
{
m_sorted_servers.clearAndDeleteAll();
m_mapped_servers.clear();
}
// ============================================================================
ServersManager::RefreshRequest * ServersManager::refreshRequest()
{
RefreshRequest * request = NULL;
if(Time::getRealTime() - m_last_load_time > SERVER_REFRESH_INTERVAL)
{
request = new RefreshRequest();
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "client-user.php");
request->setParameter("action",std::string("get_server_list"));
HTTPManager::get()->addRequest(request);
}
return request;
}
void ServersManager::refresh(RefreshRequest * input)
{
if (input->isSuccess())
{
const XMLNode * servers_xml = input->getResult()->getNode("servers");
cleanUpServers();
for (unsigned int i = 0; i < servers_xml->getNumNodes(); i++)
{
addServer(new Server(*servers_xml->getNode(i)));
}
m_last_load_time = Time::getRealTime();
}
m_info_message = input->getInfo();
//FIXME error message
}
void ServersManager::RefreshRequest::callback()
{
ServersManager::acquire()->refresh(this);
ServersManager::release();
}
// ============================================================================
Server * ServersManager::getQuickPlay()
{
if(m_sorted_servers.size() > 0)
return getServerBySort(0);
return NULL;
}
// ============================================================================
void ServersManager::setJoinedServer(uint32_t id)
{
delete m_joined_server;
//It's a copy!
m_joined_server = new Server(*getServerByID(id));
}
// ============================================================================
void ServersManager::unsetJoinedServer()
{
delete m_joined_server;
m_joined_server = NULL;
}
// ============================================================================
void ServersManager::addServer(Server * server)
{
m_sorted_servers.push_back(server);
m_mapped_servers[server->getServerId()] = server;
}
// ============================================================================
int ServersManager::getNumServers ()
{
return m_sorted_servers.size();
}
// ============================================================================
Server * ServersManager::getServerBySort (int index)
{
return m_sorted_servers.get(index);
}
// ============================================================================
Server * ServersManager::getServerByID (uint32_t id)
{
return m_mapped_servers[id];
}
} // namespace Online

View File

@ -0,0 +1,91 @@
//
// 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_SERVERS_MANAGER_HPP
#define HEADER_SERVERS_MANAGER_HPP
#include "utils/ptr_vector.hpp"
#include "utils/types.hpp"
#include "online/server.hpp"
#include "http_manager.hpp"
namespace Online {
/**
* \brief
* \ingroup online
*/
class ServersManager
{
public:
enum RequestType
{
RT_REFRESH = 1
};
class RefreshRequest : public XMLRequest
{
virtual void callback ();
public:
RefreshRequest() : XMLRequest(RT_REFRESH) {}
};
private:
ServersManager();
~ServersManager();
/** Sorted vector of servers */
PtrVector<Server> m_sorted_servers;
/** Maps server id's to the same servers*/
std::map<uint32_t, Server*> m_mapped_servers;
/** This is a pointer to a copy of the server, the moment it got joined */
Server * m_joined_server;
bool m_not_fetched;
irr::core::stringw m_info_message;
float m_last_load_time;
void refresh(RefreshRequest * input);
void cleanUpServers();
public:
// Singleton
static ServersManager* acquire();
static void release();
static void deallocate();
RefreshRequest * refreshRequest();
void setJoinedServer(uint32_t server_id);
void unsetJoinedServer();
void addServer(Server * server);
int getNumServers ();
Server * getServerByID (uint32_t server_id);
Server * getServerBySort (int index);
void sort(bool sort_desc) { m_sorted_servers.insertionSort(0, sort_desc); }
Server * getJoinedServer() { return m_joined_server; }
//Returns the best server to join
Server * getQuickPlay();
}; // class ServersManager
} // namespace Online
#endif
/*EOF*/

View File

@ -17,22 +17,20 @@
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "online/online_user.hpp"
#include "online/user.hpp"
#include <sstream>
#include <stdlib.h>
// ============================================================================
OnlineUser::OnlineUser(const irr::core::stringw &username)
{
m_name = username;
} // OnlineUser
// ============================================================================
OnlineUser::OnlineUser(const uint32_t& id)
{
m_id = id;
} // OnlineUser
namespace Online{
// ============================================================================
User::User(const irr::core::stringw &username)
{
m_name = username;
}
// ============================================================================
User::User(uint32_t id)
{
m_id = id;
}
} // namespace Online

View File

@ -21,38 +21,35 @@
#include <irrString.h>
#include "utils/types.hpp"
#include "utils/synchronised.hpp"
// ============================================================================
namespace Online{
/**
* \brief Class that represents an online registered user
* \ingroup online
*/
class OnlineUser
{
private:
/**
* \brief Class that represents an online registered user
* \ingroup online
*/
class User
{
private:
protected:
protected:
irr::core::stringw m_name;
uint32_t m_id;
User(){}
irr::core::stringw m_name;
uint32_t m_id;
OnlineUser(){}
public:
public:
/**
* Constructor
*/
OnlineUser(const irr::core::stringw &username);
OnlineUser(const uint32_t& id);
/** Returns the username. */
irr::core::stringw getUserName() const { return m_name; }
uint32_t getUserID() const { return m_id; }
User(const irr::core::stringw &username);
User(uint32_t id);
}; // class OnlineUser
irr::core::stringw getUserName() const { return m_name; }
uint32_t getUserID() const { return m_id; }
}; // class User
} // namespace Online
#endif
/*EOF*/

View File

@ -104,7 +104,7 @@ void AddonsScreen::beforeAddingWidget()
getWidget<GUIEngine::ListWidget>("list_addons");
assert(w_list != NULL);
w_list->clearColumns();
w_list->addColumn( _("Add-on name"), 2 );
w_list->addColumn( _("Add-on name"), 3 );
w_list->addColumn( _("Updated date"), 1 );
GUIEngine::SpinnerWidget* w_filter_date =
@ -140,8 +140,6 @@ void AddonsScreen::init()
getWidget<GUIEngine::RibbonWidget>("category")->setDeactivated();
GUIEngine::getFont()->setTabStop(0.66f);
if(UserConfigParams::logAddons())
std::cout << "[addons] Using directory <" + file_manager->getAddonsDir()
<< ">\n";
@ -188,8 +186,6 @@ void AddonsScreen::unloaded()
void AddonsScreen::tearDown()
{
// return tab stop to the center when leaving this screen!!
GUIEngine::getFont()->setTabStop(0.5f);
}
// ----------------------------------------------------------------------------
@ -279,10 +275,13 @@ void AddonsScreen::loadList()
s = (addon->getName()+L"\t" +
core::stringc(addon->getDateAsString().c_str())).c_str();
gui::IGUIFont* font = GUIEngine::getFont();
//FIXME I'd like to move this to CGUISTKListBox.cpp
/* gui::IGUIFont* font = GUIEngine::getFont();
// first column is 0.666% of the list's width.
// and icon width == icon height.
const unsigned int available_width = (int)(w_list->m_w*0.6666f
- m_icon_height);
if (font->getDimension(s.c_str()).Width > available_width)
@ -291,7 +290,7 @@ void AddonsScreen::loadList()
s.append("...");
}
else
{
{*/
if (addon->getDesigner().size() == 0)
{
s = addon->getName();
@ -302,7 +301,7 @@ void AddonsScreen::loadList()
s = _C("addons", "%s by %s", addon->getName().c_str(),
addon->getDesigner().c_str());
}
/*
// check if text is too long to fit
if (font->getDimension(s.c_str()).Width > available_width)
{
@ -342,10 +341,9 @@ void AddonsScreen::loadList()
} // for nlines.size()
s = final_string;
} // if
s.append("\t");
s.append(addon->getDateAsString().c_str());
}
*/
//} // if
//}
// we have no icon for featured+updateme, so if an add-on is updatable
// forget about the featured icon
@ -355,7 +353,10 @@ void AddonsScreen::loadList()
icon += 2;
}
w_list->addItem(addon->getId(), s.c_str(), icon);
PtrVector<GUIEngine::ListWidget::ListCell> * row = new PtrVector<GUIEngine::ListWidget::ListCell>;
row->push_back(new GUIEngine::ListWidget::ListCell(s.c_str(), icon, 3, false));
row->push_back(new GUIEngine::ListWidget::ListCell(addon->getDateAsString().c_str(), -1, 1, true));
w_list->addItem(addon->getId(), row);
// Highlight if it's not approved in artists debug mode.
if(UserConfigParams::m_artist_debug_mode &&
@ -365,16 +366,16 @@ void AddonsScreen::loadList()
}
}
getWidget<GUIEngine::RibbonWidget>("category")->setActivated();
if(m_type == "kart")
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_kart",
PLAYER_ID_GAME_MASTER);
else if(m_type == "track")
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_track",
PLAYER_ID_GAME_MASTER);
getWidget<GUIEngine::RibbonWidget>("category")->setActivated();
if(m_type == "kart")
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_kart",
PLAYER_ID_GAME_MASTER);
else if(m_type == "track")
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_track",
PLAYER_ID_GAME_MASTER);
else
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_update",
PLAYER_ID_GAME_MASTER);
getWidget<GUIEngine::RibbonWidget>("category")->select("tab_update",
PLAYER_ID_GAME_MASTER);
} // loadList
// ----------------------------------------------------------------------------
@ -384,7 +385,7 @@ void AddonsScreen::onColumnClicked(int column_id)
{
case 0: Addon::setSortOrder(Addon::SO_NAME); break;
case 1: Addon::setSortOrder(Addon::SO_DATE); break;
default: assert(0);
default: assert(0); break;
} // switch
/** \brief Toggle the sort order after column click **/
m_sort_desc = !m_sort_desc;
@ -412,9 +413,7 @@ void AddonsScreen::eventCallback(GUIEngine::Widget* widget,
w_list->clear();
w_list->addItem("spacer", L"");
w_list->addItem("loading",
_("Please wait while addons are updated"),
m_icon_loading);
w_list->addItem("loading",_("Please wait while addons are updated"), m_icon_loading);
}
}

View File

@ -0,0 +1,187 @@
// 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.
#define DEBUG_MENU_ITEM 0
#include "states_screens/create_server_screen.hpp"
#include <string>
#include <iostream>
#include "challenges/game_slot.hpp"
#include "challenges/unlock_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "states_screens/online_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "modes/demo_world.hpp"
#include "utils/translation.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/dialogs/server_info_dialog.hpp"
#include "online/servers_manager.hpp"
#include "online/messages.hpp"
using namespace GUIEngine;
using namespace Online;
DEFINE_SCREEN_SINGLETON( CreateServerScreen );
// ----------------------------------------------------------------------------
CreateServerScreen::CreateServerScreen() : Screen("online/create_server.stkgui")
{
m_server_creation_request = NULL;
} // CreateServerScreen
// ----------------------------------------------------------------------------
void CreateServerScreen::loadedFromFile()
{
m_name_widget = getWidget<TextBoxWidget>("name");
assert(m_name_widget != NULL);
m_name_widget->setText(CurrentUser::acquire()->getUserName() + _("'s server"));
CurrentUser::release();
m_max_players_widget = getWidget<SpinnerWidget>("max_players");
assert(m_max_players_widget != NULL);
m_max_players_widget->setValue(8);
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_create_widget = getWidget<IconButtonWidget>("create");
assert(m_create_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
} // loadedFromFile
// ----------------------------------------------------------------------------
void CreateServerScreen::beforeAddingWidget()
{
} // beforeAddingWidget
// ----------------------------------------------------------------------------
void CreateServerScreen::init()
{
Screen::init();
setInitialFocus();
DemoWorld::resetIdleTime();
m_info_widget->setText("", false);
}
// ----------------------------------------------------------------------------
void CreateServerScreen::onUpdate(float delta, irr::video::IVideoDriver* driver)
{
if(m_server_creation_request != NULL)
{
if(m_server_creation_request->isDone())
{
if(m_server_creation_request->isSuccess())
{
new ServerInfoDialog(m_server_creation_request->getCreatedServerID(), true);
}
else
{
sfx_manager->quickSound( "anvil" );
m_info_widget->setErrorColor();
m_info_widget->setText(m_server_creation_request->getInfo(), false);
}
delete m_server_creation_request;
m_server_creation_request = NULL;
//m_options_widget->setActivated();
}
else
{
m_info_widget->setDefaultColor();
m_info_widget->setText(Online::Messages::creatingServer(), false);
}
}
} // onUpdate
// ----------------------------------------------------------------------------
void CreateServerScreen::serverCreationRequest()
{
const stringw name = m_name_widget->getText().trim();
const int max_players = m_max_players_widget->getValue();
m_info_widget->setErrorColor();
if (name.size() < 4 || name.size() > 30)
{
m_info_widget->setText(_("Name has to be between 4 and 30 characters long!"), false);
}
else if (max_players < 2 || max_players > 12)
{
m_info_widget->setText(_("The maxinum number of players has to be between 2 and 12."), false);
}
else
{
//m_options_widget->setDeactivated();
m_server_creation_request = Online::CurrentUser::acquire()->requestServerCreation(name, max_players);
Online::CurrentUser::release();
return;
}
sfx_manager->quickSound("anvil");
}
// ----------------------------------------------------------------------------
void CreateServerScreen::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
if (name == m_options_widget->m_properties[PROP_ID])
{
const std::string& selection = m_options_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == m_cancel_widget->m_properties[PROP_ID])
{
StateManager::get()->escapePressed();
}
else if (selection == m_create_widget->m_properties[PROP_ID])
{
serverCreationRequest();
}
}
} // eventCallback
// ----------------------------------------------------------------------------
void CreateServerScreen::tearDown()
{
delete m_server_creation_request;
m_server_creation_request = NULL;
} // tearDown
// ----------------------------------------------------------------------------
void CreateServerScreen::onDisabledItemClicked(const std::string& item)
{
} // onDisabledItemClicked
// ----------------------------------------------------------------------------
void CreateServerScreen::setInitialFocus()
{
} // setInitialFocus
// ----------------------------------------------------------------------------
void CreateServerScreen::onDialogClose()
{
setInitialFocus();
} // onDialogClose()

View File

@ -0,0 +1,83 @@
// 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_CREATE_SERVER_SCREEN_HPP
#define HEADER_CREATE_SERVER_SCREEN_HPP
#include "guiengine/screen.hpp"
#include "guiengine/widgets.hpp"
#include "online/current_user.hpp"
namespace GUIEngine { class Widget; class ListWidget; }
/**
* \brief Handles the main menu
* \ingroup states_screens
*/
class CreateServerScreen : public GUIEngine::Screen,
public GUIEngine::ScreenSingleton<CreateServerScreen>
{
private:
friend class GUIEngine::ScreenSingleton<CreateServerScreen>;
CreateServerScreen();
GUIEngine::TextBoxWidget * m_name_widget;
GUIEngine::SpinnerWidget * m_max_players_widget;
GUIEngine::LabelWidget * m_info_widget;
GUIEngine::RibbonWidget * m_options_widget;
GUIEngine::IconButtonWidget * m_create_widget;
GUIEngine::IconButtonWidget * m_cancel_widget;
Online::CurrentUser::ServerCreationRequest * m_server_creation_request;
/** \brief Sets which widget has to be focused. Depends on the user state. */
void setInitialFocus();
void serverCreationRequest();
public:
virtual void onUpdate(float delta, irr::video::IVideoDriver* driver) OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() 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;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void init() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void tearDown() OVERRIDE;
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void onDisabledItemClicked(const std::string& item) OVERRIDE;
/** \brief Implements the callback when a dialog gets closed. */
virtual void onDialogClose() OVERRIDE;
};
#endif

View File

@ -25,39 +25,41 @@
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
#include "online/current_online_user.hpp"
#include "states_screens/dialogs/registration_dialog.hpp"
#include "online/messages.hpp"
using namespace GUIEngine;
using namespace irr;
using namespace irr::gui;
using namespace Online;
// -----------------------------------------------------------------------------
LoginDialog::LoginDialog(const Message message_type) :
ModalDialog(0.8f,0.8f)
ModalDialog(0.8f,0.9f)
{
m_self_destroy = false;
m_open_registration_dialog = false;
m_sign_in_request = NULL;
loadFromFile("online/login_dialog.stkgui");
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
irr::core::stringw info;
m_message_widget = getWidget<LabelWidget>("message");
assert(m_message_widget != NULL);
irr::core::stringw message;
if (message_type == Normal)
info = _("Fill in your username and password. ");
message = _("Fill in your username and password. ");
else if (message_type == Signing_In_Required)
info = _("You need to sign in to be able to use this feature. ");
message = _("You need to sign in to be able to use this feature. ");
else if (message_type == Registration_Required)
info = _("You need to be a registered user to enjoy this feature! "
message = _("You need to be a registered user to enjoy this feature! "
"If you do not have an account yet, you can sign up using the register icon at the bottom.");
else
info = "";
message = "";
if (message_type == Normal || message_type == Signing_In_Required)
info += _("If you do not have an account yet, you can choose to sign in as a guest "
message += _("If you do not have an account yet, you can choose to sign in as a guest "
"or press the register icon at the bottom to gain access to all the features!");
m_info_widget->setText(info, false);
m_message_widget->setText(message, false);
m_username_widget = getWidget<TextBoxWidget>("username");
assert(m_username_widget != NULL);
@ -67,8 +69,12 @@ LoginDialog::LoginDialog(const Message message_type) :
assert(m_password_widget != NULL);
m_password_widget->setPasswordBox(true,L'*');
m_message_widget = getWidget<LabelWidget>("message");
assert(m_message_widget != NULL);
m_remember_widget = getWidget<CheckBoxWidget>("remember");
assert(m_remember_widget != NULL);
m_remember_widget->setState(false);
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
@ -82,12 +88,15 @@ LoginDialog::LoginDialog(const Message message_type) :
assert(m_as_guest_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
}
// -----------------------------------------------------------------------------
LoginDialog::~LoginDialog()
{
delete m_sign_in_request;
}
@ -97,16 +106,17 @@ void LoginDialog::login()
{
const stringw username = m_username_widget->getText().trim();
const stringw password = m_password_widget->getText().trim();
stringw info = "";
if(CurrentOnlineUser::get()->signIn(username,password,info))
if (username.size() < 4 || username.size() > 30 || password.size() < 8 || password.size() > 30)
{
m_self_destroy = true;
sfx_manager->quickSound("anvil");
m_info_widget->setErrorColor();
m_info_widget->setText(_("Username and/or password invalid."), false);
}
else
{
sfx_manager->quickSound( "anvil" );
m_message_widget->setColor(irr::video::SColor(255, 255, 0, 0));
m_message_widget->setText(info, false);
m_options_widget->setDeactivated();
m_sign_in_request = Online::CurrentUser::acquire()->requestSignIn(username,password, m_remember_widget->getState());
Online::CurrentUser::release();
}
}
@ -145,13 +155,43 @@ void LoginDialog::onEnterPressedInternal()
const int playerID = PLAYER_ID_GAME_MASTER;
if (GUIEngine::isFocusedForPlayer(m_options_widget, playerID))
return;
login();
if (m_sign_in_widget->isActivated())
login();
}
// -----------------------------------------------------------------------------
bool LoginDialog::onEscapePressed()
{
return m_cancel_widget->isActivated();
}
void LoginDialog::onUpdate(float dt)
{
if(m_sign_in_request != NULL)
{
if(m_sign_in_request->isDone())
{
if(m_sign_in_request->isSuccess())
{
m_self_destroy = true;
}
else
{
sfx_manager->quickSound( "anvil" );
m_info_widget->setErrorColor();
m_info_widget->setText(m_sign_in_request->getInfo(), false);
}
delete m_sign_in_request;
m_sign_in_request = NULL;
m_options_widget->setActivated();
}
else
{
m_info_widget->setDefaultColor();
m_info_widget->setText(Online::Messages::signingIn(), false);
}
}
//If we want to open the registration dialog, we need to close this one first
m_open_registration_dialog && (m_self_destroy = true);
@ -160,9 +200,7 @@ void LoginDialog::onUpdate(float dt)
{
ModalDialog::dismiss();
if (m_open_registration_dialog)
new RegistrationDialog(0.8f, 0.9f);
new RegistrationDialog();
return;
}
}

View File

@ -21,11 +21,10 @@
#include <irrString.h>
#include "online/current_user.hpp"
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets.hpp"
/**
* \brief Dialog that allows a user to sign in
@ -38,11 +37,12 @@ private:
bool m_self_destroy;
bool m_open_registration_dialog;
GUIEngine::LabelWidget * m_info_widget;
Online::CurrentUser::SignInRequest * m_sign_in_request;
GUIEngine::LabelWidget * m_message_widget;
GUIEngine::TextBoxWidget * m_username_widget;
GUIEngine::TextBoxWidget * m_password_widget;
GUIEngine::LabelWidget * m_message_widget;
GUIEngine::CheckBoxWidget * m_remember_widget;
GUIEngine::LabelWidget * m_info_widget;
GUIEngine::RibbonWidget * m_options_widget;
GUIEngine::IconButtonWidget * m_sign_in_widget;
@ -69,8 +69,10 @@ public:
~LoginDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
virtual bool onEscapePressed();
virtual void onUpdate(float dt);
//virtual void onTextUpdated();
};

View File

@ -22,25 +22,24 @@
#include "audio/sfx_manager.hpp"
#include "config/player.hpp"
#include "guiengine/engine.hpp"
#include "guiengine/widgets/button_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/text_box_widget.hpp"
#include "guiengine/widgets/check_box_widget.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
#include "online/current_online_user.hpp"
#include "online/messages.hpp"
using namespace GUIEngine;
using namespace irr;
using namespace irr::gui;
using namespace Online;
// -----------------------------------------------------------------------------
RegistrationDialog::RegistrationDialog(const float w, const float h, const Phase phase) :
ModalDialog(w,h)
RegistrationDialog::RegistrationDialog(const Phase phase) :
ModalDialog(0.8f,0.9f)
{
m_sign_up_request = NULL;
m_activation_request = NULL;
m_self_destroy = false;
m_show_registration_info = false;
m_show_registration_terms = false;
@ -62,6 +61,8 @@ RegistrationDialog::RegistrationDialog(const float w, const float h, const Phase
RegistrationDialog::~RegistrationDialog()
{
delete m_sign_up_request;
delete m_activation_request;
}
// -----------------------------------------------------------------------------
@ -76,38 +77,38 @@ void RegistrationDialog::showRegistrationInfo(){
m_password = "";
m_password_confirm = "";
TextBoxWidget* textBox = getWidget<TextBoxWidget>("username");
assert(textBox != NULL);
textBox->setText(m_username);
textBox->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
m_username_widget = getWidget<TextBoxWidget>("username");
assert(m_username_widget != NULL);
m_username_widget->setText(m_username);
m_username_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
textBox = getWidget<TextBoxWidget>("password");
assert(textBox != NULL);
textBox->setPasswordBox(true,L'*');
m_password_widget = getWidget<TextBoxWidget>("password");
assert(m_password_widget != NULL);
m_password_widget->setPasswordBox(true,L'*');
textBox = getWidget<TextBoxWidget>("password_confirm");
assert(textBox != NULL);
textBox->setPasswordBox(true,L'*');
m_password_confirm_widget = getWidget<TextBoxWidget>("password_confirm");
assert(m_password_confirm_widget != NULL);
m_password_confirm_widget->setPasswordBox(true,L'*');
textBox = getWidget<TextBoxWidget>("email");
assert(textBox != NULL);
textBox->setText(m_email);
m_email_widget = getWidget<TextBoxWidget>("email");
assert(m_email_widget != NULL);
m_email_widget->setText(m_email);
textBox = getWidget<TextBoxWidget>("email_confirm");
assert(textBox != NULL);
textBox->setText(m_email_confirm);
m_email_confirm_widget = getWidget<TextBoxWidget>("email_confirm");
assert(m_email_confirm_widget != NULL);
m_email_confirm_widget->setText(m_email_confirm);
LabelWidget * label = getWidget<LabelWidget>("info");
assert(label != NULL);
label->setColor(irr::video::SColor(255, 255, 0, 0));
label->setText(m_registration_error, false);
ButtonWidget * button = getWidget<ButtonWidget>("next");
assert(button != NULL);
button = getWidget<ButtonWidget>("cancel");
assert(button != NULL);
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_info_widget->setErrorColor();
m_info_widget->setText(m_registration_error, false);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_next_widget = getWidget<IconButtonWidget>("next");
assert(m_next_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
}
// -----------------------------------------------------------------------------
@ -117,13 +118,23 @@ void RegistrationDialog::showRegistrationTerms(){
clearWindow();
m_phase = Terms;
loadFromFile("online/registration_terms.stkgui");
CheckBoxWidget * checkbox = getWidget<CheckBoxWidget>("accepted");
assert(checkbox != NULL);
checkbox->setState(false);
checkbox->setFocusForPlayer(PLAYER_ID_GAME_MASTER); //FIXME set focus on the terms
ButtonWidget * submitButton = getWidget<ButtonWidget>("next");
assert(submitButton != NULL);
submitButton->setDeactivated();
m_accept_terms_widget = getWidget<CheckBoxWidget>("accepted");
assert(m_accept_terms_widget != NULL);
m_accept_terms_widget->setState(false);
m_accept_terms_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER); //FIXME set focus on the terms
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_previous_widget = getWidget<IconButtonWidget>("previous");
assert(m_previous_widget != NULL);
m_next_widget = getWidget<IconButtonWidget>("next");
assert(m_next_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
m_next_widget->setDeactivated();
}
// -----------------------------------------------------------------------------
@ -133,6 +144,17 @@ void RegistrationDialog::showRegistrationActivation(){
clearWindow();
m_phase = Activation;
loadFromFile("online/registration_activation.stkgui");
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
m_info_widget->setText(m_registration_error, false);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_next_widget = getWidget<IconButtonWidget>("next");
assert(m_next_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
}
// -----------------------------------------------------------------------------
@ -140,43 +162,41 @@ void RegistrationDialog::showRegistrationActivation(){
bool RegistrationDialog::processInfoEvent(const std::string& eventSource){
if (m_phase == Info)
{
if (eventSource == "next")
if (eventSource == m_next_widget->m_properties[PROP_ID])
{
m_username = getWidget<TextBoxWidget>("username")->getText().trim();
m_password = getWidget<TextBoxWidget>("password")->getText().trim();
m_password_confirm = getWidget<TextBoxWidget>("password_confirm")->getText().trim();
m_email = getWidget<TextBoxWidget>("email")->getText().trim();
m_email_confirm = getWidget<TextBoxWidget>("email_confirm")->getText().trim();
m_username = m_username_widget->getText().trim();
m_password = m_password_widget->getText().trim();
m_password_confirm = m_password_confirm_widget->getText().trim();
m_email = m_email_widget->getText().trim();
m_email_confirm = m_email_confirm_widget->getText().trim();
//FIXME More validation of registration information
m_info_widget->setErrorColor();
if (m_password != m_password_confirm)
{
getWidget<LabelWidget>("info")->setText(_("Passwords don't match!"), false);
sfx_manager->quickSound( "anvil" );
m_info_widget->setText(_("Passwords don't match!"), false);
}
else if (m_email != m_email_confirm)
{
getWidget<LabelWidget>("info")->setText(_("Emails don't match!"), false);
sfx_manager->quickSound( "anvil" );
m_info_widget->setText(_("Emails don't match!"), false);
}
else if (m_username.size() < 5 || m_username.size() > 30)
else if (m_username.size() < 4 || m_username.size() > 30)
{
getWidget<LabelWidget>("info")->setText(_("Username has to be between 5 and 30 characters long!"), false);
sfx_manager->quickSound( "anvil" );
m_info_widget->setText(_("Username has to be between 4 and 30 characters long!"), false);
}
else if (m_password.size() < 8 || m_password.size() > 30)
{
getWidget<LabelWidget>("info")->setText(_("Password has to be between 5 and 30 characters long!"), false);
sfx_manager->quickSound( "anvil" );
m_info_widget->setText(_("Password has to be between 8 and 30 characters long!"), false);
}
else if (m_email.size() < 5 || m_email.size() > 50)
else if (m_email.size() < 4 || m_email.size() > 50)
{
getWidget<LabelWidget>("info")->setText(_("Email has to be between 5 and 50 characters long!"), false);
sfx_manager->quickSound( "anvil" );
m_info_widget->setText(_("Email has to be between 4 and 50 characters long!"), false);
}
else
{
m_show_registration_terms = true;
return true;
}
sfx_manager->quickSound( "anvil" );
return true;
}
}
@ -188,34 +208,27 @@ bool RegistrationDialog::processInfoEvent(const std::string& eventSource){
bool RegistrationDialog::processTermsEvent(const std::string& eventSource){
if (m_phase == Terms)
{
if (eventSource == "next")
if (eventSource == m_next_widget->m_properties[PROP_ID])
{
assert(getWidget<CheckBoxWidget>("accepted")->getState());
m_agreement = true;
if(CurrentOnlineUser::get()->signUp(m_username, m_password, m_password_confirm, m_email, true, m_registration_error))
{
m_show_registration_activation = true;
m_registration_error = "";
}
else
{
m_show_registration_info = true;
}
assert(m_accept_terms_widget->getState());
m_options_widget->setDeactivated();
m_info_widget->setDefaultColor();
m_info_widget->setText(Messages::signingUp(), false);
m_sign_up_request = CurrentUser::acquire()->requestSignUp(m_username, m_password, m_password_confirm, m_email, true);
CurrentUser::release();
return true;
}
else if (eventSource == "accepted")
else if (eventSource == m_accept_terms_widget->m_properties[PROP_ID])
{
CheckBoxWidget * checkbox = getWidget<CheckBoxWidget>("accepted");
bool new_state = !checkbox->getState();
checkbox->setState(new_state);
ButtonWidget * submitButton = getWidget<ButtonWidget>("next");
bool new_state = !m_accept_terms_widget->getState();
m_accept_terms_widget->setState(new_state);
if(new_state)
submitButton->setActivated();
m_next_widget->setActivated();
else
submitButton->setDeactivated();
m_next_widget->setDeactivated();
return true;
}
else if (eventSource == "previous")
else if (eventSource == m_previous_widget->m_properties[PROP_ID])
{
m_show_registration_info = true;
return true;
@ -229,7 +242,7 @@ bool RegistrationDialog::processTermsEvent(const std::string& eventSource){
bool RegistrationDialog::processActivationEvent(const std::string& eventSource){
if (m_phase == Activation)
{
if (eventSource == "next")
if (eventSource == m_next_widget->m_properties[PROP_ID])
{
//FIXME : activate
m_self_destroy = true;
@ -239,17 +252,28 @@ bool RegistrationDialog::processActivationEvent(const std::string& eventSource){
return false;
}
// -----------------------------------------------------------------------------
bool RegistrationDialog::onEscapePressed()
{
return m_cancel_widget->isActivated();
}
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation RegistrationDialog::processEvent(const std::string& eventSource)
{
if (eventSource == "cancel")
std::string selection;
if (eventSource == m_options_widget->m_properties[PROP_ID])
selection = m_options_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
else
selection = eventSource;
if (selection == m_cancel_widget->m_properties[PROP_ID])
{
m_self_destroy = true;
return GUIEngine::EVENT_BLOCK;
}
else if (processInfoEvent(eventSource) || processTermsEvent(eventSource) || processActivationEvent(eventSource))
else if (processInfoEvent(selection) || processTermsEvent(selection) || processActivationEvent(selection))
{
return GUIEngine::EVENT_BLOCK;
}
@ -260,38 +284,72 @@ GUIEngine::EventPropagation RegistrationDialog::processEvent(const std::string&
void RegistrationDialog::onEnterPressedInternal()
{
//If enter was pressed while no button was focused, then interpret as "next" press.
const int playerID = PLAYER_ID_GAME_MASTER;
bool interpret_as_next = true;
ButtonWidget * cancel_widget = getWidget<ButtonWidget>("cancel");
ButtonWidget * next_widget = getWidget<ButtonWidget>("next");
interpret_as_next = interpret_as_next &&
!GUIEngine::isFocusedForPlayer(next_widget, playerID) &&
!GUIEngine::isFocusedForPlayer(cancel_widget, playerID);
if (interpret_as_next && m_phase == Terms)
{
ButtonWidget * previous_widget = getWidget<ButtonWidget>("previous");
interpret_as_next = interpret_as_next && !GUIEngine::isFocusedForPlayer(previous_widget, playerID);
}
if (interpret_as_next)
{
if (GUIEngine::isFocusedForPlayer(m_options_widget, PLAYER_ID_GAME_MASTER))
return;
if (m_next_widget->isActivated())
processEvent("next");
}
}
// -----------------------------------------------------------------------------
void RegistrationDialog::onUpdate(float dt)
{
if (m_phase == Terms)
{
if(m_sign_up_request != NULL)
{
if(m_sign_up_request->isDone())
{
if(m_sign_up_request->isSuccess())
{
m_show_registration_activation = true;
}
else
{
sfx_manager->quickSound( "anvil" );
m_show_registration_info = true;
m_registration_error = m_sign_up_request->getInfo();
}
delete m_sign_up_request;
m_sign_up_request = NULL;
//FIXME m_options_widget->setActivated();
}
else
{
m_info_widget->setDefaultColor();
m_info_widget->setText(Messages::signingUp(), false);
}
}
}
else if (m_phase == Activation)
{
/*
XMLRequest * sign_up_request = HTTPManager::get()->getXMLResponse(Request::RT_SIGN_UP);
if(sign_up_request != NULL)
{
if(sign_up_request->isSuccess())
{
m_show_registration_activation = true;
}
else
{
sfx_manager->quickSound( "anvil" );
m_show_registration_info = true;
m_registration_error = sign_up_request->getInfo();
}
delete sign_up_request;
m_signing_up = false;
//FIXME m_options_widget->setActivated();
}*/
}
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
ModalDialog::dismiss();
}
if (m_show_registration_info)
else if (m_show_registration_info)
showRegistrationInfo();
if (m_show_registration_terms)
else if (m_show_registration_terms)
showRegistrationTerms();
if (m_show_registration_activation)
else if (m_show_registration_activation)
showRegistrationActivation();
}

View File

@ -22,6 +22,8 @@
#include <irrString.h>
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets.hpp"
#include "online/current_user.hpp"
/**
* \brief Dialog that allows a user to register
* \ingroup states_screens
@ -37,21 +39,26 @@ public:
Activation = 4
};
RegistrationDialog(const float percentWidth, const float percentHeight, const Phase phase = Info);
RegistrationDialog(const Phase phase = Info);
~RegistrationDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
virtual void onUpdate(float dt);
virtual bool onEscapePressed();
private:
Phase m_phase;
bool m_self_destroy;
bool m_show_registration_info;
bool m_show_registration_terms;
bool m_show_registration_activation;
Online::XMLRequest * m_sign_up_request;
Online::XMLRequest * m_activation_request;
//Saved user input :
irr::core::stringw m_username;
irr::core::stringw m_password;
@ -61,6 +68,21 @@ private:
irr::core::stringw m_registration_error;
bool m_agreement;
GUIEngine::TextBoxWidget * m_username_widget;
GUIEngine::TextBoxWidget * m_password_widget;
GUIEngine::TextBoxWidget * m_password_confirm_widget;
GUIEngine::TextBoxWidget * m_email_widget;
GUIEngine::TextBoxWidget * m_email_confirm_widget;
GUIEngine::LabelWidget * m_info_widget;
GUIEngine::RibbonWidget * m_options_widget;
GUIEngine::IconButtonWidget * m_previous_widget;
GUIEngine::IconButtonWidget * m_next_widget;
GUIEngine::IconButtonWidget * m_cancel_widget;
GUIEngine::CheckBoxWidget * m_accept_terms_widget;
void showRegistrationInfo();
void showRegistrationTerms();
void showRegistrationActivation();

View File

@ -0,0 +1,159 @@
// 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.
#include "states_screens/dialogs/server_info_dialog.hpp"
#include <IGUIEnvironment.h>
#include "audio/sfx_manager.hpp"
#include "config/player.hpp"
#include "guiengine/engine.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
#include "online/current_user.hpp"
#include "online/servers_manager.hpp"
#include "online/messages.hpp"
#include "states_screens/dialogs/registration_dialog.hpp"
#include "states_screens/networking_lobby.hpp"
using namespace GUIEngine;
using namespace irr;
using namespace irr::gui;
using namespace Online;
// -----------------------------------------------------------------------------
ServerInfoDialog::ServerInfoDialog(uint32_t server_id, bool from_server_creation) :
ModalDialog(0.8f,0.8f)
{
m_server_id = server_id;
m_self_destroy = false;
m_enter_lobby = false;
m_from_server_creation = from_server_creation;
m_server_join_request = NULL;
loadFromFile("online/server_info_dialog.stkgui");
m_name_widget = getWidget<LabelWidget>("name");
assert(m_name_widget != NULL);
Server * server = ServersManager::acquire()->getServerByID(m_server_id);
m_name_widget->setText(server->getName(),false);
ServersManager::release();
m_info_widget = getWidget<LabelWidget>("info");
assert(m_info_widget != NULL);
if (m_from_server_creation)
m_info_widget->setText(_("Server successfully created. You can now join it."), true);
m_options_widget = getWidget<RibbonWidget>("options");
assert(m_options_widget != NULL);
m_join_widget = getWidget<IconButtonWidget>("join");
assert(m_join_widget != NULL);
m_cancel_widget = getWidget<IconButtonWidget>("cancel");
assert(m_cancel_widget != NULL);
m_options_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
}
// -----------------------------------------------------------------------------
ServerInfoDialog::~ServerInfoDialog()
{
delete m_server_join_request;
}
// -----------------------------------------------------------------------------
void ServerInfoDialog::requestJoin()
{
m_server_join_request = Online::CurrentUser::acquire()->requestServerJoin(m_server_id);
Online::CurrentUser::release();
}
// -----------------------------------------------------------------------------
GUIEngine::EventPropagation ServerInfoDialog::processEvent(const std::string& eventSource)
{
if (eventSource == m_options_widget->m_properties[PROP_ID])
{
const std::string& selection = m_options_widget->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == m_cancel_widget->m_properties[PROP_ID])
{
m_self_destroy = true;
return GUIEngine::EVENT_BLOCK;
}
else if(selection == m_join_widget->m_properties[PROP_ID])
{
requestJoin();
return GUIEngine::EVENT_BLOCK;
}
}
return GUIEngine::EVENT_LET;
}
// -----------------------------------------------------------------------------
void ServerInfoDialog::onEnterPressedInternal()
{
//If enter was pressed while none of the buttons was focused interpret as join event
const int playerID = PLAYER_ID_GAME_MASTER;
if (GUIEngine::isFocusedForPlayer(m_options_widget, playerID))
return;
requestJoin();
}
// -----------------------------------------------------------------------------
void ServerInfoDialog::onUpdate(float dt)
{
if(m_server_join_request != NULL)
{
if(m_server_join_request->isDone())
{
if(m_server_join_request->isSuccess())
{
m_enter_lobby = true;
}
else
{
sfx_manager->quickSound( "anvil" );
m_info_widget->setErrorColor();
m_info_widget->setText(m_server_join_request->getInfo(), false);
}
delete m_server_join_request;
m_server_join_request = NULL;
}
else
{
m_info_widget->setDefaultColor();
m_info_widget->setText(Online::Messages::joiningServer(), false);
}
}
//If we want to open the registration dialog, we need to close this one first
m_enter_lobby && (m_self_destroy = true);
// It's unsafe to delete from inside the event handler so we do it here
if (m_self_destroy)
{
ModalDialog::dismiss();
if (m_from_server_creation)
StateManager::get()->popMenu();
if (m_enter_lobby)
StateManager::get()->pushScreen(NetworkingLobby::getInstance());
return;
}
}

View File

@ -0,0 +1,70 @@
// 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_INFO_DIALOG_HPP
#define HEADER_SERVER_INFO_DIALOG_HPP
#include <irrString.h>
#include "guiengine/modaldialog.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/label_widget.hpp"
#include "online/server.hpp"
#include "online/current_user.hpp"
#include "utils/types.hpp"
/**
* \brief Dialog that allows a user to sign in
* \ingroup states_screens
*/
class ServerInfoDialog : public GUIEngine::ModalDialog
{
private:
bool m_self_destroy;
bool m_enter_lobby;
bool m_from_server_creation;
Online::CurrentUser::ServerJoinRequest * m_server_join_request;
float m_load_timer;
uint32_t m_server_id;
GUIEngine::LabelWidget * m_name_widget;
GUIEngine::LabelWidget * m_info_widget;
GUIEngine::RibbonWidget * m_options_widget;
GUIEngine::IconButtonWidget * m_join_widget;
GUIEngine::IconButtonWidget * m_cancel_widget;
void requestJoin();
public:
ServerInfoDialog(uint32_t server_id, bool just_created = false);
~ServerInfoDialog();
void onEnterPressedInternal();
GUIEngine::EventPropagation processEvent(const std::string& eventSource);
virtual void onUpdate(float dt);
};
#endif

View File

@ -35,10 +35,9 @@
#include "states_screens/dialogs/message_dialog.hpp"
#include "modes/demo_world.hpp"
#include "utils/translation.hpp"
#include "online/servers_manager.hpp"
#include "online/current_online_user.hpp"
using namespace Online;
using namespace GUIEngine;
DEFINE_SCREEN_SINGLETON( NetworkingLobby );
@ -47,30 +46,30 @@ DEFINE_SCREEN_SINGLETON( NetworkingLobby );
NetworkingLobby::NetworkingLobby() : Screen("online/lobby.stkgui")
{
m_server = NULL;
} // NetworkingLobby
// ----------------------------------------------------------------------------
void NetworkingLobby::loadedFromFile()
{
m_back_widget = getWidget<IconButtonWidget>("back");
assert(m_back_widget != NULL);
m_server_name_widget = getWidget<LabelWidget>("server_name");
assert(m_server_name_widget != NULL);
m_online_status_widget = getWidget<LabelWidget>("online_status");
assert(m_online_status_widget != NULL);
m_bottom_menu_widget = getWidget<RibbonWidget>("menu_bottomrow");
assert(m_bottom_menu_widget != NULL);
/*m_sign_in_widget = (IconButtonWidget *) m_bottom_menu_widget->findWidgetNamed("sign_in");
assert(m_sign_in_widget != NULL);*/
m_exit_widget = (IconButtonWidget *) m_bottom_menu_widget->findWidgetNamed("exit");
assert(m_exit_widget != NULL);
} // loadedFromFile
// ----------------------------------------------------------------------------
bool NetworkingLobby::hasLostConnection()
{
return !CurrentOnlineUser::get()->isSignedIn();
}
// ----------------------------------------------------------------------------
void NetworkingLobby::beforeAddingWidget()
{
@ -85,7 +84,10 @@ void NetworkingLobby::init()
Screen::init();
setInitialFocus();
DemoWorld::resetIdleTime(); //FIXME : what's this?
m_online_status_widget->setText(irr::core::stringw(_("Signed in as : ")) + CurrentOnlineUser::get()->getUserName() + ".", false);
m_server = ServersManager::acquire()->getJoinedServer();
ServersManager::release();
m_server_name_widget->setText(m_server->getName(),false);
} // init
// ----------------------------------------------------------------------------
@ -97,7 +99,20 @@ void NetworkingLobby::onUpdate(float delta, irr::video::IVideoDriver* driver)
void NetworkingLobby::eventCallback(Widget* widget, const std::string& name, const int playerID)
{
if (name == m_back_widget->m_properties[PROP_ID])
{
StateManager::get()->escapePressed();
return;
}
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
if (ribbon == NULL) return;
std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == m_exit_widget->m_properties[PROP_ID])
{
StateManager::get()->escapePressed();
}
} // eventCallback
// ----------------------------------------------------------------------------

View File

@ -22,6 +22,7 @@
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "online/server.hpp"
namespace GUIEngine { class Widget; class ListWidget; }
@ -35,17 +36,19 @@ class NetworkingLobby : public GUIEngine::Screen,
private:
friend class GUIEngine::ScreenSingleton<NetworkingLobby>;
Online::Server * m_server;
NetworkingLobby();
GUIEngine::IconButtonWidget * m_back_widget;
GUIEngine::LabelWidget * m_server_name_widget;
GUIEngine::LabelWidget * m_online_status_widget;
GUIEngine::RibbonWidget * m_bottom_menu_widget;
GUIEngine::IconButtonWidget * m_sign_in_widget;
GUIEngine::IconButtonWidget * m_register_widget;
GUIEngine::IconButtonWidget * m_sign_out_widget;
GUIEngine::IconButtonWidget * m_exit_widget;
/** \brief Checks if the user is still signed in. */
bool hasLostConnection();
/** \brief Sets which widget has to be focused. Depends on the user state. */
void setInitialFocus();

View File

@ -36,7 +36,7 @@
#include "modes/demo_world.hpp"
#include "utils/translation.hpp"
#include "online/current_online_user.hpp"
#include "online/current_user.hpp"
using namespace GUIEngine;
@ -60,7 +60,7 @@ void NetworkingLobbySettings::loadedFromFile()
// ----------------------------------------------------------------------------
bool NetworkingLobbySettings::hasLostConnection()
{
return !CurrentOnlineUser::get()->isSignedIn();
return !Online::CurrentUser::acquire()->isSignedIn();
}
// ----------------------------------------------------------------------------

View File

@ -22,31 +22,31 @@
#include <string>
#include <iostream>
#include "challenges/game_slot.hpp"
#include "challenges/unlock_manager.hpp"
#include "audio/sfx_manager.hpp"
#include "graphics/irr_driver.hpp"
#include "guiengine/scalable_font.hpp"
#include "input/device_manager.hpp"
#include "input/input_manager.hpp"
#include "io/file_manager.hpp"
#include "main_loop.hpp"
#include "states_screens/online_screen.hpp"
#include "states_screens/state_manager.hpp"
#include "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/dialogs/login_dialog.hpp"
#include "states_screens/dialogs/registration_dialog.hpp"
#include "states_screens/networking_lobby.hpp"
#include "states_screens/networking_lobby_settings.hpp"
#include "states_screens/server_selection.hpp"
#include "states_screens/create_server_screen.hpp"
#include "modes/demo_world.hpp"
#include "utils/translation.hpp"
#include "online/servers_manager.hpp"
#include "online/messages.hpp"
#include "online/current_online_user.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/connect_to_server.hpp"
using namespace GUIEngine;
using namespace Online;
DEFINE_SCREEN_SINGLETON( OnlineScreen );
@ -54,11 +54,22 @@ DEFINE_SCREEN_SINGLETON( OnlineScreen );
OnlineScreen::OnlineScreen() : Screen("online/main.stkgui")
{
m_recorded_state = Not;
m_recorded_state = CurrentUser::US_SIGNED_OUT;
CurrentUser::SignInRequest * request = CurrentUser::acquire()->requestSavedSession();
if(request != NULL)
m_requests.push_back(request);
CurrentUser::release();
} // OnlineScreen
// ----------------------------------------------------------------------------
OnlineScreen::~OnlineScreen()
{
m_requests.clearAndDeleteAll();
}
// ----------------------------------------------------------------------------
void OnlineScreen::loadedFromFile()
{
//Box ? FIXME
@ -88,16 +99,9 @@ void OnlineScreen::loadedFromFile()
// ----------------------------------------------------------------------------
bool OnlineScreen::hasStateChanged()
{
State previous_state = m_recorded_state;
if(CurrentOnlineUser::get()->isSignedIn())
{
if(CurrentOnlineUser::get()->isGuest())
m_recorded_state = Guest;
else
m_recorded_state = Registered;
}
else
m_recorded_state = Not;
CurrentUser::UserState previous_state = m_recorded_state;
m_recorded_state = CurrentUser::acquire()->getUserState();
CurrentUser::release();
if (previous_state != m_recorded_state)
return true;
return false;
@ -109,21 +113,25 @@ void OnlineScreen::beforeAddingWidget()
//Set everything that could be set invisible or deactivated, to active and visible
m_bottom_menu_widget->setVisible(true);
m_top_menu_widget->setVisible(true);
hasStateChanged();
if (m_recorded_state == Registered)
if (m_recorded_state == CurrentUser::US_SIGNED_IN)
{
m_register_widget->setVisible(false);
m_sign_in_widget->setVisible(false);
}
else if (m_recorded_state == Not)
else if (m_recorded_state == CurrentUser::US_SIGNED_OUT || m_recorded_state == CurrentUser::US_SIGNING_IN || m_recorded_state == CurrentUser::US_SIGNING_OUT)
{
m_quick_play_widget->setDeactivated();
m_find_server_widget->setDeactivated();
m_create_server_widget->setDeactivated();
m_sign_out_widget->setVisible(false);
if(m_recorded_state == CurrentUser::US_SIGNING_IN || m_recorded_state == CurrentUser::US_SIGNING_OUT)
{
m_register_widget->setDeactivated();
m_sign_in_widget->setDeactivated();
}
}
else if (m_recorded_state == Guest)
else if (m_recorded_state == CurrentUser::US_GUEST)
{
m_find_server_widget->setDeactivated();
m_create_server_widget->setDeactivated();
@ -139,8 +147,10 @@ void OnlineScreen::init()
{
Screen::init();
setInitialFocus();
DemoWorld::resetIdleTime(); //FIXME : what's this?
m_online_status_widget->setText(irr::core::stringw(_("Signed in as : ")) + CurrentOnlineUser::get()->getUserName() + ".", false);
DemoWorld::resetIdleTime();
m_online_status_widget->setText(Messages::signedInAs(CurrentUser::acquire()->getUserName()), false);
CurrentUser::release();
} // init
// ----------------------------------------------------------------------------
@ -148,6 +158,36 @@ void OnlineScreen::onUpdate(float delta, irr::video::IVideoDriver* driver)
{
if (hasStateChanged())
GUIEngine::reshowCurrentScreen();
if (m_recorded_state == CurrentUser::US_SIGNING_IN)
{
m_online_status_widget->setText(Messages::signingIn(), false);
}
else if (m_recorded_state == CurrentUser::US_SIGNING_OUT)
{
m_online_status_widget->setText(Messages::signingOut(), false);
}
for(int i = m_requests.size()-1; i>=0; --i)
{
if(m_requests[i].isDone())
{
if(m_requests[i].getType() == CurrentUser::RT_SIGN_IN)
{
if(m_requests[i].isSuccess())
{
new MessageDialog(_("Signed in."));
}
else
{
sfx_manager->quickSound( "anvil" );
new MessageDialog(m_requests[i].getInfo());
}
}else if(m_requests[i].getType() == CurrentUser::RT_SIGN_OUT)
{
new MessageDialog(_("Signed out successfully."));
}
m_requests.erase(i);
}
}
} // onUpdate
// ----------------------------------------------------------------------------
@ -157,10 +197,11 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name, const
if (name == "back")
{
StateManager::get()->escapePressed();
return;
}
RibbonWidget* ribbon = dynamic_cast<RibbonWidget*>(widget);
if (ribbon == NULL) return; // what's that event??
if (ribbon == NULL) return;
std::string selection = ribbon->getSelectionIDString(PLAYER_ID_GAME_MASTER);
if (selection == "sign_in")
@ -169,42 +210,45 @@ void OnlineScreen::eventCallback(Widget* widget, const std::string& name, const
}
else if (selection == "sign_out")
{
if (CurrentOnlineUser::get()->signOut())
{
new MessageDialog( _("Signed out successfully.") );
//GUIEngine::reshowCurrentScreen();
}
else
new MessageDialog( _("An error occured while signing out.") );
CurrentUser::acquire()->requestSignOut();
CurrentUser::release();
}
else if (selection == "register")
{
new RegistrationDialog(0.8f, 0.9f);
new RegistrationDialog();
}
else if (selection == "find_server")
{
//if (m_recorded_state == Registered)
new MessageDialog("Coming soon!");
StateManager::get()->pushScreen(ServerSelection::getInstance());
}
else if (selection == "create_server")
{
//if (m_recorded_state == Registered)
StateManager::get()->pushScreen(NetworkingLobbySettings::getInstance());
StateManager::get()->pushScreen(CreateServerScreen::getInstance());
}
else if (selection == "quick_play")
{
//if (m_recorded_state == Registered || m_recorded_state == Guest) FIXME
StateManager::get()->pushScreen(NetworkingLobby::getInstance());
//FIXME temporary and the request join + join sequence should be placed in one method somewhere
/*
Server * server = ServersManager::get()->getQuickPlay();
irr::core::stringw info;
if (Online::CurrentUser::get()->requestJoin( server->getServerId(), info))
{
ServersManager::get()->setJoinedServer(server);
StateManager::get()->pushScreen(NetworkingLobby::getInstance());
}
else
{
sfx_manager->quickSound( "anvil" );
}*/
ProtocolManager::getInstance()->requestStart(new ConnectToServer(7));
}
} // eventCallback
// ----------------------------------------------------------------------------
void OnlineScreen::tearDown()
{
} // tearDown
}
// ----------------------------------------------------------------------------
void OnlineScreen::onDisabledItemClicked(const std::string& item)
@ -215,23 +259,22 @@ void OnlineScreen::onDisabledItemClicked(const std::string& item)
}
else if (item =="create_server")
{
StateManager::get()->pushScreen(NetworkingLobbySettings::getInstance());
// FIXME temporary; new LoginDialog(LoginDialog::Registration_Required);
new LoginDialog(LoginDialog::Registration_Required);
}
else if (item == "quick_play")
{
StateManager::get()->pushScreen(NetworkingLobby::getInstance());
// FIXME temporary; new LoginDialog(LoginDialog::Signing_In_Required);
new LoginDialog(LoginDialog::Signing_In_Required);
}
} // onDisabledItemClicked
// ----------------------------------------------------------------------------
void OnlineScreen::setInitialFocus()
{
if(m_recorded_state == Not)
m_bottom_menu_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
else
if(m_recorded_state == CurrentUser::US_SIGNED_IN)
m_top_menu_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
else
m_bottom_menu_widget->setFocusForPlayer(PLAYER_ID_GAME_MASTER);
} // setInitialFocus
// ----------------------------------------------------------------------------
@ -242,3 +285,4 @@ void OnlineScreen::onDialogClose()
else
setInitialFocus();
} // onDialogClose()

View File

@ -22,6 +22,8 @@
#include "guiengine/widgets/label_widget.hpp"
#include "guiengine/widgets/ribbon_widget.hpp"
#include "guiengine/widgets/icon_button_widget.hpp"
#include "online/current_user.hpp"
#include "utils/ptr_vector.hpp"
namespace GUIEngine { class Widget; class ListWidget; }
@ -36,6 +38,7 @@ private:
friend class GUIEngine::ScreenSingleton<OnlineScreen>;
OnlineScreen();
~OnlineScreen();
GUIEngine::RibbonWidget * m_top_menu_widget;
GUIEngine::IconButtonWidget * m_quick_play_widget;
@ -49,14 +52,9 @@ private:
GUIEngine::IconButtonWidget * m_register_widget;
GUIEngine::IconButtonWidget * m_sign_out_widget;
enum State
{
Not = 1,
Guest = 2,
Registered = 4
};
Online::CurrentUser::UserState m_recorded_state;
State m_recorded_state;
PtrVector<Online::XMLRequest> m_requests;
/** \brief Checks if the recorded state differs from the actual state and sets it. */
bool hasStateChanged();

View File

@ -0,0 +1,220 @@
// 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 "states_screens/dialogs/message_dialog.hpp"
#include "states_screens/dialogs/server_info_dialog.hpp"
#include "states_screens/state_manager.hpp"
#include "utils/translation.hpp"
#include "utils/string_utils.hpp"
#include "online/messages.hpp"
#include "audio/sfx_manager.hpp"
using namespace Online;
DEFINE_SCREEN_SINGLETON( ServerSelection );
// ----------------------------------------------------------------------------
ServerSelection::ServerSelection() : Screen("online/server_selection.stkgui")
{
m_selected_index = -1;
m_refresh_request = NULL;
} // ServerSelection
// ----------------------------------------------------------------------------
ServerSelection::~ServerSelection()
{
} // ServerSelection
// ----------------------------------------------------------------------------
void ServerSelection::tearDown()
{
delete m_refresh_request;
} // tearDown
// ----------------------------------------------------------------------------
void ServerSelection::refresh()
{
m_refresh_request = ServersManager::acquire()->refreshRequest();
ServersManager::release();
m_fake_refresh = (m_refresh_request == NULL ? true : false);
m_server_list_widget->clear();
m_server_list_widget->addItem("spacer", L"");
m_server_list_widget->addItem("loading", Messages::fetchingServers());
m_reload_widget->setDeactivated();
}
// ----------------------------------------------------------------------------
void ServerSelection::loadedFromFile()
{
m_back_widget = getWidget<GUIEngine::IconButtonWidget>("back");
assert(m_back_widget != NULL);
m_reload_widget = getWidget<GUIEngine::IconButtonWidget>("reload");
assert(m_reload_widget != NULL);
m_server_list_widget = getWidget<GUIEngine::ListWidget>("server_list");
assert(m_server_list_widget != NULL);
m_server_list_widget->setColumnListener(this);
} // loadedFromFile
// ----------------------------------------------------------------------------
void ServerSelection::beforeAddingWidget()
{
m_server_list_widget->clearColumns();
m_server_list_widget->addColumn( _("Name"), 3 );
m_server_list_widget->addColumn( _("Players"), 1);
}
// ----------------------------------------------------------------------------
void ServerSelection::init()
{
Screen::init();
m_sort_desc = true;
// Set the default sort order
Server::setSortOrder(Server::SO_NAME);
refresh();
} // init
// ----------------------------------------------------------------------------
/** Loads the list of all servers. The gui element will be
* updated.
* \param type Must be 'kart' or 'track'.
*/
void ServerSelection::loadList()
{
m_server_list_widget->clear();
ServersManager * manager = ServersManager::acquire();
manager->sort(m_sort_desc);
for(int i=0; i < manager->getNumServers(); i++)
{
Server * server = manager->getServerBySort(i);
core::stringw num_players;
num_players.append(StringUtils::toWString(server->getCurrentPlayers()));
num_players.append("/");
num_players.append(StringUtils::toWString(server->getMaxPlayers()));
PtrVector<GUIEngine::ListWidget::ListCell> * row = new PtrVector<GUIEngine::ListWidget::ListCell>;
row->push_back(new GUIEngine::ListWidget::ListCell(server->getName(),-1,3));
row->push_back(new GUIEngine::ListWidget::ListCell(num_players,-1,1,true));
m_server_list_widget->addItem("server", row);
}
ServersManager::release();
} // 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;
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")
{
refresh();
}
else if (name == m_server_list_widget->m_properties[GUIEngine::PROP_ID])
{
m_selected_index = m_server_list_widget->getSelectionID();
uint32_t server_id = ServersManager::acquire()->getServerBySort(m_selected_index)->getServerId();
ServersManager::release();
new ServerInfoDialog(server_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*)
{
if(m_refresh_request != NULL)
{
if(m_refresh_request->isDone())
{
if(m_refresh_request->isSuccess())
{
loadList();
}
else
{
sfx_manager->quickSound( "anvil" );
new MessageDialog(m_refresh_request->getInfo());
}
delete m_refresh_request;
m_refresh_request = NULL;
m_reload_widget->setActivated();
}
else
{
m_server_list_widget->renameItem("loading", Messages::fetchingServers());
}
}
else if(m_fake_refresh)
{
loadList();
m_fake_refresh = false;
m_reload_widget->setActivated();
}
} // onUpdate

View File

@ -0,0 +1,88 @@
// 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.hpp"
#include "online/servers_manager.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();
~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;
/** \brief To check (and set) if sort order is descending **/
bool m_sort_desc;
Online::ServersManager::RefreshRequest * m_refresh_request;
bool m_fake_refresh;
void refresh();
public:
/** Load the addons into the main list.*/
void loadList();
/** \brief implement callback from parent class GUIEngine::Screen */
virtual void loadedFromFile() 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

View File

@ -30,7 +30,7 @@
#include "main_loop.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
#include "online/online_user.hpp"
#include "online/user.hpp"
#include "utils/translation.hpp"
#include "utils/log.hpp"
@ -103,7 +103,7 @@ void StateManager::updateActivePlayerIDs()
// ----------------------------------------------------------------------------
int StateManager::createActivePlayer(PlayerProfile *profile, InputDevice *device,
OnlineUser* user)
Online::User* user)
{
ActivePlayer *p;
int i;
@ -170,7 +170,8 @@ void StateManager::escapePressed()
// when another modal dialog is visible
else if(ModalDialog::isADialogActive())
{
ModalDialog::getCurrent()->escapePressed();
if(ModalDialog::getCurrent()->onEscapePressed())
ModalDialog::getCurrent()->dismiss();
}
// In-game
else if(m_game_mode == GAME)
@ -254,7 +255,7 @@ void StateManager::onStackEmptied()
StateManager::ActivePlayer::ActivePlayer(PlayerProfile* player,
InputDevice *device,
OnlineUser* user)
Online::User* user)
{
#ifdef DEBUG
m_magic_number = 0xAC1EF1AE;

View File

@ -34,7 +34,10 @@
class AbstractKart;
class InputDevice;
struct Input;
class OnlineUser;
namespace Online
{
class User;
}
namespace GUIEngine
{
@ -73,7 +76,7 @@ public:
{
friend class StateManager;
OnlineUser *m_online_user;
Online::User *m_online_user;
PlayerProfile *m_player;
InputDevice *m_device;
@ -83,7 +86,7 @@ public:
/** ID of this player within the list of active players */
int m_id;
ActivePlayer(PlayerProfile* player, InputDevice* device, OnlineUser* user);
ActivePlayer(PlayerProfile* player, InputDevice* device, Online::User* user);
#ifdef DEBUG
unsigned int m_magic_number;
@ -125,14 +128,14 @@ public:
void setPlayerProfile(PlayerProfile* player);
// --------------------------------------------------------------------
OnlineUser* getOnlineUser()
Online::User* getOnlineUser()
{
return m_online_user;
}
// --------------------------------------------------------------------
/** Call to change the identity of this player (useful when player is
* selecting his identity) */
void setOnlineUser(OnlineUser* user) { m_online_user = user; }
void setOnlineUser(Online::User* user) { m_online_user = user; }
// --------------------------------------------------------------------
/** ID of this player within the list of active players */
@ -190,7 +193,7 @@ public:
*/
const PlayerProfile* getActivePlayerProfile(const int id);
int createActivePlayer(PlayerProfile *profile, InputDevice *device, OnlineUser* use);
int createActivePlayer(PlayerProfile *profile, InputDevice *device, Online::User* use);
void removeActivePlayer(int id);
int activePlayerCount();